@intentius/chant 0.124.40 → 0.124.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (346) hide show
  1. package/dist/__fixtures__/oidc-emulator.d.ts +49 -0
  2. package/dist/__fixtures__/oidc-emulator.d.ts.map +1 -0
  3. package/dist/__fixtures__/oidc-emulator.js +89 -0
  4. package/dist/ci-handover.d.ts +117 -0
  5. package/dist/ci-handover.d.ts.map +1 -0
  6. package/dist/ci-handover.js +217 -0
  7. package/dist/ci-identity.d.ts +190 -0
  8. package/dist/ci-identity.d.ts.map +1 -0
  9. package/dist/ci-identity.js +219 -0
  10. package/dist/cli/handlers/approve.d.ts +2 -1
  11. package/dist/cli/handlers/approve.d.ts.map +1 -1
  12. package/dist/cli/handlers/approve.js +20 -6
  13. package/dist/cli/handlers/build.d.ts.map +1 -1
  14. package/dist/cli/handlers/build.js +18 -1
  15. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  16. package/dist/cli/handlers/fan-out.js +42 -5
  17. package/dist/cli/handlers/gate-resume.d.ts +3 -0
  18. package/dist/cli/handlers/gate-resume.d.ts.map +1 -1
  19. package/dist/cli/handlers/gate-resume.js +15 -2
  20. package/dist/cli/handlers/lock.d.ts +8 -0
  21. package/dist/cli/handlers/lock.d.ts.map +1 -0
  22. package/dist/cli/handlers/lock.js +197 -0
  23. package/dist/cli/handlers/pr-env.d.ts +34 -0
  24. package/dist/cli/handlers/pr-env.d.ts.map +1 -0
  25. package/dist/cli/handlers/pr-env.js +436 -0
  26. package/dist/cli/handlers/pr.d.ts +76 -0
  27. package/dist/cli/handlers/pr.d.ts.map +1 -1
  28. package/dist/cli/handlers/pr.js +615 -55
  29. package/dist/cli/handlers/promote.d.ts.map +1 -1
  30. package/dist/cli/handlers/promote.js +9 -0
  31. package/dist/cli/handlers/query.d.ts +6 -0
  32. package/dist/cli/handlers/query.d.ts.map +1 -0
  33. package/dist/cli/handlers/query.js +80 -0
  34. package/dist/cli/handlers/run.d.ts.map +1 -1
  35. package/dist/cli/handlers/run.js +11 -0
  36. package/dist/cli/main.d.ts.map +1 -1
  37. package/dist/cli/main.js +49 -4
  38. package/dist/cli/parse-args.d.ts.map +1 -1
  39. package/dist/cli/parse-args.js +46 -2
  40. package/dist/cli/registry.d.ts +31 -2
  41. package/dist/cli/registry.d.ts.map +1 -1
  42. package/dist/components/capability.d.ts +47 -0
  43. package/dist/components/capability.d.ts.map +1 -1
  44. package/dist/components/capability.js +44 -0
  45. package/dist/components/cli-support.d.ts +6 -0
  46. package/dist/components/cli-support.d.ts.map +1 -1
  47. package/dist/components/cli-support.js +8 -1
  48. package/dist/components/driver.d.ts +10 -0
  49. package/dist/components/driver.d.ts.map +1 -1
  50. package/dist/components/driver.js +52 -2
  51. package/dist/components/fan-out-run.d.ts +37 -0
  52. package/dist/components/fan-out-run.d.ts.map +1 -1
  53. package/dist/components/fan-out-run.js +44 -4
  54. package/dist/components/gate-plan.d.ts +2 -0
  55. package/dist/components/gate-plan.d.ts.map +1 -1
  56. package/dist/components/gate-plan.js +1 -0
  57. package/dist/components/pr-environment.d.ts +298 -0
  58. package/dist/components/pr-environment.d.ts.map +1 -0
  59. package/dist/components/pr-environment.js +406 -0
  60. package/dist/components/pr-hooks.d.ts +66 -0
  61. package/dist/components/pr-hooks.d.ts.map +1 -0
  62. package/dist/components/pr-hooks.js +119 -0
  63. package/dist/components/pr-pipeline.d.ts +92 -2
  64. package/dist/components/pr-pipeline.d.ts.map +1 -1
  65. package/dist/components/pr-pipeline.js +150 -21
  66. package/dist/components/pr-policy.d.ts +109 -0
  67. package/dist/components/pr-policy.d.ts.map +1 -0
  68. package/dist/components/pr-policy.js +150 -0
  69. package/dist/components/pr-run.d.ts +6 -0
  70. package/dist/components/pr-run.d.ts.map +1 -1
  71. package/dist/components/pr-run.js +8 -3
  72. package/dist/components/wave-plan.d.ts +14 -1
  73. package/dist/components/wave-plan.d.ts.map +1 -1
  74. package/dist/components/wave-plan.js +34 -2
  75. package/dist/gate-decision.d.ts +15 -2
  76. package/dist/gate-decision.d.ts.map +1 -1
  77. package/dist/gate-decision.js +17 -2
  78. package/dist/gate-policy.d.ts +140 -0
  79. package/dist/gate-policy.d.ts.map +1 -0
  80. package/dist/gate-policy.js +242 -0
  81. package/dist/lifecycle/gate-checkpoint.d.ts +1 -1
  82. package/dist/lifecycle/gate-checkpoint.js +1 -1
  83. package/dist/{workspace/trust → lifecycle}/gate-seal.d.ts +1 -1
  84. package/dist/lifecycle/gate-seal.d.ts.map +1 -0
  85. package/dist/lifecycle/query.d.ts +68 -0
  86. package/dist/lifecycle/query.d.ts.map +1 -0
  87. package/dist/lifecycle/query.js +246 -0
  88. package/dist/lifecycle/run-ledger.d.ts +13 -0
  89. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  90. package/dist/lifecycle/run-ledger.js +16 -0
  91. package/dist/lifecycle/target-lock.d.ts +97 -0
  92. package/dist/lifecycle/target-lock.d.ts.map +1 -0
  93. package/dist/lifecycle/target-lock.js +286 -0
  94. package/dist/op/activities/activity-contracts.d.ts +30 -0
  95. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  96. package/dist/op/activities/activity-contracts.js +26 -0
  97. package/dist/op/activities/index.d.ts +2 -0
  98. package/dist/op/activities/index.d.ts.map +1 -1
  99. package/dist/op/activities/index.js +4 -0
  100. package/dist/op/activities/pr-refs.d.ts +10 -0
  101. package/dist/op/activities/pr-refs.d.ts.map +1 -0
  102. package/dist/op/activities/pr-refs.js +26 -0
  103. package/dist/op/activities/predict-behaviour.d.ts +2 -4
  104. package/dist/op/activities/predict-behaviour.d.ts.map +1 -1
  105. package/dist/op/activities/predict-behaviour.js +2 -21
  106. package/dist/op/activities/review-agent.d.ts +137 -0
  107. package/dist/op/activities/review-agent.d.ts.map +1 -0
  108. package/dist/op/activities/review-agent.js +266 -0
  109. package/dist/op/builders.d.ts +9 -0
  110. package/dist/op/builders.d.ts.map +1 -1
  111. package/dist/op/builders.js +11 -0
  112. package/dist/op/cron.d.ts +8 -0
  113. package/dist/op/cron.d.ts.map +1 -1
  114. package/dist/op/cron.js +51 -0
  115. package/dist/op/gate-approval.d.ts +20 -13
  116. package/dist/op/gate-approval.d.ts.map +1 -1
  117. package/dist/op/gate-approval.js +13 -18
  118. package/dist/op/gate-quorum.d.ts +131 -0
  119. package/dist/op/gate-quorum.d.ts.map +1 -0
  120. package/dist/op/gate-quorum.js +183 -0
  121. package/dist/op/gate-resume.d.ts +4 -2
  122. package/dist/op/gate-resume.d.ts.map +1 -1
  123. package/dist/op/gate-resume.js +5 -4
  124. package/dist/op/gate-review.js +1 -1
  125. package/dist/op/gate.d.ts +32 -4
  126. package/dist/op/gate.d.ts.map +1 -1
  127. package/dist/op/gate.js +40 -24
  128. package/dist/op/index.d.ts +6 -4
  129. package/dist/op/index.d.ts.map +1 -1
  130. package/dist/op/index.js +4 -3
  131. package/dist/op/local-executor.d.ts.map +1 -1
  132. package/dist/op/local-executor.js +9 -3
  133. package/dist/op/op-waves-run.d.ts +28 -43
  134. package/dist/op/op-waves-run.d.ts.map +1 -1
  135. package/dist/op/op-waves-run.js +170 -120
  136. package/dist/op/op-waves.d.ts +55 -3
  137. package/dist/op/op-waves.d.ts.map +1 -1
  138. package/dist/op/op-waves.js +63 -8
  139. package/dist/op/schedule-overdue.d.ts +57 -0
  140. package/dist/op/schedule-overdue.d.ts.map +1 -0
  141. package/dist/op/schedule-overdue.js +138 -0
  142. package/dist/op/stage-hooks.d.ts +132 -0
  143. package/dist/op/stage-hooks.d.ts.map +1 -0
  144. package/dist/op/stage-hooks.js +142 -0
  145. package/dist/override-gate.d.ts +2 -2
  146. package/dist/override-gate.d.ts.map +1 -1
  147. package/dist/override-gate.js +1 -1
  148. package/dist/pr-forge.d.ts +64 -0
  149. package/dist/pr-forge.d.ts.map +1 -1
  150. package/dist/pr-forge.js +331 -44
  151. package/dist/pr-loop.d.ts +107 -1
  152. package/dist/pr-loop.d.ts.map +1 -1
  153. package/dist/pr-loop.js +84 -3
  154. package/dist/pr-post.d.ts +72 -0
  155. package/dist/pr-post.d.ts.map +1 -0
  156. package/dist/pr-post.js +134 -0
  157. package/dist/pr-requires.d.ts +38 -0
  158. package/dist/pr-requires.d.ts.map +1 -0
  159. package/dist/pr-requires.js +48 -0
  160. package/dist/wave-blocked.d.ts +79 -0
  161. package/dist/wave-blocked.d.ts.map +1 -0
  162. package/dist/wave-blocked.js +245 -0
  163. package/dist/wave-engine.d.ts +6 -0
  164. package/dist/wave-engine.d.ts.map +1 -1
  165. package/dist/wave-engine.js +2 -0
  166. package/dist/wave-runtime.mjs +243 -243
  167. package/dist/workspace/__fixtures__/two-member-workspace.d.ts +1 -0
  168. package/dist/workspace/__fixtures__/two-member-workspace.d.ts.map +1 -1
  169. package/dist/workspace/__fixtures__/two-member-workspace.js +1 -1
  170. package/dist/workspace/checks/ci-workflow.d.ts.map +1 -1
  171. package/dist/workspace/checks/ci-workflow.js +19 -4
  172. package/dist/workspace/ci-branches.d.ts +51 -0
  173. package/dist/workspace/ci-branches.d.ts.map +1 -0
  174. package/dist/workspace/ci-branches.js +69 -0
  175. package/dist/workspace/ci-cloud-identity.d.ts +11 -0
  176. package/dist/workspace/ci-cloud-identity.d.ts.map +1 -0
  177. package/dist/workspace/ci-cloud-identity.js +24 -0
  178. package/dist/workspace/ci-init.d.ts.map +1 -1
  179. package/dist/workspace/ci-init.js +5 -4
  180. package/dist/workspace/ci-locks.d.ts +12 -0
  181. package/dist/workspace/ci-locks.d.ts.map +1 -0
  182. package/dist/workspace/ci-locks.js +6 -0
  183. package/dist/workspace/ci-run.d.ts +17 -1
  184. package/dist/workspace/ci-run.d.ts.map +1 -1
  185. package/dist/workspace/ci-run.js +66 -4
  186. package/dist/workspace/ci-workflow-at.d.ts +14 -0
  187. package/dist/workspace/ci-workflow-at.d.ts.map +1 -0
  188. package/dist/workspace/ci-workflow-at.js +17 -0
  189. package/dist/workspace/ci-workflow.d.ts +11 -3
  190. package/dist/workspace/ci-workflow.d.ts.map +1 -1
  191. package/dist/workspace/ci-workflow.js +10 -2
  192. package/dist/workspace/declaration.d.ts +69 -3
  193. package/dist/workspace/declaration.d.ts.map +1 -1
  194. package/dist/workspace/declaration.js +72 -1
  195. package/dist/workspace/declaration.schema.json +149 -2
  196. package/dist/workspace/identity-gate-rule.d.ts +1 -1
  197. package/dist/workspace/identity-gate-rule.d.ts.map +1 -1
  198. package/dist/workspace/identity-gate-rule.js +1 -1
  199. package/dist/workspace/identity.d.ts +1 -1
  200. package/dist/workspace/identity.d.ts.map +1 -1
  201. package/dist/workspace/lineage-upgrade.d.ts.map +1 -1
  202. package/dist/workspace/lineage-upgrade.js +8 -5
  203. package/dist/workspace/member-pipeline.d.ts +6 -0
  204. package/dist/workspace/member-pipeline.d.ts.map +1 -1
  205. package/dist/workspace/member-pipeline.js +23 -0
  206. package/dist/workspace/pr-report.schema.json +94 -3
  207. package/dist/workspace/reason-codes.d.ts +1 -1
  208. package/dist/workspace/reason-codes.d.ts.map +1 -1
  209. package/dist/workspace/reason-codes.js +1 -1
  210. package/dist/workspace/security.d.ts.map +1 -1
  211. package/dist/workspace/security.js +4 -0
  212. package/dist/workspace/status-gates.d.ts +3 -2
  213. package/dist/workspace/status-gates.d.ts.map +1 -1
  214. package/dist/workspace/status-gates.js +8 -7
  215. package/dist/workspace/status.d.ts.map +1 -1
  216. package/dist/workspace/status.js +4 -1
  217. package/dist/workspace/trust/seal.d.ts +2 -2
  218. package/dist/workspace/trust/seal.d.ts.map +1 -1
  219. package/dist/workspace/trust/seal.js +2 -2
  220. package/package.json +1 -1
  221. package/src/__fixtures__/oidc-emulator.ts +118 -0
  222. package/src/ci-handover.test.ts +209 -0
  223. package/src/ci-handover.ts +237 -0
  224. package/src/ci-identity.test.ts +201 -0
  225. package/src/ci-identity.ts +310 -0
  226. package/src/cli/handlers/approve.ts +18 -5
  227. package/src/cli/handlers/build.ts +18 -1
  228. package/src/cli/handlers/fan-out.ts +43 -6
  229. package/src/cli/handlers/gate-resume.ts +16 -2
  230. package/src/cli/handlers/lock.test.ts +98 -0
  231. package/src/cli/handlers/lock.ts +202 -0
  232. package/src/cli/handlers/operator.test.ts +3 -1
  233. package/src/cli/handlers/pr-before-merge.test.ts +276 -0
  234. package/src/cli/handlers/pr-env.ts +462 -0
  235. package/src/cli/handlers/pr-waves-blocked.test.ts +247 -0
  236. package/src/cli/handlers/pr.test.ts +184 -0
  237. package/src/cli/handlers/pr.ts +605 -61
  238. package/src/cli/handlers/promote.ts +9 -0
  239. package/src/cli/handlers/query.ts +78 -0
  240. package/src/cli/handlers/run.ts +10 -0
  241. package/src/cli/main.ts +49 -4
  242. package/src/cli/parse-args.ts +34 -2
  243. package/src/cli/registry.ts +31 -2
  244. package/src/components/capability-targets.test.ts +162 -0
  245. package/src/components/capability.ts +71 -0
  246. package/src/components/cli-support.ts +14 -1
  247. package/src/components/driver.ts +54 -3
  248. package/src/components/fan-out-run.ts +58 -3
  249. package/src/components/fan-out-waves.test.ts +45 -1
  250. package/src/components/gate-plan.ts +3 -0
  251. package/src/components/pr-environment.test.ts +249 -0
  252. package/src/components/pr-environment.ts +538 -0
  253. package/src/components/pr-hooks.test.ts +118 -0
  254. package/src/components/pr-hooks.ts +157 -0
  255. package/src/components/pr-pipeline.ts +194 -21
  256. package/src/components/pr-policy.test.ts +145 -0
  257. package/src/components/pr-policy.ts +211 -0
  258. package/src/components/pr-run.ts +14 -2
  259. package/src/components/wave-plan.ts +38 -3
  260. package/src/gate-decision-bundle.test.ts +4 -3
  261. package/src/gate-decision.ts +39 -2
  262. package/src/gate-policy-bundle.test.ts +28 -0
  263. package/src/gate-policy.test.ts +162 -0
  264. package/src/gate-policy.ts +298 -0
  265. package/src/lifecycle/gate-checkpoint.ts +1 -1
  266. package/src/{workspace/trust → lifecycle}/gate-seal.ts +1 -1
  267. package/src/lifecycle/query.test.ts +91 -0
  268. package/src/lifecycle/query.ts +315 -0
  269. package/src/lifecycle/run-ledger.ts +18 -0
  270. package/src/lifecycle/target-lock.test.ts +195 -0
  271. package/src/lifecycle/target-lock.ts +347 -0
  272. package/src/op/activities/activity-contracts.ts +31 -0
  273. package/src/op/activities/index.ts +6 -0
  274. package/src/op/activities/pr-refs.ts +28 -0
  275. package/src/op/activities/predict-behaviour.ts +3 -23
  276. package/src/op/activities/review-agent.test.ts +240 -0
  277. package/src/op/activities/review-agent.ts +355 -0
  278. package/src/op/builders.ts +13 -0
  279. package/src/op/cron.ts +44 -0
  280. package/src/op/gate-alias.test.ts +2 -2
  281. package/src/op/gate-approval.test.ts +30 -9
  282. package/src/op/gate-approval.ts +23 -26
  283. package/src/op/gate-quorum.test.ts +139 -0
  284. package/src/op/gate-quorum.ts +248 -0
  285. package/src/op/gate-resume.ts +6 -3
  286. package/src/op/gate-review.ts +1 -1
  287. package/src/op/gate.ts +64 -23
  288. package/src/op/index.ts +13 -1
  289. package/src/op/local-executor.ts +9 -2
  290. package/src/op/op-waves-hook-targets.test.ts +126 -0
  291. package/src/op/op-waves-policy-hold.test.ts +66 -0
  292. package/src/op/op-waves-quorum.test.ts +101 -0
  293. package/src/op/op-waves-run.ts +197 -183
  294. package/src/op/op-waves.ts +83 -10
  295. package/src/op/schedule-overdue.test.ts +220 -0
  296. package/src/op/schedule-overdue.ts +161 -0
  297. package/src/op/stage-hooks.ts +251 -0
  298. package/src/override-gate-bundle.test.ts +1 -1
  299. package/src/override-gate.ts +2 -2
  300. package/src/pr-forge-bundle.test.ts +2 -2
  301. package/src/pr-forge.test.ts +33 -0
  302. package/src/pr-forge.ts +347 -35
  303. package/src/pr-loop-bundle.test.ts +2 -2
  304. package/src/pr-loop.test.ts +58 -0
  305. package/src/pr-loop.ts +170 -4
  306. package/src/pr-post.test.ts +141 -0
  307. package/src/pr-post.ts +159 -0
  308. package/src/pr-requires.test.ts +184 -0
  309. package/src/pr-requires.ts +79 -0
  310. package/src/review-agent-bundle.test.ts +35 -0
  311. package/src/stage-hooks-bundle.test.ts +38 -0
  312. package/src/wave-blocked-bundle.test.ts +25 -0
  313. package/src/wave-blocked.test.ts +146 -0
  314. package/src/wave-blocked.ts +271 -0
  315. package/src/wave-engine.ts +8 -0
  316. package/src/workspace/__fixtures__/two-member-workspace.ts +2 -2
  317. package/src/workspace/checks/ci-workflow.test.ts +9 -0
  318. package/src/workspace/checks/ci-workflow.ts +18 -4
  319. package/src/workspace/ci-branches.test.ts +62 -0
  320. package/src/workspace/ci-branches.ts +79 -0
  321. package/src/workspace/ci-cloud-identity.test.ts +53 -0
  322. package/src/workspace/ci-cloud-identity.ts +23 -0
  323. package/src/workspace/ci-init.ts +5 -4
  324. package/src/workspace/ci-locks.ts +16 -0
  325. package/src/workspace/ci-run-index.test.ts +2 -1
  326. package/src/workspace/ci-run.test.ts +107 -8
  327. package/src/workspace/ci-run.ts +74 -5
  328. package/src/workspace/ci-workflow-at.ts +23 -0
  329. package/src/workspace/ci-workflow.ts +13 -2
  330. package/src/workspace/declaration.schema.json +149 -2
  331. package/src/workspace/declaration.test.ts +76 -0
  332. package/src/workspace/declaration.ts +140 -5
  333. package/src/workspace/identity-gate-rule.ts +1 -1
  334. package/src/workspace/identity.ts +1 -1
  335. package/src/workspace/lineage-upgrade.ts +11 -8
  336. package/src/workspace/member-pipeline.test.ts +29 -0
  337. package/src/workspace/member-pipeline.ts +30 -0
  338. package/src/workspace/pr-report.schema.json +94 -3
  339. package/src/workspace/reason-codes.ts +1 -1
  340. package/src/workspace/security.ts +4 -0
  341. package/src/workspace/status-gates.ts +9 -6
  342. package/src/workspace/status.ts +4 -1
  343. package/src/workspace/trust/gate-seal.test.ts +1 -1
  344. package/src/workspace/trust/seal.ts +2 -2
  345. package/dist/workspace/trust/gate-seal.d.ts.map +0 -1
  346. /package/dist/{workspace/trust → lifecycle}/gate-seal.js +0 -0
