diff --git a/go/catalogue/delivery_seat.go b/go/catalogue/delivery_seat.go index dbc80fa..7df4d86 100644 --- a/go/catalogue/delivery_seat.go +++ b/go/catalogue/delivery_seat.go @@ -42,7 +42,8 @@ func deliveryVerbs() []Verb { "paths": "the files it changes, comma-separated, from the repository's root", "base": "the branch it merges into (default main)"}, []string{"repository", "paths"})}, {Name: "checks", Description: "What the mesh's checks said of a pull request's head or of one commit: each " + - "of the commit's mesh statuses (mesh/merge-gate, mesh/repo-check, mesh/delivery, …) with its state, " + + "of the commit's mesh statuses (mesh/check, the one a main requires from R4e, hq's mesh/repo-check, " + + "mesh/delivery, …) with its state, " + "description and when it was set; the merge check's full verdict as the controller said it — each " + "layer's summary, the machine that ran it, when, its build id and its report; and whether the branch's " + "protection would let it merge, every required status being success.", diff --git a/go/delivery/gate.go b/go/delivery/gate.go index 18444c5..5fbe9fb 100644 --- a/go/delivery/gate.go +++ b/go/delivery/gate.go @@ -29,7 +29,9 @@ const ( ) // The contexts of the statuses the mesh owes the forge: the gate's, the delivery's view of a head and of a group -// (design 47), and the checker's, which is not required until R4f (ADR 0484 clause 2, ADR 0453 clause 4). +// (design 47), and the checker's. From R4e the checker's mesh/check is the one status a repository's main requires, +// in place of mesh/merge-gate and mesh/repo-check (ADR 0503 clauses 3 and 5); a main that requires only +// mesh/repo-check (hq) keeps it, and the controller writes it for a repository the checker writes no status for. const ( StatusContextMergeGate = "mesh/merge-gate" StatusContextDelivery = "mesh/delivery" diff --git a/go/delivery/module_newform_test.go b/go/delivery/module_newform_test.go new file mode 100644 index 0000000..3932e57 --- /dev/null +++ b/go/delivery/module_newform_test.go @@ -0,0 +1,32 @@ +package delivery + +import ( + "strings" + "testing" +) + +// From R4e a modules value needs no old form (novox/hq ADR 0453 clause 6; issue 1851): a value with only the new +// fingerprint, or only the reason it has none, is written and read; an old value with fp or none still reads; a value +// with no fingerprint of either form and no reason is still refused. +func TestAModulesValueNeedsNoOldForm(t *testing.T) { + fp2 := SourcePrefix2 + strings.Repeat("a", 64) + for _, m := range []Module{ + {FP2: fp2, Repository: "a/b", Commit: "c"}, + {None2: "no lock", Repository: "a/b", Commit: "c"}, + } { + data, err := EncodeModule(m) + if err != nil { + t.Fatalf("%+v was refused: %v", m, err) + } + back, err := DecodeModule(data) + if err != nil || back.FP2 != m.FP2 || back.None2 != m.None2 || back.FP != "" || back.None != "" { + t.Fatalf("decoded %+v, %v", back, err) + } + } + if _, err := DecodeModule([]byte(`{"v":1,"fp":"src1:x","repository":"a/b","commit":"c"}`)); err != nil { + t.Fatalf("an old value no longer reads: %v", err) + } + if _, err := EncodeModule(Module{Repository: "a/b", Commit: "c"}); err == nil { + t.Fatal("a value with no fingerprint and no reason was accepted") + } +} diff --git a/go/delivery/source.go b/go/delivery/source.go index 4d31073..9e79b6d 100644 --- a/go/delivery/source.go +++ b/go/delivery/source.go @@ -370,12 +370,13 @@ func (c Candidate) check() error { // Module is the value of a modules key: the module's source fingerprint, or none and why (a build that resolves // packages when built gets none, said here), and where it was computed: Repository and Commit are the trunk merge, -// Src the source revision then (0 before the gate writes source.main). Exactly one of FP and None is set. +// Src the source revision then (0 before the gate writes source.main). At most one of FP and None is set. // // From R4c the indexer writes the new form beside it (novox/hq ADR 0453 clause 6): FP2, the fingerprint of the new // form (`src2:` and 64 hex digits), or None2, why it has none; one of them whenever either is, never both; and // Manifest, the digest of the module's manifest, the key of the manifests bucket. A value written before has none of -// the three, and a reader of today's shape ignores them. +// the three, and a reader of today's shape ignores them. From R4e a value may carry the new form alone (ADR 0453 clause +// 6; issue 1851): one of FP, None, FP2 and None2 is set, and the old form stays readable. type Module struct { V int `json:"v"` FP string `json:"fp,omitempty"` @@ -443,8 +444,8 @@ func (m Module) check() error { switch { case m.FP != "" && m.None != "": return fmt.Errorf("delivery: a module has both a fingerprint and a reason for none") - case m.FP == "" && m.None == "": - return fmt.Errorf("delivery: a module has neither a fingerprint nor a reason for none") + case m.FP == "" && m.None == "" && m.FP2 == "" && m.None2 == "": + return fmt.Errorf("delivery: a module has neither a fingerprint nor a reason for none, of either form") case m.FP != "" && !strings.HasPrefix(m.FP, SourcePrefix): return fmt.Errorf("delivery: the module's fingerprint %q does not start with %s", m.FP, SourcePrefix) case m.FP2 != "" && m.None2 != "":