From cf2bb3b87d3ee56779cc086c8be5854e37ce5fc5 Mon Sep 17 00:00:00 2001 From: jochen Date: Sat, 3 Oct 2026 22:25:34 +0200 Subject: [PATCH] A bundle nothing would deliver is refused at registration (hq issue 216) The composer delivers a bundle when the runtime loads from it, a resource names it, or it is the runtime; one reached by none of them was built, recorded and pushed as success and was simply absent. Seven modules' tools went missing that way. Refused at registration, naming the field that would deliver it. --- internal/catalogue/build.go | 30 ++++++++++++++++++++++++++++++ internal/catalogue/manifest.go | 1 + internal/catalogue/runtime_test.go | 25 +++++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/internal/catalogue/build.go b/internal/catalogue/build.go index 1bc31c6..930c69a 100644 --- a/internal/catalogue/build.go +++ b/internal/catalogue/build.go @@ -436,3 +436,33 @@ func BinaryOf(a Artifact) string { } return a.Name } + +// undeliveredBundles says which of a module's bundles nothing would ever put on a machine (novox/hq +// 04-ISSUES/216). A bundle reaches a machine three ways: the node's runtime serves it (it says +// `loads`, or its module declares `tools`), a resource names it (a process, a step, an archive), or +// it is the runtime itself. One reached by none of them was built, recorded and pushed as success, +// and was simply absent — seven modules' tools went missing that way on 2026-10-03. Refused here, +// naming the field that would deliver it. +func undeliveredBundles(m Manifest) []string { + if m.Build == nil || m.Module == RuntimeModule { + return nil + } + named := map[string]bool{} + for _, r := range m.Resources { + if a, ok := r["artifact"].(string); ok && a != "" { + named[a] = true + } + } + var problems []string + for _, a := range m.Build.Artifacts { + if a.Kind != ArtifactBundle || named[a.Name] || len(a.Loads) > 0 || len(m.Tools) > 0 { + continue + } + problems = append(problems, fmt.Sprintf( + "%s: the bundle %q would be built and never reach a machine: nothing loads it, runs it or "+ + "unpacks it. A tools bundle says `loads` (the entrypoints the node's runtime serves) or its "+ + "module lists its `tools`; a daemon or a step is a resource naming it (novox/hq 04-ISSUES/216)", + m.Module, a.Name)) + } + return problems +} diff --git a/internal/catalogue/manifest.go b/internal/catalogue/manifest.go index 01686d5..aef8497 100644 --- a/internal/catalogue/manifest.go +++ b/internal/catalogue/manifest.go @@ -1373,6 +1373,7 @@ func ParseManifest(raw []byte) (Manifest, error) { } } problems = append(problems, m.Build.problems(m.Module)...) + problems = append(problems, undeliveredBundles(m)...) // **What provides the artifact store cannot be delivered through it** (novox/hq 04-ISSUES/029). // // Building publishes to the store, and the builder will not start without one. So a module diff --git a/internal/catalogue/runtime_test.go b/internal/catalogue/runtime_test.go index fa4dc43..b7f2173 100644 --- a/internal/catalogue/runtime_test.go +++ b/internal/catalogue/runtime_test.go @@ -389,3 +389,28 @@ func TestARuntimeCompiledToABinaryRunsItself(t *testing.T) { t.Errorf("the Go runtime is not told what to serve or whose it is: %v %v", env, process["user"]) } } + +// novox/hq 04-ISSUES/216: a bundle nothing loads, runs or unpacks is refused at registration; saying +// `loads`, listing `tools`, or a resource naming it admits it. +func TestABundleNothingDeliversIsRefused(t *testing.T) { + base := func() Manifest { + return Manifest{Module: "baserow", Version: "1", Build: &Build{Artifacts: []Artifact{ + {Name: "tools", Kind: ArtifactBundle, Language: "typescript", Entrypoints: []string{"tools/index.js"}}}}} + } + if p := undeliveredBundles(base()); len(p) != 1 || !strings.Contains(p[0], "never reach a machine") { + t.Fatalf("a bundle nothing delivers was admitted: %v", p) + } + loads := base() + loads.Build.Artifacts[0].Loads = []string{"tools/index.js"} + tools := base() + tools.Tools = []string{"baserow_list_rows"} + run := base() + run.Resources = []map[string]any{{"id": "daemon", "type": "process", "artifact": "tools", "run": []any{"node", "tools/index.js"}}} + runtime := base() + runtime.Module = RuntimeModule + for name, m := range map[string]Manifest{"loads": loads, "tools": tools, "a process": run, "the runtime": runtime} { + if p := undeliveredBundles(m); len(p) != 0 { + t.Errorf("a bundle delivered by %s was refused: %v", name, p) + } + } +}