@intentius/chant 0.124.33 → 0.124.35

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 (218) hide show
  1. package/dist/cli/handlers/graph.js +2 -2
  2. package/dist/cli/handlers/pr.d.ts.map +1 -1
  3. package/dist/cli/handlers/pr.js +147 -51
  4. package/dist/cli/handlers/promote.d.ts.map +1 -1
  5. package/dist/cli/handlers/promote.js +284 -81
  6. package/dist/cli/handlers/release.d.ts +12 -0
  7. package/dist/cli/handlers/release.d.ts.map +1 -1
  8. package/dist/cli/handlers/release.js +125 -10
  9. package/dist/cli/handlers/run.d.ts +3 -1
  10. package/dist/cli/handlers/run.d.ts.map +1 -1
  11. package/dist/cli/handlers/run.js +12 -2
  12. package/dist/cli/main.d.ts.map +1 -1
  13. package/dist/cli/main.js +37 -2
  14. package/dist/cli/parse-args.d.ts.map +1 -1
  15. package/dist/cli/parse-args.js +24 -0
  16. package/dist/cli/registry.d.ts +17 -1
  17. package/dist/cli/registry.d.ts.map +1 -1
  18. package/dist/components/auto-release.d.ts +8 -1
  19. package/dist/components/auto-release.d.ts.map +1 -1
  20. package/dist/components/auto-release.js +3 -2
  21. package/dist/components/green-cover.d.ts +77 -0
  22. package/dist/components/green-cover.d.ts.map +1 -0
  23. package/dist/components/green-cover.js +153 -0
  24. package/dist/components/pr-pipeline.d.ts +34 -0
  25. package/dist/components/pr-pipeline.d.ts.map +1 -1
  26. package/dist/components/pr-pipeline.js +39 -5
  27. package/dist/components/promote-rounds.d.ts +102 -0
  28. package/dist/components/promote-rounds.d.ts.map +1 -0
  29. package/dist/components/promote-rounds.js +174 -0
  30. package/dist/components/promote.d.ts +4 -1
  31. package/dist/components/promote.d.ts.map +1 -1
  32. package/dist/components/promote.js +6 -3
  33. package/dist/components/release-gate.d.ts +30 -0
  34. package/dist/components/release-gate.d.ts.map +1 -1
  35. package/dist/components/release-gate.js +92 -42
  36. package/dist/components/release-promote.d.ts +9 -0
  37. package/dist/components/release-promote.d.ts.map +1 -1
  38. package/dist/components/release-promote.js +15 -0
  39. package/dist/config.d.ts +2 -0
  40. package/dist/config.d.ts.map +1 -1
  41. package/dist/deep-observation.d.ts +11 -0
  42. package/dist/deep-observation.d.ts.map +1 -1
  43. package/dist/graph-declared.d.ts +9 -1
  44. package/dist/graph-declared.d.ts.map +1 -1
  45. package/dist/graph-declared.js +18 -3
  46. package/dist/graph-detail.d.ts.map +1 -1
  47. package/dist/graph-detail.js +30 -1
  48. package/dist/graph-ir.d.ts.map +1 -1
  49. package/dist/graph-ir.js +13 -2
  50. package/dist/lifecycle/__fixtures__/publish-fakes.d.ts.map +1 -1
  51. package/dist/lifecycle/__fixtures__/publish-fakes.js +5 -1
  52. package/dist/lifecycle/compose-refs.d.ts +52 -0
  53. package/dist/lifecycle/compose-refs.d.ts.map +1 -0
  54. package/dist/lifecycle/compose-refs.js +115 -0
  55. package/dist/lifecycle/deep-observe.d.ts.map +1 -1
  56. package/dist/lifecycle/deep-observe.js +3 -2
  57. package/dist/lifecycle/green-apply.d.ts +39 -0
  58. package/dist/lifecycle/green-apply.d.ts.map +1 -0
  59. package/dist/lifecycle/green-apply.js +51 -0
  60. package/dist/lifecycle/publish-declaration.d.ts +4 -0
  61. package/dist/lifecycle/publish-declaration.d.ts.map +1 -1
  62. package/dist/lifecycle/publish-declaration.js +15 -0
  63. package/dist/lifecycle/publish-npm.d.ts +7 -4
  64. package/dist/lifecycle/publish-npm.d.ts.map +1 -1
  65. package/dist/lifecycle/publish-npm.js +60 -13
  66. package/dist/lifecycle/release-compose.d.ts +91 -0
  67. package/dist/lifecycle/release-compose.d.ts.map +1 -0
  68. package/dist/lifecycle/release-compose.js +235 -0
  69. package/dist/lifecycle/release-cut.d.ts +8 -0
  70. package/dist/lifecycle/release-cut.d.ts.map +1 -1
  71. package/dist/lifecycle/release-cut.js +2 -0
  72. package/dist/lifecycle/release-publish.d.ts +2 -0
  73. package/dist/lifecycle/release-publish.d.ts.map +1 -1
  74. package/dist/lifecycle/release-publish.js +2 -1
  75. package/dist/lifecycle/release-store.d.ts +15 -0
  76. package/dist/lifecycle/release-store.d.ts.map +1 -1
  77. package/dist/lifecycle/release-store.js +5 -1
  78. package/dist/wave-runtime.mjs +226 -224
  79. package/dist/workspace/__fixtures__/contract-repo.d.ts.map +1 -1
  80. package/dist/workspace/__fixtures__/contract-repo.js +13 -2
  81. package/dist/workspace/check.schema.json +20 -2
  82. package/dist/workspace/checks/ci-workflow.d.ts +17 -0
  83. package/dist/workspace/checks/ci-workflow.d.ts.map +1 -0
  84. package/dist/workspace/checks/ci-workflow.js +130 -0
  85. package/dist/workspace/checks/security.d.ts +16 -1
  86. package/dist/workspace/checks/security.d.ts.map +1 -1
  87. package/dist/workspace/checks/security.js +4 -4
  88. package/dist/workspace/checks.d.ts +1 -1
  89. package/dist/workspace/checks.d.ts.map +1 -1
  90. package/dist/workspace/checks.js +4 -1
  91. package/dist/workspace/ci-green-cli.d.ts.map +1 -1
  92. package/dist/workspace/ci-green-cli.js +5 -3
  93. package/dist/workspace/ci-green-workflow.d.ts +18 -2
  94. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  95. package/dist/workspace/ci-green-workflow.js +27 -5
  96. package/dist/workspace/ci-green.d.ts +31 -0
  97. package/dist/workspace/ci-green.d.ts.map +1 -1
  98. package/dist/workspace/ci-green.js +78 -4
  99. package/dist/workspace/ci-init.d.ts +100 -0
  100. package/dist/workspace/ci-init.d.ts.map +1 -0
  101. package/dist/workspace/ci-init.js +434 -0
  102. package/dist/workspace/ci-run.d.ts +6 -0
  103. package/dist/workspace/ci-run.d.ts.map +1 -1
  104. package/dist/workspace/ci-run.js +2 -1
  105. package/dist/workspace/ci-serve.d.ts +94 -13
  106. package/dist/workspace/ci-serve.d.ts.map +1 -1
  107. package/dist/workspace/ci-serve.js +248 -30
  108. package/dist/workspace/ci-workflow.d.ts +91 -0
  109. package/dist/workspace/ci-workflow.d.ts.map +1 -0
  110. package/dist/workspace/ci-workflow.js +33 -0
  111. package/dist/workspace/declaration.d.ts +18 -0
  112. package/dist/workspace/declaration.d.ts.map +1 -1
  113. package/dist/workspace/declaration.js +9 -2
  114. package/dist/workspace/declaration.schema.json +28 -0
  115. package/dist/workspace/delivery-metrics.d.ts +3 -1
  116. package/dist/workspace/delivery-metrics.d.ts.map +1 -1
  117. package/dist/workspace/delivery-metrics.js +12 -3
  118. package/dist/workspace/init.js +2 -2
  119. package/dist/workspace/member-commands.d.ts.map +1 -1
  120. package/dist/workspace/member-commands.js +4 -0
  121. package/dist/workspace/nested-graph.d.ts.map +1 -1
  122. package/dist/workspace/nested-graph.js +1 -0
  123. package/dist/workspace/reason-codes.d.ts +9 -0
  124. package/dist/workspace/reason-codes.d.ts.map +1 -1
  125. package/dist/workspace/reason-codes.js +10 -0
  126. package/dist/workspace/release-candidates.d.ts +28 -0
  127. package/dist/workspace/release-candidates.d.ts.map +1 -1
  128. package/dist/workspace/release-candidates.js +38 -2
  129. package/dist/workspace/release-candidates.schema.json +51 -0
  130. package/dist/workspace/release-workflow.d.ts +31 -0
  131. package/dist/workspace/release-workflow.d.ts.map +1 -0
  132. package/dist/workspace/release-workflow.js +150 -0
  133. package/dist/workspace/releases.schema.json +30 -0
  134. package/package.json +1 -1
  135. package/src/cli/handlers/graph.ts +2 -2
  136. package/src/cli/handlers/pr-green.test.ts +230 -0
  137. package/src/cli/handlers/pr.ts +148 -66
  138. package/src/cli/handlers/promote.test.ts +34 -0
  139. package/src/cli/handlers/promote.ts +302 -91
  140. package/src/cli/handlers/release-compose.e2e.test.ts +133 -0
  141. package/src/cli/handlers/release.ts +112 -10
  142. package/src/cli/handlers/run.ts +12 -1
  143. package/src/cli/main.ts +37 -2
  144. package/src/cli/parse-args.ts +18 -0
  145. package/src/cli/registry.ts +17 -1
  146. package/src/codegen/release-wiring.test.ts +56 -9
  147. package/src/components/auto-release.test.ts +22 -0
  148. package/src/components/auto-release.ts +9 -2
  149. package/src/components/green-cover.test.ts +170 -0
  150. package/src/components/green-cover.ts +186 -0
  151. package/src/components/pr-pipeline.test.ts +14 -4
  152. package/src/components/pr-pipeline.ts +56 -5
  153. package/src/components/promote-rounds.test.ts +220 -0
  154. package/src/components/promote-rounds.ts +232 -0
  155. package/src/components/promote.test.ts +7 -0
  156. package/src/components/promote.ts +9 -4
  157. package/src/components/release-gate.test.ts +47 -0
  158. package/src/components/release-gate.ts +111 -46
  159. package/src/components/release-promote.test.ts +24 -1
  160. package/src/components/release-promote.ts +15 -0
  161. package/src/deep-observation.ts +8 -0
  162. package/src/graph-declared-exports.test.ts +40 -0
  163. package/src/graph-declared.test.ts +18 -0
  164. package/src/graph-declared.ts +17 -2
  165. package/src/graph-detail.test.ts +68 -1
  166. package/src/graph-detail.ts +29 -1
  167. package/src/graph-ir.ts +12 -4
  168. package/src/lifecycle/__fixtures__/publish-fakes.ts +5 -1
  169. package/src/lifecycle/compose-refs.ts +125 -0
  170. package/src/lifecycle/deep-observe.test.ts +20 -0
  171. package/src/lifecycle/deep-observe.ts +4 -2
  172. package/src/lifecycle/green-apply.ts +71 -0
  173. package/src/lifecycle/publish-declaration.ts +15 -0
  174. package/src/lifecycle/publish-npm.ts +55 -13
  175. package/src/lifecycle/publish-targets.test.ts +45 -0
  176. package/src/lifecycle/release-compose.test.ts +125 -0
  177. package/src/lifecycle/release-compose.ts +312 -0
  178. package/src/lifecycle/release-cut.ts +6 -0
  179. package/src/lifecycle/release-publish.ts +4 -1
  180. package/src/lifecycle/release-store.ts +16 -1
  181. package/src/workspace/__fixtures__/contract-repo.ts +11 -2
  182. package/src/workspace/check-contract.test.ts +3 -2
  183. package/src/workspace/check.schema.json +20 -2
  184. package/src/workspace/checks/ci-workflow.test.ts +160 -0
  185. package/src/workspace/checks/ci-workflow.ts +135 -0
  186. package/src/workspace/checks/security.ts +4 -4
  187. package/src/workspace/checks.ts +4 -1
  188. package/src/workspace/ci-green-cli.ts +5 -3
  189. package/src/workspace/ci-green-workflow.test.ts +52 -0
  190. package/src/workspace/ci-green-workflow.ts +34 -5
  191. package/src/workspace/ci-green.test.ts +33 -0
  192. package/src/workspace/ci-green.ts +85 -4
  193. package/src/workspace/ci-init.test.ts +159 -0
  194. package/src/workspace/ci-init.ts +445 -0
  195. package/src/workspace/ci-report-url.test.ts +6 -1
  196. package/src/workspace/ci-run.test.ts +18 -13
  197. package/src/workspace/ci-run.ts +8 -1
  198. package/src/workspace/ci-serve-land.e2e.test.ts +138 -0
  199. package/src/workspace/ci-serve-land.test.ts +176 -0
  200. package/src/workspace/ci-serve.test.ts +77 -43
  201. package/src/workspace/ci-serve.ts +268 -34
  202. package/src/workspace/ci-workflow.ts +71 -0
  203. package/src/workspace/declaration.schema.json +28 -0
  204. package/src/workspace/declaration.ts +32 -3
  205. package/src/workspace/delivery-metrics.ts +12 -3
  206. package/src/workspace/graph-contract.test.ts +3 -2
  207. package/src/workspace/init.ts +2 -2
  208. package/src/workspace/member-commands.test.ts +11 -4
  209. package/src/workspace/member-commands.ts +3 -0
  210. package/src/workspace/nested-graph.test.ts +4 -0
  211. package/src/workspace/nested-graph.ts +1 -0
  212. package/src/workspace/reason-codes.test.ts +2 -0
  213. package/src/workspace/reason-codes.ts +10 -0
  214. package/src/workspace/release-candidates.schema.json +51 -0
  215. package/src/workspace/release-candidates.test.ts +30 -3
  216. package/src/workspace/release-candidates.ts +54 -2
  217. package/src/workspace/release-workflow.ts +167 -0
  218. package/src/workspace/releases.schema.json +30 -0
