A merge rebuilds what it changed, and what packages it
Three faults in one path. A merge rebuilt every module built from the repository, so one change in a repository holding twenty-six of them meant twenty-six builds. A merge into a repository a module only *packages* source from rebuilt nothing — two modules are built from the control plane's own repository and neither had ever been rebuilt when it moved — because the manifest the mesh keeps carries no build section, so a build now says which repositories it read and the mesh keeps that beside what it stood on. And a module handed over by hand could record a repository with no directory inside it, which is a module nothing can ever rebuild (novox/hq 04-ISSUES/131, /132). A change inside no module's own directory is a change to what they share, and everything built from that repository is rebuilt: rebuilding too much is the safe direction, because the fault this whole path exists for is a mesh that believes it is current and is not.
This commit is contained in:
@@ -69,12 +69,20 @@ func moduleCommand(ctx context.Context, args []string) error {
|
||||
repo := set.String("source", "", "where this module comes from")
|
||||
ref := set.String("ref", "", "the branch followed there")
|
||||
commit := set.String("commit", "", "the commit this manifest was read at")
|
||||
// **Where inside the repository the module is** (novox/hq ADR 0069). A module is a
|
||||
// repository *and* a directory, and a record that carries only the repository names a
|
||||
// module.json at its root — so every later build of it looks in the wrong place and fails
|
||||
// with "no module.json at its root". Nine modules on this mesh were registered that way
|
||||
// and none of them could be rebuilt (2026-09-28).
|
||||
path := set.String("path", "", "the module's directory inside that repository")
|
||||
self := set.Bool("self", false, "the source is a path on the forge holding the git seat")
|
||||
positionals, err := parseAround(set, args[1:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(positionals) != 1 {
|
||||
return errors.New("module add <manifest.json> [--source <repo> --ref <branch> --commit <sha>]")
|
||||
return errors.New("module add <manifest.json> [--source <repo> [--self] [--path P] " +
|
||||
"--ref <branch> --commit <sha>]")
|
||||
}
|
||||
raw, err := os.ReadFile(positionals[0])
|
||||
if err != nil {
|
||||
@@ -84,23 +92,24 @@ func moduleCommand(ctx context.Context, args []string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Provenance together or not at all. A source with no commit cannot be compared against
|
||||
// anything, so it would record where the module came from and still never be able to say
|
||||
// the mesh is behind it — which is the one thing recording it is for.
|
||||
if (*repo == "") != (*commit == "") {
|
||||
return errors.New("--source and --commit go together: a source with no commit " +
|
||||
"cannot be compared against anything, and a commit with no source has nothing " +
|
||||
"to be compared with")
|
||||
from, err := whereItComesFrom(*repo, *ref, *commit, *path, *self)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := inv.RegisterModule(ctx, m, inventory.Source{
|
||||
Repository: *repo, Ref: *ref, BuiltFrom: *commit,
|
||||
}); err != nil {
|
||||
if err := inv.RegisterModule(ctx, m, from); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("%s registered", m.Module)
|
||||
if *commit != "" {
|
||||
fmt.Printf(" from %s", short(*commit))
|
||||
}
|
||||
if *repo != "" && *path == "" {
|
||||
// Said, not refused: a module really at the root is the ordinary case for a repository
|
||||
// of its own. But a repository holding many modules and a record naming none of them is
|
||||
// a module nothing can rebuild, and the person adding it is the one who knows which.
|
||||
fmt.Printf("\n no directory inside %s, so it is built from that repository's root — "+
|
||||
"`--path` if the module lives in a directory there", *repo)
|
||||
}
|
||||
if len(m.Provides) > 0 {
|
||||
fmt.Printf(", providing %s", describeOffers(m.Provides))
|
||||
}
|
||||
@@ -602,3 +611,37 @@ func issueWith(ctx context.Context, inv *inventory.Inventory, m catalogue.Manife
|
||||
"machine holding mesh-broker\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
// whereItComesFrom is the provenance a module handed over by hand records, and what a record must
|
||||
// say to be worth anything later.
|
||||
//
|
||||
// **A module is a repository and a directory inside it** (novox/hq ADR 0069). A record carrying only
|
||||
// the repository names a module.json at its root, so every later build of it looks in the wrong
|
||||
// place — nine modules on this mesh were registered that way and none of them could be rebuilt
|
||||
// (2026-09-28). The directory cannot be checked from here, because the control plane does not clone;
|
||||
// what can be checked is that the record is whole.
|
||||
func whereItComesFrom(repository, ref, commit, path string, self bool) (inventory.Source, error) {
|
||||
// Provenance together or not at all. A source with no commit cannot be compared against
|
||||
// anything, so it would record where the module came from and still never be able to say the
|
||||
// mesh is behind it — which is the one thing recording it is for.
|
||||
if (repository == "") != (commit == "") {
|
||||
return inventory.Source{}, errors.New("--source and --commit go together: a source with " +
|
||||
"no commit cannot be compared against anything, and a commit with no source has " +
|
||||
"nothing to be compared with")
|
||||
}
|
||||
// A directory or a forge with no repository is half a location, and the half it keeps is the
|
||||
// half nothing can be found with.
|
||||
if repository == "" && (path != "" || self) {
|
||||
return inventory.Source{}, errors.New("--path and --self say where inside a source and " +
|
||||
"which forge holds it, so they need --source: without one there is nothing for them " +
|
||||
"to be part of")
|
||||
}
|
||||
from := inventory.Source{Repository: repository, Ref: ref, BuiltFrom: commit, Path: path}
|
||||
if self {
|
||||
if err := onASeat(repository); err != nil {
|
||||
return inventory.Source{}, err
|
||||
}
|
||||
from.Seat = gitSeat
|
||||
}
|
||||
return from, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user