Answer plans what-if as data, the document delivery-plan answers (issue 1324)

The gate reads a delivery's plan as data once delivery-plan goes (ADR 0450 §2). The data form is an explicit
switch, `data: true`, as plans wait asks for its data: a person still gets the text. Both verbs build their
document from one function, deliveryPlanDocument, so they cannot differ; delivery-plan is unchanged (ADR 0450 §8).
This commit is contained in:
2026-10-19 21:40:26 +00:00
parent caa3fc8995
commit 23a209f3d0
5 changed files with 209 additions and 14 deletions
+24 -10
View File
@@ -784,6 +784,27 @@ func reachOfMembers(members []orderMember, entries []inventory.Entry, read map[s
return out
}
// changeMember is one change as the planner is asked about it, the same for `delivery plan` and `plans --what-if`.
func changeMember(repository, base, head string, paths, removed []string, moduleDirs *[]string) orderMember {
m := orderMember{ID: repository + "@" + head, Repository: repository, Base: base, Head: head,
Paths: paths, Removed: removed}
if moduleDirs != nil {
m.ModuleDirs, m.ModuleDirsSaid = *moduleDirs, true
}
return m
}
// deliveryPlanDocument is the answer of `delivery plan` and of `plans --what-if … --data`: one change's
// change plan with its reach, the mesh's own part in it and whether the gate would run. One function, so
// the two verbs cannot differ (novox/hq ADR 0450 §2, issue 1324).
func deliveryPlanDocument(m orderMember, entries []inventory.Entry, read map[string][]inventory.ReadRepository,
edges []inventory.Edge, policy policyOf) map[string]any {
s := pullScope(m.pull(), entries, read, edges)
plan := changePlanOf(m.Repository, m.Base, m.Head, s.Reach, entries, policy)
return map[string]any{"plan": plan, "reach": orderReach{Moved: s.Modules, Dependents: s.Dependents,
New: s.New, Manifests: s.Manifests}, "mesh": s.Mesh, "gated": s.gated()}
}
// deliveryCommand is `delivery`, the controller's verbs for the delivery's owner:
//
// delivery plan --repository owner/repo --head <commit> [--base main] --paths a,b [--module-dirs …] [--removed …]
@@ -855,22 +876,15 @@ func deliveryCommand(ctx context.Context, args []string) error {
if *repository == "" || *head == "" && *paths == "" {
return errors.New("delivery plan --repository owner/repo --head <commit> --paths a,b")
}
m := orderMember{ID: *repository + "@" + *head, Repository: *repository, Base: *base, Head: *head,
Paths: splitList(*paths), Removed: splitList(*removed)}
if d := moduleDirsOf(*moduleDirs); d != nil {
m.ModuleDirs, m.ModuleDirsSaid = *d, true
}
m := changeMember(*repository, *base, *head, splitList(*paths), splitList(*removed), moduleDirsOf(*moduleDirs))
entries, read, edges, err := theGraph(ctx, inv)
if err != nil {
return err
}
s := pullScope(m.pull(), entries, read, edges)
plan := changePlanOf(*repository, *base, *head, s.Reach, entries, func(module string) (inventory.Upgrade, bool) {
return answer(deliveryPlanDocument(m, entries, read, edges, func(module string) (inventory.Upgrade, bool) {
u, err := inv.UpgradeOf(ctx, module)
return u, err == nil
})
return answer(map[string]any{"plan": plan, "reach": orderReach{Moved: s.Modules, Dependents: s.Dependents,
New: s.New, Manifests: s.Manifests}, "mesh": s.Mesh, "gated": s.gated()})
}))
case "order":
if len(members) == 0 {
return errors.New("delivery order --members <json>: a group has members")