Build the merge preview's module trees with mesh-sdk's ModuleTrees and re-pin mesh-sdk to 78364e31, so the two fetch steps share it (issues 1675, 1676)

This commit is contained in:
2026-10-21 21:24:24 +02:00
parent d5804927b3
commit aa0eaa6c52
9 changed files with 22 additions and 122 deletions
@@ -43,11 +43,11 @@ type FetchResult struct {
// head onto it, the paths the merge changes, and the tree of each module directory (a directory holding a
// module.json) in the merge. A head that does not merge cleanly is an answer: Merge is empty, Conflicts names the
// files, and the workspace is left at the trunk commit.
Base string `json:"base,omitempty"`
Merge string `json:"merge,omitempty"`
Conflicts []string `json:"conflicts,omitempty"`
Changed []string `json:"changed,omitempty"`
Trees map[string]ModuleTree `json:"trees,omitempty"`
Base string `json:"base,omitempty"`
Merge string `json:"merge,omitempty"`
Conflicts []string `json:"conflicts,omitempty"`
Changed []string `json:"changed,omitempty"`
Trees map[string]buildstep.ModuleTree `json:"trees,omitempty"`
// Beside are the sibling repositories placed as plain directories under the workspace's beside directory, which
// build_go_test hands to the tests as MESH_CHECK_BESIDE (ADR 0484 clause 4).
Beside []Sibling `json:"beside,omitempty"`
@@ -6,8 +6,6 @@ package main
import (
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
"io/fs"
"os"
@@ -45,62 +43,10 @@ func (m *Module) merge(ctx context.Context, res *FetchResult, tree, remote, base
if res.Merge == "" {
return nil
}
res.Trees, err = m.moduleTrees(ctx, tree, res.Merge)
res.Trees, err = buildstep.ModuleTrees(ctx, m.Run, nil, tree, res.Merge)
return err
}
// ModuleTree is what the merge holds of one module directory: its tree id, the sha256 of its module.json and the sha256
// of each lock file it has (go.sum, package-lock.json), from which the checker and the indexer take the module's inputs.
type ModuleTree struct {
Tree string `json:"tree"`
Manifest string `json:"manifest"`
Locks map[string]string `json:"locks,omitempty"`
}
var lockFiles = []string{"go.sum", "package-lock.json"}
// moduleTrees are the trees, in the merge commit, of every directory of the tree that holds a module.json; the workspace
// is at the merge, so the manifest and the locks are read from it.
func (m *Module) moduleTrees(ctx context.Context, tree, merge string) (map[string]ModuleTree, error) {
r := m.Run(ctx, nil, "git", "-C", tree, "ls-files", "--", "module.json", "*/module.json")
if r.Status != 0 || r.Err != "" {
return nil, fmt.Errorf("git ls-files: %s", firstLine(r.Err+" "+r.Stderr))
}
trees := map[string]ModuleTree{}
for _, l := range strings.Split(r.Stdout, "\n") {
if l = strings.TrimSpace(l); l == "" {
continue
}
dir := filepath.ToSlash(filepath.Dir(l))
spec := merge + ":" + dir
if dir == "." {
spec = merge + "^{tree}"
}
t := m.Run(ctx, nil, "git", "-C", tree, "rev-parse", spec)
if t.Status != 0 || t.Err != "" {
return nil, fmt.Errorf("git rev-parse %s: %s", spec, firstLine(t.Err+" "+t.Stderr))
}
mt := ModuleTree{Tree: strings.TrimSpace(t.Stdout)}
raw, err := os.ReadFile(filepath.Join(tree, filepath.FromSlash(l)))
if err != nil {
return nil, err
}
mt.Manifest = sha256Hex(raw)
for _, lock := range lockFiles {
if raw, err := os.ReadFile(filepath.Join(tree, filepath.FromSlash(dir), lock)); err == nil {
if mt.Locks == nil {
mt.Locks = map[string]string{}
}
mt.Locks[lock] = sha256Hex(raw)
}
}
trees[dir] = mt
}
return trees, nil
}
func sha256Hex(b []byte) string { h := sha256.Sum256(b); return hex.EncodeToString(h[:]) }
type siblingArg struct{ repository, commit string }
func siblingsArg(v any) ([]siblingArg, error) {
@@ -2,6 +2,8 @@ package main
import (
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"os"
"path/filepath"
@@ -268,3 +270,5 @@ func TestPackagesRunOnlyInTheModuleThatHoldsThem(t *testing.T) {
t.Errorf("a package no module holds: %v", err)
}
}
func sha256Hex(b []byte) string { h := sha256.Sum256(b); return hex.EncodeToString(h[:]) }
+1 -1
View File
@@ -3,7 +3,7 @@ module meshbuildgo
go 1.26.0
require (
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021185947-afbe371003a5
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021192148-78364e318bdc
github.com/nats-io/nats-server/v2 v2.11.17
)
+2
View File
@@ -2,6 +2,8 @@ git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021093645-465beb4ea5e3 h1:OKxU64kH
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021093645-465beb4ea5e3/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021185947-afbe371003a5 h1:1BiPKRPTYpgex8rSHWT9az0BteOafGWRDzd/Ba6GAcA=
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021185947-afbe371003a5/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021192148-78364e318bdc h1:ZJScJSnF6LgFl55/VJ9RT/lNroVWun469sXtx0nlVYw=
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021192148-78364e318bdc/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=
@@ -54,11 +54,11 @@ type FetchResult struct {
// commit, the merge commit of the head onto it, the paths the merge changes and the tree of each module directory.
// A head that does not merge cleanly is an answer: Merge is empty, Conflicts names the files, and the workspace is
// left at the trunk commit with nothing installed.
Base string `json:"base,omitempty"`
Merge string `json:"merge,omitempty"`
Conflicts []string `json:"conflicts,omitempty"`
Changed []string `json:"changed,omitempty"`
Trees map[string]ModuleTree `json:"trees,omitempty"`
Base string `json:"base,omitempty"`
Merge string `json:"merge,omitempty"`
Conflicts []string `json:"conflicts,omitempty"`
Changed []string `json:"changed,omitempty"`
Trees map[string]buildstep.ModuleTree `json:"trees,omitempty"`
}
// Refusal is a module a fetch did not install the packages of.
@@ -5,8 +5,6 @@ package main
import (
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
"os"
"path/filepath"
@@ -36,58 +34,6 @@ func (m *Module) merge(ctx context.Context, run forgekey.Runner, res *FetchResul
if res.Merge == "" {
return nil
}
res.Trees, err = m.moduleTrees(ctx, tree, res.Merge)
res.Trees, err = buildstep.ModuleTrees(ctx, m.Run, m.baseEnv(), tree, res.Merge)
return err
}
// ModuleTree is what the merge holds of one module directory: its tree id, the sha256 of its module.json and the sha256
// of each lock file it has (go.sum, package-lock.json), from which the checker and the indexer take the module's inputs.
type ModuleTree struct {
Tree string `json:"tree"`
Manifest string `json:"manifest"`
Locks map[string]string `json:"locks,omitempty"`
}
var lockFiles = []string{"go.sum", "package-lock.json"}
// moduleTrees are the trees, in the merge commit, of every directory of the tree that holds a module.json; the workspace
// is at the merge, so the manifest and the locks are read from it.
func (m *Module) moduleTrees(ctx context.Context, tree, merge string) (map[string]ModuleTree, error) {
r := m.Run(ctx, m.baseEnv(), "git", "-C", tree, "ls-files", "--", "module.json", "*/module.json")
if r.Status != 0 || r.Err != "" {
return nil, fmt.Errorf("git ls-files: %s", firstLine(r.Err+" "+r.Stderr))
}
trees := map[string]ModuleTree{}
for _, l := range strings.Split(r.Stdout, "\n") {
if l = strings.TrimSpace(l); l == "" {
continue
}
dir := filepath.ToSlash(filepath.Dir(l))
spec := merge + ":" + dir
if dir == "." {
spec = merge + "^{tree}"
}
t := m.Run(ctx, m.baseEnv(), "git", "-C", tree, "rev-parse", spec)
if t.Status != 0 || t.Err != "" {
return nil, fmt.Errorf("git rev-parse %s: %s", spec, firstLine(t.Err+" "+t.Stderr))
}
mt := ModuleTree{Tree: strings.TrimSpace(t.Stdout)}
raw, err := os.ReadFile(filepath.Join(tree, filepath.FromSlash(l)))
if err != nil {
return nil, err
}
mt.Manifest = sha256Hex(raw)
for _, lock := range lockFiles {
if raw, err := os.ReadFile(filepath.Join(tree, filepath.FromSlash(dir), lock)); err == nil {
if mt.Locks == nil {
mt.Locks = map[string]string{}
}
mt.Locks[lock] = sha256Hex(raw)
}
}
trees[dir] = mt
}
return trees, nil
}
func sha256Hex(b []byte) string { h := sha256.Sum256(b); return hex.EncodeToString(h[:]) }
+1 -1
View File
@@ -2,4 +2,4 @@ module meshbuildnode
go 1.26.0
require git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021185947-afbe371003a5
require git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021192148-78364e318bdc
+2
View File
@@ -2,3 +2,5 @@ git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021093645-465beb4ea5e3 h1:OKxU64kH
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021093645-465beb4ea5e3/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021185947-afbe371003a5 h1:1BiPKRPTYpgex8rSHWT9az0BteOafGWRDzd/Ba6GAcA=
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021185947-afbe371003a5/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021192148-78364e318bdc h1:ZJScJSnF6LgFl55/VJ9RT/lNroVWun469sXtx0nlVYw=
git.novox.be/novox/mesh-sdk/go v0.1.14-0.20261021192148-78364e318bdc/go.mod h1:ouERNpZizzwZ0HLEtAypsY9FR20FyUgUYRni6J7kVCY=