diff --git a/go/delivery/builder.go b/go/delivery/builder.go index faf2eff..fd414b8 100644 --- a/go/delivery/builder.go +++ b/go/delivery/builder.go @@ -165,7 +165,8 @@ type ToolchainUsed struct { // BuilderBuild is the value of a builder build key: its State (queued, building, done or failed), By the builder // instance that holds it, Step what it is doing or did last, Manifest the digest of the module's manifest (the key of // the indexer's manifests bucket), Artifacts when done, Toolchains by language when it built or is building (a done -// build names them, so two builders that differ are seen: ADR 0405 clause 2), and Error when failed. +// build names them, so two builders that differ are seen: ADR 0405 clause 2), Error when failed, and Waits when queued for a +// package version. type BuilderBuild struct { V int `json:"v"` State string `json:"state"` @@ -175,6 +176,10 @@ type BuilderBuild struct { Artifacts []BuiltArtifact `json:"artifacts,omitempty"` Toolchains map[string]ToolchainUsed `json:"toolchains,omitempty"` Error string `json:"error,omitempty"` + // Waits is, on a queued key only, the package version `@` the module's lock names and the registry + // does not yet hold: the key is not claimed until that package's trunk key is done and published (novox/hq ADR 0500 + // clause 6). A reader that does not know the field reads the key as queued. + Waits string `json:"waits,omitempty"` } func (b BuilderBuild) check() error { @@ -207,6 +212,14 @@ func (b BuilderBuild) check() error { return fmt.Errorf("delivery: the reference %q of the %s %q %s", a.Reference, a.Kind, a.Name, p) } } + if b.Waits != "" { + if b.State != BuildQueued { + return fmt.Errorf("delivery: a %s build waits for %q; only a queued key waits for a package", b.State, b.Waits) + } + if p := (BuiltArtifact{Kind: "package", Reference: b.Waits}).referenceProblem(); p != "" { + return fmt.Errorf("delivery: the package a key waits for, %q, %s", b.Waits, p) + } + } switch b.State { case BuildQueued, BuildBuilding: if len(b.Artifacts) > 0 || b.Error != "" { diff --git a/go/delivery/builder_reference_test.go b/go/delivery/builder_reference_test.go index ab8e26b..b8f804a 100644 --- a/go/delivery/builder_reference_test.go +++ b/go/delivery/builder_reference_test.go @@ -96,3 +96,23 @@ func TestOnlyAPushFailureIsBuiltAgainBeforeTheFingerprintChanges(t *testing.T) { } } +// A key whose module's lock names a version of the group's package not yet published waits, queued, saying which +// (ADR 0500 clause 6): an older reader reads it as queued, and only a queued key waits. +func TestAKeyWaitsQueuedForAPackageVersion(t *testing.T) { + b := BuilderBuild{State: BuildQueued, Manifest: digestOf('4'), Waits: "@novox/mesh-sdk@0.1.15"} + data, err := EncodeBuilderBuild(b) + if err != nil { + t.Fatal(err) + } + back, err := DecodeBuilderBuild(data) + if err != nil || back.Waits != b.Waits || back.State != BuildQueued { + t.Fatalf("decoded %+v, %v", back, err) + } + building := BuilderBuild{State: BuildBuilding, By: "x", Waits: "@novox/mesh-sdk@0.1.15"} + if _, err := EncodeBuilderBuild(building); err == nil { + t.Fatal("a building key that waits was accepted") + } + if _, err := EncodeBuilderBuild(BuilderBuild{State: BuildQueued, Waits: "mesh-sdk"}); err == nil { + t.Fatal("a wait naming no version was accepted") + } +}