@intentius/chant 0.124.32 → 0.124.33

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 (281) hide show
  1. package/dist/ci-jobs.d.ts +4 -0
  2. package/dist/ci-jobs.d.ts.map +1 -1
  3. package/dist/ci-jobs.js +9 -2
  4. package/dist/cli/handlers/build.d.ts.map +1 -1
  5. package/dist/cli/handlers/build.js +18 -3
  6. package/dist/cli/handlers/lifecycle-health.d.ts +16 -0
  7. package/dist/cli/handlers/lifecycle-health.d.ts.map +1 -0
  8. package/dist/cli/handlers/lifecycle-health.js +150 -0
  9. package/dist/cli/handlers/lifecycle.d.ts +26 -0
  10. package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
  11. package/dist/cli/handlers/lifecycle.js +1 -1
  12. package/dist/cli/handlers/pr.d.ts +2 -0
  13. package/dist/cli/handlers/pr.d.ts.map +1 -1
  14. package/dist/cli/handlers/pr.js +124 -2
  15. package/dist/cli/handlers/promote.d.ts.map +1 -1
  16. package/dist/cli/handlers/promote.js +16 -1
  17. package/dist/cli/handlers/release.d.ts +16 -1
  18. package/dist/cli/handlers/release.d.ts.map +1 -1
  19. package/dist/cli/handlers/release.js +83 -11
  20. package/dist/cli/main.d.ts.map +1 -1
  21. package/dist/cli/main.js +81 -21
  22. package/dist/cli/parse-args.d.ts.map +1 -1
  23. package/dist/cli/parse-args.js +23 -1
  24. package/dist/cli/registry.d.ts +18 -4
  25. package/dist/cli/registry.d.ts.map +1 -1
  26. package/dist/components/deploy-inputs.d.ts +91 -0
  27. package/dist/components/deploy-inputs.d.ts.map +1 -0
  28. package/dist/components/deploy-inputs.js +184 -0
  29. package/dist/components/driver.d.ts.map +1 -1
  30. package/dist/components/driver.js +9 -0
  31. package/dist/components/gate-plan.d.ts +8 -0
  32. package/dist/components/gate-plan.d.ts.map +1 -1
  33. package/dist/components/gate-plan.js +6 -0
  34. package/dist/components/pr-pipeline.d.ts +33 -10
  35. package/dist/components/pr-pipeline.d.ts.map +1 -1
  36. package/dist/components/pr-pipeline.js +42 -11
  37. package/dist/components/pr-run.d.ts +1 -1
  38. package/dist/components/pr-run.d.ts.map +1 -1
  39. package/dist/components/release-compile.d.ts +37 -2
  40. package/dist/components/release-compile.d.ts.map +1 -1
  41. package/dist/components/release-compile.js +64 -8
  42. package/dist/components/release-promote.d.ts +17 -3
  43. package/dist/components/release-promote.d.ts.map +1 -1
  44. package/dist/components/release-promote.js +79 -18
  45. package/dist/components/verbs/bom-writer.d.ts +1 -1
  46. package/dist/components/verbs/bom-writer.d.ts.map +1 -1
  47. package/dist/components/verbs/lockfile-sbom-generator.d.ts +20 -0
  48. package/dist/components/verbs/lockfile-sbom-generator.d.ts.map +1 -1
  49. package/dist/components/verbs/lockfile-sbom-generator.js +41 -4
  50. package/dist/components/wave-plan.d.ts +10 -0
  51. package/dist/components/wave-plan.d.ts.map +1 -1
  52. package/dist/components/wave-plan.js +32 -4
  53. package/dist/graph-detail.d.ts.map +1 -1
  54. package/dist/graph-detail.js +32 -7
  55. package/dist/health.d.ts +110 -0
  56. package/dist/health.d.ts.map +1 -0
  57. package/dist/health.js +105 -0
  58. package/dist/health.schema.json +191 -0
  59. package/dist/lexicon.d.ts +27 -0
  60. package/dist/lexicon.d.ts.map +1 -1
  61. package/dist/lifecycle/merge-record.d.ts +104 -0
  62. package/dist/lifecycle/merge-record.d.ts.map +1 -0
  63. package/dist/lifecycle/merge-record.js +102 -0
  64. package/dist/lifecycle/publish-attachments.d.ts +8 -5
  65. package/dist/lifecycle/publish-attachments.d.ts.map +1 -1
  66. package/dist/lifecycle/publish-attachments.js +27 -13
  67. package/dist/lifecycle/publish-npm.d.ts +3 -2
  68. package/dist/lifecycle/publish-npm.d.ts.map +1 -1
  69. package/dist/lifecycle/publish-npm.js +4 -3
  70. package/dist/lifecycle/release-at.d.ts +40 -0
  71. package/dist/lifecycle/release-at.d.ts.map +1 -0
  72. package/dist/lifecycle/release-at.js +83 -0
  73. package/dist/lifecycle/release-cut.d.ts.map +1 -1
  74. package/dist/lifecycle/release-cut.js +23 -12
  75. package/dist/lifecycle/release-publish.d.ts +28 -12
  76. package/dist/lifecycle/release-publish.d.ts.map +1 -1
  77. package/dist/lifecycle/release-publish.js +29 -17
  78. package/dist/lifecycle/release-store.d.ts +25 -2
  79. package/dist/lifecycle/release-store.d.ts.map +1 -1
  80. package/dist/lifecycle/release-store.js +40 -13
  81. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  82. package/dist/lifecycle/run-ledger.js +1 -0
  83. package/dist/lint/rules/op/index.d.ts +2 -1
  84. package/dist/lint/rules/op/index.d.ts.map +1 -1
  85. package/dist/lint/rules/op/index.js +4 -2
  86. package/dist/lint/rules/op/ops018-shell-image-digest.d.ts +10 -0
  87. package/dist/lint/rules/op/ops018-shell-image-digest.d.ts.map +1 -0
  88. package/dist/lint/rules/op/ops018-shell-image-digest.js +38 -0
  89. package/dist/op/activities/activity-contracts.d.ts +5 -0
  90. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  91. package/dist/op/activities/activity-contracts.js +3 -0
  92. package/dist/op/activities/shell.d.ts +38 -0
  93. package/dist/op/activities/shell.d.ts.map +1 -1
  94. package/dist/op/activities/shell.js +89 -3
  95. package/dist/op/builders.d.ts +7 -0
  96. package/dist/op/builders.d.ts.map +1 -1
  97. package/dist/op/builders.js +7 -0
  98. package/dist/op/runtime.d.ts +2 -0
  99. package/dist/op/runtime.d.ts.map +1 -1
  100. package/dist/pr-loop.d.ts +14 -3
  101. package/dist/pr-loop.d.ts.map +1 -1
  102. package/dist/pr-loop.js +15 -5
  103. package/dist/pr-report-url.d.ts +2 -2
  104. package/dist/pr-report-url.d.ts.map +1 -1
  105. package/dist/runner-start.d.ts +179 -0
  106. package/dist/runner-start.d.ts.map +1 -0
  107. package/dist/runner-start.js +277 -0
  108. package/dist/wave-runtime.mjs +235 -228
  109. package/dist/workspace/check.schema.json +70 -2
  110. package/dist/workspace/checks/security.d.ts +35 -0
  111. package/dist/workspace/checks/security.d.ts.map +1 -0
  112. package/dist/workspace/checks/security.js +305 -0
  113. package/dist/workspace/checks.d.ts +2 -0
  114. package/dist/workspace/checks.d.ts.map +1 -1
  115. package/dist/workspace/checks.js +5 -0
  116. package/dist/workspace/ci-builds.d.ts +163 -0
  117. package/dist/workspace/ci-builds.d.ts.map +1 -0
  118. package/dist/workspace/ci-builds.js +315 -0
  119. package/dist/workspace/ci-green-cli.d.ts +2 -1
  120. package/dist/workspace/ci-green-cli.d.ts.map +1 -1
  121. package/dist/workspace/ci-green-cli.js +25 -5
  122. package/dist/workspace/ci-green-forge.d.ts +12 -0
  123. package/dist/workspace/ci-green-forge.d.ts.map +1 -1
  124. package/dist/workspace/ci-green-forge.js +12 -0
  125. package/dist/workspace/ci-green-workflow.d.ts +55 -1
  126. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  127. package/dist/workspace/ci-green-workflow.js +128 -1
  128. package/dist/workspace/ci-green.d.ts +89 -4
  129. package/dist/workspace/ci-green.d.ts.map +1 -1
  130. package/dist/workspace/ci-green.js +310 -23
  131. package/dist/workspace/ci-last-green.schema.json +49 -0
  132. package/dist/workspace/ci-list.schema.json +35 -1
  133. package/dist/workspace/ci-run-index.d.ts +1 -1
  134. package/dist/workspace/ci-run-index.d.ts.map +1 -1
  135. package/dist/workspace/ci-run-index.schema.json +1 -1
  136. package/dist/workspace/ci-run.d.ts +12 -6
  137. package/dist/workspace/ci-run.d.ts.map +1 -1
  138. package/dist/workspace/ci-run.js +72 -16
  139. package/dist/workspace/ci-runner-start.d.ts +77 -0
  140. package/dist/workspace/ci-runner-start.d.ts.map +1 -0
  141. package/dist/workspace/ci-runner-start.js +185 -0
  142. package/dist/workspace/ci-serve.d.ts +76 -7
  143. package/dist/workspace/ci-serve.d.ts.map +1 -1
  144. package/dist/workspace/ci-serve.js +153 -19
  145. package/dist/workspace/declaration.d.ts +17 -0
  146. package/dist/workspace/declaration.d.ts.map +1 -1
  147. package/dist/workspace/declaration.js +3 -0
  148. package/dist/workspace/declaration.schema.json +23 -0
  149. package/dist/workspace/ls.d.ts +2 -0
  150. package/dist/workspace/ls.d.ts.map +1 -1
  151. package/dist/workspace/ls.js +1 -1
  152. package/dist/workspace/ls.schema.json +2 -1
  153. package/dist/workspace/member-pipeline.d.ts +1 -0
  154. package/dist/workspace/member-pipeline.d.ts.map +1 -1
  155. package/dist/workspace/member-pipeline.js +2 -0
  156. package/dist/workspace/merge-record.schema.json +49 -0
  157. package/dist/workspace/pr-report.schema.json +3 -3
  158. package/dist/workspace/reason-codes.d.ts +17 -0
  159. package/dist/workspace/reason-codes.d.ts.map +1 -1
  160. package/dist/workspace/reason-codes.js +18 -0
  161. package/dist/workspace/release-candidates.d.ts +129 -0
  162. package/dist/workspace/release-candidates.d.ts.map +1 -0
  163. package/dist/workspace/release-candidates.js +233 -0
  164. package/dist/workspace/release-candidates.schema.json +353 -0
  165. package/dist/workspace/security.d.ts +40 -0
  166. package/dist/workspace/security.d.ts.map +1 -0
  167. package/dist/workspace/security.js +99 -0
  168. package/package.json +8 -1
  169. package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +1 -1
  170. package/src/ci-jobs.ts +11 -2
  171. package/src/cli/handlers/build.test.ts +36 -0
  172. package/src/cli/handlers/build.ts +18 -3
  173. package/src/cli/handlers/lifecycle-health.test.ts +123 -0
  174. package/src/cli/handlers/lifecycle-health.ts +157 -0
  175. package/src/cli/handlers/lifecycle.ts +1 -1
  176. package/src/cli/handlers/pr-deploy-inputs.test.ts +209 -0
  177. package/src/cli/handlers/pr-record.test.ts +201 -0
  178. package/src/cli/handlers/pr.test.ts +22 -0
  179. package/src/cli/handlers/pr.ts +127 -4
  180. package/src/cli/handlers/promote.test.ts +17 -0
  181. package/src/cli/handlers/promote.ts +16 -1
  182. package/src/cli/handlers/release-cut-at.e2e.test.ts +115 -0
  183. package/src/cli/handlers/release-publish-targets.e2e.test.ts +2 -2
  184. package/src/cli/handlers/release-verify.e2e.test.ts +12 -10
  185. package/src/cli/handlers/release.e2e.test.ts +19 -28
  186. package/src/cli/handlers/release.ts +81 -11
  187. package/src/cli/main.ts +81 -21
  188. package/src/cli/parse-args.ts +17 -1
  189. package/src/cli/registry.ts +18 -4
  190. package/src/components/deploy-inputs.test.ts +108 -0
  191. package/src/components/deploy-inputs.ts +225 -0
  192. package/src/components/driver.ts +11 -0
  193. package/src/components/gate-plan.ts +9 -0
  194. package/src/components/pr-pipeline.ts +56 -15
  195. package/src/components/pr-run.ts +1 -1
  196. package/src/components/release-compile.test.ts +34 -0
  197. package/src/components/release-compile.ts +89 -8
  198. package/src/components/release-promote.test.ts +55 -2
  199. package/src/components/release-promote.ts +93 -23
  200. package/src/components/verbs/bom-writer.ts +1 -1
  201. package/src/components/verbs/lockfile-sbom-generator.test.ts +36 -0
  202. package/src/components/verbs/lockfile-sbom-generator.ts +43 -5
  203. package/src/components/wave-plan.ts +32 -4
  204. package/src/graph-detail.test.ts +57 -0
  205. package/src/graph-detail.ts +33 -7
  206. package/src/health.schema.json +191 -0
  207. package/src/health.test.ts +62 -0
  208. package/src/health.ts +178 -0
  209. package/src/lexicon.ts +41 -1
  210. package/src/lifecycle/merge-record.test.ts +111 -0
  211. package/src/lifecycle/merge-record.ts +154 -0
  212. package/src/lifecycle/publish-attachments.ts +25 -13
  213. package/src/lifecycle/publish-npm.ts +4 -3
  214. package/src/lifecycle/publish-targets.test.ts +34 -4
  215. package/src/lifecycle/release-at.test.ts +48 -0
  216. package/src/lifecycle/release-at.ts +100 -0
  217. package/src/lifecycle/release-cut.test.ts +41 -0
  218. package/src/lifecycle/release-cut.ts +22 -11
  219. package/src/lifecycle/release-publish.test.ts +43 -13
  220. package/src/lifecycle/release-publish.ts +38 -18
  221. package/src/lifecycle/release-store.ts +57 -13
  222. package/src/lifecycle/run-ledger.test.ts +13 -0
  223. package/src/lifecycle/run-ledger.ts +1 -0
  224. package/src/lint/rules/op/index.ts +4 -2
  225. package/src/lint/rules/op/ops018-shell-image-digest.test.ts +60 -0
  226. package/src/lint/rules/op/ops018-shell-image-digest.ts +48 -0
  227. package/src/op/activities/activity-contracts.ts +3 -0
  228. package/src/op/activities/shell-container.e2e.test.ts +67 -0
  229. package/src/op/activities/shell.test.ts +44 -1
  230. package/src/op/activities/shell.ts +110 -3
  231. package/src/op/builders.ts +7 -0
  232. package/src/op/runtime.ts +2 -0
  233. package/src/op/step-console.test.ts +4 -2
  234. package/src/pr-loop.test.ts +29 -0
  235. package/src/pr-loop.ts +26 -7
  236. package/src/pr-report-url.ts +2 -2
  237. package/src/runner-start-bundle.test.ts +29 -0
  238. package/src/runner-start.test.ts +179 -0
  239. package/src/runner-start.ts +329 -0
  240. package/src/workspace/check-contract.test.ts +3 -2
  241. package/src/workspace/check.schema.json +70 -2
  242. package/src/workspace/checks/security.test.ts +138 -0
  243. package/src/workspace/checks/security.ts +305 -0
  244. package/src/workspace/checks.ts +5 -0
  245. package/src/workspace/ci-builds.e2e.test.ts +208 -0
  246. package/src/workspace/ci-builds.test.ts +174 -0
  247. package/src/workspace/ci-builds.ts +385 -0
  248. package/src/workspace/ci-green-builds.test.ts +180 -0
  249. package/src/workspace/ci-green-cli.test.ts +54 -0
  250. package/src/workspace/ci-green-cli.ts +26 -5
  251. package/src/workspace/ci-green-forge.ts +24 -0
  252. package/src/workspace/ci-green-workflow.test.ts +84 -1
  253. package/src/workspace/ci-green-workflow.ts +139 -2
  254. package/src/workspace/ci-green.test.ts +5 -2
  255. package/src/workspace/ci-green.ts +359 -27
  256. package/src/workspace/ci-last-green.schema.json +49 -0
  257. package/src/workspace/ci-list.schema.json +35 -1
  258. package/src/workspace/ci-run-index.schema.json +1 -1
  259. package/src/workspace/ci-run-index.ts +1 -1
  260. package/src/workspace/ci-run.test.ts +24 -7
  261. package/src/workspace/ci-run.ts +78 -16
  262. package/src/workspace/ci-runner-start.test.ts +151 -0
  263. package/src/workspace/ci-runner-start.ts +193 -0
  264. package/src/workspace/ci-serve-builds.test.ts +86 -0
  265. package/src/workspace/ci-serve.test.ts +59 -0
  266. package/src/workspace/ci-serve.ts +177 -22
  267. package/src/workspace/declaration.schema.json +23 -0
  268. package/src/workspace/declaration.test.ts +17 -0
  269. package/src/workspace/declaration.ts +22 -1
  270. package/src/workspace/ls.schema.json +2 -1
  271. package/src/workspace/ls.ts +3 -2
  272. package/src/workspace/member-pipeline.ts +2 -1
  273. package/src/workspace/merge-record.schema.json +49 -0
  274. package/src/workspace/pr-report.schema.json +3 -3
  275. package/src/workspace/reason-codes.test.ts +2 -0
  276. package/src/workspace/reason-codes.ts +18 -0
  277. package/src/workspace/release-candidates.schema.json +353 -0
  278. package/src/workspace/release-candidates.test.ts +106 -0
  279. package/src/workspace/release-candidates.ts +315 -0
  280. package/src/workspace/security.test.ts +70 -0
  281. package/src/workspace/security.ts +118 -0
