diff --git a/modules/mesh-build-go/cmd/mesh-build-go/level.go b/modules/mesh-build-go/cmd/mesh-build-go/level.go index 9043b1db..0b867566 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/level.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/level.go @@ -142,10 +142,15 @@ func (m *Module) nodeToolchains() []string { return []string{dir} } -// Has says whether this node has a need a check ask or a package's tests name (issue 890; mesh-sdk delivery.AskNeeds), -// read from the node itself at every ask: node-build-node when the Node build module's toolchains directory holds an -// installed toolchain this account may read, given to the integration level as nodeToolchains gives it, and node and npm -// are installed, as mesh-build-node's integration tests look for them before they run. Any other need it lacks. +// nodeToolchainMark is the file the Node build module writes in a toolchain directory once it is installed whole +// (mesh-build-node toolchain.go installedMark). +const nodeToolchainMark = ".installed" + +// Has says whether this node has a need a check ask or a package's tests name (issue 890, ADR 0552; mesh-sdk +// delivery.AskNeeds), read from the node itself at every ask: node-build-node when the Node build module's toolchains +// directory, given to the integration level as nodeToolchains gives it, holds a toolchain installed whole (its mark and +// its package-lock.json readable by this account), and node, npm and bwrap are installed: what mesh-build-node's +// integration tests (realMachine) look for before they run. Any other need it lacks. func (m *Module) Has(need string) bool { if m.HasNeed != nil { return m.HasNeed(need) @@ -156,15 +161,26 @@ func (m *Module) Has(need string) bool { if len(dirs) == 0 { return false } - if entries, err := os.ReadDir(dirs[0]); err != nil || len(entries) == 0 { - return false - } - for _, p := range []string{"node", "npm"} { + for _, p := range []string{"node", "npm", "bwrap"} { if _, err := exec.LookPath(p); err != nil { return false } } - return true + entries, err := os.ReadDir(dirs[0]) + if err != nil { + return false + } + for _, e := range entries { + dir := filepath.Join(dirs[0], e.Name()) + if _, err := os.Stat(filepath.Join(dir, nodeToolchainMark)); err != nil { + continue + } + if f, err := os.Open(filepath.Join(dir, "package-lock.json")); err == nil { + f.Close() + return true + } + } + return false } return false } diff --git a/modules/mesh-build-go/cmd/mesh-build-go/node_toolchains_test.go b/modules/mesh-build-go/cmd/mesh-build-go/node_toolchains_test.go index bd032546..b1ecbe7c 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/node_toolchains_test.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/node_toolchains_test.go @@ -75,7 +75,7 @@ func TestANodeWithoutNodeToolchainsRunsTheLevelWithNothingMoreBound(t *testing.T // Issue 890/AC4: such a node lacks node-build-node; one with an installed toolchain and node and npm has it; nothing // else is had. bin := t.TempDir() - for _, p := range []string{"node", "npm"} { + for _, p := range []string{"node", "npm", "bwrap"} { if err := os.WriteFile(filepath.Join(bin, p), []byte("#!/bin/sh\n"), 0o755); err != nil { t.Fatal(err) } @@ -90,15 +90,27 @@ func TestANodeWithoutNodeToolchainsRunsTheLevelWithNothingMoreBound(t *testing.T if m.Has(delivery.NeedNodeBuildNode) { t.Error("a node with an empty toolchains directory has node-build-node") } - if err := os.Mkdir(filepath.Join(installed, "0.1.0"), 0o755); err != nil { + half := filepath.Join(installed, "0.1.0") + if err := os.Mkdir(half, 0o755); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(half, "package-lock.json"), []byte("{}"), 0o644); err != nil { + t.Fatal(err) + } + if m.Has(delivery.NeedNodeBuildNode) { + t.Error("a toolchain without its installed mark counts") + } + if err := os.WriteFile(filepath.Join(half, nodeToolchainMark), nil, 0o644); err != nil { t.Fatal(err) } if !m.Has(delivery.NeedNodeBuildNode) || m.Has("gpu") { t.Errorf("with a toolchain installed: node-build-node %v, gpu %v; want true, false", m.Has(delivery.NeedNodeBuildNode), m.Has("gpu")) } - t.Setenv("PATH", t.TempDir()) + if err := os.Remove(filepath.Join(bin, "bwrap")); err != nil { + t.Fatal(err) + } if m.Has(delivery.NeedNodeBuildNode) { - t.Error("a node with no node installed has node-build-node") + t.Error("a node with no bubblewrap installed has node-build-node") } } diff --git a/modules/mesh-build-go/go.mod b/modules/mesh-build-go/go.mod index d44cc621..b2f31200 100644 --- a/modules/mesh-build-go/go.mod +++ b/modules/mesh-build-go/go.mod @@ -3,7 +3,7 @@ module meshbuildgo go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026123512-bb713103371a + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026130105-45564e69a648 github.com/distribution/distribution/v3 v3.1.2 github.com/nats-io/nats-server/v2 v2.11.17 github.com/nats-io/nats.go v1.54.0 diff --git a/modules/mesh-build-go/go.sum b/modules/mesh-build-go/go.sum index 5c5c5ca0..88077cab 100644 --- a/modules/mesh-build-go/go.sum +++ b/modules/mesh-build-go/go.sum @@ -2,6 +2,8 @@ git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026095702-79649c3fa9f4 h1:05sVel/U git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026095702-79649c3fa9f4/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026123512-bb713103371a h1:ZxKOtc8LusZEEpbbu41lYxJiaITN8lZCIcasA5kdgGQ= git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026123512-bb713103371a/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026130105-45564e69a648 h1:UUhWHYnaTJwgkgoYhQtJrm+r5S5UNAQ4DRMlt4x21Hg= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261026130105-45564e69a648/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= github.com/alicebob/miniredis/v2 v2.35.0 h1:QwLphYqCEAo1eu1TqPRN2jgVMPBweeQcR21jeqDCONI= github.com/alicebob/miniredis/v2 v2.35.0/go.mod h1:TcL7YfarKPGDAthEtl5NBeHZfeUQj6OXMm/+iu5cLMM= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0=