Files
mesh-catalog/modules/mesh-delivery-gate/cmd/mesh-delivery-gate/checked_shim_test.go
T
jschoubben 5ff337e0dc Gate keeps the merge's six states and asks the controller nothing (issue 1946, R6-C1, C2, C4)
Release 6 deletes the plans: the walk half of the holder, the controller port, the carry-over of the former module and the verbs times, what-if, release, stop and retire-history go; the table holds proposed, ready, rejected, merged, held and closed; the delivery's status and view name the source revision the merge moved.
2026-10-24 16:26:36 +02:00

143 lines
4.4 KiB
Go

package main
import (
"encoding/json"
"strings"
"time"
sdk "git.novox.be/novox/mesh-sdk/go/delivery"
)
// ctxGate and ctxRepo are the two statuses mesh/check replaced: only a base that a revert gives them again requires them
// (unchecked.go mergeChecks), so only tests of that name them.
const (
ctxGate = "mesh/merge-gate"
ctxRepo = "mesh/repo-check"
)
// shimCheckedKey is the key a test hears a verdict under: said as the checker's (see Checked).
const shimCheckedKey = "mesh-controller.checked"
// CheckedEvent is a verdict as these tests state it. The gate follows no verdict of the controller any more (issue 1318,
// ADR 0524 §5): the shim below says it the way the mesh says it now, as the head's mesh/check and the checker's verdict at
// the heads, so the table, the Approve and the merges are exercised on the one path they have.
type CheckedEvent struct {
Owner string
Repo string
Number int
Commit string
Verdict string
Summary string
ID string
On string
Report string
Gate *struct {
Verdict string `json:"verdict"`
Summary string `json:"summary"`
Modules []string `json:"modules,omitempty"`
Dependents []string `json:"dependents,omitempty"`
}
RepoCheck *struct {
Verdict string `json:"verdict"`
Summary string `json:"summary"`
}
Group string
Members []struct {
Owner string `json:"owner"`
Repo string `json:"repo"`
Commit string `json:"commit"`
Trunk string `json:"trunk,omitempty"`
}
Trunk string
Beside map[string]string
Took string
}
// Checked takes a verdict as the checker's: the head's mesh/check, and the checker's verdict at the heads its Approve covers.
func (h *Holder) Checked(c CheckedEvent) {
h.mu.Lock()
defer h.mu.Unlock()
state := map[string]string{"pass": "success", "warning": "warning", "fail": "failure", "error": "error"}[c.Verdict]
if state == "" {
state = "error"
}
if c.Group != "" {
g := h.groups[c.Group]
if g == nil {
return
}
named := map[string]string{}
for _, m := range c.Members {
if m.Trunk != "" {
named[strings.ToLower(m.Owner+"/"+m.Repo)] = m.Trunk
}
}
h.putChecker(h.membersOf(g), c.Verdict, named)
return
}
repository := strings.ToLower(c.Owner + "/" + c.Repo)
id := IDOf(repository, c.Commit)
if h.deliveries[id] == nil && c.Number != 0 {
d := &Delivery{ID: id, Repository: repository, Commit: c.Commit, Number: c.Number, Created: h.Now()}
if t, err := Apply(d, EvAnnounced, false, Facts{Now: h.Now(), Why: "its verdict arrived before its head was heard"}); err == nil {
h.moved(d, []Transition{t})
}
}
d := h.deliveries[id]
if d == nil {
return
}
words := map[string]string{"success": "pass", "warning": "pass", "failure": "failed: " + c.Summary, "error": "error"}[state]
line := words + " " + shortOf(c.Commit, 12)
if c.Trunk != "" {
line += " on " + shortOf(c.Trunk, 12) // a verdict that names no trunk commit is judged against none
}
h.takeCheckStatus(repository, c.Commit, state, line+" | "+c.Summary)
if d := h.deliveries[id]; d != nil && state == "success" && d.Ready != nil && d.Ready.Merged == nil {
h.mergeAgainNow(d) // as the forge's success status event does (CommitStatus)
}
if d := h.deliveries[id]; d != nil && d.Check != nil && c.Beside != nil {
d.Check.Beside, d.Check.Took = c.Beside, c.Took
}
if d := h.deliveries[id]; d != nil {
h.putChecker(h.askMembers(d), c.Verdict, nil)
}
}
// putChecker keeps the checker's verdict at these members' heads, judged on each repository's trunk the members name or, for
// none named, the one the check line named.
func (h *Holder) putChecker(members []*Delivery, verdict string, named map[string]string) {
state := "pass"
switch verdict {
case "pass", "warning":
default:
state = "fail"
}
hash, err := sdk.HeadsHash(headsOf(members))
if err != nil {
return
}
trunks := map[string]string{}
for _, d := range members {
if d.Check != nil && d.Check.Trunk != "" {
trunks[strings.ToLower(d.Repository)] = d.Check.Trunk
}
if d.TrunkNow != "" && trunks[strings.ToLower(d.Repository)] == "" {
trunks[strings.ToLower(d.Repository)] = d.TrunkNow
}
}
for repository, trunk := range named {
trunks[repository] = trunk
}
value, _ := json.Marshal(map[string]any{"v": 1, "group": "g", "heads": hash, "trunk": trunks, "state": state})
if h.checker == nil {
h.checker = map[string]checkerVerdict{}
}
var v checkerVerdict
_ = json.Unmarshal(value, &v)
h.checker[hash] = v
h.Poke()
}
var _ = time.Second