package/dist/pr-loop.d.ts CHANGED
@@ -47,6 +47,7 @@
47
47
  * `identity.gates` entry covers every member.
48
48
  */
49
49
  import type { ChangeSetDocument } from "./change-set.js";
50
+ import type { PrRequireOutcome } from "./pr-requires.js";
50
51
  /** The schema a pull-request report names in `$schema`. */
51
52
  export declare const PR_REPORT_SCHEMA_ID = "https://intentius.io/chant/schemas/workspace/pr-report/v1/pr-report.schema.json";
52
53
  /** The read-contract version the report follows. */
@@ -63,6 +64,14 @@ export declare const PR_REPORT_WAVES_FLOOR = "0.124.32";
63
64
  export declare const PR_REPORT_PLANNED_OUTPUTS_FLOOR = "0.124.32";
64
65
  /** The chant that writes the `record` stage and the `recorded` status (#4168 step 1). */
65
66
  export declare const PR_REPORT_RECORD_FLOOR = "0.124.33";
67
+ /** The first chant whose report can carry `hooks` (#4288). */
68
+ export declare const PR_REPORT_HOOKS_FLOOR = "0.124.41";
69
+ /** The first chant whose plan report can carry `overdue` (#4289). */
70
+ export declare const PR_REPORT_OVERDUE_FLOOR = "0.124.41";
71
+ /** The first chant whose report can carry `policy` and the `policy-denied` and `policy-error` refusals (#4294). */
72
+ export declare const PR_REPORT_POLICY_FLOOR = "0.124.41";
73
+ /** The first chant whose apply report can carry `beforeMerge` and the `requires-unmet` and `before-merge-off` refusals (#4301, ws-106). */
74
+ export declare const PR_REPORT_BEFORE_MERGE_FLOOR = "0.124.42";
66
75
  /** The gate a pull request's apply waits on, unless the pipeline names another. */
