90 lines
4.2 KiB
Go
90 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
)
|
|
|
|
// A walk stopped by hand while its tier waited — modules asked on the builder's keys, two built and never sent, the next
|
|
// tier not yet asked — is resumed by `plans retry` (issue 1886): set building again, its stop cleared, the asks it holds
|
|
// kept, so the next look carries it on as any walk. Nothing in it failed, so the retry of failed builds had nothing to do
|
|
// and refused it, leaving a stopped R4e with no verb to carry its 48 modules on.
|
|
func TestRetryResumesAWalkStoppedByHand(t *testing.T) {
|
|
at := time.Date(2026, 10, 23, 0, 1, 53, 0, time.UTC)
|
|
sent := at.Add(-time.Hour)
|
|
p := inventory.Plan{ID: "plan-r4e", Repository: "novox/mesh-sdk", Branch: "main", Commit: "7aacbc16",
|
|
Created: at.Add(-2 * time.Hour), State: inventory.PlanFailed, Tier: 1,
|
|
Note: "stopped by a person at tier 1: issue 1886",
|
|
Delivery: &inventory.PlanDelivery{Stopped: "a person (fix-1886@shanks)", StoppedWhy: "issue 1886",
|
|
Kept: []inventory.PlanKept{{Module: "mesh-controller"}}},
|
|
Modules: map[string]*inventory.PlanModule{}}
|
|
tier0 := []string{"mesh-controller", "mesh-sdk", "pacman", "route-proxy"}
|
|
for _, m := range tier0 {
|
|
p.Modules[m] = &inventory.PlanModule{State: "built", BuiltAt: &sent, SentAt: &sent}
|
|
}
|
|
var tier1 []string
|
|
for _, m := range []string{"build-agent", "mesh-tools"} {
|
|
tier1 = append(tier1, m)
|
|
p.Modules[m] = &inventory.PlanModule{State: "built", BuiltAt: &sent}
|
|
}
|
|
onKeys := []string{"mesh-build-go", "mesh-build-image", "mesh-build-node", "mesh-delivery-checker",
|
|
"mesh-delivery-forge-bridge", "mesh-delivery-gate", "mesh-delivery-indexer", "mesh-delivery-view"}
|
|
for _, m := range onKeys {
|
|
tier1 = append(tier1, m)
|
|
p.Modules[m] = &inventory.PlanModule{State: "asked", AskedAt: &sent, Key: true, Build: "build-" + m}
|
|
}
|
|
tier2 := []string{"gitea", "mesh-catalog", "mongodb"}
|
|
for _, m := range tier2 {
|
|
p.Modules[m] = &inventory.PlanModule{}
|
|
}
|
|
p.Tiers = [][]string{tier0, tier1, tier2}
|
|
|
|
if err := retryRefusal(p, []inventory.Plan{p}, ownPathOf(nil)); err != nil {
|
|
t.Fatalf("a walk stopped by hand with its tier waiting was refused a retry: %v", err)
|
|
}
|
|
said := resumeStopped(&p)
|
|
if p.State != inventory.PlanBuilding {
|
|
t.Errorf("resumed walk is %s, wanted building", p.State)
|
|
}
|
|
if p.Delivery.Stopped != "" || p.Delivery.StoppedWhy != "" || len(p.Delivery.Kept) > 0 {
|
|
t.Errorf("resumed walk still says it stopped: %+v", p.Delivery)
|
|
}
|
|
if !strings.Contains(p.Note, "resumed by hand") || !strings.Contains(p.Note, "a person (fix-1886@shanks)") {
|
|
t.Errorf("the note does not record the hand resume and the stop it undid: %q", p.Note)
|
|
}
|
|
for _, m := range onKeys {
|
|
if s := p.Modules[m]; s.State != "asked" || !s.Key || s.Build != "build-"+m {
|
|
t.Errorf("%s's ask was not kept for the look to hand on: %+v", m, s)
|
|
}
|
|
}
|
|
for _, w := range []string{"plan-r4e", "tier 2 of 3", "8 asked", "2 built and not sent", "3 not yet asked"} {
|
|
if !strings.Contains(said, w) {
|
|
t.Errorf("the answer %q does not say %q", said, w)
|
|
}
|
|
}
|
|
|
|
// What it still refuses: a walk stopped with nothing left in its tier, and one a related open walk runs beside.
|
|
done := p
|
|
done.State, done.Delivery = inventory.PlanFailed, &inventory.PlanDelivery{Stopped: "a person"}
|
|
done.Modules = map[string]*inventory.PlanModule{}
|
|
for _, tier := range done.Tiers {
|
|
for _, m := range tier {
|
|
done.Modules[m] = &inventory.PlanModule{State: "built", BuiltAt: &sent, SentAt: &sent}
|
|
}
|
|
}
|
|
if err := retryRefusal(done, nil, ownPathOf(nil)); err == nil || !strings.Contains(err.Error(), "nothing in tier 1") {
|
|
t.Errorf("a stopped walk with nothing left in its tier was retried: %v", err)
|
|
}
|
|
stopped := p
|
|
stopped.State, stopped.Delivery = inventory.PlanFailed, &inventory.PlanDelivery{Stopped: "a person"}
|
|
beside := inventory.Plan{ID: "plan-442", Repository: "novox/mesh-sdk", Branch: "release", Commit: "bbadbb2a",
|
|
Created: at, State: inventory.PlanBuilding, Tiers: [][]string{{"mesh-sdk"}},
|
|
Modules: map[string]*inventory.PlanModule{"mesh-sdk": {State: "asked"}}}
|
|
if err := retryRefusal(stopped, []inventory.Plan{beside}, ownPathOf(nil)); err == nil || !strings.Contains(err.Error(), "one walk at a time") {
|
|
t.Errorf("a stopped walk was resumed beside a related open walk: %v", err)
|
|
}
|
|
}
|