Files
mesh-delivery/modules/mesh-delivery-checker/internal/check/series.go
T
jschoubben 890b8f36e9 DLV-C4: the checker names each change of a package series a pull request makes in its status line
Design 32 (A package, its series): the review of a change sees every series it raises. For each module a
pull request touches, every artifact its trunk manifest and its head's manifest both declare whose series
differs is named as "<module>/<artifact> series <trunk> → <head>" in the pull request's mesh/check line,
never dropped when the line is cut; a manifest that cannot be read is said in the same place. Rows in
TestTheIndexersJudgeJudgesTheChangesManifests (raised: named; kept: not named); the raised row failed
first. gofmt of the integration test's imports (M2).

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
2026-11-04 14:28:18 +01:00

108 lines
3.2 KiB
Go

package check
import (
"context"
"fmt"
"slices"
"strings"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
// A change of a package series is named in the verdict, so the review of the change sees it (design 32 *A package, its
// series*; DLV-C4): for each module a pull request touches, every artifact both its trunk manifest and its head's
// manifest declare whose series differs, as `<module>/<artifact> series <trunk> → <head>`. An artifact that names none
// is in catalogue.DefaultSeries. A manifest that cannot be read is said in the same words, never left out.
// seriesChanges names, on the case per pull request, each change of an artifact's series the pull request makes.
func (st *state) seriesChanges(ctx context.Context) {
if st.j.Read == nil {
return
}
var trunk map[string]string
if st.j.Manifests != nil {
trunk = st.j.Manifests.ManifestDigests()
}
for _, p := range st.c.Pulls {
var words []string
for _, module := range p.Modules {
if trunk[module] == "" {
continue // new on this pull request: no series is changed
}
was, err := st.j.Read.Manifest(ctx, trunk[module])
if err != nil {
words = append(words, fmt.Sprintf("%s: the trunk's series not read (%v)", module, err))
continue
}
var now catalogue.Manifest
switch digest := p.Fps[module].Manifest; {
case digest == trunk[module]:
continue
case digest != "":
if now, err = st.j.Read.Manifest(ctx, digest); err != nil {
words = append(words, fmt.Sprintf("%s: the head's series not read (%v)", module, err))
continue
}
case st.j.Forge != nil:
var found bool
if now, _, found, err = st.manifestAtHead(ctx, p, module); err != nil {
words = append(words, fmt.Sprintf("%s: the head's series not read (%v)", module, err))
continue
} else if !found {
continue
}
default:
continue
}
words = append(words, seriesMoved(module, was, now)...)
}
if len(words) > 0 {
st.c.series(pullKey(p), words)
}
}
}
// seriesMoved are the artifacts of module whose series the head's manifest changes from the trunk's.
func seriesMoved(module string, was, now catalogue.Manifest) []string {
if was.Build == nil || now.Build == nil {
return nil
}
before := map[string]string{}
for _, a := range was.Build.Artifacts {
before[a.Name] = a.SeriesOf()
}
var out []string
for _, a := range now.Build.Artifacts {
if old, ok := before[a.Name]; ok && old != a.SeriesOf() {
out = append(out, fmt.Sprintf("%s/%s series %s → %s", module, a.Name, old, a.SeriesOf()))
}
}
slices.Sort(out)
return out
}
// series keeps, of a pull request (pullKey), the words of the series changes it makes.
func (c *Case) series(key string, words []string) {
c.notesMu.Lock()
defer c.notesMu.Unlock()
if c.seriesOf == nil {
c.seriesOf = map[string][]string{}
}
c.seriesOf[key] = words
}
// Series are the series changes a pull request (pullKey) makes, as the check named them; none when it makes none.
func (c *Case) Series(key string) []string {
c.notesMu.Lock()
defer c.notesMu.Unlock()
return slices.Clone(c.seriesOf[key])
}
// seriesWords is a pull request's series changes for its status line.
func seriesWords(c *Case, p Pull) string {
if c == nil {
return ""
}
return strings.Join(c.Series(pullKey(p)), ", ")
}