Runner (A-336): a publish heard before its branch's half starts with no steps

A-336 holds for every start of a pipeline: a package-published heard before
its branch's catalog half was held still placed steps from empty entries. Its
pipelines now start with no steps, placed by A-327's path once the half is
held. The hand start already refuses a branch whose half is not held.

Builds: design 47 G §200, A-327, A-336

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-13 02:43:18 +01:00
parent d827d1abf0
commit bf852f27aa
2 changed files with 22 additions and 3 deletions
@@ -396,7 +396,9 @@ func (s *Starter) Published(ev builds.PackagePublished, outdated func(catalog.Ou
if err != nil {
return 0, fmt.Errorf("outdated of %s on %s: %w", ev.Artifact, ev.Branch, err)
}
half, _ := view(ev.Branch)
// A publish heard before its branch's half is held starts its pipelines with no steps, never placed from empty entries
// (§200, A-336); Waiting places them once the half is held.
half, held := view(ev.Branch)
started := 0
var first error
for _, o := range a.Behind {
@@ -404,10 +406,10 @@ func (s *Starter) Published(ev builds.PackagePublished, outdated func(catalog.Ou
continue
}
b := Begin{Branch: ev.Branch, Source: ev.Source, Module: o.Module, Revision: half.Revision, Entries: half.Entries,
Published: &seat.Published{Artifact: ev.Artifact, Version: ev.Version}}
Published: &seat.Published{Artifact: ev.Artifact, Version: ev.Version}, unheld: !held}
if e, ok := half.Entries[o.Module]; ok {
b.Commit, b.Fp, b.Repository = e.Commit, e.Fp, e.Repository
} else {
} else if held {
s.logf("the catalog half of %s holds no entry of %s, behind %s: its pipeline starts without its commit", ev.Branch, o.Module, ev.Artifact)
}
ok, err := s.Start(b)
@@ -195,4 +195,21 @@ func TestAPipelineStartedBeforeItsRegistrationIsPlacedWhenItArrives(t *testing.T
if n != 1 || err != nil || len(p.Steps) == 0 {
t.Errorf("the half of next placed %d (%v): %d steps, want the take-in's pipeline placed", n, err, len(p.Steps))
}
// A-336: so does a package published heard before its branch's half is held.
held = false
outdated := func(catalog.OutdatedInput) (catalog.OutdatedAnswer, error) {
return catalog.OutdatedAnswer{Behind: []catalog.Outdated{{Module: "app", Kind: outdatedKind}}}, nil
}
if n, err := s.Published(builds.PackagePublished{Artifact: "mesh-sdk:go", Branch: "next", Source: 7, Module: "mesh-sdk", Version: "0.1.17"}, outdated, late); n != 1 || err != nil {
t.Fatalf("the publish before the half started %d (%v)", n, err)
}
if p, _, _ := store.Get("next.7.app"); len(p.Steps) != 0 {
t.Fatalf("a publish before its branch's half placed %d steps from empty entries, want none", len(p.Steps))
}
held = true
n, err = s.Waiting(store.memStore, "next", late)
p, _, _ = store.Get("next.7.app")
if n != 1 || err != nil || len(p.Steps) == 0 {
t.Errorf("the half of next placed %d (%v): %d steps, want the publish's pipeline placed", n, err, len(p.Steps))
}
}