@@ -0,0 +1,91 @@
1
+ /**
2
+ * The local files a component's steps deploy from, and their content digests
3
+ * (#4155).
4
+ *
5
+ * A component gate approves `componentPlanDigest` (./gate-plan.ts). A step
6
+ * whose capability has a `plan` is bound by what it plans. Every other step
7
+ * was bound only by its input as written, so a Helm chart, a kustomize
8
+ * directory or a static site's tree could change after review without moving
9
+ * the digest. This module names those files and hashes them, so the digest
10
+ * moves when they do.
11
+ *
12
+ * Which fields name a path is data, as the template fields are in
13
+ * ./release-compile.ts and the unit fields in ./deploy-units.ts: a kind's
14
+ * fields in {@link DEPLOY_INPUT_FIELDS}, plus `template`, `manifest` and
15
+ * `values` on any step ({@link TEMPLATE_FIELDS}). Only a literal path counts:
16
+ * a value wired from another step (`@Build.uri`) or an `archive:` path is a
17
+ * build output, and binding it would make an approval unusable by a build
18
+ * that is not reproducible. The build steps' own sources are bound instead.
19
+ *
20
+ * - A file is hashed by its bytes.
21
+ * - A directory is hashed over the files under it that git does not ignore
22
+ * (`git ls-files --cached --others --exclude-standard`), each by its path
23
+ * and bytes, so `node_modules` and a build's `dist` inside a Docker context
24
+ * are left out. Outside a git repository every file is hashed except under
25
+ * `.git` and `node_modules`.
26
+ * - A directory git ignores as a whole is a build output. It is not hashed;
27
+ * the step is listed as unbound, with that reason.
28
+ * - A path that does not exist is left out. One that appears later moves the
29
+ * digest.
30
+ *
31
+ * A step whose kind runs content chant can't name, such as `shell`, is listed
32
+ * as unbound ({@link UNBOUND_KINDS}), so the plan note can show a reviewer
33
+ * what the approval does not cover.
34
+ */
35
+ import type { DriverPhase, DriverStep } from "./driver.js";
36
+ /** The fields that name every step's deployed file, whatever its kind (as ./release-compile.ts reads them). */
37
+ export declare const TEMPLATE_FIELDS: readonly string[];
38
+ /** Per kind, the fields beyond {@link TEMPLATE_FIELDS} that name a local file or directory the step deploys or builds from. */
39
+ export declare const DEPLOY_INPUT_FIELDS: Readonly<Record<string, readonly string[]>>;
40
+ /** Kinds that deploy content chant can't name from their input: a command, an agent's work. */
41
+ export declare const UNBOUND_KINDS: readonly string[];
42
+ /** One path a step names. */
43
+ export interface DeployInputRef {
44
+ phase: string;
45
+ kind: string;
46
+ field: string;
47
+ /** Relative to the member's directory, as written. */
48
+ path: string;
49
+ }
50
+ /** A named path and the digest of what is there. */
51
+ export interface DeployInputDigest {
52
+ path: string;
53
+ /** `sha256:<hex>` of a file's bytes, or a plan digest over a directory's files. */
54
+ digest: string;
55
+ }
56
+ /** A step the digest does not cover, and why. */
57
+ export interface UnboundStep {
58
+ phase: string;
59
+ kind: string;
60
+ reason: string;
61
+ }
62
+ /** What a component's steps deploy from: the digests, and the steps they can't cover. */
63
+ export interface ComponentDeployInputs {
64
+ inputs: DeployInputDigest[];
65
+ unbound: UnboundStep[];
66
+ }
67
+ /** Every capability step of a composition with its phase, nested phases included, gates left out. */
68
+ export declare function stepsWithPhase(phases: readonly DriverPhase[]): Array<{
69
+ phase: string;
70
+ step: DriverStep;
71
+ }>;
72
+ /** The literal paths one step names, in field order. A Docker build's Dockerfile is named under its context. */
73
+ export declare function stepInputRefs(phase: string, step: DriverStep): DeployInputRef[];
74
+ /** The files under `dir` (relative to `root`) a directory digest covers, relative to `root`, sorted. */
75
+ export declare function directoryFiles(root: string, dir: string): string[];
76
+ /** Every file under `dir`, relative to `root`, sorted, leaving out `.git` and `node_modules`. What a cut records of a directory git ignores. */
77
+ export declare function walkFiles(root: string, dir: string): string[];
78
+ /** Whether git ignores `path` (relative to `root`). False outside a git repository. */
79
+ export declare function ignoredByGit(root: string, path: string): boolean;
80
+ /** `sha256:<hex>` of a file's bytes. */
81
+ export declare function fileDigest(file: string): string;
82
+ /** The digest of the files under `dir`: a plan digest over each file's path (from `dir`) and bytes. */
83
+ export declare function directoryDigest(root: string, dir: string): string;
84
+ /**
85
+ * What a component's steps deploy from, read under `root` (the member's
86
+ * directory). `include` picks the steps to read, all of them by default; the
87
+ * wave planner passes the steps without a `plan`, which their plan does not
88
+ * already cover.
89
+ */
90
+ export declare function componentDeployInputs(phases: readonly DriverPhase[], root: string, include?: (step: DriverStep) => boolean): ComponentDeployInputs;
91
+ //# sourceMappingURL=deploy-inputs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy-inputs.d.ts","sourceRoot":"","sources":["../../src/components/deploy-inputs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAOH,OAAO,KAAK,EAAc,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEpE,+GAA+G;AAC/G,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAAuC,CAAC;AAErF,+HAA+H;AAC/H,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAa3E,CAAC;AAEF,+FAA+F;AAC/F,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAA2B,CAAC;AAEvE,6BAA6B;AAC7B,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,oDAAoD;AACpD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,iDAAiD;AACjD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,yFAAyF;AACzF,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAaD,qGAAqG;AACrG,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAUzG;AAED,gHAAgH;AAChH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,cAAc,EAAE,CAY/E;AAOD,wGAAwG;AACxG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAWlE;AAED,gJAAgJ;AAChJ,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAY7D;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED,wCAAwC;AACxC,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,uGAAuG;AACvG,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAOjE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAoB,GAClD,qBAAqB,CA4BvB"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * The local files a component's steps deploy from, and their content digests
3
+ * (#4155).
4
+ *
5
+ * A component gate approves `componentPlanDigest` (./gate-plan.ts). A step
6
+ * whose capability has a `plan` is bound by what it plans. Every other step
7
+ * was bound only by its input as written, so a Helm chart, a kustomize
8
+ * directory or a static site's tree could change after review without moving
9
+ * the digest. This module names those files and hashes them, so the digest
10
+ * moves when they do.
11
+ *
12
+ * Which fields name a path is data, as the template fields are in
13
+ * ./release-compile.ts and the unit fields in ./deploy-units.ts: a kind's
14
+ * fields in {@link DEPLOY_INPUT_FIELDS}, plus `template`, `manifest` and
15
+ * `values` on any step ({@link TEMPLATE_FIELDS}). Only a literal path counts:
16
+ * a value wired from another step (`@Build.uri`) or an `archive:` path is a
17
+ * build output, and binding it would make an approval unusable by a build
18
+ * that is not reproducible. The build steps' own sources are bound instead.
19
+ *
20
+ * - A file is hashed by its bytes.
21
+ * - A directory is hashed over the files under it that git does not ignore
22
+ * (`git ls-files --cached --others --exclude-standard`), each by its path
23
+ * and bytes, so `node_modules` and a build's `dist` inside a Docker context
24
+ * are left out. Outside a git repository every file is hashed except under
25
+ * `.git` and `node_modules`.
26
+ * - A directory git ignores as a whole is a build output. It is not hashed;
27
+ * the step is listed as unbound, with that reason.
28
+ * - A path that does not exist is left out. One that appears later moves the
29
+ * digest.
30
+ *
31
+ * A step whose kind runs content chant can't name, such as `shell`, is listed
32
+ * as unbound ({@link UNBOUND_KINDS}), so the plan note can show a reviewer
33
+ * what the approval does not cover.
34
+ */
35
+ import { spawnSync } from "node:child_process";
36
+ import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
37
+ import { join, relative, resolve, sep } from "node:path";
38
+ import { sha256Hex } from "../content-digest.js";
39
+ import { computePlanDigest } from "../lifecycle/plan-digest.js";
40
+ /** The fields that name every step's deployed file, whatever its kind (as ./release-compile.ts reads them). */
41
+ export const TEMPLATE_FIELDS = ["template", "manifest", "values"];
42
+ /** Per kind, the fields beyond {@link TEMPLATE_FIELDS} that name a local file or directory the step deploys or builds from. */
43
+ export const DEPLOY_INPUT_FIELDS = {
44
+ "helm-upgrade": ["chart"],
45
+ "kustomize-apply": ["dir"],
46
+ "fly-release": ["plan"],
47
+ "fly-rollback": ["plan"],
48
+ "s3-sync": ["from"],
49
+ "r2-sync": ["from"],
50
+ "copy-to-host": ["from"],
51
+ "wrangler-deploy": ["config"],
52
+ "wrangler-versions-promote": ["config"],
53
+ "docker-build": ["context"],
54
+ "zip-package": ["source"],
55
+ "jvm-build": ["path"],
56
+ };
57
+ /** Kinds that deploy content chant can't name from their input: a command, an agent's work. */
58
+ export const UNBOUND_KINDS = ["shell", "run-agent"];
59
+ function isGate(step) {
60
+ return step.kind === "gate";
61
+ }
62
+ function isPhase(step) {
63
+ return typeof step.phase === "string" && Array.isArray(step.steps);
64
+ }
65
+ const isLiteralPath = (v) => typeof v === "string" && v !== "" && !v.startsWith("@") && !v.startsWith("$") && !v.startsWith("archive:");
66
+ /** Every capability step of a composition with its phase, nested phases included, gates left out. */
67
+ export function stepsWithPhase(phases) {
68
+ const out = [];
69
+ const walk = (phase) => {
70
+ for (const step of phase.steps) {
71
+ if (isPhase(step))
72
+ walk(step);
73
+ else if (!isGate(step))
74
+ out.push({ phase: phase.phase, step });
75
+ }
76
+ };
77
+ phases.forEach(walk);
78
+ return out;
79
+ }
80
+ /** The literal paths one step names, in field order. A Docker build's Dockerfile is named under its context. */
81
+ export function stepInputRefs(phase, step) {
82
+ const out = [];
83
+ for (const field of [...TEMPLATE_FIELDS, ...(DEPLOY_INPUT_FIELDS[step.kind] ?? [])]) {
84
+ const raw = step[field];
85
+ for (const value of Array.isArray(raw) ? raw : [raw]) {
86
+ if (isLiteralPath(value))
87
+ out.push({ phase, kind: step.kind, field, path: value });
88
+ }
89
+ }
90
+ if (step.kind === "docker-build" && isLiteralPath(step.context) && isLiteralPath(step.dockerfile)) {
91
+ out.push({ phase, kind: step.kind, field: "dockerfile", path: join(step.context, step.dockerfile) });
92
+ }
93
+ return out;
94
+ }
95
+ function git(root, args) {
96
+ const r = spawnSync("git", ["-C", root, ...args], { encoding: "utf-8", maxBuffer: 256 * 1024 * 1024 });
97
+ return { ok: r.status === 0, out: r.stdout ?? "" };
98
+ }
99
+ /** The files under `dir` (relative to `root`) a directory digest covers, relative to `root`, sorted. */
100
+ export function directoryFiles(root, dir) {
101
+ const listed = git(root, ["ls-files", "-z", "--cached", "--others", "--exclude-standard", "--", dir]);
102
+ if (listed.ok) {
103
+ return [...new Set(listed.out.split("\0").filter((p) => p !== ""))]
104
+ .filter((p) => {
105
+ const full = resolve(root, p);
106
+ return existsSync(full) && statSync(full).isFile();
107
+ })
108
+ .sort();
109
+ }
110
+ return walkFiles(root, dir);
111
+ }
112
+ /** Every file under `dir`, relative to `root`, sorted, leaving out `.git` and `node_modules`. What a cut records of a directory git ignores. */
113
+ export function walkFiles(root, dir) {
114
+ const out = [];
115
+ const walk = (abs) => {
116
+ for (const entry of readdirSync(abs, { withFileTypes: true })) {
117
+ if (entry.name === ".git" || entry.name === "node_modules")
118
+ continue;
119
+ const full = join(abs, entry.name);
120
+ if (entry.isDirectory())
121
+ walk(full);
122
+ else if (entry.isFile())
123
+ out.push(relative(root, full).split(sep).join("/"));
124
+ }
125
+ };
126
+ walk(resolve(root, dir));
127
+ return out.sort();
128
+ }
129
+ /** Whether git ignores `path` (relative to `root`). False outside a git repository. */
130
+ export function ignoredByGit(root, path) {
131
+ return git(root, ["check-ignore", "-q", "--", path]).ok;
132
+ }
133
+ /** `sha256:<hex>` of a file's bytes. */
134
+ export function fileDigest(file) {
135
+ return `sha256:${sha256Hex(readFileSync(file))}`;
136
+ }
137
+ /** The digest of the files under `dir`: a plan digest over each file's path (from `dir`) and bytes. */
138
+ export function directoryDigest(root, dir) {
139
+ const base = resolve(root, dir);
140
+ const files = directoryFiles(root, dir).map((p) => ({
141
+ path: relative(base, resolve(root, p)).split(sep).join("/"),
142
+ digest: fileDigest(resolve(root, p)),
143
+ }));
144
+ return computePlanDigest("directory", files);
145
+ }
146
+ /**
147
+ * What a component's steps deploy from, read under `root` (the member's
148
+ * directory). `include` picks the steps to read, all of them by default; the
149
+ * wave planner passes the steps without a `plan`, which their plan does not
150
+ * already cover.
151
+ */
152
+ export function componentDeployInputs(phases, root, include = () => true) {
153
+ const inputs = new Map();
154
+ const unbound = [];
155
+ for (const { phase, step } of stepsWithPhase(phases)) {
156
+ if (!include(step))
157
+ continue;
158
+ if (UNBOUND_KINDS.includes(step.kind)) {
159
+ unbound.push({ phase, kind: step.kind, reason: `a ${step.kind} step runs content chant can't name from its input` });
160
+ continue;
161
+ }
162
+ for (const ref of stepInputRefs(phase, step)) {
163
+ if (inputs.has(ref.path))
164
+ continue;
165
+ const full = resolve(root, ref.path);
166
+ if (!existsSync(full))
167
+ continue;
168
+ if (statSync(full).isDirectory()) {
169
+ if (ignoredByGit(root, ref.path)) {
170
+ unbound.push({ phase, kind: step.kind, reason: `its ${ref.field} "${ref.path}" is a directory git ignores, so a build output; bind its sources through the step that builds it` });
171
+ continue;
172
+ }
173
+ inputs.set(ref.path, directoryDigest(root, ref.path));
174
+ }
175
+ else {
176
+ inputs.set(ref.path, fileDigest(full));
177
+ }
178
+ }
179
+ }
180
+ return {
181
+ inputs: [...inputs].map(([path, digest]) => ({ path, digest })).sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0)),
182
+ unbound,
183
+ };
184
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/components/driver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/components/driver.ts"],"names":[],"mappings":"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"}
@@ -51,6 +51,7 @@ import { evaluateGate, gitGateLedgerPort } from "../op/gate.js";
51
51
  import { gateName } from "../op/gate-name.js";
