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.
143 lines
4.4 KiB
Go
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
|