U2c: a package left unpublished by a build that reserved no version counts as done
The builder's unpublished count held every package without a reference and named the Node build module for all of them, so a Go package built by a build reserving none (another watched branch, a manifest with no MAJOR.MINOR, a candidate) left its key never done and was sent to the wrong seat. A reserving build's package is published under its version or its build fails, so the count now holds images alone. Builds: design 47 G A-289, §371 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -96,22 +96,22 @@ func GoneStep(gone []string) string {
|
||||
return "claimed again: the artifact store no longer holds " + strings.Join(gone, ", ")
|
||||
}
|
||||
|
||||
// Unpublished is whether a done build holds an image built without a push or a package built without a publish: it has
|
||||
// no reference (a candidate's, ADR 0487 clause 12, ADR 0498 clauses 5 and 6).
|
||||
// Unpublished is whether a done build holds an image built without a push: it has no reference (a candidate's, ADR 0487
|
||||
// clause 12). A package left unpublished is a build's that reserved no version, which counts as done (design 47 G A-289,
|
||||
// §371): a reserving build's package is published under its version or its build fails.
|
||||
func Unpublished(b builds.BuilderBuild, seats *buildrun.BuildSeats) bool {
|
||||
return len(UnpublishedModules(b, seats)) > 0
|
||||
}
|
||||
|
||||
// UnpublishedModules are the build modules that publish what a done build holds unpublished: the image build module for
|
||||
// an image, the Node build module for a package; sorted, none when it holds nothing unpublished.
|
||||
// an image; none when it holds nothing unpublished, and none for a package (A-289: never one seat for every package).
|
||||
func UnpublishedModules(b builds.BuilderBuild, seats *buildrun.BuildSeats) []string {
|
||||
if b.State != builds.BuildDone {
|
||||
return nil
|
||||
}
|
||||
var image, pkg bool
|
||||
var image bool
|
||||
for _, a := range b.Artifacts {
|
||||
image = image || (a.Kind == catalogue.ArtifactImage && a.Reference == "")
|
||||
pkg = pkg || (a.Kind == catalogue.ArtifactPackage && a.Reference == "")
|
||||
}
|
||||
var out []string
|
||||
if image {
|
||||
@@ -119,11 +119,6 @@ func UnpublishedModules(b builds.BuilderBuild, seats *buildrun.BuildSeats) []str
|
||||
out = append(out, bm.Module)
|
||||
}
|
||||
}
|
||||
if pkg {
|
||||
if bm, err := seats.For("typescript", catalogue.ArtifactPackage); err == nil {
|
||||
out = append(out, bm.Module)
|
||||
}
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out
|
||||
}
|
||||
@@ -159,7 +154,8 @@ func Unreferenced(b builds.BuilderBuild) bool {
|
||||
// - no key: it is created building, by this builder; a create that finds the key made meanwhile gets nothing;
|
||||
// - a done key is not taken again (the same source is never built twice), except one whose bundle, archive or upstream
|
||||
// copy names no reference (Unreferenced, a key done before R4e: ADR 0498 clause 8), which is claimed building as a new
|
||||
// revision and built whole, and one whose image or package was built unpublished as a candidate's once the trunk
|
||||
// revision and built whole, and one whose image was built unpublished as a candidate's once the trunk (a package left
|
||||
// unpublished counts as done, A-289)
|
||||
// names it (ClaimOptions.Trunk): that is taken as it stands, with the done value, and its builder writes the new
|
||||
// revision when the publishing build ends (ADR 0498 clause 6). From R4e one node builds each fingerprint (ADR 0478
|
||||
// clause 4), so a key built on one node is never built again for a second;
|
||||
|
||||
@@ -3,6 +3,7 @@ package build
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"slices"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
@@ -234,3 +235,24 @@ func hex64(c byte) string {
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// Design 47 G A-289 (§371): a done key's package left unpublished (a Go package or a TypeScript one, of a build that
|
||||
// reserved no version) counts as done and is published by no build seat; an image built without a push still is not done
|
||||
// and is published by the image build module.
|
||||
func TestAnUnpublishedPackageCountsAsDoneAndAnUnpushedImageDoesNot(t *testing.T) {
|
||||
for _, c := range []struct {
|
||||
name string
|
||||
art builds.BuiltArtifact
|
||||
want []string
|
||||
}{
|
||||
{"a Go package", builds.BuiltArtifact{Name: "go-overlay", Kind: "package", Digest: digest}, nil},
|
||||
{"a TypeScript package", builds.BuiltArtifact{Name: "lib", Kind: "package", Digest: digest}, nil},
|
||||
{"a published package", builds.BuiltArtifact{Name: "lib", Kind: "package", Digest: digest, Reference: "git.example/m/go@0.1.5"}, nil},
|
||||
{"an image built without a push", builds.BuiltArtifact{Name: "img", Kind: "image", Digest: digest}, []string{testImage}},
|
||||
} {
|
||||
b := builds.BuilderBuild{State: builds.BuildDone, Artifacts: []builds.BuiltArtifact{c.art}}
|
||||
if got := UnpublishedModules(b, testSeats()); !slices.Equal(got, c.want) || Unpublished(b, testSeats()) != (len(c.want) > 0) {
|
||||
t.Errorf("%s: unpublished by %v, want %v", c.name, got, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -628,7 +628,7 @@ func (b *Builder) try(ctx context.Context, module string, m meshcatalog.ModulesB
|
||||
// Said aloud (issue 1937): the key was done, and the store's collector deleted what it names.
|
||||
b.logf("%s: built again: the artifact store no longer holds %s", cl.Key, strings.Join(cl.Gone, ", "))
|
||||
}
|
||||
// A done key taken again builds only what is missing: the image or the package built unpublished as a candidate's; the
|
||||
// A done key taken again builds only what is missing: the image built unpublished as a candidate's (A-289); the
|
||||
// other artifacts stay as the done key has them (ADR 0487 clauses 5 and 8, ADR 0498 clause 6).
|
||||
var prior *builds.BuilderBuild
|
||||
var only map[string]bool
|
||||
|
||||
Reference in New Issue
Block a user