67
76
  export declare const PR_APPLY_GATE = "pr-apply";
68
77
  /**
@@ -152,6 +161,8 @@ export interface PrMember {
152
161
  round?: number;
153
162
  /** Apply stage (#3999): why the first round's plan did not apply. */
154
163
  held?: string;
164
+ /** A blocked member's (#4291): the component whose failure held it, past any component blocked in between. */
165
+ blockedBy?: string;
155
166
  }
156
167
  /** A round of plans an apply made after an upstream applied (#3999), the report's `rounds`. */
157
168
  export interface PrRound {
@@ -232,7 +243,21 @@ export type PrRefusal =
232
243
  /** `--wave-gate`: an approval of the wave's gate stands for another digest, so its plan moved since. */
233
244
  | "wave-plan-changed"
234
245
  /** `--wave-gate` with `--wave <k>`: an earlier wave has work left, or no record says it applied. */
235
- | "earlier-wave";
246
+ | "earlier-wave"
247
+ /** Under `ci.locks` (#4293): another open pull request holds a lock on a target this apply reaches. */
248
+ | "locked"
249
+ /** `ci.policy` at base denied the plan (#4294), and no override of it counts. */
250
+ | "policy-denied"
251
+ /** `ci.policy` at base could not be run, or gave no answer chant can read (#4294). */
252
+ | "policy-error"
253
+ /** `pr-apply --before-merge` (#4301): the pull request is not approved, mergeable, undiverged or green; `beforeMerge` says which. */
254
+ | "requires-unmet"
255
+ /** `pr-apply --before-merge`: the declaration at base does not set `ci.workflow` to `apply-before-merge` for the member. */
256
+ | "before-merge-off";
257
+ /** An apply before merge (#4301, ws-106): the requires checks the forge answered, in order. */
258
+ export interface PrBeforeMerge {
259
+ requires: PrRequireOutcome[];
260
+ }
236
261
  /**
237
262
  * One wave of an apply with `--wave-gate` (#4003): what it planned, where it
238
263
  * got to, and which approval it applied or waits under.
@@ -261,6 +286,62 @@ export interface PrWave {
261
286
  /** Why the approved change set does not cover the wave's plan, one line per member. */
262
287
  moved?: string[];
263
288
  }
