BL3: the build seat's ask carries the version the build reserved, empty for a build reserving none
Builds: design 47 G §573, §370 Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-builder/builds"
|
||||
"git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
||||
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
||||
|
||||
"mesh-delivery-builder/internal/versions"
|
||||
@@ -65,7 +66,16 @@ func TestABuildReservesItsVersionAtItsStartOnceTheCatalogFilled(t *testing.T) {
|
||||
}
|
||||
|
||||
res.filled = true
|
||||
// Design 47 G §573: the build's ask carries the reserved version.
|
||||
var askedVersions []string
|
||||
r.asks.Answer = func(a buildstep.StepAsk) buildstep.Step {
|
||||
askedVersions = append(askedVersions, a.Version)
|
||||
return r.answer(a)
|
||||
}
|
||||
v := r.consider(t, "modules/m")
|
||||
if len(askedVersions) == 0 || slices.ContainsFunc(askedVersions, func(v string) bool { return v != "0.1.5" }) {
|
||||
t.Fatalf("the asks carried versions %q, want the reserved 0.1.5 on each", askedVersions)
|
||||
}
|
||||
if v.State != builds.BuildDone || len(res.reserved) != 1 || !slices.Equal(res.reserved[0], []string{"m:tool"}) || res.series[0] != "0.1" {
|
||||
t.Fatalf("build %+v reserved %v in %v, want done and one reservation of m:tool in 0.1", v.State, res.reserved, res.series)
|
||||
}
|
||||
@@ -81,11 +91,19 @@ func TestABuildReservesItsVersionAtItsStartOnceTheCatalogFilled(t *testing.T) {
|
||||
r2 := newRig(t, goBundle)
|
||||
res2 := &fakeReservations{filled: true}
|
||||
r2.b.Reserved = res2
|
||||
var unversioned []string
|
||||
r2.asks.Answer = func(a buildstep.StepAsk) buildstep.Step {
|
||||
unversioned = append(unversioned, a.Version)
|
||||
return r2.answer(a)
|
||||
}
|
||||
var journal []string
|
||||
r2.b.Logf = func(f string, a ...any) { journal = append(journal, fmt.Sprintf(f, a...)) }
|
||||
if v := r2.consider(t, "modules/m"); v.State != builds.BuildDone || len(res2.reserved) != 0 {
|
||||
t.Errorf("a manifest with no MAJOR.MINOR: state %s, reserved %v", v.State, res2.reserved)
|
||||
}
|
||||
if len(unversioned) == 0 || slices.ContainsFunc(unversioned, func(v string) bool { return v != "" }) {
|
||||
t.Errorf("a build reserving none asked with versions %q, want none", unversioned)
|
||||
}
|
||||
// G §505: the builder writes in its journal, naming the module, that it reserved nothing.
|
||||
if !slices.ContainsFunc(journal, func(l string) bool { return strings.HasPrefix(l, "m: ") && strings.Contains(l, "not MAJOR.MINOR") }) {
|
||||
t.Errorf("journal %q, want a line naming m and saying its version is not MAJOR.MINOR", journal)
|
||||
|
||||
@@ -552,7 +552,7 @@ func (b *Builder) try(ctx context.Context, module string, m meshcatalog.ModulesB
|
||||
b.mu.Lock()
|
||||
b.builds[key] = withdraw
|
||||
b.mu.Unlock()
|
||||
result = b.build(run, module, m, plan, planErr, prior, only, b.notes(cl))
|
||||
result = b.build(run, module, m, plan, planErr, prior, only, b.notes(cl), reserved.Version)
|
||||
b.mu.Lock()
|
||||
delete(b.builds, key)
|
||||
b.mu.Unlock()
|
||||
@@ -646,6 +646,7 @@ func failed(format string, args ...any) builds.BuilderBuild {
|
||||
// lane is the build of a plan's tasks of one build module on one node.
|
||||
type lane struct {
|
||||
module, node string // node is the one that pulled the lane's ask
|
||||
version string // the version the build reserved, MAJOR.MINOR.PATCH, empty for a build that reserves none (design 47 G §573)
|
||||
tasks []Task
|
||||
toolchain *builds.ToolchainUsed
|
||||
digests map[string]string // artifact -> digest
|
||||
@@ -656,7 +657,7 @@ type lane struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (b *Builder) build(ctx context.Context, module string, m meshcatalog.ModulesByModuleValue, plan Plan, planErr error, prior *builds.BuilderBuild, only map[string]bool, asked *askNotes) builds.BuilderBuild {
|
||||
func (b *Builder) build(ctx context.Context, module string, m meshcatalog.ModulesByModuleValue, plan Plan, planErr error, prior *builds.BuilderBuild, only map[string]bool, asked *askNotes, version string) builds.BuilderBuild {
|
||||
switch {
|
||||
case planErr != nil:
|
||||
return failed("%s", planErr)
|
||||
@@ -697,7 +698,7 @@ func (b *Builder) build(ctx context.Context, module string, m meshcatalog.Module
|
||||
}
|
||||
}
|
||||
// One ask builds each fingerprint's part of a build module, on whichever node pulls it (ADR 0525 §3).
|
||||
lanes = append(lanes, &lane{module: bm, tasks: tasks, toolchain: toolchain, digests: map[string]string{}, references: map[string]string{}})
|
||||
lanes = append(lanes, &lane{module: bm, version: version, tasks: tasks, toolchain: toolchain, digests: map[string]string{}, references: map[string]string{}})
|
||||
}
|
||||
if key, err := builds.BuilderBuildKey(module, m.Fp2); err == nil {
|
||||
b.handLanes(key, len(lanes))
|
||||
@@ -952,7 +953,7 @@ func (b *Builder) runLane(ctx context.Context, l *lane, repository string, m mes
|
||||
if needsFetch(l.tasks) {
|
||||
job.Fetch = &req
|
||||
}
|
||||
ask := sdkstep.StepAsk{ID: sdkstep.NewID(), Kind: kind, Language: language, Asker: builds.BuilderModule, At: time.Now(), Build: job}
|
||||
ask := sdkstep.StepAsk{ID: sdkstep.NewID(), Kind: kind, Language: language, Asker: builds.BuilderModule, At: time.Now(), Version: l.version, Build: job}
|
||||
if language == sdkstep.AskGo && job.Fetch != nil && len(m.Packages) > 0 {
|
||||
// The versions of the mesh packages the fingerprint was computed with (novox/hq ADR 0573 §2): the build module writes
|
||||
// them into the workspace, whatever the repository's go.mod names.
|
||||
|
||||
Reference in New Issue
Block a user