Unify trunk on main: initialization → main #3

Merged
jschoubben merged 58 commits from initialization into main 2026-09-05 01:13:33 +00:00
Showing only changes of commit af9d316258 - Show all commits
+62
View File
@@ -1298,3 +1298,65 @@ func TestAContainerGivenNoNamesIsRunAsBefore(t *testing.T) {
}
}
}
// Defends the ordering half of novox/hq work breakdown 1.3: resources are applied in the order
// the module declared them.
//
// **Already true, and untested until now** — the apply loop walks `d.Resources` and sorts nothing,
// so a module that needs one thing before another says so by writing it first. Worth an assertion
// because it is the kind of property a later change would break silently: sorting the resources
// for any good reason at all — by type, by identity, for a tidier report — would still pass every
// other test in this package.
//
// It is sequence, not readiness. A container started is not a container ready, and nothing here
// waits: what depends on something being *usable* retries, which is what both example
// provisioners do and is more robust than start ordering, because a dependency can also restart
// long after everything was applied.
func TestResourcesAreAppliedInTheOrderTheyWereDeclared(t *testing.T) {
dir := t.TempDir()
var order []string
done := map[string]bool{}
run := func(_ context.Context, name string, args ...string) (string, error) {
order = append(order, name+" "+strings.Join(args, " "))
// `verify` is the idempotency check, so it has to fail before the step and pass after —
// a stub that always succeeds means every action is already done and nothing ever runs,
// which is what the first version of this test measured.
if name == "check" {
if !done[args[0]] {
return "", fmt.Errorf("not yet")
}
return "", nil
}
done[args[0]] = true
return "", nil
}
_ = dir
// Trusted, because the link may not carry an action and only a bundle may (novox/hq ADR 0005).
// Actions are used here because they are the one shape whose execution is observable through
// the runner, which is what makes the order visible at all.
d, err := declaration.ParseTrusted([]byte(`{"declaration":1,"resources":[` +
`{"id":"first","type":"action","command":["step","one"],"verify":["check","one"]},` +
`{"id":"second","type":"action","command":["step","two"],"verify":["check","two"]},` +
`{"id":"third","type":"action","command":["step","three"],"verify":["check","three"]}]}`))
if err != nil {
t.Fatal(err)
}
if _, _, err := Apply(context.Background(), archHost(t), d, store.State{},
store.OriginCarried, run, nil, nil); err != nil {
t.Fatal(err)
}
var ran []string
for _, line := range order {
if strings.HasPrefix(line, "step ") {
ran = append(ran, strings.TrimPrefix(line, "step "))
}
}
want := []string{"one", "two", "three"}
if strings.Join(ran, ",") != strings.Join(want, ",") {
t.Fatalf("declared one, two, three and ran %v — a module that needs one thing before "+
"another has no way to say so", ran)
}
}