From 3e5d4c30ffa72e63599ec41d37f72fffddfd23ec Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 23 Oct 2026 15:41:55 +0200 Subject: [PATCH] Let a composition not run say why, the assigner not running among it, and name the indexer's words for a removed module, so a check never waits for a composition nobody makes (issue 1297, B3d) --- go/delivery/checker.go | 10 ++++++++-- go/delivery/checker_test.go | 10 ++++++++++ go/delivery/source.go | 4 ++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/go/delivery/checker.go b/go/delivery/checker.go index 81c0dc9..679985b 100644 --- a/go/delivery/checker.go +++ b/go/delivery/checker.go @@ -96,10 +96,16 @@ type LevelResult struct { // The states of a Composition (ADR 0484 clause 6): the composition check is the assigner's, so until it delivers a // verdict says CompositionNotRun, and a line never says the composition passed on that. +// +// A composition not run may say why in its Words: AssignerNotRunning when no instance of the assigner is online, so a +// check never waits for a composition nobody is making (issue 1297). const ( CompositionNotRun = "not-run" CompositionPass = "pass" CompositionFail = "fail" + + // AssignerNotRunning is the Words of a composition not run because no instance of the assigner is online. + AssignerNotRunning = "the assigner is not running" ) // Composition is what the check of the machines' composition made of a verdict: its State (not-run, pass or fail), the @@ -156,8 +162,8 @@ func (c *Composition) check() error { } switch c.State { case CompositionNotRun: - if c.Words != "" || c.SDK != "" || len(c.Machines) > 0 { - return fmt.Errorf("delivery: the verdict's composition is not run and says nothing of words, the mesh-sdk commit or machines") + if c.SDK != "" || len(c.Machines) > 0 { + return fmt.Errorf("delivery: the verdict's composition is not run and names no mesh-sdk commit or machines") } case CompositionPass: if c.SDK == "" { diff --git a/go/delivery/checker_test.go b/go/delivery/checker_test.go index 296da52..22d4611 100644 --- a/go/delivery/checker_test.go +++ b/go/delivery/checker_test.go @@ -262,6 +262,16 @@ func TestVerdictCarriesSkippedCompositionAndOverBound(t *testing.T) { if _, err := EncodeVerdict(notRun); err != nil { t.Errorf("a composition not yet run refused: %v", err) } + // 1297: a composition not run says why when the assigner is not running, and round-trips with its words. + notRunning := passVerdict() + notRunning.Composition = &Composition{State: CompositionNotRun, Words: AssignerNotRunning} + data, err = EncodeVerdict(notRunning) + if err != nil { + t.Fatalf("a composition not run because the assigner is not running refused: %v", err) + } + if back, err := DecodeVerdict(data); err != nil || back.Composition.Words != AssignerNotRunning { + t.Errorf("its words came back as %+v, %v", back.Composition, err) + } failed := passVerdict() failed.State, failed.Failed = VerdictFail, FailedFirst{Machine: "ace", Words: "x"} failed.Composition = &Composition{State: CompositionFail, Words: "path /etc/x is owned by two modules", SDK: failed.SDK, Machines: []string{"ace"}} diff --git a/go/delivery/source.go b/go/delivery/source.go index 145b4e2..535f771 100644 --- a/go/delivery/source.go +++ b/go/delivery/source.go @@ -271,6 +271,10 @@ type CandidatePull struct { Fps map[string]CandidateModule `json:"fps,omitempty"` } +// CandidateNoneNoModule is the None2 of a candidate's module whose directory the merge preview names no manifest for: +// the change removes the module. The indexer writes it and the assigner reads it as a removal (issue 1297). +const CandidateNoneNoModule = "the merge preview names no manifest for the module's directory" + // CandidateModule is one touched module's new-form fingerprint FP2 (`src2:` and 64 hex digits), or None2, the reason // it has none; exactly one of them. Manifest is the digest of the module's manifest as read at the preview. type CandidateModule struct {