52
52
  import { GateNotRecordableError } from "../lifecycle/no-record.js";
53
53
  import { componentPlanDigest } from "./gate-plan.js";
54
+ import { componentDeployInputs } from "./deploy-inputs.js";
54
55
  import { isPlanMovedError, PLAN_MOVED_EXIT_CODE } from "./capability.js";
55
56
  import { isPromotedArtifact } from "./auto-release.js";
56
57
  import { gateEventsOf, joinRunEventSinks, progressSinkOf } from "../run-event-stream.js";
@@ -570,6 +571,11 @@ async function rollbackExecuted(executed, ctx, registry) {
570
571
  return records;
571
572
  }
572
573
  // ── Per-component deploy ─────────────────────────────────────────────────
574
+ /** Whether a component's composition has a gate step anywhere, nested phases and `rollback` included. */
575
+ function hasGateStep(component) {
576
+ const walk = (steps) => steps.some((step) => isGateStep(step) || (Array.isArray(step.steps) && walk(step.steps)));
577
+ return [...component.deploy, ...(component.rollback ?? [])].some((p) => walk(p.steps));
578
+ }
573
579
  /**
574
580
  * Run one component's `deploy` composition. On terminal failure: unwind every
575
581
  * executed step in reverse via its capability's `rollback` (saga
@@ -610,6 +616,9 @@ export async function runComponentDeploy(component, ctx, registry, componentOutp
610
616
  component,
611
617
  ...(ctx.vars ? { vars: ctx.vars } : {}),
612
618
  ...(release !== undefined ? { release } : {}),
619
+ // #4155: the files the steps deploy from, read where the steps read
620
+ // them. Only a gate reads the digest, so a run with none skips the hashing.
621
+ ...(hasGateStep(component) ? { inputs: componentDeployInputs(component.deploy, process.cwd()).inputs } : {}),
613
622
  }),
614
623
  };
615
624
  const records = [];
@@ -17,6 +17,11 @@
17
17
  * its publish output against a recorded digest that is not in the
18
18
  * composition, so it passes that digest here.
19
19
  * - `vars`, the environment config the caller resolved ahead of the run.
20
+ * - The content digests of the local files the steps deploy from (#4155,
21
+ * ./deploy-inputs.ts): a chart, a manifest, a site's tree, a build step's
22
+ * sources. A file changed after review moves the digest. The key is left
23
+ * out when no step names an existing file, so a composition that deploys
24
+ * none keeps the digest it had before #4155.
20
25
  *
21
26
  * ## What it leaves out
22
27
  *
@@ -26,6 +31,7 @@
26
31
  * upstream components. The run id and the time are left out for the reasons
27
32
  * `../lifecycle/plan-digest.ts` gives.
28
33
  */
