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:
@@ -61,12 +61,43 @@ type mergeCheckInput struct {
|
||||
repository, tree string
|
||||
// changed are the paths the change touches, for the width of its rebuild.
|
||||
changed []string
|
||||
// group are the other heads of a delivery group composed with this one (novox/hq ADR 0239), each laid
|
||||
// over the mesh after the one before: the group judged as one future state.
|
||||
group []groupChange
|
||||
// admin is a PostgreSQL the gate may create and drop databases in.
|
||||
admin string
|
||||
// say is where progress goes; the verdict is returned.
|
||||
say io.Writer
|
||||
}
|
||||
|
||||
// groupChange is one other head of a delivery group: its repository, its checkout and what it changes.
|
||||
type groupChange struct {
|
||||
Repository string `json:"repository"`
|
||||
Tree string `json:"tree"`
|
||||
Changed []string `json:"changed,omitempty"`
|
||||
}
|
||||
|
||||
// readGroup reads the other heads of a group's composed check from the file the build seat wrote.
|
||||
func readGroup(path string) ([]groupChange, error) {
|
||||
if path == "" {
|
||||
return nil, nil
|
||||
}
|
||||
raw, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var g []groupChange
|
||||
if err := json.Unmarshal(raw, &g); err != nil {
|
||||
return nil, fmt.Errorf("the group's heads are not readable: %w", err)
|
||||
}
|
||||
for _, c := range g {
|
||||
if c.Repository == "" || c.Tree == "" {
|
||||
return nil, errors.New("a head of the group names no repository or no checkout")
|
||||
}
|
||||
}
|
||||
return g, nil
|
||||
}
|
||||
|
||||
// mergeVerdict is what the gate found.
|
||||
type mergeVerdict struct {
|
||||
Verdict string `json:"verdict"` // pass, warning or fail
|
||||
@@ -129,6 +160,8 @@ func mergeGateCommand(ctx context.Context, args []string) error {
|
||||
repository := set.String("repository", "", "owner/repository of the change")
|
||||
tree := set.String("tree", "", "the change's checkout: every module.json in it replaces the mesh's")
|
||||
changed := set.String("changed", "", "the paths the change touches, comma-separated, for its rebuild's width")
|
||||
group := set.String("group", "", "a delivery group's other heads, as JSON [{repository, tree, changed}], composed "+
|
||||
"with this one as one future state (novox/hq ADR 0239)")
|
||||
asJSON := set.Bool("json", false, "print the verdict as JSON")
|
||||
if _, err := parseAround(set, args); err != nil {
|
||||
return err
|
||||
@@ -144,12 +177,16 @@ func mergeGateCommand(ctx context.Context, args []string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
others, err := readGroup(*group)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out := io.Writer(os.Stdout)
|
||||
if *asJSON {
|
||||
out = os.Stderr
|
||||
}
|
||||
v, err := judgeChange(ctx, mergeCheckInput{facts: f, repository: *repository, tree: *tree, changed: splitList(*changed),
|
||||
admin: *admin, say: out})
|
||||
group: others, admin: *admin, say: out})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -212,24 +249,37 @@ func judgeChange(ctx context.Context, in mergeCheckInput) (mergeVerdict, error)
|
||||
// which may differ from what the mesh holds for reasons that are not this change's (a module pinned
|
||||
// at an older commit, a main the mesh has not built yet).
|
||||
var reach *mergeReach
|
||||
if in.repository != "" && len(in.changed) > 0 {
|
||||
r, err := reachOfChange(in.facts, in.repository, in.changed, in.tree)
|
||||
if err != nil {
|
||||
v.Notes = append(v.Notes, "what a merge of the change would rebuild could not be worked out, so every "+
|
||||
"definition in its tree is judged: "+err.Error())
|
||||
} else {
|
||||
reach = &r
|
||||
// The change, then each other head of its delivery group laid over it in turn (novox/hq ADR 0239): one
|
||||
// future state of the mesh, judged as the group would leave it.
|
||||
heads := append([]groupChange{{Repository: in.repository, Tree: in.tree, Changed: in.changed}}, in.group...)
|
||||
for i, h := range heads {
|
||||
var r *mergeReach
|
||||
if h.Repository != "" && len(h.Changed) > 0 {
|
||||
got, err := reachOfChange(in.facts, h.Repository, h.Changed, h.Tree)
|
||||
if err != nil {
|
||||
v.Notes = append(v.Notes, "what a merge of "+h.Repository+" would rebuild could not be worked out, so "+
|
||||
"every definition in its tree is judged: "+err.Error())
|
||||
} else {
|
||||
r = &got
|
||||
}
|
||||
}
|
||||
if i == 0 {
|
||||
reach = r
|
||||
}
|
||||
if h.Tree == "" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if in.tree != "" {
|
||||
var failures []string
|
||||
change, failures, err = shelfWithChange(base, sources, in.facts, in.repository, in.tree, v.Modules,
|
||||
scopeOfReach(reach, in.repository))
|
||||
change, failures, err = shelfWithChange(change, sources, in.facts, h.Repository, h.Tree, v.Modules,
|
||||
scopeOfReach(r, h.Repository))
|
||||
if err != nil {
|
||||
return v, err
|
||||
}
|
||||
v.Failures = append(v.Failures, failures...)
|
||||
}
|
||||
if len(in.group) > 0 {
|
||||
say("a delivery group: %d head(s) composed together", len(heads))
|
||||
}
|
||||
say("judging %d module(s) changed against %d machine(s), as the snapshot of %s says they run",
|
||||
len(v.Modules), len(in.facts.Machines), in.facts.Taken.Format(time.RFC3339))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user