289
+ /** A scheduled watch or reconcile Op that stopped running (#4289, `op/schedule-overdue.ts`). */
290
+ export interface PrOverdue {
291
+ op: string;
292
+ cron: string;
293
+ /** The job's last run, or the pipeline file's first commit when `neverRan` (ISO 8601). */
294
+ since: string;
295
+ neverRan?: boolean;
296
+ message: string;
297
+ }
298
+ /**
299
+ * What `ci.policy` at base said about the change set (#4294). Rule ids are
300
+ * `<package>.<rule>`.
301
+ */
302
+ export interface PrPolicyReport {
303
+ /** `denied` wins over `held`. `error`: the policy did not run or gave no readable answer. */
304
+ result: "passed" | "denied" | "held" | "error";
305
+ /** The result shape read: `conftest` or `opa`. */
306
+ engine: "conftest" | "opa";
307
+ /** The commit the settings and the policy were read at. */
308
+ base: string;
309
+ denials: Array<{
310
+ rule: string;
311
+ message: string;
312
+ }>;
313
+ /** The ids of the rules that denied, sorted: what an override names. */
314
+ rules?: string[];
315
+ holds: Array<{
316
+ rule: string;
317
+ message: string;
318
+ }>;
319
+ warnings: string[];
320
+ error?: string;
321
+ /** The override that lets the denied plan through. */
322
+ override?: {
323
+ by: string;
324
+ at: string;
325
+ reason: string;
326
+ digest: string;
327
+ };
328
+ /** While denied: the command that overrides the denial. */
329
+ overrideCommand?: string;
330
+ }
331
+ /**
332
+ * One stage hook a pull-request job ran (#4288), from `ci.hooks` in the
333
+ * workspace declaration at base. The shape of an Op waves hook outcome.
334
+ */
335
+ export interface PrHookOutcome {
336
+ /** `before-observe`, `before-plan`, `after-plan`, `before-apply` or `after-apply`. */
337
+ moment: string;
338
+ name: string;
339
+ /** The component, for a `perRun` hook. */
340
+ target?: string;
341
+ exit: number;
342
+ /** `held`: an `onFailure: approve` hook failed, which the pull request's gate answers. */
343
+ outcome: "passed" | "failed" | "held";
344
+ }
264
345
  /**
265
346
  * The document `pr-plan` and `pr-apply` write (`pr-report.schema.json`).
266
347
  * The terragucci plan report (#3349) reads it; fields are only ever added.
@@ -324,6 +405,14 @@ export interface PrReport {
324
405
  waveGate?: string;
325
406
  /** With `waveGate`: each wave reached so far, in order. */
326
407
  waves?: PrWave[];
