U2b: the reserved version reaches each artifact's build, and a versioned ask names each artifact's registry seat

The ask carried the reserved version (§573), but the build modules' shared run gave each
artifact's build only the artifact's own version, which no asker sets, so no build got
MESH_VERSION and a Go package was packed as a candidate and never published. The run now
gives every build the ask's version, and the builder names the registry seat each artifact
of a versioned build is published through, so a Go package is published under its
reserved version on go-package-registry.

Builds: design 47 G §370, §573, §458; design 51 *Publishing*

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-12 16:13:13 +01:00
parent 4332246f79
commit e313248b5f
4 changed files with 47 additions and 3 deletions
@@ -204,3 +204,37 @@ func TestAReservedBuildKeepsWhatItsStepResolvedAndWasBuiltWith(t *testing.T) {
t.Errorf("journal %q, want the package no edge names said", journal)
}
}
// TestAModuleWhoseOnlyArtifactIsAGoPackageIsBuiltUnderItsReservedVersion: design 47 G §370 — a module whose one artifact is
// a Go package (mesh-wireguard's go-overlay) is planned on the Go build seat, its ask carries the reserved version and names
// the seat go-package-registry the package is published and tagged through, and the build is done; a build reserving none
// names no seat.
func TestAModuleWhoseOnlyArtifactIsAGoPackageIsBuiltUnderItsReservedVersion(t *testing.T) {
goPackage := catalogue.Artifact{Name: "go-overlay", Kind: catalogue.ArtifactPackage, Language: "go", Paths: []string{"go"}}
for _, c := range []struct {
name, series, version, seat string
}{
{"reserved", "0.1", "0.1.5", versions.SeatGoPackages},
{"reserving none", "1", "", ""},
} {
t.Run(c.name, func(t *testing.T) {
r := newRig(t, goPackage)
r.mf.byDigest[mdigest('a')] = catalogue.Manifest{Module: "m", Version: c.series, Build: &catalogue.Build{Artifacts: []catalogue.Artifact{goPackage}}}
r.b.Reserved = &fakeReservations{filled: true}
r.bm.packages["go-overlay"] = "git.novox.be/novox/mesh-networking/go@v0.1.5" // the Go build module's published reference
var asked []buildstep.StepAsk
r.asks.Answer = func(a buildstep.StepAsk) buildstep.Step {
asked = append(asked, a)
return r.answer(a)
}
v := r.consider(t, "modules/m")
if v.State != builds.BuildDone {
t.Fatalf("state %s (%s), want done", v.State, v.Error)
}
if len(asked) != 1 || asked[0].Language != buildstep.AskGo || asked[0].Version != c.version || asked[0].Build == nil ||
len(asked[0].Build.Artifacts) != 1 || asked[0].Build.Artifacts[0] != (buildstep.AskArtifact{Artifact: "go-overlay", Seat: c.seat}) {
t.Fatalf("asks %+v, want one Go ask with version %q naming go-overlay on seat %q", asked, c.version, c.seat)
}
})
}
}
@@ -1055,6 +1055,10 @@ func (b *Builder) runLane(ctx context.Context, l *lane, repository string, m mes
a := sdkstep.AskArtifact{Artifact: t.Artifact}
if t.Kind == catalogue.ArtifactUpstream {
a.From = t.From // the copy runs no code of a change: the module's name, the artifact and its pin
} else if seat, _, ok := versions.SeatOf(t.Kind, t.Language); ok && l.version != "" {
// A build under a reserved version names the registry seat each artifact is published through, so a Go package is
// published and tagged under it (design 47 G §370; design 51 *Publishing*).
a.Seat = seat
}
job.Artifacts = append(job.Artifacts, a)
}
+6 -2
View File
@@ -61,7 +61,7 @@ func RunAsk(ctx context.Context, steps AskSteps, ask sdkstep.StepAsk) (any, erro
if ask.Build != nil {
job := *ask.Build
job.Fetch = withPackages(job.Fetch, ask.Packages)
return steps.build(ctx, job)
return steps.build(ctx, job, ask.Version)
}
if ask.Step != nil {
return steps.runStep(ctx, ask)
@@ -167,7 +167,9 @@ func (s AskSteps) onToolchain(ctx context.Context, want *sdkstep.ToolchainUsed)
return &tc, nil
}
func (s AskSteps) build(ctx context.Context, job sdkstep.BuildJob) (any, error) {
// build runs a build job; version is the version the ask carries (design 47 G §573), which each artifact's build is given
// as its argument version, the build's MESH_VERSION (§370), unless the artifact names its own.
func (s AskSteps) build(ctx context.Context, job sdkstep.BuildJob, version string) (any, error) {
answer := sdkstep.BuildAnswer{}
tc, err := s.onToolchain(ctx, job.Toolchain)
if err != nil {
@@ -240,6 +242,8 @@ func (s AskSteps) build(ctx context.Context, job sdkstep.BuildJob) (any, error)
}
if a.Version != "" {
args["version"] = a.Version
} else if version != "" {
args["version"] = version
}
Phase(ctx, "build "+a.Artifact)
out, err = s.Build(ctx, args)
@@ -89,6 +89,8 @@ func TestRunAskBuilds(t *testing.T) {
Fetch: &sdkstep.Fetch{Repository: "novox/x", Commit: runCommit},
Artifacts: []sdkstep.AskArtifact{{Artifact: "base", From: "registry/b@sha256:00"}, {Artifact: "bundle"}, {Artifact: "lib", Seat: "go-package-registry", Version: "v0.1.15"}}})
a.Packages = sdkstep.PackageVersions{"git.novox.be/novox/mesh-sdk/go": runCommit}
// Design 47 G §573, §370: the version the ask carries reaches each artifact's build; one the artifact names stays its own.
a.Version = "0.1.16"
out, err := RunAsk(context.Background(), steps, a)
if err != nil {
t.Fatal(err)
@@ -99,7 +101,7 @@ func TestRunAskBuilds(t *testing.T) {
got := strings.Join(r.calls, "\n")
want := `copy {"artifact":"base","from":"registry/b@sha256:00","module":"m"}
fetch {"commit":"` + runCommit + `","packages":{"git.novox.be/novox/mesh-sdk/go":"` + runCommit + `"},"repository":"novox/x"}
build {"artifact":"bundle","module":"modules/m","publish":true,"workspace":"/w/1"}
build {"artifact":"bundle","module":"modules/m","publish":true,"version":"0.1.16","workspace":"/w/1"}
build {"artifact":"lib","module":"modules/m","publish":true,"seat":"go-package-registry","version":"v0.1.15","workspace":"/w/1"}
imports {"module":"modules/m","workspace":"/w/1"}`
if got != want {