Write the merge preview of each head the checker fetched, for the indexer's fingerprints (issue 1680)

This commit is contained in:
2026-10-21 21:12:48 +02:00
parent cfbd5b6d2d
commit e175343837
3 changed files with 123 additions and 0 deletions
@@ -454,3 +454,53 @@ func TestAGroupIsOneVerdictAndEachMembersTestsReadTheOthersAtTheirHeads(t *testi
func TestAnExaminerIsAJudgeOfTheChecker(t *testing.T) {
var _ Judge = (*Examiner)(nil)
}
const (
manA = "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a"
)
func TestACleanMergeWritesItsPreviewWithTheTreesManifestsAndLocks(t *testing.T) { // 1445/AC1
b := newBench(t)
b.fetch.Trees = map[string]MergeTree{
"modules/avahi": {Tree: "7777777777777777777777777777777777777777", Manifest: manA, Locks: map[string]string{"go.sum": "ff00"}},
"modules/bare": {Tree: "8888888888888888888888888888888888888888"}, // no manifest digest: left out
}
b.judge(t, caseOf(t, pullOf(repoA, 7, head1)))
key, _ := delivery.PreviewKey(repoA, head1, trunkA)
raw, _, found, _ := b.prev.Get(context.Background(), key)
if !found {
t.Fatalf("no preview %s; the bucket holds %v", key, b.prev.vals)
}
pv, err := delivery.DecodePreview(raw)
if err != nil {
t.Fatal(err)
}
m := pv.Modules["modules/avahi"]
if pv.Merge != b.fetch.Merge || pv.Trunk != trunkA || pv.Head != head1 || len(pv.Modules) != 1 || m.Tree != "7777777777777777777777777777777777777777" || m.Manifest != manA || m.Locks["go.sum"] != "ff00" {
t.Errorf("preview = %+v", pv)
}
}
func TestAHeadThatDoesNotMergeWritesNoPreview(t *testing.T) { // 1445/AC5
b := newBench(t)
b.fetch = Fetched{Workspace: "ws1", Commit: head1, Base: trunkA, Conflicts: []string{"go.mod"}}
b.judge(t, caseOf(t, pullOf(repoA, 7, head1)))
if len(b.prev.vals) != 0 {
t.Errorf("previews %v written for a head that does not merge", b.prev.vals)
}
}
func TestAPreviewIsWrittenOnceAndAnExistingKeyStands(t *testing.T) {
b := newBench(t)
b.judge(t, caseOf(t, pullOf(repoA, 7, head1)))
b.fetch.Merge = "5656565656565656565656565656565656565656"
b.judge(t, caseOf(t, pullOf(repoA, 7, head1)))
key, _ := delivery.PreviewKey(repoA, head1, trunkA)
if b.prev.creates[key] != 1 {
t.Errorf("the preview was created %d times, want once", b.prev.creates[key])
}
raw, _, _, _ := b.prev.Get(context.Background(), key)
if pv, _ := delivery.DecodePreview(raw); pv.Merge == b.fetch.Merge {
t.Error("the second merge commit replaced the first")
}
}
@@ -202,6 +202,7 @@ func (st *state) fetchAll(ctx context.Context) *delivery.Verdict {
began := st.j.now()
defer func() { st.clone = st.j.now().Sub(began) }()
for _, p := range st.c.Pulls {
var merged []Fetched
for _, bm := range st.j.Modules.BuildModules(p.Repository) {
node, tc, err := st.choose(bm)
if err != nil {
@@ -226,8 +227,10 @@ func (st *state) fetchAll(ctx context.Context) *delivery.Verdict {
return fail(node, fmt.Sprintf("%s#%d does not merge into the trunk: files in conflict: %s", p.Repository, p.Number, strings.Join(t.fetched.Conflicts, ", ")))
}
t.changed = t.fetched.Changed
merged = append(merged, t.fetched)
st.targets = append(st.targets, t)
}
st.j.writePreview(ctx, p, merged)
}
return nil
}
@@ -0,0 +1,70 @@
package check
import (
"context"
"errors"
"fmt"
"regexp"
"git.novox.be/novox/mesh-sdk/go/delivery"
)
var digest64 = regexp.MustCompile(`^[0-9a-f]{64}$`)
// PreviewOf is what the fetch steps said of a pull request's head merged onto its trunk head, as the value of a previews
// key (ADR 0484 clause 3): the merge commit and, for each module directory the fetches named with a manifest, its tree, the
// digest of its manifest and the hashes of its lock files. The fetches of the repository's build modules merge the same
// trees; the first one's merge commit is kept. A module directory with no tree or no manifest digest is left out, so the
// indexer gives its module no fingerprint and says why. It answers false when no fetch merged.
func PreviewOf(p Pull, fetched []Fetched) (delivery.Preview, bool) {
var merge string
mods := map[string]delivery.PreviewModule{}
for _, f := range fetched {
if f.Merge == "" {
continue
}
if merge == "" {
merge = f.Merge
}
for dir, t := range f.Trees {
if t.Tree == "" || !digest64.MatchString(t.Manifest) {
continue
}
mods[dir] = delivery.PreviewModule{Tree: t.Tree, Manifest: t.Manifest, Locks: t.Locks}
}
}
if merge == "" {
return delivery.Preview{}, false
}
pv := delivery.Preview{Repository: p.Repository, Head: p.Head, Trunk: p.Trunk, Merge: merge}
if len(mods) > 0 {
pv.Modules = mods
}
return pv, true
}
// writePreview writes the preview of a pull request by a create: one writer per key, and the same head on the same trunk
// head merges to the same trees, so a key that exists stands. A head that did not merge has no preview. A failure is said
// and does not fail the check: the preview is for the indexer's fingerprints, not for the verdict.
func (j *Examiner) writePreview(ctx context.Context, p Pull, fetched []Fetched) {
if j.Previews == nil {
return
}
pv, ok := PreviewOf(p, fetched)
if !ok {
return
}
key, err := delivery.PreviewKey(p.Repository, p.Head, p.Trunk)
if err == nil {
var data []byte
if data, err = delivery.EncodePreview(pv); err == nil {
_, err = j.Previews.Create(ctx, key, data)
if errors.Is(err, ErrConflict) {
return
}
}
}
if err != nil {
j.logf("%s#%d: the preview cannot be written: %v", p.Repository, p.Number, fmt.Errorf("%w", err))
}
}