From 985e2008ba259a563e18be248bf37a0c80e9fbc2 Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 30 Sep 2026 09:55:54 +0200 Subject: [PATCH] A bundle in a compiled language may name which command it builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit novox/hq 04-ISSUES/142. A bundle is refused if it names what it is built from, because a bundle is the module's own directory compiled whole and naming a source would be describing its own build. That reason holds for an interpreted language and cannot hold for a compiled one. A repository written in Go carries several commands — the host and its bootstrap live in one — and "the module's own directory" is then not a package at all. So a compiled bundle may say which package, and says the module root by saying nothing. The refusal stands for every interpreted bundle, which is what it was written for. Found by writing the host's manifest, which is the first bundle in a compiled language this mesh has had. --- internal/catalogue/build.go | 9 ++++++- internal/catalogue/go_bundle_test.go | 37 ++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 internal/catalogue/go_bundle_test.go diff --git a/internal/catalogue/build.go b/internal/catalogue/build.go index 94d54be..90b4bbb 100644 --- a/internal/catalogue/build.go +++ b/internal/catalogue/build.go @@ -142,7 +142,14 @@ func (b *Build) problems(module string) []string { // is which compiler — because the mesh chooses that, and cannot choose for a module that // has not said. if a.Kind == ArtifactBundle || a.Kind == ArtifactPackage { - if a.From != "" { + // **Except for a language that compiles to a binary, where it names which one** + // (novox/hq 04-ISSUES/142). A bundle in an interpreted language is the module's own + // directory compiled whole, and naming a source would be describing its own build. A + // repository written in a compiled language holds several commands — the host and its + // bootstrap live in one, and the mesh needs the host — and "the module's own directory" + // is then not a package at all. So the compiled case may say which package, and says + // the module root by saying nothing. + if a.From != "" && !compilesToABinary(a.Language) { problems = append(problems, fmt.Sprintf( "%s: %q is a bundle and names what it is built from (%q). A bundle is built "+ "from the module's own directory; what it says is the language", diff --git a/internal/catalogue/go_bundle_test.go b/internal/catalogue/go_bundle_test.go new file mode 100644 index 0000000..eb6cd2b --- /dev/null +++ b/internal/catalogue/go_bundle_test.go @@ -0,0 +1,37 @@ +package catalogue + +import "testing" + +// A bundle is the module's own directory compiled whole, and naming a source would be describing its +// own build. That holds for an interpreted language and cannot hold for a compiled one: a repository +// written in Go carries several commands — the host and its bootstrap live in one — and "the module's +// own directory" is then not a package at all (novox/hq 04-ISSUES/142). + +func TestAGoBundleMayNameItsCommand(t *testing.T) { + b := &Build{Artifacts: []Artifact{{ + Name: "host-arch", Kind: ArtifactBundle, Language: "go", System: "arch", + From: "cmd/mesh-host", + }}} + if p := b.problems("mesh-host"); len(p) != 0 { + t.Fatalf("a go bundle naming its command was refused: %v", p) + } +} + +func TestAnInterpretedBundleStillMayNotNameASource(t *testing.T) { + b := &Build{Artifacts: []Artifact{{ + Name: "tools", Kind: ArtifactBundle, Language: "typescript", From: "src", + }}} + p := b.problems("something") + if len(p) == 0 { + t.Fatal("an interpreted bundle naming what it is built from was accepted") + } +} + +func TestACompiledBundleStillMustSayItsSystem(t *testing.T) { + b := &Build{Artifacts: []Artifact{{ + Name: "host", Kind: ArtifactBundle, Language: "go", From: "cmd/mesh-host", + }}} + if len(b.problems("mesh-host")) == 0 { + t.Fatal("a compiled bundle with no system was accepted") + } +}