diff --git a/modules/mesh-build-go/cmd/mesh-build-go/fetch.go b/modules/mesh-build-go/cmd/mesh-build-go/fetch.go index 732db4e5..a262ddb6 100644 --- a/modules/mesh-build-go/cmd/mesh-build-go/fetch.go +++ b/modules/mesh-build-go/cmd/mesh-build-go/fetch.go @@ -84,7 +84,7 @@ func (m *Module) fetchTool() StepTool { func (m *Module) fetch(ctx context.Context, args map[string]any) (any, error) { // What the builder and the checker ask, in mesh-sdk's one form (ADR 0499 §4): with the module's directory and its - // named paths, the workspace is narrowed to them (narrow.go). + // named paths, the workspace is narrowed to them (buildstep.Narrow). req, err := buildstep.ParseFetchRequest(args) if err != nil { return nil, err @@ -115,7 +115,7 @@ func (m *Module) fetch(ctx context.Context, args map[string]any) (any, error) { return nil, err } if (base == "" || res.Merge != "") && len(req.Paths) > 0 { - if err := narrow(tree, req); err != nil { + if err := buildstep.Narrow(tree, req); err != nil { return nil, err } // Said beside the tree, so the steps that list the tree's go.mod files leave out those narrowed away. @@ -187,7 +187,7 @@ func (m *Module) goModDirs(ctx context.Context, tree string) ([]string, error) { if l = strings.TrimSpace(l); l != "" && !inTestdata(l) { if narrowed(tree) { if _, err := os.Stat(filepath.Join(tree, filepath.FromSlash(l))); err != nil { - continue // outside a narrowed workspace's paths (narrow.go): no module of this build + continue // outside a narrowed workspace's paths (buildstep.Narrow): no module of this build } } dirs = append(dirs, filepath.ToSlash(filepath.Dir(l))) diff --git a/modules/mesh-build-go/cmd/mesh-build-go/narrow.go b/modules/mesh-build-go/cmd/mesh-build-go/narrow.go deleted file mode 100644 index af4fb38d..00000000 --- a/modules/mesh-build-go/cmd/mesh-build-go/narrow.go +++ /dev/null @@ -1,83 +0,0 @@ -package main - -// The narrowed workspace (novox/hq ADR 0499 §4; issue 1758, the lead's decision L8): a build of a module whose every -// artifact names its paths sees only those paths, the module's manifest and its lock files. The paths come from the -// builder's request (buildstep.FetchRequest's Dir and Paths, from the indexer's kept inputs), never from a manifest. -// Everything else of the fetched tree is removed before any run step, so a read outside fails, naming the path. - -import ( - "fmt" - "os" - "path" - "path/filepath" - "sort" - - "git.novox.be/novox/mesh-sdk/go/buildstep" -) - -// narrowKept are the files of the module's directory a narrowed workspace keeps beside its paths: the manifest and the -// lock files of both languages. -var narrowKept = []string{"module.json", "package.json", "package-lock.json", "go.mod", "go.sum"} - -// narrow removes from tree everything but r's paths in its module directory, the manifest and the lock files (and the -// repository's .git). A request naming no paths leaves the tree whole. A named path the tree lacks fails, naming it. -func narrow(tree string, r buildstep.FetchRequest) error { - if len(r.Paths) == 0 { - return nil - } - dir := path.Clean(r.Dir) - keep := map[string]bool{} - for _, p := range r.Paths { - rel := path.Join(dir, path.Clean(p)) - if _, err := os.Lstat(filepath.Join(tree, filepath.FromSlash(rel))); err != nil { - return fmt.Errorf("the path %s the request names is not in the commit: %w", rel, err) - } - keep[rel] = true - } - for _, f := range narrowKept { - keep[path.Join(dir, f)] = true - } - return prune(tree, "", keep) -} - -// prune removes under tree/rel everything that is neither kept nor above or below a kept path. -func prune(tree, rel string, keep map[string]bool) error { - entries, err := os.ReadDir(filepath.Join(tree, filepath.FromSlash(rel))) - if err != nil { - return err - } - names := make([]string, 0, len(entries)) - for _, e := range entries { - names = append(names, e.Name()) - } - sort.Strings(names) - for _, name := range names { - p := path.Join(rel, name) - if rel == "" && name == ".git" { - continue - } - switch { - case keep[p]: - continue // a kept path, whole - case holdsKept(p, keep): - if err := prune(tree, p, keep); err != nil { - return err - } - default: - if err := os.RemoveAll(filepath.Join(tree, filepath.FromSlash(p))); err != nil { - return err - } - } - } - return nil -} - -// holdsKept says whether a kept path lies below p. -func holdsKept(p string, keep map[string]bool) bool { - for k := range keep { - if len(k) > len(p) && k[:len(p)+1] == p+"/" { - return true - } - } - return false -} diff --git a/modules/mesh-build-go/cmd/mesh-build-go/narrow_test.go b/modules/mesh-build-go/cmd/mesh-build-go/narrow_test.go deleted file mode 100644 index ba73232c..00000000 --- a/modules/mesh-build-go/cmd/mesh-build-go/narrow_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package main - -import ( - "os" - "path/filepath" - "slices" - "strings" - "testing" - - "git.novox.be/novox/mesh-sdk/go/buildstep" -) - -func files(t *testing.T, root string) []string { - t.Helper() - var out []string - filepath.WalkDir(root, func(p string, d os.DirEntry, err error) error { - if err == nil && !d.IsDir() { - rel, _ := filepath.Rel(root, p) - if !strings.HasPrefix(rel, ".git/") { - out = append(out, filepath.ToSlash(rel)) - } - } - return nil - }) - slices.Sort(out) - return out -} - -func narrowFixture(t *testing.T) string { - t.Helper() - tree := t.TempDir() - for _, f := range []string{".git/HEAD", "README.md", "module.json", "package.json", "package-lock.json", "tsconfig.json", - "src/index.ts", "src/deep/a.ts", "test/a.test.ts", "go/go.mod", "go/x.go", "other/module.json", "srcx/b.ts"} { - p := filepath.Join(tree, filepath.FromSlash(f)) - if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil { - t.Fatal(err) - } - if err := os.WriteFile(p, []byte(f), 0o644); err != nil { - t.Fatal(err) - } - } - return tree -} - -// ADR 0499 §4: a request naming paths leaves only those, the manifest and the lock files (and .git); a path the commit -// lacks fails naming it; a request naming none leaves the tree whole. -func TestTheWorkspaceIsNarrowedToTheNamedPathsTheManifestAndTheLocks(t *testing.T) { - tree := narrowFixture(t) - r := buildstep.FetchRequest{Dir: ".", Paths: []string{"src", "test", "tsconfig.json"}} - if err := narrow(tree, r); err != nil { - t.Fatal(err) - } - want := []string{"module.json", "package-lock.json", "package.json", "src/deep/a.ts", "src/index.ts", "test/a.test.ts", "tsconfig.json"} - if got := files(t, tree); !slices.Equal(got, want) { - t.Errorf("kept %v, want %v", got, want) - } - if _, err := os.Stat(filepath.Join(tree, ".git", "HEAD")); err != nil { - t.Errorf("the repository's .git went: %v", err) - } - tree = narrowFixture(t) - if err := narrow(tree, buildstep.FetchRequest{Dir: "go", Paths: []string{"x.go"}}); err != nil { - t.Fatal(err) - } - if got := files(t, tree); !slices.Equal(got, []string{"go/go.mod", "go/x.go"}) { - t.Errorf("a module in a directory kept %v", got) - } - tree = narrowFixture(t) - if err := narrow(tree, buildstep.FetchRequest{Dir: ".", Paths: []string{"lib"}}); err == nil || !strings.Contains(err.Error(), "lib") { - t.Errorf("a path the commit lacks answered %v", err) - } - tree = narrowFixture(t) - before := files(t, tree) - if err := narrow(tree, buildstep.FetchRequest{}); err != nil || !slices.Equal(files(t, tree), before) { - t.Errorf("a request naming no paths changed the tree: %v", err) - } -} diff --git a/modules/mesh-build-go/go.mod b/modules/mesh-build-go/go.mod index 43f574f3..259b0d60 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.20261022160024-9cb4d59093a7 + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022163107-d1af87a83a52 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 eb2b8834..583add3c 100644 --- a/modules/mesh-build-go/go.sum +++ b/modules/mesh-build-go/go.sum @@ -1,5 +1,5 @@ -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022160024-9cb4d59093a7 h1:wK9O1CgNk7mo3IdJqW/CCx/hebg+1F0rkvW8CvJfnRM= -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022160024-9cb4d59093a7/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022163107-d1af87a83a52 h1:5k04XjpfYCq6j7rCM6Dy6FfrsBk5iUJlbwGf6WhUOUc= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022163107-d1af87a83a52/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= diff --git a/modules/mesh-build-image/go.mod b/modules/mesh-build-image/go.mod index f3f4bd7a..72b71801 100644 --- a/modules/mesh-build-image/go.mod +++ b/modules/mesh-build-image/go.mod @@ -3,7 +3,7 @@ module meshbuildimage go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022160024-9cb4d59093a7 + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022163107-d1af87a83a52 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-image/go.sum b/modules/mesh-build-image/go.sum index 28ab5678..910d3ad5 100644 --- a/modules/mesh-build-image/go.sum +++ b/modules/mesh-build-image/go.sum @@ -1,5 +1,5 @@ -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022160024-9cb4d59093a7 h1:wK9O1CgNk7mo3IdJqW/CCx/hebg+1F0rkvW8CvJfnRM= -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022160024-9cb4d59093a7/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022163107-d1af87a83a52 h1:5k04XjpfYCq6j7rCM6Dy6FfrsBk5iUJlbwGf6WhUOUc= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022163107-d1af87a83a52/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op h1:Z/MZK75wC/NSrkgqeNIa7jexam9uWzhLmFTSCPI/kn0= github.com/antithesishq/antithesis-sdk-go v0.7.0-default-no-op/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI= github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= diff --git a/modules/mesh-build-node/cmd/mesh-build-node/fetch.go b/modules/mesh-build-node/cmd/mesh-build-node/fetch.go index 16ca4d06..e0ca6bf3 100644 --- a/modules/mesh-build-node/cmd/mesh-build-node/fetch.go +++ b/modules/mesh-build-node/cmd/mesh-build-node/fetch.go @@ -107,7 +107,7 @@ func (m *Module) fetchTool() StepTool { func (m *Module) fetch(ctx context.Context, args map[string]any) (any, error) { // What the builder and the checker ask, in mesh-sdk's one form (ADR 0499 §4): with the module's directory and its - // named paths, the workspace is narrowed to them (narrow.go). + // named paths, the workspace is narrowed to them (buildstep.Narrow). req, err := buildstep.ParseFetchRequest(args) if err != nil { return nil, err @@ -142,7 +142,7 @@ func (m *Module) fetch(ctx context.Context, args map[string]any) (any, error) { } } if len(req.Paths) > 0 { - if err := narrow(tree, req); err != nil { + if err := buildstep.Narrow(tree, req); err != nil { return nil, err } // Said beside the tree, so the listing of the tree's modules leaves out those narrowed away. @@ -208,7 +208,7 @@ func (m *Module) typeScriptModules(ctx context.Context, tree string) (dirs []str } raw, err := os.ReadFile(filepath.Join(tree, filepath.FromSlash(l))) if os.IsNotExist(err) && narrowed(tree) { - continue // outside a narrowed workspace's paths (narrow.go): no module of this build + continue // outside a narrowed workspace's paths (buildstep.Narrow): no module of this build } if err != nil { return nil, nil, err diff --git a/modules/mesh-build-node/cmd/mesh-build-node/narrow.go b/modules/mesh-build-node/cmd/mesh-build-node/narrow.go deleted file mode 100644 index af4fb38d..00000000 --- a/modules/mesh-build-node/cmd/mesh-build-node/narrow.go +++ /dev/null @@ -1,83 +0,0 @@ -package main - -// The narrowed workspace (novox/hq ADR 0499 §4; issue 1758, the lead's decision L8): a build of a module whose every -// artifact names its paths sees only those paths, the module's manifest and its lock files. The paths come from the -// builder's request (buildstep.FetchRequest's Dir and Paths, from the indexer's kept inputs), never from a manifest. -// Everything else of the fetched tree is removed before any run step, so a read outside fails, naming the path. - -import ( - "fmt" - "os" - "path" - "path/filepath" - "sort" - - "git.novox.be/novox/mesh-sdk/go/buildstep" -) - -// narrowKept are the files of the module's directory a narrowed workspace keeps beside its paths: the manifest and the -// lock files of both languages. -var narrowKept = []string{"module.json", "package.json", "package-lock.json", "go.mod", "go.sum"} - -// narrow removes from tree everything but r's paths in its module directory, the manifest and the lock files (and the -// repository's .git). A request naming no paths leaves the tree whole. A named path the tree lacks fails, naming it. -func narrow(tree string, r buildstep.FetchRequest) error { - if len(r.Paths) == 0 { - return nil - } - dir := path.Clean(r.Dir) - keep := map[string]bool{} - for _, p := range r.Paths { - rel := path.Join(dir, path.Clean(p)) - if _, err := os.Lstat(filepath.Join(tree, filepath.FromSlash(rel))); err != nil { - return fmt.Errorf("the path %s the request names is not in the commit: %w", rel, err) - } - keep[rel] = true - } - for _, f := range narrowKept { - keep[path.Join(dir, f)] = true - } - return prune(tree, "", keep) -} - -// prune removes under tree/rel everything that is neither kept nor above or below a kept path. -func prune(tree, rel string, keep map[string]bool) error { - entries, err := os.ReadDir(filepath.Join(tree, filepath.FromSlash(rel))) - if err != nil { - return err - } - names := make([]string, 0, len(entries)) - for _, e := range entries { - names = append(names, e.Name()) - } - sort.Strings(names) - for _, name := range names { - p := path.Join(rel, name) - if rel == "" && name == ".git" { - continue - } - switch { - case keep[p]: - continue // a kept path, whole - case holdsKept(p, keep): - if err := prune(tree, p, keep); err != nil { - return err - } - default: - if err := os.RemoveAll(filepath.Join(tree, filepath.FromSlash(p))); err != nil { - return err - } - } - } - return nil -} - -// holdsKept says whether a kept path lies below p. -func holdsKept(p string, keep map[string]bool) bool { - for k := range keep { - if len(k) > len(p) && k[:len(p)+1] == p+"/" { - return true - } - } - return false -} diff --git a/modules/mesh-build-node/cmd/mesh-build-node/narrow_test.go b/modules/mesh-build-node/cmd/mesh-build-node/narrow_test.go deleted file mode 100644 index ba73232c..00000000 --- a/modules/mesh-build-node/cmd/mesh-build-node/narrow_test.go +++ /dev/null @@ -1,76 +0,0 @@ -package main - -import ( - "os" - "path/filepath" - "slices" - "strings" - "testing" - - "git.novox.be/novox/mesh-sdk/go/buildstep" -) - -func files(t *testing.T, root string) []string { - t.Helper() - var out []string - filepath.WalkDir(root, func(p string, d os.DirEntry, err error) error { - if err == nil && !d.IsDir() { - rel, _ := filepath.Rel(root, p) - if !strings.HasPrefix(rel, ".git/") { - out = append(out, filepath.ToSlash(rel)) - } - } - return nil - }) - slices.Sort(out) - return out -} - -func narrowFixture(t *testing.T) string { - t.Helper() - tree := t.TempDir() - for _, f := range []string{".git/HEAD", "README.md", "module.json", "package.json", "package-lock.json", "tsconfig.json", - "src/index.ts", "src/deep/a.ts", "test/a.test.ts", "go/go.mod", "go/x.go", "other/module.json", "srcx/b.ts"} { - p := filepath.Join(tree, filepath.FromSlash(f)) - if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil { - t.Fatal(err) - } - if err := os.WriteFile(p, []byte(f), 0o644); err != nil { - t.Fatal(err) - } - } - return tree -} - -// ADR 0499 §4: a request naming paths leaves only those, the manifest and the lock files (and .git); a path the commit -// lacks fails naming it; a request naming none leaves the tree whole. -func TestTheWorkspaceIsNarrowedToTheNamedPathsTheManifestAndTheLocks(t *testing.T) { - tree := narrowFixture(t) - r := buildstep.FetchRequest{Dir: ".", Paths: []string{"src", "test", "tsconfig.json"}} - if err := narrow(tree, r); err != nil { - t.Fatal(err) - } - want := []string{"module.json", "package-lock.json", "package.json", "src/deep/a.ts", "src/index.ts", "test/a.test.ts", "tsconfig.json"} - if got := files(t, tree); !slices.Equal(got, want) { - t.Errorf("kept %v, want %v", got, want) - } - if _, err := os.Stat(filepath.Join(tree, ".git", "HEAD")); err != nil { - t.Errorf("the repository's .git went: %v", err) - } - tree = narrowFixture(t) - if err := narrow(tree, buildstep.FetchRequest{Dir: "go", Paths: []string{"x.go"}}); err != nil { - t.Fatal(err) - } - if got := files(t, tree); !slices.Equal(got, []string{"go/go.mod", "go/x.go"}) { - t.Errorf("a module in a directory kept %v", got) - } - tree = narrowFixture(t) - if err := narrow(tree, buildstep.FetchRequest{Dir: ".", Paths: []string{"lib"}}); err == nil || !strings.Contains(err.Error(), "lib") { - t.Errorf("a path the commit lacks answered %v", err) - } - tree = narrowFixture(t) - before := files(t, tree) - if err := narrow(tree, buildstep.FetchRequest{}); err != nil || !slices.Equal(files(t, tree), before) { - t.Errorf("a request naming no paths changed the tree: %v", err) - } -} diff --git a/modules/mesh-build-node/go.mod b/modules/mesh-build-node/go.mod index 568a566a..5fed451e 100644 --- a/modules/mesh-build-node/go.mod +++ b/modules/mesh-build-node/go.mod @@ -3,7 +3,7 @@ module meshbuildnode go 1.26.0 require ( - git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022160024-9cb4d59093a7 + git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022163107-d1af87a83a52 github.com/distribution/distribution/v3 v3.1.2 github.com/nats-io/nats.go v1.54.0 ) diff --git a/modules/mesh-build-node/go.sum b/modules/mesh-build-node/go.sum index 53e95299..57ba3529 100644 --- a/modules/mesh-build-node/go.sum +++ b/modules/mesh-build-node/go.sum @@ -1,5 +1,5 @@ -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022160024-9cb4d59093a7 h1:wK9O1CgNk7mo3IdJqW/CCx/hebg+1F0rkvW8CvJfnRM= -git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022160024-9cb4d59093a7/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022163107-d1af87a83a52 h1:5k04XjpfYCq6j7rCM6Dy6FfrsBk5iUJlbwGf6WhUOUc= +git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261022163107-d1af87a83a52/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=