34
+ import type { DeployInputDigest } from "./deploy-inputs.js";
29
35
  import type { DriverComponent } from "./driver.js";
30
36
  /** What a component gate's plan digest is taken over. */
31
37
  export interface ComponentGatePlan {
@@ -34,6 +40,8 @@ export interface ComponentGatePlan {
34
40
  vars?: Record<string, unknown>;
35
41
  /** The recorded digest a promote or rollback deploys, when the caller has one. */
36
42
  release?: string;
43
+ /** What the steps deploy from (`componentDeployInputs`), when the caller read it. */
44
+ inputs?: readonly DeployInputDigest[];
37
45
  }
38
46
  /** The plan digest a component gate records and approves. */
39
47
  export declare function componentPlanDigest(plan: ComponentGatePlan): string;
@@ -1 +1 @@
1
- {"version":3,"file":"gate-plan.d.ts","sourceRoot":"","sources":["../../src/components/gate-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,yDAAyD;AACzD,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,eAAe,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,6DAA6D;AAC7D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAUnE"}
1
+ {"version":3,"file":"gate-plan.d.ts","sourceRoot":"","sources":["../../src/components/gate-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,yDAAyD;AACzD,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,eAAe,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,MAAM,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACvC;AAED,6DAA6D;AAC7D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAWnE"}
@@ -17,6 +17,11 @@
17
17
  * its publish output against a recorded digest that is not in the
18
18
  * composition, so it passes that digest here.
19
19
  * - `vars`, the environment config the caller resolved ahead of the run.
20
+ * - The content digests of the local files the steps deploy from (#4155,
21
+ * ./deploy-inputs.ts): a chart, a manifest, a site's tree, a build step's
22
+ * sources. A file changed after review moves the digest. The key is left
23
+ * out when no step names an existing file, so a composition that deploys
24
+ * none keeps the digest it had before #4155.
20
25
  *
21
26
  * ## What it leaves out
22
27
  *
@@ -37,5 +42,6 @@ export function componentPlanDigest(plan) {
37
42
  rollback: component.rollback ?? null,
38
43
  vars: plan.vars ?? null,
39
44
  release: plan.release ?? null,
45
+ ...(plan.inputs && plan.inputs.length > 0 ? { inputs: plan.inputs } : {}),
40
46
  });
41
47
  }
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * The jobs of a generated pull-request pipeline (#3183): a plan job on every
3
- * pull request and an apply job on every push to the target branch.
3
+ * pull request and, on every push to the target branch, a record job, or an
4
+ * apply job when the pipeline opts into apply on merge (#4168).
4
5
  *
5
6
  * Each forge's generator (the github, gitlab and forgejo lexicons) adds its
6
7
  * own triggers, permissions and artifact handling; the commands and the
@@ -9,11 +10,19 @@
9
10
  * - The plan job runs `chant components pr-plan` against the pull request's
10
11
  * target commit. It posts the note and the `chant/plan` status and writes
11
12
  * nothing to `chant/lifecycle`, since it runs the pull request's code.
12
- * - The apply job runs `chant components pr-apply` against the commit the
13
+ * - The record job (#4168 step 1, the default) runs `chant components
14
+ * pr-record` against the commit the push replaced. It plans the same
15
+ * members on the merged commit, stores the change set and writes the merge
16
+ * record, `_merges/<commit>.json` on `chant/lifecycle`. It applies nothing:
17
+ * a release that carries the commit deploys it. It needs write access to
18
+ * `chant/lifecycle`. One record runs at a time per environment.
19
+ * - With `applyOnMerge` the apply job takes the record job's place. It runs
20
+ * `chant components pr-apply` against the commit the
13
21
  * push replaced, finds the pull request that merged the pushed commit
14
22
  * through the forge, and applies only when an approval stands for the
15
- * digest it plans. With `requireReview` (the default) the approver must
16
- * also have approved the pull request on the forge. It needs write access
23
+ * digest it plans. With `requireReview` (off by default since #4168, on
24
+ * under the `review-rules` security group) the approver must also have
25
+ * approved the pull request on the forge. It needs write access
17
26
  * to `chant/lifecycle`, to record the pending fact when the gate stops it.
18
27
  * One apply runs at a time per environment.
19
28
  *
@@ -35,6 +44,7 @@
35
44
  * it too. With `reportUrl` both pass `--report-url`, which copies the report,
36
45
  * the change set and the events where a reader outside CI can fetch them;
37
46
  * the job's own environment brings the credentials an `s3://` URL needs.
47
+ * The record job passes the same flags as the apply.
38
48
  *
39
49
  * With `build` (#4088) both jobs run the project's build and `chant lint`
40
50
  * before their command, and fail on an error. A `cfn-deploy` member's plan
@@ -104,8 +114,16 @@ export interface PrLoopPipelineOptions {
104
114
  * GitHub and Forgejo; on GitLab, the project's default branch.
105
115
  */
106
116
  branch?: string;
107
- /** Count an approval only from someone who approved the pull request on the forge. Default true. */
117
+ /** Count an approval only from someone who approved the pull request on the forge. Default false (#4168): review rules are opt-in. */
108
118
  requireReview?: boolean;
119
+ /** The job on merge (apply, or record since #4168) has `chant ci run` refuse to start without a runner-start statement for it (`--require-runner-start`, #4147), as under the `isolated-runners` security group (#4168). Default false. */
120
+ requireRunnerStart?: boolean;
121
+ /**
122
+ * Apply the approved plan on merge (#4168), as every pull-request pipeline
123
+ * did before #4168: the apply job in place of the record job. Default
124
+ * false, so a merge deploys nothing. `waveGate` needs it.
125
+ */
126
+ applyOnMerge?: boolean;
109
127
  /**
110
128
  * Stream each job's run events (#4007): `--events-json` on both commands,
111
129
  * and `CHANT_RUN_EVENTS_DIR` set to {@link PR_LOOP_EVENTS_DIR}. Default false.
@@ -146,8 +164,8 @@ export interface PrLoopPipelineOptions {
146
164
  }
147
165
  /** One job's command and the forge values it reads, as environment variables for its step. */
148
166
  export interface PrLoopJob {
149
- /** `plan` or `apply`. */
150
- jobName: "plan" | "apply";
167
+ /** `plan`, `apply` or `record` (#4168). */
168
+ jobName: "plan" | "apply" | "record";
151
169
  /** The command line. Reads `$BASE_SHA` and, for the plan, `$PR_NUMBER`. */
152
170
  command: string;
153
171
  /**
@@ -178,11 +196,14 @@ export interface PrLoopJob {
178
196
  /** The lines `build` (#4088) runs before a job's command: the build, then the lint. Empty without the option. */
179
197
  export declare function prLoopBuildLines(env: string, options?: PrLoopPipelineOptions): string[];
180
198
  /**
181
- * The two jobs for `forge`. `member` is the workspace member the pipeline is
182
- * generated for; the commands then run in its directory, so `--output` is
183
- * relative to it.
199
+ * The jobs for `forge`: plan, apply and record, in that order. A generator
200
+ * writes the plan and, on merge, {@link prLoopMergeJob}'s choice of the
201
+ * other two. `member` is the workspace member the pipeline is generated for;
202
+ * the commands then run in its directory, so `--output` is relative to it.
184
203
  */
185
204
  export declare function prLoopJobs(forge: ForgeKind, env: string, options?: PrLoopPipelineOptions, member?: string): PrLoopJob[];
205
+ /** The job a push to the target branch runs (#4168): `record`, or `apply` when the pipeline opts into apply on merge. */
206
+ export declare function prLoopMergeJob(jobs: readonly PrLoopJob[], options?: PrLoopPipelineOptions): PrLoopJob;
186
207
  /**
187
208
  * The pull-request options with `--wave-gate` beside `--pr-loop` (#4003):
188
209
  * the apply gets a gate per wave. A canary or a fixed base is refused, since
@@ -211,6 +232,8 @@ export declare function prLoopWaveJobs(components: DriverComponent[], apply: PrL
211
232
  * apart from a single project's `chant-apply-<env>`.
212
233
  */
213
234
  export declare function prApplyGroup(env: string, member?: string): string;
235
+ /** The group that keeps one record job at a time per environment and member (#4168), named as {@link prApplyGroup} names the apply's. */
236
+ export declare function prRecordGroup(env: string, member?: string): string;
214
237
  /**
215
238
  * The cache key the apply job keeps its attempt record under (#3543), with
216
239
  * `commit` the forge's expression for the pushed commit. A push of another
@@ -1 +1 @@
1
- {"version":3,"file":"pr-pipeline.d.ts","sourceRoot":"","sources":["../../src/components/pr-pipeline.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pr-pipeline.d.ts","sourceRoot":"","sources":["../../src/components/pr-pipeline.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * The jobs of a generated pull-request pipeline (#3183): a plan job on every
3
- * pull request and an apply job on every push to the target branch.
3
+ * pull request and, on every push to the target branch, a record job, or an
4
+ * apply job when the pipeline opts into apply on merge (#4168).
4
5
  *
5
6
  * Each forge's generator (the github, gitlab and forgejo lexicons) adds its
6
7
  * own triggers, permissions and artifact handling; the commands and the
@@ -9,11 +10,19 @@
9
10
  * - The plan job runs `chant components pr-plan` against the pull request's
10
11
  * target commit. It posts the note and the `chant/plan` status and writes
11
12
  * nothing to `chant/lifecycle`, since it runs the pull request's code.
12
- * - The apply job runs `chant components pr-apply` against the commit the
13
+ * - The record job (#4168 step 1, the default) runs `chant components
14
+ * pr-record` against the commit the push replaced. It plans the same
15
+ * members on the merged commit, stores the change set and writes the merge
16
+ * record, `_merges/<commit>.json` on `chant/lifecycle`. It applies nothing:
17
+ * a release that carries the commit deploys it. It needs write access to
18
+ * `chant/lifecycle`. One record runs at a time per environment.
19
+ * - With `applyOnMerge` the apply job takes the record job's place. It runs
20
+ * `chant components pr-apply` against the commit the
13
21
  * push replaced, finds the pull request that merged the pushed commit
14
22
  * through the forge, and applies only when an approval stands for the
15
- * digest it plans. With `requireReview` (the default) the approver must
16
- * also have approved the pull request on the forge. It needs write access
23
+ * digest it plans. With `requireReview` (off by default since #4168, on
24
+ * under the `review-rules` security group) the approver must also have
25
+ * approved the pull request on the forge. It needs write access
17
26
  * to `chant/lifecycle`, to record the pending fact when the gate stops it.
18
27
  * One apply runs at a time per environment.
19
28
  *
@@ -35,6 +44,7 @@
35
44
  * it too. With `reportUrl` both pass `--report-url`, which copies the report,
36
45
  * the change set and the events where a reader outside CI can fetch them;
37
46
  * the job's own environment brings the credentials an `s3://` URL needs.
47
+ * The record job passes the same flags as the apply.
38
48
  *
39
49
  * With `build` (#4088) both jobs run the project's build and `chant lint`
40
50
  * before their command, and fail on an error. A `cfn-deploy` member's plan
@@ -109,9 +119,10 @@ export function prLoopBuildLines(env, options = {}) {
109
119
  return [options.buildCommand ?? `chant build --env ${env}`, "chant lint"];
110
120
  }
111
121
  /**
112
- * The two jobs for `forge`. `member` is the workspace member the pipeline is
113
- * generated for; the commands then run in its directory, so `--output` is
114
- * relative to it.
122
+ * The jobs for `forge`: plan, apply and record, in that order. A generator
123
+ * writes the plan and, on merge, {@link prLoopMergeJob}'s choice of the
124
+ * other two. `member` is the workspace member the pipeline is generated for;
125
+ * the commands then run in its directory, so `--output` is relative to it.
115
126
  */
116
127
  export function prLoopJobs(forge, env, options = {}, member) {
117
128
  const gate = options.gate ?? PR_APPLY_GATE;
@@ -133,9 +144,10 @@ export function prLoopJobs(forge, env, options = {}, member) {
133
144
  "chant", "ci", "run", job, "--in-place", ...(job === "plan" ? ["--no-push"] : []),
134
145
  "--base", '"$BASE_SHA"', ...(job === "plan" ? ["--pr", '"$PR_NUMBER"'] : []),
135
146
  "--env", env, "--gate", gate, "--forge", forge,
136
- ...(options.waveGate ? ["--wave-gate", options.waveGate] : []),
137
- ...(job === "apply" && options.branch ? ["--branch", JSON.stringify(options.branch)] : []),
138
- ...(job === "apply" && options.requireReview === false ? ["--no-require-review"] : []),
147
+ ...(job !== "record" && options.waveGate ? ["--wave-gate", options.waveGate] : []),
148
+ ...(job !== "plan" && options.branch ? ["--branch", JSON.stringify(options.branch)] : []),
149
+ ...(job === "apply" && options.requireReview === true ? ["--require-review"] : []),
150
+ ...(job !== "plan" && options.requireRunnerStart === true ? ["--require-runner-start"] : []),
139
151
  ...(options.events ? ["--events-json"] : []),
140
152
  ...(options.reportUrl ? ["--report-url", JSON.stringify(options.reportUrl)] : []),
141
153
  ];
@@ -157,7 +169,7 @@ export function prLoopJobs(forge, env, options = {}, member) {
157
169
  jobName: "apply",
158
170
  command: [
159
171
  "chant", "components", "pr-apply", "--base", '"$BASE_SHA"', ...common,
160
- ...(options.requireReview === false ? [] : ["--require-review"]),
172
+ ...(options.requireReview === true ? ["--require-review"] : []),
161
173
  ...(options.waveGate ? ["--wave-gate", options.waveGate] : []),
162
174
  "--resume", PR_APPLY_RECORD,
163
175
  ].join(" "),
@@ -166,8 +178,20 @@ export function prLoopJobs(forge, env, options = {}, member) {
166
178
  ...build,
167
179
  run: { command: ciRun("apply").join(" "), env: runEnv(applyEnv) },
168
180
  },
181
+ {
182
+ jobName: "record",
183
+ command: ["chant", "components", "pr-record", "--base", '"$BASE_SHA"', ...common].join(" "),
184
+ env: applyEnv,
185
+ setup: [github ? githubBaseFallback(options.branch) : gitlabBaseFallback(options.branch)],
186
+ ...build,
187
+ run: { command: ciRun("record").join(" "), env: runEnv(applyEnv) },
188
+ },
169
189
  ];
170
190
  }
191
+ /** The job a push to the target branch runs (#4168): `record`, or `apply` when the pipeline opts into apply on merge. */
192
+ export function prLoopMergeJob(jobs, options = {}) {
193
+ return jobs.find((j) => j.jobName === (options.applyOnMerge ? "apply" : "record"));
194
+ }
171
195
  /**
172
196
  * The pull-request options with `--wave-gate` beside `--pr-loop` (#4003):
173
197
  * the apply gets a gate per wave. A canary or a fixed base is refused, since
@@ -177,6 +201,9 @@ export function prLoopJobs(forge, env, options = {}, member) {
177
201
  export function prLoopWithWaves(prLoop, gatedWaves) {
178
202
  if (!gatedWaves)
179
203
  return prLoop;
204
+ if (!prLoop.applyOnMerge) {
205
+ throw new Error("--wave-gate beside --pr-loop gates the apply on merge, so it needs --apply-on-merge (#4168); without it a merge records the plan and a release deploys it");
206
+ }
180
207
  if (gatedWaves.canary?.length)
181
208
  throw new Error("a pull-request pipeline's waves are the change's derivation, so it takes no --canary; drop --canary");
182
209
  if (gatedWaves.base !== undefined)
@@ -217,6 +244,10 @@ export function prLoopWaveJobs(components, apply) {
217
244
  export function prApplyGroup(env, member) {
218
245
  return member ? `chant-apply.${member}.${env}` : `chant-apply-${env}`;
219
246
  }
247
+ /** The group that keeps one record job at a time per environment and member (#4168), named as {@link prApplyGroup} names the apply's. */
248
+ export function prRecordGroup(env, member) {
249
+ return member ? `chant-record.${member}.${env}` : `chant-record-${env}`;
250
+ }
220
251
  /**
221
252
  * The cache key the apply job keeps its attempt record under (#3543), with
222
253
  * `commit` the forge's expression for the pushed commit. A push of another
@@ -307,7 +307,7 @@ export declare function prWavePlan(plan: FanOutPlan, components: DriverComponent
307
307
  */
308
308
  export declare function waveNotCovered(approved: ChangeSetDocument, fresh: ChangeSetDocument, approvedMembers?: readonly PrMember[]): string[];
309
309
  export interface PrReportInput {
310
- stage: "plan" | "apply";
310
+ stage: "plan" | "apply" | "record";
311
311
  pr: number | null;
312
312
  env: string;
313
313
  /** The workspace member whose pipeline runs the stage (#3465). */