Write the merge preview of each head the checker fetched, for the indexer's fingerprints (issue 1680)
This commit is contained in:
@@ -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))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user