Refuse a retry of a failed plan that a newer done plan of its branch has passed (issue 1328, ADR 0451)
This commit is contained in:
@@ -190,3 +190,64 @@ func TestNoClockRetriesAFailedPlan(t *testing.T) {
|
||||
t.Fatalf("a plan failed beyond the window is still raised: %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
// A later plan of the same repository and branch, in a state, made after the failed one.
|
||||
func laterPlan(id, branch, state string, after inventory.Plan) inventory.Plan {
|
||||
q := aFailedPlan(id, func(p *inventory.Plan) {
|
||||
p.State, p.Branch, p.Created = state, branch, after.Created.Add(time.Hour)
|
||||
})
|
||||
return q
|
||||
}
|
||||
|
||||
// 1328/AC1: a later done plan of the same repository and branch makes `plans retry` refuse, naming the later plan.
|
||||
func TestARetryIsRefusedWhenALaterPlanOfTheBranchIsDone(t *testing.T) {
|
||||
failed := aFailedPlan("plan-1", func(p *inventory.Plan) { p.Branch, p.Created = "main", time.Date(2026, 10, 19, 12, 0, 0, 0, time.UTC) })
|
||||
later := laterPlan("plan-2", "main", inventory.PlanDone, failed)
|
||||
err := retryRefusal(failed, []inventory.Plan{failed, later}, map[string]string{})
|
||||
if err == nil || !strings.Contains(err.Error(), "plan-2") || !strings.Contains(err.Error(), "passed") {
|
||||
t.Fatalf("the retry was not refused, naming the later plan: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 1328/AC2: with the later plan still open the refusal is today's; a later done plan of another branch refuses nothing.
|
||||
func TestARetryIsRefusedAsBeforeWhileTheLaterPlanIsOpenAndNotForAnotherBranch(t *testing.T) {
|
||||
failed := aFailedPlan("plan-1", func(p *inventory.Plan) { p.Branch, p.Created = "main", time.Date(2026, 10, 19, 12, 0, 0, 0, time.UTC) })
|
||||
open := laterPlan("plan-2", "main", inventory.PlanBuilding, failed)
|
||||
err := retryRefusal(failed, []inventory.Plan{failed, open}, map[string]string{})
|
||||
if err == nil || !strings.Contains(err.Error(), "supersedes it") {
|
||||
t.Fatalf("with the later plan open the refusal is not today's: %v", err)
|
||||
}
|
||||
other := laterPlan("plan-3", "feature/x", inventory.PlanDone, failed)
|
||||
if err := retryRefusal(failed, []inventory.Plan{failed, other}, map[string]string{}); err != nil {
|
||||
t.Fatalf("a later done plan of another branch refused the retry: %v", err)
|
||||
}
|
||||
earlier := laterPlan("plan-4", "main", inventory.PlanDone, failed)
|
||||
earlier.Created = failed.Created.Add(-time.Hour)
|
||||
if err := retryRefusal(failed, []inventory.Plan{failed, earlier}, map[string]string{}); err != nil {
|
||||
t.Fatalf("an earlier done plan refused the retry: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 1328/AC3: such a plan's plan-failed condition has no action and says it was passed by a newer delivery.
|
||||
func TestAPassedFailedPlanHasNoActionAndSaysItWasPassed(t *testing.T) {
|
||||
now := time.Date(2026, 10, 19, 18, 30, 0, 0, time.UTC)
|
||||
failed := aFailedPlan("plan-1", func(p *inventory.Plan) { p.Branch, p.Created = "main", now.Add(-5*time.Hour) })
|
||||
later := laterPlan("plan-2", "main", inventory.PlanDone, failed)
|
||||
f := calm(now)
|
||||
f.failed = []failedPlanFacts{failedFactsFor(failed, later)}
|
||||
got := watchPlansFailed(f)
|
||||
if len(got) != 1 || len(got[0].Actions) != 0 {
|
||||
t.Fatalf("%+v", got)
|
||||
}
|
||||
o := got[0]
|
||||
if !strings.Contains(o.Explanation, "newer delivery") || !strings.Contains(o.Explanation, "passed") {
|
||||
t.Errorf("the words do not say it was passed by a newer delivery: %q", o.Explanation)
|
||||
}
|
||||
if strings.Contains(o.Explanation, "details say why") {
|
||||
t.Errorf("the generic fallback was said: %q", o.Explanation)
|
||||
}
|
||||
words := conditions.Words{Headline: o.Headline, Explanation: o.Explanation, Resolved: o.Resolved, Needs: o.Needs}
|
||||
if why, ok := conditions.PlainWords(words, "g14", "shanks"); !ok {
|
||||
t.Errorf("not plain: %s\n%+v", why, words)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user