Let a walk wait for its delivery's word, and serve the delivery's owner (hq ADR 0239)
While the mesh-delivery seat has a holder on record, a merge that moves no core module opens its walk and asks nothing until mesh-delivery or a person says go; nothing of it is registered before its turn, so no other send carries it. The controller keeps the planner, the gate, sending and the walk, and gains the verbs the owner asks with: delivery-plan, -order, -check (a group composed as one future state), deliver, delivery-stop, delivery-walks; every walk kept is said as plan-moved.
This commit is contained in:
@@ -81,6 +81,19 @@ type CheckSpec struct {
|
||||
// Toolchains is every toolchain the mesh holds, by language, for a script that declares another.
|
||||
Toolchain string
|
||||
Toolchains map[string]string
|
||||
// Group are a delivery group's other heads (novox/hq ADR 0239), each cloned beside this one at its head
|
||||
// and composed with it by the gate as one future state. The repository's own check is not run for a
|
||||
// group: each member's pull request runs its own.
|
||||
Group []GroupHead
|
||||
}
|
||||
|
||||
// GroupHead is one other head of a delivery group's composed check.
|
||||
type GroupHead struct {
|
||||
Owner string
|
||||
Repo string
|
||||
Repository string
|
||||
Ref string
|
||||
Paths []string
|
||||
}
|
||||
|
||||
// Gated is whether the change touches the mesh's graph, and so whether the gate runs.
|
||||
@@ -141,6 +154,9 @@ const (
|
||||
EnvVerdict = "MESH_CHECK_VERDICT"
|
||||
EnvBeside = "MESH_CHECK_BESIDE"
|
||||
EnvModules = "MESH_CHECK_MODULES"
|
||||
// EnvGroup is a delivery group's other heads, as JSON, for the gate (novox/hq ADR 0239); empty for a
|
||||
// pull request checked alone.
|
||||
EnvGroup = "MESH_CHECK_GROUP"
|
||||
)
|
||||
|
||||
// CheckTimeout bounds one check; a check that runs past it is an error, not a pass.
|
||||
@@ -234,6 +250,32 @@ func Check(ctx context.Context, run Runner, spec CheckSpec, workspace, registry
|
||||
say("check", "beside it %s at %s", dir, short(b.Ref))
|
||||
}
|
||||
|
||||
// A delivery group's other heads (novox/hq ADR 0239), each at its head, for the gate to compose with this.
|
||||
groupFile := ""
|
||||
if len(spec.Group) > 0 {
|
||||
var heads []map[string]any
|
||||
for i, g := range spec.Group {
|
||||
dir := fmt.Sprintf("group-%d", i)
|
||||
if g.Repo != "" && safeName.MatchString(g.Repo) {
|
||||
dir = "group-" + g.Repo
|
||||
}
|
||||
if err := clone(g.Repository, g.Ref, dir); err != nil {
|
||||
return CheckVerdict{}, fmt.Errorf("a head of the group, %w", err)
|
||||
}
|
||||
say("check", "with it, of its group, %s/%s at %s", g.Owner, g.Repo, short(g.Ref))
|
||||
heads = append(heads, map[string]any{"repository": g.Owner + "/" + g.Repo,
|
||||
"tree": filepath.Join(root, dir), "changed": g.Paths})
|
||||
}
|
||||
raw, err := json.Marshal(heads)
|
||||
if err != nil {
|
||||
return CheckVerdict{}, err
|
||||
}
|
||||
groupFile = filepath.Join(root, "group.json")
|
||||
if err := os.WriteFile(groupFile, raw, 0o644); err != nil {
|
||||
return CheckVerdict{}, err
|
||||
}
|
||||
}
|
||||
|
||||
// The facts, and the versions they say the mesh runs.
|
||||
if registry == "" {
|
||||
return CheckVerdict{}, errors.New("no artifact store to read the facts snapshot from")
|
||||
@@ -316,6 +358,7 @@ func Check(ctx context.Context, run Runner, spec CheckSpec, workspace, registry
|
||||
EnvTestStore + "=" + storeURL, EnvTestBus + "=nats://" + bus, EnvRepository + "=" + spec.Owner + "/" + spec.Repo,
|
||||
EnvChanged + "=" + strings.Join(spec.Paths, ","), EnvBeside + "=" + root,
|
||||
EnvModules + "=" + strings.Join(append(append([]string{}, spec.Modules...), spec.New...), ","),
|
||||
EnvGroup + "=" + groupFile,
|
||||
"GOCACHE=" + filepath.Join(workspace, "go-cache"), "GOMODCACHE=" + filepath.Join(workspace, "go-modules")}
|
||||
|
||||
v := CheckVerdict{}
|
||||
@@ -346,6 +389,10 @@ func Check(ctx context.Context, run Runner, spec CheckSpec, workspace, registry
|
||||
|
||||
// **The repository's own check**, in the toolchain it declares.
|
||||
switch {
|
||||
case len(spec.Group) > 0:
|
||||
// A group's composed check judges the heads together; each member's own tests are its pull request's.
|
||||
v.Repo = &Layer{Verdict: "pass", Summary: "a group's composed check: each member's own " + CheckScript +
|
||||
" runs on its pull request"}
|
||||
case !hasScript:
|
||||
v.Repo = &Layer{Verdict: "warning", Summary: noScript}
|
||||
case timedOut():
|
||||
@@ -447,7 +494,8 @@ func gateLayer(ctx context.Context, spec CheckSpec, tree, root, gate, verdictFil
|
||||
// 2. Every machine composed with the change.
|
||||
if err := running(inToolchain(tree, append(env, EnvVerdict+"="+verdictFile), "sh", "-c",
|
||||
`"$MESH_GATE" merge-gate --facts "$MESH_FACTS" --store "$MESH_GATE_POSTGRES" `+
|
||||
`--repository "$MESH_CHECK_REPOSITORY" --tree . --changed "$MESH_CHECK_CHANGED" --json > "$MESH_CHECK_VERDICT"`)); err != nil {
|
||||
`--repository "$MESH_CHECK_REPOSITORY" --tree . --changed "$MESH_CHECK_CHANGED" `+
|
||||
`${MESH_CHECK_GROUP:+--group "$MESH_CHECK_GROUP"} --json > "$MESH_CHECK_VERDICT"`)); err != nil {
|
||||
if ctx.Err() != nil {
|
||||
return "error", "the check was ended during the merge gate"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user