408
+ /**
409
+ * Plan stage (#4289): the scheduled watch and reconcile Ops whose cron has
410
+ * fired at least twice since their job last ran, or since their pipeline
411
+ * file was added when no run is on record. Absent when none is overdue or
412
+ * the forge was not asked. Added within contract 1 by chant
413
+ * {@link PR_REPORT_OVERDUE_FLOOR}.
414
+ */
415
+ overdue?: PrOverdue[];
327
416
  /** Component names: which changed, which run because they depend on one, and what the change touched that no component deploys. */
328
417
  selection: {
329
418
  changed: string[];
@@ -335,6 +424,23 @@ export interface PrReport {
335
424
  };
336
425
  members: PrMember[];
337
426
  changeSet: ChangeSetDocument;
427
+ /**
428
+ * The stage hooks the job ran (#4288), in order. Absent when it ran none.
429
+ * Added within contract 1 by chant {@link PR_REPORT_HOOKS_FLOOR}.
430
+ */
431
+ hooks?: PrHookOutcome[];
432
+ /**
433
+ * What `ci.policy` at base said about the change set (#4294). Absent when
434
+ * the base sets no policy, or the stage reached no plan to judge. Added
435
+ * within contract 1 by chant {@link PR_REPORT_POLICY_FLOOR}.
436
+ */
437
+ policy?: PrPolicyReport;
438
+ /**
439
+ * `pr-apply --before-merge` (#4301): the requires checks. Absent on every
440
+ * other stage. Added within contract 1 by chant
441
+ * {@link PR_REPORT_BEFORE_MERGE_FLOOR}.
442
+ */
443
+ beforeMerge?: PrBeforeMerge;
338
444
  }
339
445
  /** The counts a member's entries add up to. */
340
446
  export declare function memberCounts(doc: Pick<ChangeSetDocument, "summary">, member: string): PrMemberCounts;
