BG8, BN8, BI2: each artifact carries the version the ask names
A Go program is linked with -X main.meshVersion beside main.builtFor, a Node program's package.json version is set, an image is labelled org.opencontainers.image.version; a build with no version stamps none. Builds: design 47 G §458, §573 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -26,6 +26,8 @@ const (
|
||||
recipeFlags = "-trimpath -buildvcs=false"
|
||||
recipeLinkerFlags = "-s -w"
|
||||
recipeSystemStamp = "main.builtFor"
|
||||
// versionStamp is the Go variable a program carries its version in (design 47 G §458).
|
||||
versionStamp = "main.meshVersion"
|
||||
// outDir is where a build leaves an artifact in the module's directory (builder.Out).
|
||||
outDir = ".mesh-build"
|
||||
)
|
||||
@@ -153,6 +155,10 @@ func (m *Module) build(ctx context.Context, args map[string]any) (any, error) {
|
||||
if system := strings.TrimSpace(art.System); system != "" {
|
||||
linker += " -X " + recipeSystemStamp + "=" + system
|
||||
}
|
||||
// A build asked with a version carries it in main.meshVersion beside main.builtFor; one with none stamps none (§458).
|
||||
if version != "" {
|
||||
linker += " -X " + versionStamp + "=" + version
|
||||
}
|
||||
cmd := []string{"-C", dir, "build", "-ldflags", linker, "-o", filepath.Join(out, binary), "./" + strings.Trim(art.From, "./")}
|
||||
// Shut off (ADR 0448): the shared caches are written by a trunk build alone (publish), a candidate's go build writes
|
||||
// beneath a throwaway layer.
|
||||
|
||||
@@ -273,6 +273,13 @@ func TestTheBuildGetsTheVersionTheAskCarriesAsMeshVersion(t *testing.T) {
|
||||
}
|
||||
got := ""
|
||||
for _, r := range *calls {
|
||||
// §458: the program is linked with main.meshVersion beside main.builtFor, and with no version none is stamped.
|
||||
if strings.Contains(r.line, " build ") && strings.Contains(r.line, "-X main.meshVersion=") != (version != "") {
|
||||
t.Errorf("ask version %q: the go build line is %q", version, r.line)
|
||||
}
|
||||
if version != "" && strings.Contains(r.line, " build ") && !strings.Contains(r.line, "-X main.meshVersion="+version) {
|
||||
t.Errorf("ask version %q: the go build line lacks main.meshVersion: %q", version, r.line)
|
||||
}
|
||||
if strings.HasPrefix(r.line, "go ") {
|
||||
for _, e := range r.env {
|
||||
if strings.HasPrefix(e, "MESH_VERSION=") {
|
||||
|
||||
@@ -172,7 +172,7 @@ func (m *Module) build(ctx context.Context, args map[string]any) (any, error) {
|
||||
argv = append(argv, imageArgs(manifest)...)
|
||||
// The version the build ask carries is the build argument MESH_VERSION (design 47 G §370).
|
||||
if version != "" {
|
||||
argv = append(argv, "--build-arg", "MESH_VERSION="+version)
|
||||
argv = append(argv, "--build-arg", "MESH_VERSION="+version, "--label", "org.opencontainers.image.version="+version) // the label of §458
|
||||
}
|
||||
argv = append(argv, contextDir)
|
||||
if r := m.Run(ctx, m.env(), "buildah", argv...); r.Status != 0 || r.Err != "" {
|
||||
|
||||
@@ -338,12 +338,12 @@ func TestTheImageBuildGetsTheVersionTheAskCarriesAsMeshVersion(t *testing.T) {
|
||||
t.Fatalf("step = %+v", st)
|
||||
}
|
||||
bud := f.called("bud")
|
||||
if len(bud) != 1 || !strings.Contains(bud[0].line, "--build-arg MESH_VERSION=1.4.3") {
|
||||
if len(bud) != 1 || !strings.Contains(bud[0].line, "--build-arg MESH_VERSION=1.4.3") || !strings.Contains(bud[0].line, "--label org.opencontainers.image.version=1.4.3") {
|
||||
t.Fatalf("bud = %+v", bud)
|
||||
}
|
||||
m, f, states = setup(t, same)
|
||||
runBuild(t, m, states, nil)
|
||||
if bud := f.called("bud"); len(bud) != 1 || strings.Contains(bud[0].line, "MESH_VERSION") {
|
||||
if bud := f.called("bud"); len(bud) != 1 || (strings.Contains(bud[0].line, "MESH_VERSION") || strings.Contains(bud[0].line, "image.version")) {
|
||||
t.Fatalf("a build with no version: %+v", bud)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,6 +137,14 @@ func (m *Module) build(ctx context.Context, args map[string]any) (any, error) {
|
||||
if err := copyPackages(filepath.Join(m.toolchainDir(), "node_modules"), filepath.Join(stage, "node_modules")); err != nil {
|
||||
return nil, fmt.Errorf("providing the toolchain's packages to the build: %w", err)
|
||||
}
|
||||
// A program reads its own version from its package.json `version`, which is the version the ask carries (§458); the
|
||||
// staged copy is the build's own, so nothing is restored. A build with no version, or a module with no package.json,
|
||||
// keeps what it carries.
|
||||
if _, err := os.Stat(filepath.Join(dir, "package.json")); err == nil && version != "" {
|
||||
if _, err := setPackageVersion(dir, version); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
out, final := Out(a.Name), Out(a.Name)+".bundled"
|
||||
if err := os.MkdirAll(filepath.Join(dir, out), 0o755); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -328,3 +328,24 @@ func TestTheBundleBuildGetsTheVersionTheAskCarriesAsMeshVersion(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Design 47 G §458 (BN8): a Node program reads its version from its package.json `version`, which is the version the
|
||||
// ask carries; a build with no version keeps what the package.json carries.
|
||||
func TestTheBundleCarriesTheAsksVersionInItsPackageJSON(t *testing.T) {
|
||||
for _, c := range []struct{ version, want string }{{"1.4.3", "1.4.3"}, {"", "0.0.0"}} {
|
||||
m, f, work := builtMachine(t, "")
|
||||
workspaceWith(t, work, map[string]string{"modules/m/package.json": `{"name":"m","version":"0.0.0"}`})
|
||||
args := buildArgs()
|
||||
if c.version != "" {
|
||||
args["version"] = c.version
|
||||
}
|
||||
if _, err := m.build(context.Background(), args); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = f
|
||||
raw, err := os.ReadFile(filepath.Join(work, "w1", "stage-tools", "modules", "module", "package.json"))
|
||||
if err != nil || !strings.Contains(string(raw), `"version": "`+c.want+`"`) && !strings.Contains(string(raw), `"version":"`+c.want+`"`) {
|
||||
t.Errorf("ask version %q: the staged package.json is %q (%v), want version %s", c.version, raw, err, c.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user