@@ -1 +1 @@
1
- {"version":3,"file":"contract-repo.d.ts","sourceRoot":"","sources":["../../../src/workspace/__fixtures__/contract-repo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,OAAO,MAAM,eAAe,CAAC;AAGpC,6CAA6C;AAC7C,eAAO,MAAM,IAAI,QAAwE,CAAC;AAI1F,gGAAgG;AAChG,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAED,wBAAgB,UAAU,CAAC,MAAM,SAAoB,GAAG,MAAM,CAI7D;AAED,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAM1D;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,IAAI,CAO7G;AAED,uFAAuF;AACvF,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,MAAM,UAAQ,GAAG,MAAM,CAS3G;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,MAAM,EAAE,MAAM,SAAyB,GAAG,MAAM,MAAM,CAQ9F;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,SAAS,GAAG,MAAM,CAIhE;AAED,QAAA,MAAM,GAAG,SAAiD,CAAC;AAE3D,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,UAAU,CAAC,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC;IAAC,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CAStH;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,eAAO,MAAM,WAAW,YAAa,OAAO,EAAE,UAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WACL,CAAC;AAE1E;;;GAGG;AACH,eAAO,MAAM,gBAAgB,6XAU5B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,sZASjC,CAAC"}
1
+ {"version":3,"file":"contract-repo.d.ts","sourceRoot":"","sources":["../../../src/workspace/__fixtures__/contract-repo.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,OAAO,MAAM,eAAe,CAAC;AAGpC,6CAA6C;AAC7C,eAAO,MAAM,IAAI,QAAwE,CAAC;AAI1F,gGAAgG;AAChG,wBAAgB,YAAY,IAAI,IAAI,CAEnC;AAED,wBAAgB,UAAU,CAAC,MAAM,SAAoB,GAAG,MAAM,CAI7D;AAED,wBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,CAM1D;AAED,iFAAiF;AACjF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,IAAI,CAO7G;AAED,uFAAuF;AACvF,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,MAAM,UAAQ,GAAG,MAAM,CAS3G;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,MAAM,EAAE,MAAM,SAAyB,GAAG,MAAM,MAAM,CAiB9F;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,SAAS,GAAG,MAAM,CAIhE;AAED,QAAA,MAAM,GAAG,SAAiD,CAAC;AAE3D,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,UAAU,CAAC,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC;IAAC,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CAStH;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,eAAO,MAAM,WAAW,YAAa,OAAO,EAAE,UAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,WACL,CAAC;AAE1E;;;GAGG;AACH,eAAO,MAAM,gBAAgB,6XAU5B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,sZASjC,CAAC"}
@@ -22,7 +22,7 @@ export function scratchDir(prefix = "chant-contract-") {
22
22
  return d;
23
23
  }
24
24
  export function git(cwd, ...args) {
25
- return execFileSync("git", ["-c", "user.name=t", "-c", "user.email=t@example.com", "-c", "commit.gpgsign=false", ...args], {
25
+ return execFileSync("git", ["-c", "user.name=t", "-c", "user.email=t@example.com", "-c", "commit.gpgsign=false", "-c", "gc.auto=0", "-c", "maintenance.auto=false", ...args], {
26
26
  cwd,
27
27
  encoding: "utf-8",
28
28
  stdio: ["ignore", "pipe", "pipe"],
@@ -61,7 +61,18 @@ export function repoFixture(build, prefix = "chant-contract-copy-") {
61
61
  if (template === undefined || !existsSync(template))
62
62
  template = build();
63
63
  const root = scratchDir(prefix);
64
- cpSync(template, root, { recursive: true });
64
+ // A commit can leave a detached `git gc --auto` or maintenance run moving
65
+ // the template's objects, and a copy that meets it fails with ENOENT on
66
+ // .git/objects. Copy once more after it settles.
67
+ try {
68
+ cpSync(template, root, { recursive: true });
69
+ }
70
+ catch (err) {
71
+ if (err.code !== "ENOENT")
72
+ throw err;
73
+ rmSync(root, { recursive: true, force: true });
74
+ cpSync(template, root, { recursive: true });
75
+ }
65
76
  return root;
66
77
  };
67
78
  }
@@ -332,7 +332,16 @@
332
332
 
333
333
  "security-runner-start-no-role",
334
334
 
335
- "security-trust-unreadable"
335
+ "security-trust-unreadable",
336
+ "ci-workflow-green-undeclared",
337
+ "ci-workflow-no-pre-merge",
338
+ "ci-workflow-apply-in-green",
339
+ "ci-workflow-no-components",
340
+ "ci-workflow-no-environments",
341
+ "ci-workflow-ungated-env",
342
+ "ci-workflow-pipeline-missing",
343
+ "ci-workflow-pipeline-differs",
344
+ "ci-workflow-publish-missing"
336
345
  ],
337
346
  "description": "For WSP001: why the declaration can't be read. For WSP121 to WSP127, the box finding (#2726, #2727, #2780, #2850). For WSP117, work-acceptance-unmet (#2772). For WSP118, flag-stale (#4024). For WSP131 to WSP133, the diagram finding (#2764)."
338
347
  }
@@ -445,7 +454,16 @@
445
454
 
446
455
  "security-runner-start-no-role",
447
456
 
448
- "security-trust-unreadable"
457
+ "security-trust-unreadable",
458
+ "ci-workflow-green-undeclared",
459
+ "ci-workflow-no-pre-merge",
460
+ "ci-workflow-apply-in-green",
461
+ "ci-workflow-no-components",
462
+ "ci-workflow-no-environments",
463
+ "ci-workflow-ungated-env",
464
+ "ci-workflow-pipeline-missing",
465
+ "ci-workflow-pipeline-differs",
466
+ "ci-workflow-publish-missing"
449
467
  ],
450
468
  "description": "For WSP001: why the declaration can't be read. For WSP121 to WSP127, the box finding (#2726, #2727, #2780, #2850). For WSP117, work-acceptance-unmet (#2772). For WSP118, flag-stale (#4024). For WSP131 to WSP133, the diagram finding (#2764)."
451
469
  },
@@ -0,0 +1,17 @@
1
+ /**
2
+ * WSP151 (#4168 step 6): what a member under `ci.workflow` still lacks.
3
+ *
4
+ * A declaration that names no workflow gets no finding from this file. The
5
+ * requirements and their codes are {@link CI_WORKFLOW_REQUIREMENTS}
6
+ * (../ci-workflow.ts). Like the security checklists (./security.ts), the
7
+ * check reads files and never runs them: `chant.config.ts` for the
8
+ * environments (its literal `environments`, as `workspace status` reads it),
9
+ * `*.component.ts` for components and gates, and the forge pipeline files for
10
+ * the jobs. A generated file that differs from what its generator writes is
11
+ * WSP101 to WSP106's to report; this check asks only whether the jobs the
12
+ * workflow needs are there.
13
+ */
14
+ import type { WorkspaceCheck } from "../checks.js";
15
+ export declare const WSP_CI_WORKFLOW = "WSP151";
16
+ export declare const CI_WORKFLOW_CHECKS: readonly WorkspaceCheck[];
17
+ //# sourceMappingURL=ci-workflow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci-workflow.d.ts","sourceRoot":"","sources":["../../../src/workspace/checks/ci-workflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAuB,MAAM,WAAW,CAAC;AAQrE,eAAO,MAAM,eAAe,WAAW,CAAC;AAaxC,eAAO,MAAM,kBAAkB,EAAE,SAAS,cAAc,EAmGvD,CAAC"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * WSP151 (#4168 step 6): what a member under `ci.workflow` still lacks.
3
+ *
4
+ * A declaration that names no workflow gets no finding from this file. The
5
+ * requirements and their codes are {@link CI_WORKFLOW_REQUIREMENTS}
6
+ * (../ci-workflow.ts). Like the security checklists (./security.ts), the
7
+ * check reads files and never runs them: `chant.config.ts` for the
8
+ * environments (its literal `environments`, as `workspace status` reads it),
9
+ * `*.component.ts` for components and gates, and the forge pipeline files for
10
+ * the jobs. A generated file that differs from what its generator writes is
11
+ * WSP101 to WSP106's to report; this check asks only whether the jobs the
12
+ * workflow needs are there.
13
+ */
14
+ import { appliesOnMerge, STUB_MARKER, workflowOf } from "../ci-workflow.js";
15
+ import { matchesCheckRun } from "../ci-green.js";
16
+ import { staticPromotionOrder } from "../promotion-order.js";
17
+ import { joinPath } from "../tree.js";
18
+ import { allPipelineFiles, commandLines, componentFiles, read } from "./security.js";
19
+ export const WSP_CI_WORKFLOW = "WSP151";
20
+ const memberDir = (dir) => (dir === "." ? "" : dir);
21
+ const PLAN = /\bci\s+run\s+plan\b|\bcomponents\s+pr-plan\b/;
22
+ const RECORD = /\bci\s+run\s+record\b|\bcomponents\s+pr-record\b/;
23
+ const APPLY = /\bci\s+run\s+apply\b|\bcomponents\s+pr-apply\b/;
24
+ const TICK = /\bci\s+tick\b/;
25
+ const PUBLISH = /\brelease\s+publish\b/;
26
+ /** The apply job names a required phase could match. */
27
+ const APPLY_JOB_NAMES = ["apply", "pr-apply"];
28
+ export const CI_WORKFLOW_CHECKS = [
29
+ {
30
+ id: WSP_CI_WORKFLOW,
31
+ name: "ci-workflow",
32
+ description: "Under ci.workflow: ci.green with pre-merge phases and no apply job required, each member with a component, environments and a gate on each component, and pipeline files that plan, record (or apply under apply on merge), tick and publish.",
33
+ severity: "warning",
34
+ configurable: true,
35
+ check(ctx) {
36
+ const d = ctx.declaration;
37
+ const under = d.members
38
+ .map((m) => ({ member: m, workflow: workflowOf(d, m) }))
39
+ .filter((u) => u.workflow !== null)
40
+ // The top level's workflow covers the members that build with chant; a member that names one itself is held to it.
41
+ .filter((u) => u.member.ciWorkflow !== null || ctx.tree.stat(joinPath(memberDir(u.member.dir), "chant.config.ts")) === "file");
42
+ if (under.length === 0 && !d.ci?.workflow)
43
+ return [];
44
+ const pointer = d.ci?.workflow ? "/ci/workflow" : `${under[0].member.pointer}/ci/workflow`;
45
+ const out = [];
46
+ const finding = (code, message, at = {}) => {
47
+ out.push({
48
+ checkId: this.id,
49
+ severity: this.severity,
50
+ code,
51
+ message: `${code}: ${message}`,
52
+ pointer: at.pointer ?? pointer,
53
+ ...(at.entity !== undefined ? { entity: at.entity } : {}),
54
+ ...(at.treeFile !== undefined ? { treeFile: at.treeFile, line: at.line ?? 1, column: 1 } : {}),
55
+ });
56
+ };
57
+ const green = d.ci?.green ?? null;
58
+ if (!green) {
59
+ finding("ci-workflow-green-undeclared", "the workspace follows a ci.workflow and declares no ci.green, so no commit gets a verdict and no release can be cut; run chant ci init or add a ci.green block");
60
+ }
61
+ else {
62
+ if ((green.preMerge ?? []).length === 0) {
63
+ finding("ci-workflow-no-pre-merge", "ci.green.preMerge names no phase, so nothing says which checks run before the branch moves; name the quick ones", { pointer: green.pointer });
64
+ }
65
+ for (const name of green.require) {
66
+ const phase = green.phases.find((p) => p.name === name);
67
+ const hit = phase?.runs.find((pattern) => APPLY_JOB_NAMES.some((job) => matchesCheckRun(pattern, job)));
68
+ if (phase && hit) {
69
+ finding("ci-workflow-apply-in-green", `the required phase ${name} matches the apply job with ${JSON.stringify(hit)}, so an apply that waits for a green commit would wait on itself; drop the pattern`, { pointer: phase.pointer });
70
+ }
71
+ }
72
+ }
73
+ for (const { member } of under) {
74
+ const dir = memberDir(member.dir);
75
+ const components = componentFiles(ctx.tree, dir);
76
+ if (components.length === 0) {
77
+ finding("ci-workflow-no-components", `member ${member.name} declares no component, so nothing of it can be cut or promoted; chant ci init writes a stub`, { pointer: member.pointer, entity: member.name });
78
+ }
79
+ else if (components.every((f) => (read(ctx.tree, f) ?? "").includes(STUB_MARKER))) {
80
+ finding("ci-workflow-no-components", `member ${member.name}'s only component is the stub chant ci init wrote (${components[0]}); say how it is built and deployed, then delete its ${STUB_MARKER} line`, { pointer: member.pointer, entity: member.name, treeFile: components[0] });
81
+ }
82
+ const configPath = joinPath(dir, "chant.config.ts");
83
+ const config = read(ctx.tree, configPath);
84
+ // A config whose environments aren't literals can't be read without running it; say nothing rather than guess.
85
+ const order = config === null ? [] : staticPromotionOrder(config);
86
+ if (order !== undefined && order.length === 0) {
87
+ finding("ci-workflow-no-environments", `member ${member.name}'s chant.config.ts declares no environments, so a release has nowhere to be promoted to`, { pointer: member.pointer, entity: member.name, ...(config !== null ? { treeFile: configPath } : {}) });
88
+ }
89
+ for (const file of components) {
90
+ const text = read(ctx.tree, file) ?? "";
91
+ if (/\bgate\s*\(|kind\s*:\s*["']gate["']/.test(text))
92
+ continue;
93
+ const last = order && order.length > 0 ? order[order.length - 1].name : "the last environment";
94
+ finding("ci-workflow-ungated-env", `${file} has no gate, so a promote to ${last} waits on no approval; add a gate() step`, { pointer: member.pointer, entity: member.name, treeFile: file });
95
+ }
96
+ }
97
+ const files = allPipelineFiles(ctx);
98
+ const has = (re) => files.some((f) => f.lines.some((l) => re.test(l)));
99
+ const applyOnMerge = under.some((u) => appliesOnMerge(u.workflow)) || (d.ci?.workflow ? appliesOnMerge(d.ci.workflow) : false);
100
+ const missing = [
101
+ ...(has(PLAN) ? [] : ["a plan job (ci run plan)"]),
102
+ // #4168 step 9: every merge is recorded, apply on merge or not, since the apply reads the merge records.
103
+ ...(has(RECORD) ? [] : ["a record job (ci run record)"]),
104
+ ...(has(TICK) ? [] : ["chant ci tick"]),
105
+ ];
106
+ if (missing.length > 0) {
107
+ finding("ci-workflow-pipeline-missing", `no pipeline file runs ${missing.join(", ")}; generate them with chant build --components --generate <forge> --pr-loop and chant ci workflow`);
108
+ }
109
+ if (!applyOnMerge) {
110
+ for (const l of commandLines(ctx, APPLY)) {
111
+ finding("ci-workflow-pipeline-differs", `${l.path} applies on merge, and the workflow is trunk-curated, where a merge records the plan and deploys nothing; regenerate without --apply-on-merge, or set ci.workflow to trunk-curated+apply-on-merge`, { treeFile: l.path, line: l.line });
112
+ }
113
+ }
114
+ else if (!has(APPLY) && has(RECORD)) {
115
+ const l = commandLines(ctx, RECORD)[0];
116
+ finding("ci-workflow-pipeline-differs", `${l.path} records on merge, and the workflow is trunk-curated+apply-on-merge; regenerate with --apply-on-merge`, { treeFile: l.path, line: l.line });
117
+ }
118
+ else {
119
+ // #4168 step 9: an apply measured from a push's base applies each merge; the workflow applies green commits.
120
+ for (const l of commandLines(ctx, APPLY).filter((c) => /--base\b/.test(c.text) || (/\bcomponents\s+pr-apply\b/.test(c.text) && !/--green\b/.test(c.text)))) {
121
+ finding("ci-workflow-pipeline-differs", `${l.path} applies each merge, and under trunk-curated+apply-on-merge the apply applies the newest green commit; regenerate with --apply-on-merge`, { treeFile: l.path, line: l.line });
122
+ }
123
+ }
124
+ if (!has(PUBLISH)) {
125
+ finding("ci-workflow-publish-missing", "no pipeline file runs chant release publish, so a cut release is never published; generate one with chant release workflow");
126
+ }
127
+ return out;
128
+ },
129
+ },
130
+ ];
@@ -23,7 +23,8 @@
23
23
  * pipeline file that runs `chant release publish`, `chant ci tick` or
24
24
  * `chant components pr-apply`.
25
25
  */
26
- import type { WorkspaceCheck } from "../checks.js";
26
+ import type { WorkspaceCheck, WorkspaceCheckContext } from "../checks.js";
27
+ import { type WorkspaceTree } from "../tree.js";
27
28
  /** The read contract's codes for the security findings, carried as `code` on each. */
28
29
  export declare const SECURITY_FINDING_CODES: readonly ["security-signers-missing", "security-release-gate-missing", "security-publish-allows-unsigned", "security-sbom-disabled", "security-sbom-unsourced", "security-publish-no-provenance", "security-component-no-sbom", "security-component-no-verify", "security-signed-since-unset", "security-runner-untrusted", "security-tick-no-key", "security-review-not-required", "security-attribution-any", "security-gate-unsigned", "security-runner-start-no-key", "security-runner-start-no-role", "security-trust-unreadable"];
29
30
  export declare const WSP_SECURITY_VERIFIED_RELEASES = "WSP161";
@@ -31,5 +32,19 @@ export declare const WSP_SECURITY_SUPPLY_CHAIN = "WSP162";
31
32
  export declare const WSP_SECURITY_WHO_RAN_IT = "WSP163";
32
33
  export declare const WSP_SECURITY_REVIEW_RULES = "WSP164";
33
34
  export declare const WSP_SECURITY_ISOLATED_RUNNERS = "WSP165";
35
+ export declare function read(tree: WorkspaceTree, path: string): string | null;
36
+ /** Every pipeline file of the workspace: its root's, and each member's. */
37
+ export declare function allPipelineFiles(ctx: WorkspaceCheckContext): {
38
+ path: string;
39
+ lines: string[];
40
+ }[];
41
+ /** The lines of the pipeline files that run a chant command, `command` naming it, such as `release publish`. */
42
+ export declare function commandLines(ctx: WorkspaceCheckContext, command: RegExp): {
43
+ path: string;
44
+ line: number;
45
+ text: string;
46
+ }[];
47
+ /** The member's `*.component.ts` files, walked a few levels down, past node_modules and build output. */
48
+ export declare function componentFiles(tree: WorkspaceTree, dir: string, depth?: number): string[];
34
49
  export declare const SECURITY_CHECKS: readonly WorkspaceCheck[];
35
50
  //# sourceMappingURL=security.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../src/workspace/checks/security.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAA8C,MAAM,WAAW,CAAC;AAU5F,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,ygBAkBO,CAAC;AAI3C,eAAO,MAAM,8BAA8B,WAAW,CAAC;AACvD,eAAO,MAAM,yBAAyB,WAAW,CAAC;AAClD,eAAO,MAAM,uBAAuB,WAAW,CAAC;AAChD,eAAO,MAAM,yBAAyB,WAAW,CAAC;AAClD,eAAO,MAAM,6BAA6B,WAAW,CAAC;AA0GtD,eAAO,MAAM,eAAe,EAAE,SAAS,cAAc,EAuIpD,CAAC"}
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../../src/workspace/checks/security.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAuB,MAAM,WAAW,CAAC;AAI5F,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,SAAS,CAAC;AAMvD,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,ygBAkBO,CAAC;AAI3C,eAAO,MAAM,8BAA8B,WAAW,CAAC;AACvD,eAAO,MAAM,yBAAyB,WAAW,CAAC;AAClD,eAAO,MAAM,uBAAuB,WAAW,CAAC;AAChD,eAAO,MAAM,yBAAyB,WAAW,CAAC;AAClD,eAAO,MAAM,6BAA6B,WAAW,CAAC;AAsBtD,wBAAgB,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOrE;AAkBD,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,qBAAqB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,EAAE,CAGhG;AAED,gHAAgH;AAChH,wBAAgB,YAAY,CAAC,GAAG,EAAE,qBAAqB,EAAE,OAAO,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAExH;AAED,yGAAyG;AACzG,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,MAAM,EAAE,CAQpF;AAuCD,eAAO,MAAM,eAAe,EAAE,SAAS,cAAc,EAuIpD,CAAC"}
@@ -70,7 +70,7 @@ function groupPointer(declaration, group) {
70
70
  const m = declaration.members.find((e) => e.security.includes(group));
71
71
  return m ? `${m.pointer}/security/${m.security.indexOf(group)}` : "/security";
72
72
  }
73
- function read(tree, path) {
73
+ export function read(tree, path) {
74
74
  if (tree.stat(path) !== "file")
75
75
  return null;
76
76
  try {
@@ -99,16 +99,16 @@ function pipelineFiles(tree, dir) {
99
99
  return out;
100
100
  }
101
101
  /** Every pipeline file of the workspace: its root's, and each member's. */
102
- function allPipelineFiles(ctx) {
102
+ export function allPipelineFiles(ctx) {
103
103
  const dirs = new Set(["", ...ctx.declaration.members.map((m) => memberDir(m.dir))]);
104
104
  return [...dirs].flatMap((d) => pipelineFiles(ctx.tree, d));
105
105
  }
106
106
  /** The lines of the pipeline files that run a chant command, `command` naming it, such as `release publish`. */
107
- function commandLines(ctx, command) {
107
+ export function commandLines(ctx, command) {
108
108
  return allPipelineFiles(ctx).flatMap((f) => f.lines.flatMap((text, i) => (command.test(text) ? [{ path: f.path, line: i + 1, text }] : [])));
109
109
  }
110
110
  /** The member's `*.component.ts` files, walked a few levels down, past node_modules and build output. */
111
- function componentFiles(tree, dir, depth = 4) {
111
+ export function componentFiles(tree, dir, depth = 4) {
112
112
  const out = [];
113
113
  for (const e of tree.list(dir) ?? []) {
114
114
  if (e.type === "dir") {
@@ -37,7 +37,7 @@
37
37
  * | WSP126, WSP127 | box intent: the decision record a box names exists, and constrains a member or path of this workspace (#2850, #2857) |
38
38
  * | WSP141, WSP142 | member links resolved against a live read, with `--live` (#2549) |
39
39
  * | WSP131 to WSP133 | diagram artifacts: source and render exist, a recorded source hash still matches (#2764) |
40
- * | WSP151 | reserved for the `ci.workflow` preset (#4168 step 6) |
40
+ * | WSP151 | what a member under `ci.workflow` still lacks (#4168 step 6) |
41
41
  * | WSP161 to WSP165 | the security groups the declaration opts into: what each still lacks (#4168 step 7) |
42
42
  */
43
43
  import type { LintDiagnostic, LintRule, Severity } from "../lint/rule.js";
@@ -1 +1 @@
1
- {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/workspace/checks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/workspace/checks.ts"],"names":[],"mappings":"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"}
@@ -37,7 +37,7 @@
37
37
  * | WSP126, WSP127 | box intent: the decision record a box names exists, and constrains a member or path of this workspace (#2850, #2857) |
38
38
  * | WSP141, WSP142 | member links resolved against a live read, with `--live` (#2549) |
39
39
  * | WSP131 to WSP133 | diagram artifacts: source and render exist, a recorded source hash still matches (#2764) |
40
- * | WSP151 | reserved for the `ci.workflow` preset (#4168 step 6) |
40
+ * | WSP151 | what a member under `ci.workflow` still lacks (#4168 step 6) |
41
41
  * | WSP161 to WSP165 | the security groups the declaration opts into: what each still lacks (#4168 step 7) |
42
42
  */
43
43
  import { realpathSync } from "node:fs";
@@ -56,6 +56,7 @@ import { RECORD_CHECKS } from "./checks/records.js";
56
56
  import { BOX_CHECKS } from "./checks/boxes.js";
57
57
  import { DIAGRAM_CHECKS } from "./checks/diagrams.js";
58
58
  import { SECURITY_CHECKS } from "./checks/security.js";
59
+ import { CI_WORKFLOW_CHECKS } from "./checks/ci-workflow.js";
59
60
  import { loadDeclaredKinds } from "./declared-kinds.js";
60
61
  import { resolveBoxIntents } from "./box-intent.js";
61
62
  import { gatherLexiconOutputs } from "./lexicon-outputs.js";
@@ -273,6 +274,8 @@ export const WORKSPACE_CHECKS = [
273
274
  ...DIAGRAM_CHECKS,
274
275
  // Links resolved against a live read, with --live (#2549), WSP141 and WSP142.
275
276
  ...LIVE_CHECKS,
277
+ // What a member under ci.workflow still lacks (#4168 step 6), WSP151.
278
+ ...CI_WORKFLOW_CHECKS,
276
279
  // The security groups the declaration opts into (#4168 step 7), WSP161 to WSP165.
277
280
  ...SECURITY_CHECKS,
278
281
  ];
@@ -1 +1 @@
1
- {"version":3,"file":"ci-green-cli.d.ts","sourceRoot":"","sources":["../../src/workspace/ci-green-cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAmE,cAAc,EAAE,MAAM,YAAY,CAAC;AAW7G,OAAO,EAAE,cAAc,EAAE,CAAC;AAe1B,wBAAsB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBzE;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBpE;AAID,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBpE;AAeD,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA+DxE"}
1
+ {"version":3,"file":"ci-green-cli.d.ts","sourceRoot":"","sources":["../../src/workspace/ci-green-cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAmE,cAAc,EAAE,MAAM,YAAY,CAAC;AAW7G,OAAO,EAAE,cAAc,EAAE,CAAC;AAe1B,wBAAsB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBzE;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBpE;AAID,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBpE;AAeD,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAiExE"}
@@ -153,7 +153,9 @@ export async function runCiWorkflow(ctx) {
153
153
  const sources = readWorkflowSources(repoRoot, fromRepo);
154
154
  const scan = workflowsHolding(green, sources);
155
155
  // #4169: the triggers and concurrency of the workflows holding a phase that sets build. Refused before anything is written.
156
- const edits = buildTriggerEdits(green, sources);
156
+ // #4220: under a ci.workflow, composed releases' branches run the phases and tick too.
157
+ const compose = declaration.ci?.workflow !== undefined || declaration.members.some((m) => m.ciWorkflow !== null);
158
+ const edits = buildTriggerEdits(green, sources, { compose });
157
159
  const extra = ctx.args.ciWorkflows ?? [];
158
160
  const workflows = [...new Set([...scan.workflows, ...extra])].sort();
159
161
  for (const f of scan.unreadable)
@@ -186,11 +188,11 @@ export async function runCiWorkflow(ctx) {
186
188
  const workspaceRoot = relative(repoRoot, root).split(sep).join("/") || ".";
187
189
  // The install runs in the workspace root, so its lockfile there keys setup-node's npm cache.
188
190
  const npmLock = ctx.args.ciInstall && existsSync(join(root, "package-lock.json")) ? (workspaceRoot === "." ? "package-lock.json" : `${workspaceRoot}/package-lock.json`) : undefined;
189
- const yaml = renderCiGreenWorkflow({ green, workflows, chantVersion: readerVersion(), workspaceRoot, chant: ctx.args.ciChant, install: ctx.args.ciInstall, npmLock, push, ...(runnerKeySecret ? { runnerKeySecret } : {}) });
191
+ const yaml = renderCiGreenWorkflow({ green, workflows, chantVersion: readerVersion(), workspaceRoot, chant: ctx.args.ciChant, install: ctx.args.ciInstall, npmLock, push, ...(runnerKeySecret ? { runnerKeySecret } : {}), ...(compose ? { compose } : {}) });
190
192
  const written = writeWorkflowFile(target, ciGreenHeader(command, member ? "member" : "root") + yaml);
191
193
  if (member)
192
194
  recordGeneratedFiles(member.memberRoot, [{ path: fromRepo, command }]);
193
- console.log(`Wrote ${written}: ticks when ${workflows.join(", ")} complete${workflows.length === 1 ? "s" : ""} on ${green.branch}, and every 15 minutes.`);
195
+ console.log(`Wrote ${written}: ticks when ${workflows.join(", ")} complete${workflows.length === 1 ? "s" : ""} on ${green.branch}${compose ? " or a chant/compose/ branch" : ""}, and every 15 minutes.`);
194
196
  for (const e of edits) {
195
197
  if (!e.changed)
196
198
  continue;
@@ -106,7 +106,15 @@ export interface WorkflowInput {
106
106
  * The key's principal needs the `runner` role in `.chant/trust.json`.
107
107
  */
108
108
  runnerKeySecret?: string;
109
+ /**
110
+ * The workspace declares a `ci.workflow` (#4220), so composed releases
111
+ * live on `chant/compose/<name>` branches (#4168 4.3): the tick also runs
112
+ * when a phase workflow completes on one of them.
113
+ */
114
+ compose?: boolean;
109
115
  }
116
+ /** The branch filter for composed releases' branches (#4220). */
117
+ export declare const COMPOSE_BRANCHES = "chant/compose/**";
110
118
  /**
111
119
  * A token the checkout persists for the tick's `git push`: a repository
112
120
  * secret, or a GitHub App's installation token minted from its id (an
@@ -153,12 +161,20 @@ export interface BuildTriggerEdit {
153
161
  * branch, so no push cancels or replaces another's run; elsewhere, such as
154
162
  * a pull request, a new push cancels the run it supersedes.
155
163
  *
156
- * Only the top-level `on:` (for `newest`) and `concurrency:` blocks change,
164
+ * With `compose` (#4220, a workspace declaring `ci.workflow`), both builds
165
+ * also run on pushes to `chant/compose/**`: `newest` adds the filter to the
166
+ * branches it writes, `every` adds it to an existing `push.branches` list,
167
+ * and `every`'s group keys a compose branch's runs by commit, as the trunk
168
+ * branch's.
169
+ *
170
+ * Only the top-level `on:` (for `newest`, or `every` with `compose`) and `concurrency:` blocks change,
157
171
  * each under {@link BUILD_BLOCK_MARKER}; the rest of the file is kept as it
158
172
  * is. Throws when one workflow holds a phase of each build, which no one
159
173
  * concurrency group can serve.
160
174
  */
161
- export declare function buildTriggerEdits(green: CiGreen, sources: readonly WorkflowSource[]): BuildTriggerEdit[];
175
+ export declare function buildTriggerEdits(green: CiGreen, sources: readonly WorkflowSource[], options?: {
176
+ compose?: boolean;
177
+ }): BuildTriggerEdit[];
162
178
  /**
163
179
  * Replace the top-level `key:` block of a YAML file with `value` (or with
164
180
  * `value`'s lines, the key's own line first), under
@@ -1 +1 @@
1
- {"version":3,"file":"ci-green-workflow.d.ts","sourceRoot":"","sources":["../../src/workspace/ci-green-workflow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ci-green-workflow.d.ts","sourceRoot":"","sources":["../../src/workspace/ci-green-workflow.ts"],"names":[],"mappings":"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"}
@@ -50,6 +50,7 @@ import { GENERATED_MARKER } from "../discovery/files.js";
50
50
  import { emitYAMLEntry, parseYAMLDocument } from "../yaml.js";
51
51
  import { matchesCheckRun } from "./ci-green.js";
52
52
  import { githubSecretOrJobToken } from "../ci-jobs.js";
53
+ import { COMPOSE_BRANCH_PREFIX } from "../lifecycle/compose-refs.js";
53
54
  /** Where the workflow goes, relative to the repository root. */
54
55
  export const CI_GREEN_WORKFLOW_FILE = ".github/workflows/chant-ci-green.yml";
55
56
  export const CI_GREEN_WORKFLOW_NAME = "chant-ci-green";
@@ -149,6 +150,8 @@ export function readWorkflowSources(repoRoot, skip) {
149
150
  .map((path) => ({ path, text: readFileSync(join(repoRoot, path), "utf-8") }));
150
151
  }
151
152
  const q = (s) => JSON.stringify(s);
153
+ /** The branch filter for composed releases' branches (#4220). */
154
+ export const COMPOSE_BRANCHES = `${COMPOSE_BRANCH_PREFIX}**`;
152
155
  /** A secret or variable name GitHub accepts: letters, digits and underscores, not starting with a digit. */
153
156
  export const ACTIONS_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
154
157
  /** The workflow's YAML, without the generated-file header. Deterministic: the same input writes the same bytes. */
@@ -184,6 +187,8 @@ export function renderCiGreenWorkflow(input) {
184
187
  ` - ${q(green.branch)}`,
185
188
  // #4169: a build the tick asked for runs at a ci/build/<sha> tag, and its completion ticks too.
186
189
  ...(newestPhases(green) ? [` - ${q("ci/build/**")}`] : []),
190
+ // #4220: a composed commit's phases run on its chant/compose/<name> branch, and their completion ticks too.
191
+ ...(input.compose ? [` - ${q(COMPOSE_BRANCHES)}`] : []),
187
192
  " schedule:",
188
193
  " - cron: \"*/15 * * * *\"",
189
194
  " workflow_dispatch: {}",
@@ -248,12 +253,19 @@ export const BUILD_BLOCK_MARKER = "# Written by chant ci workflow from ci.green'
248
253
  * branch, so no push cancels or replaces another's run; elsewhere, such as
249
254
  * a pull request, a new push cancels the run it supersedes.
250
255
  *
251
- * Only the top-level `on:` (for `newest`) and `concurrency:` blocks change,
256
+ * With `compose` (#4220, a workspace declaring `ci.workflow`), both builds
257
+ * also run on pushes to `chant/compose/**`: `newest` adds the filter to the
258
+ * branches it writes, `every` adds it to an existing `push.branches` list,
259
+ * and `every`'s group keys a compose branch's runs by commit, as the trunk
260
+ * branch's.
261
+ *
262
+ * Only the top-level `on:` (for `newest`, or `every` with `compose`) and `concurrency:` blocks change,
252
263
  * each under {@link BUILD_BLOCK_MARKER}; the rest of the file is kept as it
253
264
  * is. Throws when one workflow holds a phase of each build, which no one
254
265
  * concurrency group can serve.
255
266
  */
256
- export function buildTriggerEdits(green, sources) {
267
+ export function buildTriggerEdits(green, sources, options = {}) {
268
+ const compose = options.compose === true;
257
269
  const out = [];
258
270
  for (const s of sources) {
259
271
  let doc;
@@ -280,18 +292,28 @@ export function buildTriggerEdits(green, sources) {
280
292
  delete on.schedule;
281
293
  const push = isObject(on.push) ? { ...on.push } : {};
282
294
  const branches = Array.isArray(push.branches) ? push.branches.filter((b) => typeof b === "string") : [];
283
- push.branches = branches.includes(green.branch) ? branches : [...branches, green.branch];
295
+ const withBranch = branches.includes(green.branch) ? branches : [...branches, green.branch];
296
+ push.branches = compose && !withBranch.includes(COMPOSE_BRANCHES) ? [...withBranch, COMPOSE_BRANCHES] : withBranch;
284
297
  const { push: _push, workflow_dispatch: dispatch, ...rest } = on;
285
298
  text = writeTopLevel(text, "on", { push, workflow_dispatch: dispatch ?? {}, ...rest });
286
299
  text = writeTopLevel(text, "concurrency", { group: `chant-build-${tag}-\${{ github.ref }}`, "cancel-in-progress": false });
287
300
  }
288
301
  else {
289
302
  const main = `refs/heads/${green.branch}`;
303
+ // A push filter that lists branches gains the compose branches; one with no list already runs on every branch.
304
+ const on = isObject(doc) && isObject(doc.on) ? doc.on : undefined;
305
+ const pushOn = on && isObject(on.push) ? on.push : undefined;
306
+ if (compose && on && pushOn && Array.isArray(pushOn.branches) && !pushOn.branches.includes(COMPOSE_BRANCHES)) {
307
+ text = writeTopLevel(text, "on", { ...on, push: { ...pushOn, branches: [...pushOn.branches, COMPOSE_BRANCHES] } });
308
+ }
309
+ // #4220: a compose branch's commits each get a verdict, so its runs are keyed by commit, as the trunk branch's are.
310
+ const keyed = compose ? `(github.ref == '${main}' || startsWith(github.ref, 'refs/heads/${COMPOSE_BRANCH_PREFIX}'))` : `github.ref == '${main}'`;
311
+ const unkeyed = compose ? `!${keyed}` : `github.ref != '${main}'`;
290
312
  // Written as lines: the emitter would quote the expression, and GitHub reads it the same either way.
291
313
  text = writeTopLevel(text, "concurrency", [
292
314
  "concurrency:",
293
- ` group: chant-build-${tag}-\${{ github.ref == '${main}' && github.sha || github.ref }}`,
294
- ` cancel-in-progress: \${{ github.ref != '${main}' }}`,
315
+ ` group: chant-build-${tag}-\${{ ${keyed} && github.sha || github.ref }}`,
316
+ ` cancel-in-progress: \${{ ${unkeyed} }}`,
295
317
  ]);
296
318
  }
297
319
  out.push({ path: s.path, build, phases, text, changed: text !== s.text });
@@ -248,6 +248,16 @@ export declare function readCiTags(top: string, green?: CiGreen | null, base?: s
248
248
  * and `ci run` and `chant run` warn about a run they leave unsigned.
249
249
  */
250
250
  export declare function signedRunsRequired(cwd: string): string | null;
251
+ /** The declaration's `ci.green`, read where `cwd` is, and the git top. */
252
+ export declare function readGreen(cwd: string): {
253
+ green: CiGreen;
254
+ top: string;
255
+ workspace: {
256
+ name: string;
257
+ root: string;
258
+ file: string;
259
+ };
260
+ };
251
261
  export interface TickRequest {
252
262
  cwd: string;
253
263
  /**
@@ -271,12 +281,20 @@ export interface TickRequest {
271
281
  */
272
282
  runnerKey?: string;
273
283
  }
284
+ /** One compose branch a tick walked (#4168 4.3): its composed commits within the window. */
285
+ export interface ComposedBranchTick {
286
+ branch: string;
287
+ ref: string;
288
+ commits: TickCommit[];
289
+ }
274
290
  export interface TickResult {
275
291
  branch: string;
276
292
  window: string;
277
293
  /** The ref the commits were read from. */
278
294
  ref: string;
279
295
  commits: TickCommit[];
296
+ /** The compose branches walked (#4168 4.3), each with its composed commits judged. Their tags are in `made`. */
297
+ composed: ComposedBranchTick[];
280
298
  /** The tags made and pushed, or that would be under `dryRun`. */
281
299
  made: string[];
282
300
  /** The builds asked for (#4169), as `ci/build/<sha>` tags made and pushed, or that would be under `dryRun`. */
@@ -355,6 +373,19 @@ export declare function opRunCheckRun(record: OpRunRecord, signer: string | null
355
373
  * elsewhere. Reads local refs only.
356
374
  */
357
375
  export declare function readOpRunSource(cwd: string, top: string, base: string, signedSince?: string | null): Promise<OpRunSource>;
376
+ /**
377
+ * Judge `ci.green.preMerge` on `commit` from the Op run records on the ledger
378
+ * (#4168 4.4), as `ci serve --land` does before it moves the target. The
379
+ * trust policy is read at `base`, the target's head. An unsigned run counts
380
+ * as the tick counts one: always, unless `ci.green.signedSince` asks for a
381
+ * signature. Throws {@link CiGreenError} when the declaration has no
382
+ * `ci.green` or names no pre-merge phase.
383
+ */
384
+ export declare function judgePreMerge(req: {
385
+ cwd: string;
386
+ commit: string;
387
+ base: string;
388
+ }): Promise<CommitVerdict>;
358
389
  /**
359
390
  * What `chant run <op> --key` signs a run's record with (#4044): the runner
360
391
  * key `.chant/trust.json` at the checkout's `HEAD` lists for a principal