Judge a moved module in the merge gate as a real build hands it its templates, so the gate no longer refuses every moved module (issue 876)
mesh/merge-gate head efc5f901afb7 merged into trunk cf897e89fe31 — pass: [release feat/57-config-and-provisioning, judged by its controller 93b947cc53b5] t…
mesh/repo-check head efc5f901afb7 merged into trunk cf897e89fe31 — pass: [release feat/57-config-and-provisioning, judged by its controller 93b947cc53b5] i…
mesh/delivery delivered
mesh/merge-gate head efc5f901afb7 merged into trunk cf897e89fe31 — pass: [release feat/57-config-and-provisioning, judged by its controller 93b947cc53b5] t…
mesh/repo-check head efc5f901afb7 merged into trunk cf897e89fe31 — pass: [release feat/57-config-and-provisioning, judged by its controller 93b947cc53b5] i…
mesh/delivery delivered
This commit is contained in:
@@ -585,11 +585,18 @@ func shelfWithChange(base map[string]catalogue.Manifest, sources map[string]inve
|
||||
return err
|
||||
}
|
||||
m, err := catalogue.ParseManifestWith(raw, predefined)
|
||||
// The manifest as written, still naming its templates: what the stand-in build resolves, as a real build
|
||||
// does, so a moved module is handed its templates (issue 876).
|
||||
written := m
|
||||
var texts map[string]string
|
||||
if err == nil {
|
||||
// Each template's text from the tree beside the manifest, as the build reads it back from the archive it
|
||||
// packs (novox/hq ADR 0349 §2): so a change to a template alone is a change to its module.
|
||||
m, err = catalogue.WithTemplatesFrom(m, filepath.Dir(path))
|
||||
}
|
||||
if err == nil && written.Templated() {
|
||||
texts, err = catalogue.ReadTemplates(written, filepath.Dir(path))
|
||||
}
|
||||
if err != nil {
|
||||
if inScope(dir) {
|
||||
failures = append(failures, fmt.Sprintf("%s: the controller judging this (%s) refuses it — %s",
|
||||
@@ -614,7 +621,7 @@ func shelfWithChange(base map[string]catalogue.Manifest, sources map[string]inve
|
||||
"of one module name (issue 239)", orRoot(dir), m.Module, s.Repository))
|
||||
return nil
|
||||
}
|
||||
resolved, err := standInBuild(m)
|
||||
resolved, err := standInBuild(written, texts)
|
||||
if err == nil {
|
||||
// As registration reads a built manifest: strictly, again (takeIn).
|
||||
var raw []byte
|
||||
@@ -737,15 +744,24 @@ func builtAlike(m catalogue.Manifest) string {
|
||||
// standInBuild resolves a manifest as a build would, with artifacts nobody built: a digest made from the
|
||||
// module's and the artifact's names, in the store's own vocabulary. Composition and validation read the
|
||||
// shape of a reference, never its bytes.
|
||||
func standInBuild(m catalogue.Manifest) (catalogue.Manifest, error) {
|
||||
func standInBuild(m catalogue.Manifest, texts map[string]string) (catalogue.Manifest, error) {
|
||||
if m.Build == nil {
|
||||
return m.Resolve(nil)
|
||||
}
|
||||
// The templates archive carries each template's text by its path inside the archive, as a build reads it back.
|
||||
archive, inside := catalogue.TemplatesArtifact(m), m.TemplatesDir()+"/"
|
||||
read := map[string]string{}
|
||||
for template, text := range texts {
|
||||
read[strings.TrimPrefix(template, inside)] = text
|
||||
}
|
||||
var built []catalogue.Built
|
||||
for _, a := range m.Build.Artifacts {
|
||||
sum := sha256.Sum256([]byte("gate\x00" + m.Module + "\x00" + a.Name))
|
||||
digest := fmt.Sprintf("sha256:%x", sum)
|
||||
b := catalogue.Built{Name: a.Name, Kind: a.Kind, Digest: digest}
|
||||
if a.Name == archive && archive != "" {
|
||||
b.Texts = read
|
||||
}
|
||||
switch a.Kind {
|
||||
case catalogue.ArtifactImage, catalogue.ArtifactUpstream:
|
||||
b.Reference = catalogue.ArtifactStoreScheme + m.Module + "/" + a.Name + "@" + digest
|
||||
|
||||
@@ -185,11 +185,11 @@ func TestTheMergeGateResolvesATemplatedModuleToItsInlineTwin(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m, err = catalogue.WithTemplatesFrom(m, dir)
|
||||
texts, err := catalogue.ReadTemplates(m, dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
resolved, err := standInBuild(m)
|
||||
resolved, err := standInBuild(m, texts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -239,3 +239,34 @@ func TestModuleCheckReadsTemplatesFromTheTemplatesDirectoryTheManifestNames(t *t
|
||||
t.Fatalf("a template outside the templates directory the manifest names passed:\n%s", got.String())
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 876: the gate judges a moved module that names its templates as registration reads it after a real build,
|
||||
// handed its templates; it refused every such module as "marked moved and names no template". This calls the gate's
|
||||
// own shelf (shelfWithChange), which needs no database.
|
||||
func TestReplay876(t *testing.T) {
|
||||
moved := strings.Replace(templatedNotifier, `"version":"1",`, `"version":"1","moved":true,`, 1)
|
||||
judge := func(manifest string, files map[string]string) (map[string]catalogue.Manifest, []string) {
|
||||
tree := t.TempDir()
|
||||
aTemplatedModule(t, filepath.Join(tree, "modules", "notifier"), manifest, files)
|
||||
out, failures, err := shelfWithChange(map[string]catalogue.Manifest{}, nil, snapshot.Facts{},
|
||||
"novox/mesh-catalog", tree, map[string]string{}, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return out, failures
|
||||
}
|
||||
out, failures := judge(moved, map[string]string{"files/notifier.conf": "volume = 3\n"})
|
||||
if len(failures) > 0 {
|
||||
t.Fatalf("a moved module naming its templates was refused: %v", failures)
|
||||
}
|
||||
if h := out["notifier"].Handed; h == nil || h.Templates["conf"] != "notifier.conf" {
|
||||
t.Fatalf("the gate did not hand the moved module its templates: %+v", h)
|
||||
}
|
||||
|
||||
// A moved module naming no template is still refused.
|
||||
none := strings.Replace(strings.Replace(moved, `"template":"files/notifier.conf"`,
|
||||
`"content":"volume = 3\n"`, 1), `"build":{"artifacts":[{"name":"files","kind":"archive","from":"files"}]},`, "", 1)
|
||||
if _, failures := judge(none, nil); len(failures) != 1 || !strings.Contains(failures[0], "names no template") {
|
||||
t.Fatalf("a moved module naming no template was not refused: %v", failures)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ func consumersPlaceholderProblems(m Manifest, r map[string]any) []string {
|
||||
// client alone fills it, so on a machine that does not hand the module it is **left out** of the declaration, never
|
||||
// written as that text or as an empty list the provider would read as no consumers, and never the reason the module is
|
||||
// refused: a provider not handed there keeps working as it did, from its grant files (novox/hq ADR 0373, issue 780).
|
||||
// A moved module judged from its repository's tree (WithTemplatesFrom: `module check`, the merge gate), on a machine
|
||||
// A moved module judged from its repository's tree (WithTemplatesFrom: `module check`), on a machine
|
||||
// that would hand it, has no templates archive to hand and is judged as it composes; there the placeholder is judged
|
||||
// and taken out of the text, since what is composed so is never sent (judged answers whether the file is so judged).
|
||||
func consumersHandedOnly(m Manifest, r map[string]any, with Rendering) (judged, leftOut bool) {
|
||||
|
||||
Reference in New Issue
Block a user