Unify pre-execution stage decisions
This commit is contained in:
@@ -244,9 +244,9 @@ func executePlan(ctx context.Context, cfg *config.Config, plan BoundedPlan, opts
|
||||
fmt.Errorf("fingerprint semantic configuration for stage %q: %w", s.Name(), err),
|
||||
)
|
||||
}
|
||||
action := decideStageAction(s, m, opts.Force)
|
||||
decision := decideStageExecution(recordedStageStatus(m, s.Name()), opts.Force, nil)
|
||||
|
||||
if action == stageActionSkip {
|
||||
if decision.action == stageActionSkip {
|
||||
validation, err := evaluateStageResume(ctx, s, stageEnv, m, semanticConfig)
|
||||
if err != nil {
|
||||
return nil, persistSessionTerminalFailure(
|
||||
@@ -254,12 +254,10 @@ func executePlan(ctx context.Context, cfg *config.Config, plan BoundedPlan, opts
|
||||
fmt.Errorf("validate resume for stage %q: %w", s.Name(), err),
|
||||
)
|
||||
}
|
||||
if validation != nil && !validation.Resumable {
|
||||
decision = decideStageExecution(recordedStageStatus(m, s.Name()), opts.Force, validation)
|
||||
if decision.markSelectedStale {
|
||||
staleAt := nowUTC()
|
||||
m.MarkStageStale(s.Name(), staleAt, validation.Reason)
|
||||
if _, err := invalidateDependentSucceededStagesWithReason(
|
||||
m, s.Name(), staleAt, staleReasonNotResumable,
|
||||
); err != nil {
|
||||
if _, err := applyPreExecutionDecision(m, s.Name(), decision, staleAt); err != nil {
|
||||
return nil, persistSessionTerminalFailure(
|
||||
ctx, env.ManifestStore, manifestPath, m,
|
||||
fmt.Errorf("invalidate dependents after resume validation for stage %q: %w", s.Name(), err),
|
||||
@@ -271,12 +269,11 @@ func executePlan(ctx context.Context, cfg *config.Config, plan BoundedPlan, opts
|
||||
fmt.Errorf("save manifest after resume validation for stage %q: %w", s.Name(), err),
|
||||
)
|
||||
}
|
||||
env.Logger.Info("stage result is not resumable", "stage", s.Name(), "reason", validation.Reason)
|
||||
action = stageActionRun
|
||||
env.Logger.Info("stage result is not resumable", "stage", s.Name(), "reason", decision.selectedStaleReason)
|
||||
}
|
||||
}
|
||||
|
||||
if action == stageActionSkip {
|
||||
if decision.action == stageActionSkip {
|
||||
skipped = append(skipped, s.Name())
|
||||
env.Logger.Info("skipping stage", "stage", s.Name(), "reason", "already_succeeded", "force", opts.Force)
|
||||
continue
|
||||
@@ -286,14 +283,11 @@ func executePlan(ctx context.Context, cfg *config.Config, plan BoundedPlan, opts
|
||||
priorAnalyzeState := captureAnalyzeState(m, s.Name())
|
||||
|
||||
now := nowUTC()
|
||||
m.MarkStageRunning(s.Name(), now)
|
||||
if opts.Force {
|
||||
if _, err := invalidateDependentSucceededStagesWithReason(m, s.Name(), now, staleReasonForcedReplacement); err != nil {
|
||||
return nil, persistSessionTerminalFailure(
|
||||
ctx, env.ManifestStore, manifestPath, m,
|
||||
fmt.Errorf("invalidate dependents before forced stage %q: %w", s.Name(), err),
|
||||
)
|
||||
}
|
||||
if _, err := beginStageAttempt(m, s.Name(), decision, now); err != nil {
|
||||
return nil, persistSessionTerminalFailure(
|
||||
ctx, env.ManifestStore, manifestPath, m,
|
||||
fmt.Errorf("invalidate dependents before forced stage %q: %w", s.Name(), err),
|
||||
)
|
||||
}
|
||||
env.Logger.Info("starting stage", "stage", s.Name())
|
||||
if err := env.ManifestStore.Save(ctx, manifestPath, m); err != nil {
|
||||
@@ -340,16 +334,11 @@ func executePlan(ctx context.Context, cfg *config.Config, plan BoundedPlan, opts
|
||||
if result != nil && result.Disposition == stage.StageDispositionSkipped {
|
||||
skipped = append(skipped, s.Name())
|
||||
skippedAt := nowUTC()
|
||||
m.MarkStageSkipped(s.Name(), skippedAt, result.SkipReason)
|
||||
applyStageResultToManifest(m, s.Name(), result)
|
||||
setSessionStageSemanticConfig(m, s.Name(), semanticConfig)
|
||||
if !priorOutcome.isSameSelfSkip(result.SkipReason) {
|
||||
if _, err := invalidateDependentSucceededStagesWithReason(m, s.Name(), skippedAt, staleReasonSelfSkip); err != nil {
|
||||
return nil, persistSessionTerminalFailure(
|
||||
ctx, env.ManifestStore, manifestPath, m,
|
||||
fmt.Errorf("invalidate dependents after stage %q self-skip: %w", s.Name(), err),
|
||||
)
|
||||
}
|
||||
if _, err := applyCompletedStageOutcome(m, s.Name(), result, nil, semanticConfig, priorOutcome, skippedAt); err != nil {
|
||||
return nil, persistSessionTerminalFailure(
|
||||
ctx, env.ManifestStore, manifestPath, m,
|
||||
fmt.Errorf("invalidate dependents after stage %q self-skip: %w", s.Name(), err),
|
||||
)
|
||||
}
|
||||
if err := env.ManifestStore.Save(ctx, manifestPath, m); err != nil {
|
||||
return nil, persistSessionTerminalFailure(
|
||||
@@ -367,18 +356,13 @@ func executePlan(ctx context.Context, cfg *config.Config, plan BoundedPlan, opts
|
||||
sessionOutputs = analyzeProjectionOutputs(analyzeProjection.session)
|
||||
}
|
||||
succeededAt := nowUTC()
|
||||
m.MarkStageSucceeded(s.Name(), succeededAt, sessionOutputs)
|
||||
applyAnalyzeProjection(m, analyzeProjection)
|
||||
applyStageResultToManifest(m, s.Name(), result)
|
||||
setSessionStageSemanticConfig(m, s.Name(), semanticConfig)
|
||||
if !priorOutcome.exists || priorOutcome.status != manifest.StatusSucceeded {
|
||||
if _, err := invalidateDependentSucceededStagesWithReason(m, s.Name(), succeededAt, staleReasonChangedResult); err != nil {
|
||||
return nil, persistSessionTerminalFailure(
|
||||
ctx, env.ManifestStore, manifestPath, m,
|
||||
fmt.Errorf("invalidate dependents after changed stage %q result: %w", s.Name(), err),
|
||||
)
|
||||
}
|
||||
if _, err := applyCompletedStageOutcome(m, s.Name(), result, sessionOutputs, semanticConfig, priorOutcome, succeededAt); err != nil {
|
||||
return nil, persistSessionTerminalFailure(
|
||||
ctx, env.ManifestStore, manifestPath, m,
|
||||
fmt.Errorf("invalidate dependents after changed stage %q result: %w", s.Name(), err),
|
||||
)
|
||||
}
|
||||
applyAnalyzeProjection(m, analyzeProjection)
|
||||
|
||||
if err := env.ManifestStore.Save(ctx, manifestPath, m); err != nil {
|
||||
operationErr := fmt.Errorf("save manifest after stage %q: %w", s.Name(), err)
|
||||
|
||||
Reference in New Issue
Block a user