mesh/delivery-group group feat/registry-milestone rejected: composed together: the checker's verdict at the members' heads (8a80e8e86858): unit: git.novox.be/n…
mesh/delivery closed: a newer head of the same pull request
mesh/check failed (4): unit: git.novox.be/novox/m…; and 3 more | 62fe1cc36d30 on f2b332de73d6 | judged by the candidate's mesh-build-go at e8757a23634d
Quick fix: add the one require to mesh-build-go's go.mod (a minute). Thorough fix, chosen because the kind was met twice (a local go.work resolving what go.mod never names) and hides itself from every local build: checks/requiredmodules reads every go.mod and Go source (tests and tagged files included), finds the owning module by the longest module line among the repositories beside, and fails in go test and the repository check before any push. The scan over the seven group heads found this one instance. Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
79 lines
3.4 KiB
Go
79 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func tree(t *testing.T, files map[string]string) string {
|
|
t.Helper()
|
|
root := t.TempDir()
|
|
for p, c := range files {
|
|
full := filepath.Join(root, p)
|
|
if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(full, []byte(c), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
return root
|
|
}
|
|
|
|
const aMod = "module git.novox.be/novox/r/a\n\ngo 1.22\n"
|
|
const bMod = "module git.novox.be/novox/r/b/sub\n\ngo 1.22\n"
|
|
|
|
// A module that imports a package of a mesh module its go.mod does not require is refused, in a test file and behind a
|
|
// build tag too; the module's own packages, a required module's and a nested module's (only when required) are not.
|
|
func TestAModuleImportsOnlyWhatItRequires(t *testing.T) {
|
|
src := func(imp string) string { return "package x\n\nimport _ \"" + imp + "\"\n" }
|
|
for _, row := range []struct {
|
|
name string
|
|
files map[string]string
|
|
want string
|
|
}{
|
|
{"its own package", map[string]string{"a/go.mod": aMod, "a/x.go": src("git.novox.be/novox/r/a/other")}, ""},
|
|
{"a required module", map[string]string{"a/go.mod": aMod + "\nrequire git.novox.be/novox/r/b/sub v0.0.0\n", "a/x.go": src("git.novox.be/novox/r/b/sub/pkg"), "b/go.mod": bMod}, ""},
|
|
{"a required module in a block", map[string]string{"a/go.mod": aMod + "\nrequire (\n\tgit.novox.be/novox/r/b/sub v0.0.0 // indirect\n)\n", "a/x.go": src("git.novox.be/novox/r/b/sub/pkg"), "b/go.mod": bMod}, ""},
|
|
{"a module not required", map[string]string{"a/go.mod": aMod, "a/x.go": src("git.novox.be/novox/r/b/sub/pkg"), "b/go.mod": bMod}, "x.go imports git.novox.be/novox/r/b/sub/pkg"},
|
|
{"a test file", map[string]string{"a/go.mod": aMod, "a/x_test.go": src("git.novox.be/novox/r/b/sub/pkg"), "b/go.mod": bMod}, "x_test.go imports"},
|
|
{"an integration file", map[string]string{"a/go.mod": aMod, "a/x.go": "//go:build integration\n\n" + src("git.novox.be/novox/r/b/sub/pkg"), "b/go.mod": bMod}, "x.go imports"},
|
|
{"a module the longest owner is not", map[string]string{"a/go.mod": aMod + "\nrequire git.novox.be/novox/r/b v0.0.0\n", "a/x.go": src("git.novox.be/novox/r/b/sub/pkg"), "b/go.mod": "module git.novox.be/novox/r/b\n", "b/sub/go.mod": bMod}, "does not require"},
|
|
{"a testdata fixture", map[string]string{"a/go.mod": aMod, "a/testdata/x.go": src("git.novox.be/novox/r/b/sub/pkg"), "a/x.go": "package x\n"}, ""},
|
|
{"an outside module", map[string]string{"a/go.mod": aMod, "a/x.go": src("github.com/x/y")}, ""},
|
|
} {
|
|
t.Run(row.name, func(t *testing.T) {
|
|
got, err := Findings([]string{tree(t, row.files)}, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if all := strings.Join(got, "\n"); (row.want == "") != (all == "") || !strings.Contains(all, row.want) {
|
|
t.Fatalf("findings = %q, want one containing %q", all, row.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// The script's run of this check over the real tree (novox/hq ADR 0529 clause 2): the repositories cloned beside it, when
|
|
// the check says where, tell which module owns a path.
|
|
func TestEveryCatalogueModuleRequiresWhatItImports(t *testing.T) {
|
|
var known []string
|
|
if beside := os.Getenv("MESH_CHECK_BESIDE"); beside != "" {
|
|
es, _ := os.ReadDir(beside)
|
|
for _, e := range es {
|
|
if e.IsDir() && e.Name() != "mesh-catalog" {
|
|
known = append(known, filepath.Join(beside, e.Name()))
|
|
}
|
|
}
|
|
}
|
|
got, err := Findings([]string{filepath.Join("..", "..")}, known)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, f := range got {
|
|
t.Error(f)
|
|
}
|
|
}
|