Give delivery.Module the toolchains its fingerprint was computed with, and '.' as a root module's path, so the builder builds a key only with its own toolchain (issue 1615)
mesh/merge-gate head 89dd57bed05d merged into trunk 465beb4ea5e3 — pass, with a note: builds mesh-sdk (+41 dependent(s)) → ace, g14, novox, shanks; no bus …
mesh/repo-check head 89dd57bed05d merged into trunk 465beb4ea5e3 — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (typescript)…
mesh/delivery delivered
mesh/merge-gate head 89dd57bed05d merged into trunk 465beb4ea5e3 — pass, with a note: builds mesh-sdk (+41 dependent(s)) → ace, g14, novox, shanks; no bus …
mesh/repo-check head 89dd57bed05d merged into trunk 465beb4ea5e3 — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (typescript)…
mesh/delivery delivered
This commit is contained in:
+16
-2
@@ -389,11 +389,20 @@ type Module struct {
|
|||||||
Src uint64 `json:"src,omitempty"`
|
Src uint64 `json:"src,omitempty"`
|
||||||
Repository string `json:"repository"`
|
Repository string `json:"repository"`
|
||||||
Commit string `json:"commit"`
|
Commit string `json:"commit"`
|
||||||
// Path is the module's directory in its repository, trimmed of slashes, empty when its manifest is the repository's
|
// Path is the module's directory in its repository, trimmed of slashes, and RootPath (".") when its manifest is the
|
||||||
// root (novox/hq ADR 0478 clause 8): the build tools need it. A value written before has none.
|
// repository's root (novox/hq ADR 0478 clause 8, issue 1615): the build tools need it. Empty means not known: a value
|
||||||
|
// written before the indexer learned paths has none.
|
||||||
Path string `json:"path,omitempty"`
|
Path string `json:"path,omitempty"`
|
||||||
|
// Toolchains are the toolchains FP2 was computed with, by language (go, typescript): the version installed and the
|
||||||
|
// build module's recipe version the build nodes agreed on then (novox/hq ADR 0477 clause 2, ADR 0478 clause 3). A builder
|
||||||
|
// builds the fingerprint only with these. Empty when FP2 is empty or the module has no toolchain; a value written
|
||||||
|
// before has none (issue 1615).
|
||||||
|
Toolchains map[string]ToolchainUsed `json:"toolchains,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RootPath is Module.Path of a module whose manifest is its repository's root.
|
||||||
|
const RootPath = "."
|
||||||
|
|
||||||
// KeptInputs2 are SourceInputs2 without the module's name (the key has it) and without toolchains (those come from
|
// KeptInputs2 are SourceInputs2 without the module's name (the key has it) and without toolchains (those come from
|
||||||
// the build modules' toolchain keys when the fingerprint is computed): what a Module keeps of a merge.
|
// the build modules' toolchain keys when the fingerprint is computed): what a Module keeps of a merge.
|
||||||
type KeptInputs2 struct {
|
type KeptInputs2 struct {
|
||||||
@@ -421,6 +430,11 @@ func (m Module) check() error {
|
|||||||
case m.FP2 != "" && m.None2 != "":
|
case m.FP2 != "" && m.None2 != "":
|
||||||
return fmt.Errorf("delivery: a module has both fp2 and none2")
|
return fmt.Errorf("delivery: a module has both fp2 and none2")
|
||||||
}
|
}
|
||||||
|
for language, t := range m.Toolchains {
|
||||||
|
if t.Version == "" || t.Recipe == "" {
|
||||||
|
return fmt.Errorf("delivery: the module's toolchain of %q needs its version and its recipe version", language)
|
||||||
|
}
|
||||||
|
}
|
||||||
if m.Inputs2 != nil && m.Manifest == "" {
|
if m.Inputs2 != nil && m.Manifest == "" {
|
||||||
return fmt.Errorf("delivery: a module keeps new-form inputs but has no manifest digest")
|
return fmt.Errorf("delivery: a module keeps new-form inputs but has no manifest digest")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -397,3 +397,31 @@ func TestModulePath(t *testing.T) { // 1588/AC1
|
|||||||
t.Errorf("a module without a path encodes %s", again)
|
t.Errorf("a module without a path encodes %s", again)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestModuleRootPathAndToolchains(t *testing.T) { // 1615/AC1, AC2
|
||||||
|
tc := map[string]ToolchainUsed{"go": {Version: "go1.27.1", Recipe: "1"}, "typescript": {Version: "tsc5", Recipe: "2"}}
|
||||||
|
data, err := EncodeModule(Module{FP: "src1:x", Repository: "a/b", Commit: "c", Path: RootPath, Toolchains: tc})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(string(data), `"path":"."`) || !strings.Contains(string(data), `"toolchains":{"go":{"version":"go1.27.1","recipe":"1"}`) {
|
||||||
|
t.Errorf("encoded %s", data)
|
||||||
|
}
|
||||||
|
m, err := DecodeModule(data)
|
||||||
|
if err != nil || m.Path != RootPath || !reflect.DeepEqual(m.Toolchains, tc) {
|
||||||
|
t.Errorf("round trip = %+v, %v", m, err)
|
||||||
|
}
|
||||||
|
// A value written before has none: it decodes and encodes without the key.
|
||||||
|
old, err := DecodeModule([]byte(`{"v":1,"fp":"src1:x","repository":"a/b","commit":"c","path":"modules/a"}`))
|
||||||
|
if err != nil || old.Toolchains != nil {
|
||||||
|
t.Fatalf("old shape = %+v, %v", old, err)
|
||||||
|
}
|
||||||
|
if again, _ := EncodeModule(old); strings.Contains(string(again), "toolchains") {
|
||||||
|
t.Errorf("a module without toolchains encodes %s", again)
|
||||||
|
}
|
||||||
|
for _, bad := range []map[string]ToolchainUsed{{"go": {Recipe: "1"}}, {"go": {Version: "v"}}} {
|
||||||
|
if _, err := EncodeModule(Module{FP: "src1:x", Repository: "a/b", Commit: "c", Toolchains: bad}); err == nil {
|
||||||
|
t.Errorf("toolchains %v accepted", bad)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user