@@ -1 +1 @@
1
- {"version":3,"file":"pr-loop.d.ts","sourceRoot":"","sources":["../src/pr-loop.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pr-loop.d.ts","sourceRoot":"","sources":["../src/pr-loop.ts"],"names":[],"mappings":"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"}
package/dist/pr-loop.js CHANGED
@@ -63,6 +63,14 @@ export const PR_REPORT_WAVES_FLOOR = "0.124.32";
63
63
  export const PR_REPORT_PLANNED_OUTPUTS_FLOOR = "0.124.32";
64
64
  /** The chant that writes the `record` stage and the `recorded` status (#4168 step 1). */
65
65
  export const PR_REPORT_RECORD_FLOOR = "0.124.33";
66
+ /** The first chant whose report can carry `hooks` (#4288). */
67
+ export const PR_REPORT_HOOKS_FLOOR = "0.124.41";
68
+ /** The first chant whose plan report can carry `overdue` (#4289). */
69
+ export const PR_REPORT_OVERDUE_FLOOR = "0.124.41";
70
+ /** The first chant whose report can carry `policy` and the `policy-denied` and `policy-error` refusals (#4294). */
71
+ export const PR_REPORT_POLICY_FLOOR = "0.124.41";
72
+ /** The first chant whose apply report can carry `beforeMerge` and the `requires-unmet` and `before-merge-off` refusals (#4301, ws-106). */
73
+ export const PR_REPORT_BEFORE_MERGE_FLOOR = "0.124.42";
66
74
  /** The gate a pull request's apply waits on, unless the pipeline names another. */
67
75
  export const PR_APPLY_GATE = "pr-apply";
68
76
  /**
@@ -143,11 +151,15 @@ function headline(report) {
143
151
  case "recorded":
144
152
  return `Recorded the plan of ${members} on merge. Nothing applied: a release that carries this commit deploys it.`;
145
153
  case "plan-failed":
154
+ if (report.hooks?.some((h) => h.outcome === "failed"))
155
+ return "A hook failed, so nothing can apply.";
146
156
  return `Planning failed for ${report.members.filter((m) => m.status === "plan-failed").length} of ${members}, so nothing can apply.`;
147
157
  case "applied":
148
158
  return `Applied ${members}.`;
149
- case "failed":
150
- return `The apply failed: ${report.members.filter((m) => m.status === "failed").length} failed, ${report.members.filter((m) => m.status === "applied").length} applied.`;
159
+ case "failed": {
160
+ const blocked = report.members.filter((m) => m.status === "blocked").length;
161
+ return `The apply failed: ${report.members.filter((m) => m.status === "failed").length} failed, ${blocked > 0 ? `${blocked} blocked, ` : ""}${report.members.filter((m) => m.status === "applied").length} applied.`;
162
+ }
151
163
  case "wave-applied": {
152
164
  const applied = (report.waves ?? []).filter((w) => w.status === "applied").map((w) => w.wave);
153
165
  const total = report.selection.waves.length;
@@ -161,6 +173,49 @@ function headline(report) {
161
173
  return `Applied ${report.members.filter((m) => m.status === "applied").length} of ${members}; ${report.members.filter((m) => m.status === "waiting").length} wait on an approval of the plan made after their upstream applied.`;
162
174
  }
163
175
  }
176
+ /**
177
+ * The blocked set (#4291): each component a failure held, grouped by the
178
+ * component that failed, and that the rest went on. Undefined when nothing
179
+ * is blocked.
180
+ */
181
+ function blockedLine(members) {
182
+ const byRoot = new Map();
183
+ for (const m of members) {
184
+ if (m.status !== "blocked")
185
+ continue;
186
+ const by = m.blockedBy ?? "a dependency";
187
+ byRoot.set(by, (byRoot.get(by) ?? new Set()).add(m.component));
188
+ }
189
+ if (byRoot.size === 0)
190
+ return undefined;
191
+ const groups = [...byRoot]
192
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
193
+ .map(([by, names]) => `${[...names].sort().map(code).join(", ")} (blocked by ${by === "a dependency" ? by : code(by)})`);
194
+ return `Blocked, so not applied: ${groups.join("; ")}. A failure blocks only the members that depend on it, so the rest went on.`;
195
+ }
196
+ /** The policy's lines in the note (#4294): what denied or held the plan, and how a denial is overridden. */
197
+ function policyLines(report) {
198
+ const p = report.policy;
199
+ if (!p)
200
+ return [];
201
+ const at = `read at ${code(short(p.base))}`;
202
+ const each = (list) => list.map((f) => `- ${code(f.rule)}: ${f.message}`);
203
+ const out = [""];
204
+ if (p.result === "error")
205
+ out.push(`Policy (${p.engine}, ${at}) could not be checked, so nothing applies: ${p.error ?? "no answer"}.`);
206
+ else if (p.result === "passed")
207
+ out.push(`Policy (${p.engine}, ${at}) passed.`);
208
+ if (p.denials.length > 0) {
209
+ out.push(p.override ? `Policy (${p.engine}, ${at}) denied this plan; ${code(p.override.by)} overrode it: ${p.override.reason}` : `Policy (${p.engine}, ${at}) denied this plan:`, ...each(p.denials));
210
+ if (!p.override && p.overrideCommand)
211
+ out.push("", `A person the overriders file at base lists may override it once pr-apply has recorded the denial: ${code(p.overrideCommand)}`);
212
+ }
213
+ if (p.holds.length > 0)
214
+ out.push(`Policy (${p.engine}, ${at}) holds this plan for a person's approval of its digest:`, ...each(p.holds));
215
+ if (p.warnings.length > 0)
216
+ out.push(`Policy warnings: ${p.warnings.join("; ")}`);
217
+ return out;
218
+ }
164
219
  /** Who a wave applied or waits under, as a table cell. */
165
220
  function waveApproval(w) {
166
221
  const whose = w.approval === "pull-request" ? "the pull request's" : "its own";
@@ -219,6 +274,8 @@ export function renderPrNote(report, options = {}) {
219
274
  ];
220
275
  if (report.message)
221
276
  out.push("", `> ${report.message.split("\n").join("\n> ")}`);
277
+ for (const o of report.overdue ?? [])
278
+ out.push("", `Warning: ${o.message}`);
222
279
  if (report.resumed && report.resumed.applied.length > 0) {
223
280
  out.push("", `Resumed under the same approval: ${report.resumed.applied.map(code).join(", ")} applied in an earlier attempt and did not run again.`);
224
281
  }
@@ -227,6 +284,7 @@ export function renderPrNote(report, options = {}) {
227
284
  for (const m of report.members) {
228
285
  const holes = memberHoleReasons(report, m.member);
229
286
  const status = STATUS_WORDS[m.status] +
287
+ (m.status === "blocked" && m.blockedBy ? ` by ${code(m.blockedBy)}` : "") +
230
288
  (m.inputsMoved?.length ? `, inputs from ${m.inputsMoved.join(", ")} moved` : "") +
231
289
  (holes.length > 0 ? `; ${holes.length > 2 ? `${holes[0]}; and ${holes.length - 1} more, listed under Holes` : holes.join("; ")}` : "");
232
290
  // A member whose plan has holes and no entries says nothing about what
@@ -239,7 +297,18 @@ export function renderPrNote(report, options = {}) {
239
297
  out.push("", "A member whose inputs moved applied the plan it was approved with. The next run plans it against the new values.");
240
298
  }
241
299
  }
300
+ const blocked = blockedLine(report.members);
301
+ if (blocked)
302
+ out.push("", blocked);
242
303
  out.push(...waveLines(report, options.approver ?? "<you>"));
304
+ // #4288: the hooks that did not pass, by name; a passed hook is a count.
305
+ const hooks = report.hooks ?? [];
306
+ if (hooks.length > 0) {
307
+ const passed = hooks.filter((h) => h.outcome === "passed").length;
308
+ const other = hooks.filter((h) => h.outcome !== "passed").map((h) => `${code(h.name)} ${h.moment}${h.target ? ` for ${code(h.target)}` : ""} ${h.outcome === "held" ? "held" : "failed"} (exit ${h.exit})`);
309
+ out.push("", `Hooks: ${passed} passed${other.length > 0 ? `; ${other.join("; ")}` : ""}.`);
310
+ }
311
+ out.push(...policyLines(report));
243
312
  if (report.selection.unclaimed.length > 0) {
244
313
  out.push("", `Changed, and deployed by no component: ${report.selection.unclaimed.map(code).join(", ")}.`);
245
314
  }
@@ -334,7 +403,16 @@ export function prStatusDescription(report) {
334
403
  text = "refused: an earlier wave has not applied";
335
404
  break;
336
405
  }
337
- text = `refused: ${report.refusal === "plan-changed" ? "the plan changed after review" : report.refusal === "not-a-reviewer" ? "the approver has not approved the pull request" : report.refusal === "author-approved" ? "the approver wrote the change" : report.refusal === "no-pull-request" ? "no pull request merged this commit" : "the plan is not approved"}`;
406
+ if (report.refusal === "requires-unmet" || report.refusal === "before-merge-off") {
407
+ const unmet = (report.beforeMerge?.requires ?? []).filter((r) => !r.passed).map((r) => r.name);
408
+ text = report.refusal === "before-merge-off" ? "refused: this workspace does not apply before merge" : `refused: ${unmet.join(", ") || "a require"} unmet for an apply before merge`;
409
+ break;
410
+ }
411
+ if (report.refusal === "policy-denied" || report.refusal === "policy-error") {
412
+ text = report.refusal === "policy-denied" ? `refused: the policy denied the plan (${(report.policy?.rules ?? []).join(", ")})` : "refused: the policy could not be checked";
413
+ break;
414
+ }
415
+ text = `refused: ${report.refusal === "plan-changed" ? "the plan changed after review" : report.refusal === "not-a-reviewer" ? "the approver has not approved the pull request" : report.refusal === "author-approved" ? "the approver wrote the change" : report.refusal === "no-pull-request" ? "no pull request merged this commit" : report.refusal === "locked" ? "another pull request holds a target lock" : "the plan is not approved"}`;
338
416
  break;
339
417
  }
340
418
  }
@@ -345,6 +423,9 @@ export function prStatusState(report) {
345
423
  // #4168 decision 1: a merge whose plan differs from the approved one is recorded, and its status fails.
346
424
  if (report.status === "recorded")
347
425
  return report.approval.status === "changed" ? "failure" : "success";
426
+ // #4294: a plan the policy denied, with no override, or one it could not check, fails at the plan stage as it would at the apply.
427
+ if (report.status === "planned" && report.policy && (report.policy.result === "error" || (report.policy.result === "denied" && !report.policy.override)))
428
+ return "failure";
348
429
  if (report.status === "planned" || report.status === "applied" || report.status === "wave-applied" || report.status === "nothing")
349
430
  return "success";
350
431
  if (report.status === "refused" && (report.refusal === "not-approved" || report.refusal === "wave-not-approved"))
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Post a pull request's plan note and its `chant/plan` status from the plan
3
+ * report (#4295), in a job or a process that runs none of the change's code.
4
+ *
5
+ * The plan job runs the pull request's code and holds no forge token
6
+ * (./ci-handover.ts), so `pr-plan --no-status` only writes its report. Then
7
+ * `chant components pr-post` in the `plan-note` job, or `chant ci run plan`
8
+ * once its steps settle, reads the report and posts.
9
+ *
10
+ * The report is the change's: its code could write anything into it. So it
11
+ * is read as data. The pull request, the head, the environment and the
12
+ * member come from the caller, never the report, and a report that names
13
+ * others is refused. The note is rendered again here from the report, and
14
+ * every hidden HTML comment after its first line is defused, so a forged
15
+ * marker cannot claim another environment's note. A plan job that failed
16
+ * fails the status whatever its report says.
17
+ */
18
+ import { type PrOverdue, type PrReport } from "./pr-loop.js";
19
+ import { type PrForge } from "./pr-forge.js";
20
+ /** The plan report's file under the report directory. */
21
+ export declare const PR_PLAN_REPORT_FILE = "pr-plan.json";
22
+ /** What {@link postPlanReport} posts for. */
23
+ export interface PlanPostInput {
24
+ forge: PrForge;
25
+ /** The report directory the plan job wrote, `.chant/pr`. */
26
+ dir: string;
27
+ /** The pull request, from the forge's event. */
28
+ pr: number;
29
+ /** The commit the plan job checked out, from the forge's event. */
30
+ head: string;
31
+ env: string;
32
+ member?: string;
33
+ /** The plan job's own result (`needs.plan.result`). `failure` fails the status. */
34
+ result?: string;
35
+ /**
36
+ * The scheduled Ops that stopped running (#4289), asked here since the plan
37
+ * job held no token to ask with. It replaces any `overdue` in the report.
38
+ */
39
+ overdue?: () => Promise<PrOverdue[]>;
40
+ }
41
+ /** What {@link postPlanReport} did. */
42
+ export interface PlanPostResult {
43
+ state: "success" | "failure" | "pending";
44
+ description: string;
45
+ /** Whether a note was posted. A refused or missing report posts none. */
46
+ noted: boolean;
47
+ /** Why the report was not used, when it was not. */
48
+ refused?: string;
49
+ warnings: string[];
50
+ }
51
+ /**
52
+ * Read the plan report under `dir` and check it is the one the caller ran:
53
+ * a plan report for the same pull request, head, environment and member.
54
+ * Returns the report, or why it is not used.
55
+ */
56
+ export declare function readPlanReport(input: Pick<PlanPostInput, "dir" | "pr" | "head" | "env" | "member">): {
57
+ report: PrReport;
58
+ } | {
59
+ refused: string;
60
+ };
61
+ /**
62
+ * The note for `report`, rendered here, with every `<!--` after the marker
63
+ * line written as `&lt;!--`, so the note carries no hidden marker but its own.
64
+ */
65
+ export declare function planNoteFor(report: PrReport, forge: Pick<PrForge, "kind" | "host">, marker: string): string;
66
+ /**
67
+ * Post the status and the note for the plan report under `input.dir`. A
68
+ * forge that refuses a call is a warning. A report that is missing or not
69
+ * the caller's sets a failed status and posts no note.
70
+ */
71
+ export declare function postPlanReport(input: PlanPostInput): Promise<PlanPostResult>;
72
+ //# sourceMappingURL=pr-post.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pr-post.d.ts","sourceRoot":"","sources":["../src/pr-post.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,EAAmF,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3I,OAAO,EAAoB,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAG5D,yDAAyD;AACzD,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAElD,6CAA6C;AAC7C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,OAAO,CAAC;IACf,4DAA4D;IAC5D,GAAG,EAAE,MAAM,CAAC;IACZ,gDAAgD;IAChD,EAAE,EAAE,MAAM,CAAC;IACX,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;CACtC;AAED,uCAAuC;AACvC,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,KAAK,EAAE,OAAO,CAAC;IACf,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAID;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,IAAI,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC,GAAG;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAoB/I;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQ3G;AAID;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC,CAkDlF"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Post a pull request's plan note and its `chant/plan` status from the plan
3
+ * report (#4295), in a job or a process that runs none of the change's code.
4
+ *
5
+ * The plan job runs the pull request's code and holds no forge token
6
+ * (./ci-handover.ts), so `pr-plan --no-status` only writes its report. Then
7
+ * `chant components pr-post` in the `plan-note` job, or `chant ci run plan`
8
+ * once its steps settle, reads the report and posts.
9
+ *
10
+ * The report is the change's: its code could write anything into it. So it
11
+ * is read as data. The pull request, the head, the environment and the
12
+ * member come from the caller, never the report, and a report that names
13
+ * others is refused. The note is rendered again here from the report, and
14
+ * every hidden HTML comment after its first line is defused, so a forged
15
+ * marker cannot claim another environment's note. A plan job that failed
16
+ * fails the status whatever its report says.
17
+ */
18
+ import { existsSync, readFileSync } from "node:fs";
19
+ import { join } from "node:path";
20
+ import { prNoteMarker, prStatusContext, prStatusDescription, prStatusState, renderPrNote } from "./pr-loop.js";
21
+ import { forgePrincipalOf } from "./pr-forge.js";
22
+ import { GITHUB_COMMENT_LIMIT, GITLAB_NOTE_LIMIT } from "./plan-summary.js";
23
+ /** The plan report's file under the report directory. */
24
+ export const PR_PLAN_REPORT_FILE = "pr-plan.json";
25
+ const SHA = /^[0-9a-f]{40}$/;
26
+ /**
27
+ * Read the plan report under `dir` and check it is the one the caller ran:
28
+ * a plan report for the same pull request, head, environment and member.
29
+ * Returns the report, or why it is not used.
30
+ */
31
+ export function readPlanReport(input) {
32
+ const file = join(input.dir, PR_PLAN_REPORT_FILE);
33
+ if (!existsSync(file))
34
+ return { refused: "the plan job wrote no report" };
35
+ let doc;
36
+ try {
37
+ doc = JSON.parse(readFileSync(file, "utf-8"));
38
+ }
39
+ catch (err) {
40
+ return { refused: `the plan report does not read: ${err instanceof Error ? err.message : String(err)}` };
41
+ }
42
+ if (!doc || typeof doc !== "object" || Array.isArray(doc))
43
+ return { refused: "the plan report is not an object" };
44
+ const r = doc;
45
+ if (r.stage !== "plan")
46
+ return { refused: `the report is not a plan report (stage ${JSON.stringify(r.stage)})` };
47
+ if (r.pr !== input.pr)
48
+ return { refused: `the report is for pull request ${JSON.stringify(r.pr)}, not ${input.pr}` };
49
+ if (typeof r.head !== "string" || !SHA.test(r.head) || r.head !== input.head)
50
+ return { refused: `the report is for head ${JSON.stringify(r.head)}, not ${input.head}` };
51
+ if (r.env !== input.env)
52
+ return { refused: `the report is for environment ${JSON.stringify(r.env)}, not ${input.env}` };
53
+ if ((r.member ?? undefined) !== input.member)
54
+ return { refused: `the report is for member ${JSON.stringify(r.member ?? null)}, not ${JSON.stringify(input.member ?? null)}` };
55
+ if (!Array.isArray(r.members) || !r.changeSet || typeof r.changeSet !== "object" || !r.selection || typeof r.selection !== "object" || !r.approval || typeof r.approval !== "object") {
56
+ return { refused: "the plan report is missing its members, change set, selection or approval" };
57
+ }
58
+ return { report: doc };
59
+ }
60
+ /**
61
+ * The note for `report`, rendered here, with every `<!--` after the marker
62
+ * line written as `&lt;!--`, so the note carries no hidden marker but its own.
63
+ */
64
+ export function planNoteFor(report, forge, marker) {
65
+ const note = renderPrNote(report, {
66
+ limit: forge.kind === "gitlab" ? GITLAB_NOTE_LIMIT : GITHUB_COMMENT_LIMIT,
67
+ approver: forgePrincipalOf(forge.kind, forge.host, "<your-login>"),
68
+ });
69
+ const at = note.indexOf("\n");
70
+ const rest = (at < 0 ? "" : note.slice(at + 1)).split("<!--").join("&lt;!--");
71
+ return `${marker}\n${rest}`;
72
+ }
73
+ const cut = (text, max = 140) => (text.length > max ? `${text.slice(0, max - 3)}...` : text);
74
+ /**
75
+ * Post the status and the note for the plan report under `input.dir`. A
76
+ * forge that refuses a call is a warning. A report that is missing or not
77
+ * the caller's sets a failed status and posts no note.
78
+ */
79
+ export async function postPlanReport(input) {
80
+ const warnings = [];
81
+ const context = prStatusContext("plan", input.member);
82
+ const read = readPlanReport(input);
83
+ const failedJob = input.result === "failure" || input.result === "cancelled";
84
+ let state;
85
+ let description;
86
+ let note;
87
+ let refused;
88
+ if ("refused" in read) {
89
+ refused = read.refused;
90
+ state = "failure";
91
+ description = cut(read.refused);
92
+ }
93
+ else {
94
+ let report = read.report;
95
+ if (input.overdue) {
96
+ const { overdue: _forged, ...rest } = report;
97
+ const found = await input.overdue().catch(() => []);
98
+ report = (found.length > 0 ? { ...rest, overdue: found } : rest);
99
+ }
100
+ try {
101
+ state = prStatusState(report);
102
+ description = prStatusDescription(report);
103
+ // A member the change does not reach has nothing to say on the pull request (as pr-plan's own publish).
104
+ if (!(input.member && report.status === "nothing" && !report.overdue?.length))
105
+ note = planNoteFor(report, input.forge, prNoteMarker(input.env, input.member));
106
+ }
107
+ catch (err) {
108
+ refused = `the plan report does not render: ${err instanceof Error ? err.message : String(err)}`;
109
+ state = "failure";
110
+ description = cut(refused);
111
+ note = undefined;
112
+ }
113
+ if (failedJob && state !== "failure") {
114
+ state = "failure";
115
+ description = cut(`the plan job failed; ${description}`);
116
+ }
117
+ }
118
+ try {
119
+ await input.forge.setStatus(input.head, { context, state, description: cut(description), ...(input.forge.runUrl ? { url: input.forge.runUrl } : {}) });
120
+ }
121
+ catch (err) {
122
+ warnings.push(`could not set the ${context} status: ${err instanceof Error ? err.message : String(err)}`);
123
+ }
124
+ if (note !== undefined) {
125
+ try {
126
+ await input.forge.upsertNote(input.pr, prNoteMarker(input.env, input.member), note);
127
+ }
128
+ catch (err) {
129
+ warnings.push(`could not post the note on #${input.pr}: ${err instanceof Error ? err.message : String(err)}`);
130
+ note = undefined;
131
+ }
132
+ }
133
+ return { state, description: cut(description), noted: note !== undefined, ...(refused ? { refused } : {}), warnings };
134
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The requires checks of an apply before merge (#4301, ws-106): the pull
3
+ * request is approved, mergeable, undiverged and its checks passed, each
4
+ * asked of the forge through its {@link PrForge} method. All four must pass.
5
+ *
6
+ * The checks are terragucci's `apply.requires` (comment-apply.ts:781-860 at
7
+ * INTENTIUS/terragucci e6cb431), with no setting to drop one. A check the
8
+ * forge has not settled, such as GitHub working out whether a pull request
9
+ * can merge, is asked again a few times before it counts as unmet.
10
+ *
11
+ * Like ./pr-forge.ts this imports nothing beyond it, so a product bundles it
12
+ * without the TypeScript toolchain.
13
+ */
14
+ import type { PrForge, PrRequireResult } from "./pr-forge.js";
15
+ /** The four checks, in the order they run and the report lists them. */
16
+ export declare const PR_APPLY_REQUIRES: readonly ["approved", "mergeable", "undiverged", "checks"];
17
+ export type PrApplyRequire = (typeof PR_APPLY_REQUIRES)[number];
18
+ /** One check as the pull-request report's `beforeMerge.requires` holds it. */
19
+ export interface PrRequireOutcome extends PrRequireResult {
20
+ name: PrApplyRequire;
21
+ }
22
+ export interface PrRequiresOptions {
23
+ /** Status names the `checks` require leaves out: the apply's own. */
24
+ ignore?: readonly string[];
25
+ /** How many times a pending check is asked in all. Default 5. */
26
+ reads?: number;
27
+ /** The wait between reads. Default 3 seconds. */
28
+ wait?: (ms: number) => Promise<void>;
29
+ }
30
+ /**
31
+ * Ask `forge` each of the four checks for pull request `pr` at `head`. A
32
+ * forge client without a method, or a call that throws, gives an unmet
33
+ * check with the reason, so nothing applies on a check nobody made.
34
+ */
35
+ export declare function checkPrRequires(forge: PrForge, pr: number, head: string, opts?: PrRequiresOptions): Promise<PrRequireOutcome[]>;
36
+ /** The unmet checks as one line, or null when all four passed. */
37
+ export declare function unmetRequires(outcomes: readonly PrRequireOutcome[]): string | null;
38
+ //# sourceMappingURL=pr-requires.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pr-requires.d.ts","sourceRoot":"","sources":["../src/pr-requires.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE3D,wEAAwE;AACxE,eAAO,MAAM,iBAAiB,YAAI,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,CAAU,CAAC;AAE5F,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhE,8EAA8E;AAC9E,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,IAAI,EAAE,cAAc,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,qEAAqE;IACrE,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAKD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA6BzI;AAED,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,GAAG,MAAM,GAAG,IAAI,CAIlF"}
@@ -0,0 +1,48 @@
1
+ /** The four checks, in the order they run and the report lists them. */
2
+ export const PR_APPLY_REQUIRES = ["approved", "mergeable", "undiverged", "checks"];
3
+ const READS = 5;
4
+ const WAIT_MS = 3000;
5
+ /**
6
+ * Ask `forge` each of the four checks for pull request `pr` at `head`. A
7
+ * forge client without a method, or a call that throws, gives an unmet
8
+ * check with the reason, so nothing applies on a check nobody made.
9
+ */
10
+ export async function checkPrRequires(forge, pr, head, opts = {}) {
11
+ const wait = opts.wait ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
12
+ const reads = Math.max(1, opts.reads ?? READS);
13
+ const ask = {
14
+ approved: forge.prApproved ? () => forge.prApproved(pr, head) : undefined,
15
+ mergeable: forge.prMergeable ? () => forge.prMergeable(pr, head) : undefined,
16
+ undiverged: forge.prUndiverged ? () => forge.prUndiverged(pr, head) : undefined,
17
+ checks: forge.prChecksPassed ? () => forge.prChecksPassed(pr, head, opts.ignore ?? []) : undefined,
18
+ };
19
+ const out = [];
20
+ for (const name of PR_APPLY_REQUIRES) {
21
+ const call = ask[name];
22
+ if (!call) {
23
+ out.push({ name, passed: false, reason: `this ${forge.kind} client cannot say` });
24
+ continue;
25
+ }
26
+ let result;
27
+ for (let read = 1;; read++) {
28
+ try {
29
+ result = await call();
30
+ }
31
+ catch (err) {
32
+ result = { passed: false, reason: `could not ask ${forge.kind}: ${err instanceof Error ? err.message : String(err)}` };
33
+ }
34
+ if (result.passed || !result.pending || read >= reads)
35
+ break;
36
+ await wait(WAIT_MS);
37
+ }
38
+ out.push({ name, ...result });
39
+ }
40
+ return out;
41
+ }
42
+ /** The unmet checks as one line, or null when all four passed. */
43
+ export function unmetRequires(outcomes) {
44
+ const unmet = outcomes.filter((o) => !o.passed);
45
+ if (unmet.length === 0)
46
+ return null;
47
+ return unmet.map((o) => `${o.name}: ${o.reason}`).join("; ");
48
+ }