Unify pre-execution stage decisions
This commit is contained in:
@@ -73,26 +73,20 @@ func Plan(ctx context.Context, args []string, out io.Writer) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("plan: fingerprint semantic configuration for stage %q: %w", selectedStage.Name(), err)
|
||||
}
|
||||
action := decideStageAction(selectedStage, model, request.Force)
|
||||
decision := decideStageExecution(recordedStageStatus(model, selectedStage.Name()), request.Force, nil)
|
||||
var validation *stage.ResumeValidation
|
||||
if action == stageActionSkip {
|
||||
if decision.action == stageActionSkip {
|
||||
checked, validationErr := evaluateStageResume(ctx, selectedStage, stageEnv, model, semanticConfig)
|
||||
if validationErr != nil {
|
||||
return fmt.Errorf("plan: validate resume for stage %q: %w", selectedStage.Name(), validationErr)
|
||||
}
|
||||
validation = checked
|
||||
if checked != nil && !checked.Resumable {
|
||||
at := time.Now().UTC()
|
||||
model.MarkStageStale(selectedStage.Name(), at, checked.Reason)
|
||||
if _, invalidationErr := invalidateDependentSucceededStagesWithReason(
|
||||
model, selectedStage.Name(), at, staleReasonNotResumable,
|
||||
); invalidationErr != nil {
|
||||
return fmt.Errorf("plan: model resume invalidation for stage %q: %w", selectedStage.Name(), invalidationErr)
|
||||
}
|
||||
action = stageActionRun
|
||||
}
|
||||
decision = decideStageExecution(recordedStageStatus(model, selectedStage.Name()), request.Force, checked)
|
||||
}
|
||||
if action == stageActionRun && selectedStage.Name() == "analyze" {
|
||||
if _, err := applyPreExecutionDecision(model, selectedStage.Name(), decision, time.Now().UTC()); err != nil {
|
||||
return fmt.Errorf("plan: model resume invalidation for stage %q: %w", selectedStage.Name(), err)
|
||||
}
|
||||
if decision.action == stageActionRun && selectedStage.Name() == "analyze" {
|
||||
if validator, ok := selectedStage.(stage.ResumeValidator); ok {
|
||||
checked, validationErr := validator.ValidateResume(ctx, stageEnv, model)
|
||||
if validationErr != nil {
|
||||
@@ -102,12 +96,12 @@ func Plan(ctx context.Context, args []string, out io.Writer) error {
|
||||
validation = &checked
|
||||
}
|
||||
}
|
||||
if action == stageActionRun {
|
||||
if decision.action == stageActionRun {
|
||||
runCount++
|
||||
} else {
|
||||
skipCount++
|
||||
}
|
||||
if _, err := fmt.Fprintf(out, "%s: %s\n", selectedStage.Name(), action); err != nil {
|
||||
if _, err := fmt.Fprintf(out, "%s: %s\n", selectedStage.Name(), decision.action); err != nil {
|
||||
return err
|
||||
}
|
||||
if validation != nil && validation.Analyze != nil {
|
||||
@@ -115,8 +109,8 @@ func Plan(ctx context.Context, args []string, out io.Writer) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if action == stageActionRun {
|
||||
if err := modelPlannedStageRun(model, selectedStage, cfg, request.Force, semanticConfig); err != nil {
|
||||
if decision.action == stageActionRun {
|
||||
if err := modelPlannedStageRun(model, selectedStage, cfg, decision, semanticConfig); err != nil {
|
||||
return fmt.Errorf("plan: model stage %q: %w", selectedStage.Name(), err)
|
||||
}
|
||||
}
|
||||
@@ -149,40 +143,23 @@ func modelPlannedStageRun(
|
||||
model *manifest.Manifest,
|
||||
selectedStage stage.Stage,
|
||||
cfg *config.Config,
|
||||
force bool,
|
||||
decision preExecutionDecision,
|
||||
semanticConfig *manifest.SemanticConfigFingerprint,
|
||||
) error {
|
||||
prior := capturePriorStageOutcome(model, selectedStage.Name())
|
||||
at := time.Now().UTC()
|
||||
model.MarkStageRunning(selectedStage.Name(), at)
|
||||
if force {
|
||||
if _, err := invalidateDependentSucceededStagesWithReason(
|
||||
model, selectedStage.Name(), at, staleReasonForcedReplacement,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := beginStageAttempt(model, selectedStage.Name(), decision, at); err != nil {
|
||||
return err
|
||||
}
|
||||
if reason := plannedSelfSkipReason(selectedStage.Name(), cfg); reason != "" {
|
||||
model.MarkStageSkipped(selectedStage.Name(), at, reason)
|
||||
setSessionStageSemanticConfig(model, selectedStage.Name(), semanticConfig)
|
||||
if !prior.isSameSelfSkip(reason) {
|
||||
_, err := invalidateDependentSucceededStagesWithReason(
|
||||
model, selectedStage.Name(), at, staleReasonSelfSkip,
|
||||
)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
_, err := applyCompletedStageOutcome(model, selectedStage.Name(), &stage.StageResult{
|
||||
Disposition: stage.StageDispositionSkipped,
|
||||
SkipReason: reason,
|
||||
}, nil, semanticConfig, prior, at)
|
||||
return err
|
||||
}
|
||||
model.MarkStageSucceeded(selectedStage.Name(), at, nil)
|
||||
setSessionStageSemanticConfig(model, selectedStage.Name(), semanticConfig)
|
||||
if !prior.exists || prior.status != manifest.StatusSucceeded {
|
||||
if _, err := invalidateDependentSucceededStagesWithReason(
|
||||
model, selectedStage.Name(), at, staleReasonChangedResult,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
_, err := applyCompletedStageOutcome(model, selectedStage.Name(), &stage.StageResult{}, nil, semanticConfig, prior, at)
|
||||
return err
|
||||
}
|
||||
|
||||
func plannedSelfSkipReason(stageName string, cfg *config.Config) string {
|
||||
|
||||
Reference in New Issue
Block a user