Tell a rebuild that changes nothing by its artifacts and its manifest (hq ADR 0236)

This commit is contained in:
jochen
2026-10-06 18:56:54 +02:00
parent 37229b4db5
commit 41f7b2c152
2 changed files with 33 additions and 29 deletions
+4 -29
View File
@@ -54,13 +54,13 @@ type busPending struct {
machines []string
from map[string]string
to string
// same are the commits whose build made the same artifacts as the build the mesh holds.
// same are the commits whose build made the same artifacts and manifest as the build the mesh holds.
same map[string]bool
}
// moves is whether sending the machine would replace its bus: a build it was not last sent, unless the
// two builds made the same artifacts — a rebuild of the same source for another module's merge changes
// nothing the machine runs.
// two builds made the same artifacts from the same manifest — a rebuild of the same source for another
// module's merge changes nothing the machine runs.
func (b busPending) moves(machine string) bool {
from, known := b.from[machine]
if b.module == "" || b.to == "" || (known && sameCommit(from, b.to)) {
@@ -93,7 +93,7 @@ func pendingBus(ctx context.Context, inv *inventory.Inventory) (busPending, erro
return b, err
}
b.from, b.same = map[string]string{}, map[string]bool{}
made, err := madeBy(ctx, inv, b.module)
made, err := inv.BuildFingerprints(ctx, b.module)
if err != nil {
return b, err
}
@@ -397,28 +397,3 @@ func withBusStep(ctx context.Context) context.Context {
}
func busStepSending(ctx context.Context) bool { on, _ := ctx.Value(busStepKey{}).(bool); return on }
// madeBy is, per commit, the artifacts the newest worked build of a module from it made, as one sorted
// string: what tells a rebuild that changes nothing from one that does.
func madeBy(ctx context.Context, inv *inventory.Inventory, module string) (map[string]string, error) {
builds, err := inv.Builds(ctx, module, 50)
if err != nil {
return nil, err
}
out := map[string]string{}
for _, b := range builds {
if !b.Worked() || b.Commit == "" {
continue
}
if _, seen := out[b.Commit]; seen {
continue
}
var refs []string
for _, a := range b.Made {
refs = append(refs, a.Name+"="+a.Reference)
}
sort.Strings(refs)
out[b.Commit] = strings.Join(refs, " ")
}
return out, nil
}
+29
View File
@@ -2,6 +2,8 @@ package inventory
import (
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
@@ -216,3 +218,30 @@ func (i *Inventory) RestoreModule(ctx context.Context, b Build) error {
}
return nil
}
// BuildFingerprints is, per commit, what the newest successful build of a module from it would put on a
// machine — its artifacts and its manifest, hashed — so a rebuild that changes nothing there is told
// from one that does (the bus's planned step, ADR 0236).
func (i *Inventory) BuildFingerprints(ctx context.Context, module string) (map[string]string, error) {
rows, err := i.store.Pool().Query(ctx,
`select commit_hash, made, coalesce(manifest::text, '') from build
where module = $1 and failed = '' and commit_hash <> '' order by at desc limit 50`, module)
if err != nil {
return nil, err
}
defer rows.Close()
out := map[string]string{}
for rows.Next() {
var commit, manifest string
var made []byte
if err := rows.Scan(&commit, &made, &manifest); err != nil {
return nil, err
}
if _, seen := out[commit]; seen {
continue
}
sum := sha256.Sum256(append(append(made, 0), []byte(manifest)...))
out[commit] = hex.EncodeToString(sum[:])
}
return out, rows.Err()
}