Invalidate downstream results when stages are replaced
This commit is contained in:
@@ -3,6 +3,7 @@ package app
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/artifacts"
|
||||
@@ -23,22 +24,40 @@ type stageDecision struct {
|
||||
Action stageAction
|
||||
}
|
||||
|
||||
const (
|
||||
staleReasonForcedReplacement = "upstream stage was force-run"
|
||||
staleReasonChangedResult = "upstream stage result changed"
|
||||
staleReasonFailure = "upstream stage failed"
|
||||
staleReasonSelfSkip = "upstream stage self-skipped"
|
||||
staleReasonNotResumable = "upstream stage result was not resumable"
|
||||
)
|
||||
|
||||
type priorStageOutcome struct {
|
||||
exists bool
|
||||
status manifest.StageStatus
|
||||
skipReason string
|
||||
outputs int
|
||||
}
|
||||
|
||||
func decideStageActions(stages []stage.Stage, m *manifest.Manifest, force bool) []stageDecision {
|
||||
out := make([]stageDecision, 0, len(stages))
|
||||
for _, s := range stages {
|
||||
action := stageActionRun
|
||||
// TODO: incorporate stale detection once checksum/input change tracking is implemented.
|
||||
if !force && stageSucceeded(m, s.Name()) {
|
||||
action = stageActionSkip
|
||||
}
|
||||
out = append(out, stageDecision{
|
||||
Stage: s,
|
||||
Action: action,
|
||||
Action: decideStageAction(s, m, force),
|
||||
})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func decideStageAction(s stage.Stage, m *manifest.Manifest, force bool) stageAction {
|
||||
// TODO: incorporate stale detection once checksum/input change tracking is implemented.
|
||||
if !force && stageSucceeded(m, s.Name()) {
|
||||
return stageActionSkip
|
||||
}
|
||||
return stageActionRun
|
||||
}
|
||||
|
||||
func stageSucceeded(m *manifest.Manifest, name string) bool {
|
||||
if m == nil || m.Stages == nil {
|
||||
return false
|
||||
@@ -47,6 +66,29 @@ func stageSucceeded(m *manifest.Manifest, name string) bool {
|
||||
return sr != nil && sr.Status == manifest.StatusSucceeded
|
||||
}
|
||||
|
||||
func capturePriorStageOutcome(m *manifest.Manifest, name string) priorStageOutcome {
|
||||
if m == nil || m.Stages == nil || m.Stages[name] == nil {
|
||||
return priorStageOutcome{}
|
||||
}
|
||||
record := m.Stages[name]
|
||||
outcome := priorStageOutcome{
|
||||
exists: true,
|
||||
status: record.Status,
|
||||
outputs: len(record.Outputs),
|
||||
}
|
||||
if record.Error != nil && record.Error.Code == "skipped" {
|
||||
outcome.skipReason = record.Error.Message
|
||||
}
|
||||
return outcome
|
||||
}
|
||||
|
||||
func (o priorStageOutcome) isSameSelfSkip(reason string) bool {
|
||||
return o.exists &&
|
||||
o.status == manifest.StatusSkipped &&
|
||||
o.outputs == 0 &&
|
||||
o.skipReason == strings.TrimSpace(reason)
|
||||
}
|
||||
|
||||
func loadManifestIfPresent(ctx context.Context, cfg *config.Config) (*manifest.Manifest, error) {
|
||||
path := artifacts.SessionManifestPathForCampaign(
|
||||
cfg.Pipeline.Workspace.Root,
|
||||
@@ -91,10 +133,6 @@ func downstreamStageNames(stageName string) []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func invalidateDownstreamSucceededStages(m *manifest.Manifest, upstreamStage string, at time.Time) []string {
|
||||
return invalidateDownstreamSucceededStagesWithReason(m, upstreamStage, at, "upstream stage rerun with force")
|
||||
}
|
||||
|
||||
func invalidateDownstreamSucceededStagesWithReason(m *manifest.Manifest, upstreamStage string, at time.Time, reason string) []string {
|
||||
if m == nil || m.Stages == nil {
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user