Files
mesh-delivery/modules/mesh-delivery-checker/internal/check/preview.go
T

87 lines
2.8 KiB
Go

package check
import (
"context"
"errors"
"fmt"
"regexp"
"slices"
"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. A head that does not merge has a preview of the files in conflict
// alone, so the indexer says the candidate's modules have no fingerprint because it does not merge (issue 1445). It
// answers false when no fetch was made.
func PreviewOf(p Pull, fetched []Fetched) (delivery.Preview, bool) {
var merge string
var conflicts []string
mods := map[string]delivery.PreviewModule{}
for _, f := range fetched {
if len(f.Conflicts) > 0 {
conflicts = append(conflicts, f.Conflicts...)
}
}
if len(conflicts) > 0 {
slices.Sort(conflicts)
return delivery.Preview{Repository: p.Repository, Head: p.Head, Trunk: p.Trunk, Conflicts: slices.Compact(conflicts)}, true
}
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.Announce != nil {
j.Announce(ctx, EventPreviewWritten, key)
}
}
}
if err != nil {
j.logf("%s#%d: the preview cannot be written: %v", p.Repository, p.Number, fmt.Errorf("%w", err))
}
}