A module names the module its build stands on, not a copy of it

A fingerprint written into a recipe names one particular copy of the base — the
copy on whichever machine the person typing it was using. On any other mesh that
copy has never existed, so the build stops on its first line with a message
about an image nobody can look up. Three modules in the catalogue were in
exactly that state, and the line each of them replaced was equally dead.

A module now names the module and artifact instead, and the mesh answers with
what it holds. The builder is still a thing that clones, builds and answers: the
answer travels with the question, because only the mesh knows what it has.

A base the mesh has not built is refused before anything is built, naming which
module has to exist first.
This commit is contained in:
2026-09-13 23:53:22 +02:00
parent cb5108a864
commit cfe2816495
9 changed files with 269 additions and 16 deletions
+44
View File
@@ -100,3 +100,47 @@ func (i *Inventory) Builds(ctx context.Context, module string, limit int) ([]Bui
}
return out, rows.Err()
}
// Held is every artifact this mesh has built, keyed "<module>/<artifact>".
//
// **The newest successful build of each module wins**, which is the same rule the rest of the mesh
// uses for what a module currently is. A module rebuilt to something broken and then rebuilt again
// is at the second one; a module whose last build failed is at the last one that worked, because a
// failure published nothing and the thing it published before is still what exists.
//
// Only successes, and only builds that knew what they were building: a build that failed before it
// could read a manifest has no module to be the artifact of.
func (i *Inventory) Held(ctx context.Context) (map[string]string, error) {
rows, err := i.store.Pool().Query(ctx,
`select distinct on (module) module, made
from build
where module is not null and module <> '' and failed = ''
order by module, at desc`)
if err != nil {
return nil, err
}
defer rows.Close()
held := map[string]string{}
for rows.Next() {
var module string
var raw []byte
if err := rows.Scan(&module, &raw); err != nil {
return nil, err
}
var made []Artifact
if err := json.Unmarshal(raw, &made); err != nil {
// Skipped rather than fatal. One unreadable build record should not stop every other
// module's base from being answerable — and the build that needs this one will say
// plainly that it is missing.
continue
}
for _, artifact := range made {
if artifact.Name == "" || artifact.Reference == "" {
continue
}
held[module+"/"+artifact.Name] = artifact.Reference
}
}
return held, rows.Err()
}