@intentius/chant 0.124.28 → 0.124.30

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 (449) hide show
  1. package/dist/build-params.d.ts +34 -1
  2. package/dist/build-params.d.ts.map +1 -1
  3. package/dist/build-params.js +31 -1
  4. package/dist/change-set-graph.d.ts +8 -1
  5. package/dist/change-set-graph.d.ts.map +1 -1
  6. package/dist/change-set-graph.js +4 -2
  7. package/dist/change-set.d.ts +10 -0
  8. package/dist/change-set.d.ts.map +1 -1
  9. package/dist/change-set.js +4 -3
  10. package/dist/cli/build-params-cli.d.ts +7 -1
  11. package/dist/cli/build-params-cli.d.ts.map +1 -1
  12. package/dist/cli/build-params-cli.js +17 -8
  13. package/dist/cli/commands/build.d.ts.map +1 -1
  14. package/dist/cli/commands/build.js +6 -3
  15. package/dist/cli/handlers/approve.d.ts.map +1 -1
  16. package/dist/cli/handlers/approve.js +45 -0
  17. package/dist/cli/handlers/build.d.ts.map +1 -1
  18. package/dist/cli/handlers/build.js +18 -4
  19. package/dist/cli/handlers/fan-out.d.ts +9 -0
  20. package/dist/cli/handlers/fan-out.d.ts.map +1 -1
  21. package/dist/cli/handlers/fan-out.js +67 -8
  22. package/dist/cli/handlers/lifecycle-gc.d.ts +19 -0
  23. package/dist/cli/handlers/lifecycle-gc.d.ts.map +1 -0
  24. package/dist/cli/handlers/lifecycle-gc.js +143 -0
  25. package/dist/cli/handlers/pr.d.ts +11 -3
  26. package/dist/cli/handlers/pr.d.ts.map +1 -1
  27. package/dist/cli/handlers/pr.js +134 -26
  28. package/dist/cli/handlers/promote.d.ts +7 -0
  29. package/dist/cli/handlers/promote.d.ts.map +1 -1
  30. package/dist/cli/handlers/promote.js +210 -33
  31. package/dist/cli/handlers/release.d.ts +62 -5
  32. package/dist/cli/handlers/release.d.ts.map +1 -1
  33. package/dist/cli/handlers/release.js +414 -28
  34. package/dist/cli/handlers/run.d.ts +11 -1
  35. package/dist/cli/handlers/run.d.ts.map +1 -1
  36. package/dist/cli/handlers/run.js +67 -6
  37. package/dist/cli/main.d.ts.map +1 -1
  38. package/dist/cli/main.js +91 -10
  39. package/dist/cli/parse-args.d.ts.map +1 -1
  40. package/dist/cli/parse-args.js +73 -2
  41. package/dist/cli/registry.d.ts +32 -4
  42. package/dist/cli/registry.d.ts.map +1 -1
  43. package/dist/cli/run-events.d.ts +3 -2
  44. package/dist/cli/run-events.d.ts.map +1 -1
  45. package/dist/cli/run-events.js +5 -3
  46. package/dist/components/auto-release.d.ts +2 -0
  47. package/dist/components/auto-release.d.ts.map +1 -1
  48. package/dist/components/auto-release.js +1 -0
  49. package/dist/components/capability.d.ts +9 -0
  50. package/dist/components/capability.d.ts.map +1 -1
  51. package/dist/components/driver.d.ts +8 -0
  52. package/dist/components/driver.d.ts.map +1 -1
  53. package/dist/components/driver.js +35 -0
  54. package/dist/components/fan-out-inputs.d.ts +69 -0
  55. package/dist/components/fan-out-inputs.d.ts.map +1 -0
  56. package/dist/components/fan-out-inputs.js +169 -0
  57. package/dist/components/fan-out-record.d.ts +13 -0
  58. package/dist/components/fan-out-record.d.ts.map +1 -1
  59. package/dist/components/fan-out-record.js +16 -0
  60. package/dist/components/fan-out-run.d.ts.map +1 -1
  61. package/dist/components/fan-out-run.js +50 -0
  62. package/dist/components/fan-out.d.ts +4 -0
  63. package/dist/components/fan-out.d.ts.map +1 -1
  64. package/dist/components/pr-pipeline.d.ts +49 -0
  65. package/dist/components/pr-pipeline.d.ts.map +1 -1
  66. package/dist/components/pr-pipeline.js +38 -4
  67. package/dist/components/pr-run.d.ts +20 -2
  68. package/dist/components/pr-run.d.ts.map +1 -1
  69. package/dist/components/pr-run.js +26 -13
  70. package/dist/components/promote.d.ts +23 -0
  71. package/dist/components/promote.d.ts.map +1 -1
  72. package/dist/components/promote.js +60 -2
  73. package/dist/components/release-compile.d.ts +9 -0
  74. package/dist/components/release-compile.d.ts.map +1 -1
  75. package/dist/components/release-compile.js +9 -3
  76. package/dist/components/release-gate.d.ts +11 -1
  77. package/dist/components/release-gate.d.ts.map +1 -1
  78. package/dist/components/release-gate.js +10 -4
  79. package/dist/components/wave-plan.d.ts +16 -0
  80. package/dist/components/wave-plan.d.ts.map +1 -1
  81. package/dist/components/wave-plan.js +36 -2
  82. package/dist/config.d.ts +38 -0
  83. package/dist/config.d.ts.map +1 -1
  84. package/dist/config.js +2 -0
  85. package/dist/flag-params.d.ts +54 -0
  86. package/dist/flag-params.d.ts.map +1 -0
  87. package/dist/flag-params.js +130 -0
  88. package/dist/lifecycle/__fixtures__/publish-fakes.d.ts +120 -0
  89. package/dist/lifecycle/__fixtures__/publish-fakes.d.ts.map +1 -0
  90. package/dist/lifecycle/__fixtures__/publish-fakes.js +304 -0
  91. package/dist/lifecycle/change-set-store.d.ts +2 -1
  92. package/dist/lifecycle/change-set-store.d.ts.map +1 -1
  93. package/dist/lifecycle/change-set-store.js +2 -1
  94. package/dist/lifecycle/delivery-metrics.d.ts +139 -0
  95. package/dist/lifecycle/delivery-metrics.d.ts.map +1 -0
  96. package/dist/lifecycle/delivery-metrics.js +145 -0
  97. package/dist/lifecycle/deploy-outcome.d.ts +81 -0
  98. package/dist/lifecycle/deploy-outcome.d.ts.map +1 -0
  99. package/dist/lifecycle/deploy-outcome.js +101 -0
  100. package/dist/lifecycle/gate-change-set.d.ts +10 -1
  101. package/dist/lifecycle/gate-change-set.d.ts.map +1 -1
  102. package/dist/lifecycle/gate-change-set.js +35 -3
  103. package/dist/lifecycle/gate-ledger.d.ts +2 -3
  104. package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
  105. package/dist/lifecycle/git.d.ts +30 -1
  106. package/dist/lifecycle/git.d.ts.map +1 -1
  107. package/dist/lifecycle/git.js +31 -5
  108. package/dist/lifecycle/index.d.ts +4 -0
  109. package/dist/lifecycle/index.d.ts.map +1 -1
  110. package/dist/lifecycle/index.js +4 -0
  111. package/dist/lifecycle/mixed-environment.d.ts +95 -0
  112. package/dist/lifecycle/mixed-environment.d.ts.map +1 -0
  113. package/dist/lifecycle/mixed-environment.js +154 -0
  114. package/dist/lifecycle/publish-attachments.d.ts +79 -0
  115. package/dist/lifecycle/publish-attachments.d.ts.map +1 -0
  116. package/dist/lifecycle/publish-attachments.js +179 -0
  117. package/dist/lifecycle/publish-credentials.d.ts +37 -0
  118. package/dist/lifecycle/publish-credentials.d.ts.map +1 -0
  119. package/dist/lifecycle/publish-credentials.js +69 -0
  120. package/dist/lifecycle/publish-declaration.d.ts +97 -0
  121. package/dist/lifecycle/publish-declaration.d.ts.map +1 -0
  122. package/dist/lifecycle/publish-declaration.js +83 -0
  123. package/dist/lifecycle/publish-forge.d.ts +53 -0
  124. package/dist/lifecycle/publish-forge.d.ts.map +1 -0
  125. package/dist/lifecycle/publish-forge.js +298 -0
  126. package/dist/lifecycle/publish-npm.d.ts +61 -0
  127. package/dist/lifecycle/publish-npm.d.ts.map +1 -0
  128. package/dist/lifecycle/publish-npm.js +242 -0
  129. package/dist/lifecycle/publish-oci.d.ts +64 -0
  130. package/dist/lifecycle/publish-oci.d.ts.map +1 -0
  131. package/dist/lifecycle/publish-oci.js +383 -0
  132. package/dist/lifecycle/publish-record.d.ts +66 -0
  133. package/dist/lifecycle/publish-record.d.ts.map +1 -0
  134. package/dist/lifecycle/publish-record.js +84 -0
  135. package/dist/lifecycle/publish-targets.d.ts +45 -0
  136. package/dist/lifecycle/publish-targets.d.ts.map +1 -0
  137. package/dist/lifecycle/publish-targets.js +85 -0
  138. package/dist/lifecycle/release-cut.d.ts +48 -1
  139. package/dist/lifecycle/release-cut.d.ts.map +1 -1
  140. package/dist/lifecycle/release-cut.js +116 -23
  141. package/dist/lifecycle/release-join.d.ts +95 -0
  142. package/dist/lifecycle/release-join.d.ts.map +1 -0
  143. package/dist/lifecycle/release-join.js +139 -0
  144. package/dist/lifecycle/release-ledger.d.ts +8 -3
  145. package/dist/lifecycle/release-ledger.d.ts.map +1 -1
  146. package/dist/lifecycle/release-ledger.js +2 -0
  147. package/dist/lifecycle/release-publish.d.ts +312 -0
  148. package/dist/lifecycle/release-publish.d.ts.map +1 -0
  149. package/dist/lifecycle/release-publish.js +335 -0
  150. package/dist/lifecycle/release-revocation.d.ts +80 -0
  151. package/dist/lifecycle/release-revocation.d.ts.map +1 -0
  152. package/dist/lifecycle/release-revocation.js +123 -0
  153. package/dist/lifecycle/release-store.d.ts +12 -2
  154. package/dist/lifecycle/release-store.d.ts.map +1 -1
  155. package/dist/lifecycle/release-store.js +4 -2
  156. package/dist/lifecycle/release-verify.d.ts +61 -0
  157. package/dist/lifecycle/release-verify.d.ts.map +1 -0
  158. package/dist/lifecycle/release-verify.js +92 -0
  159. package/dist/lifecycle/release-workstation.d.ts +91 -0
  160. package/dist/lifecycle/release-workstation.d.ts.map +1 -0
  161. package/dist/lifecycle/release-workstation.js +180 -0
  162. package/dist/lifecycle/retention-policy.d.ts +45 -0
  163. package/dist/lifecycle/retention-policy.d.ts.map +1 -0
  164. package/dist/lifecycle/retention-policy.js +43 -0
  165. package/dist/lifecycle/retention.d.ts +185 -0
  166. package/dist/lifecycle/retention.d.ts.map +1 -0
  167. package/dist/lifecycle/retention.js +400 -0
  168. package/dist/lifecycle/run-ledger.d.ts +1 -1
  169. package/dist/lifecycle/run-ledger.d.ts.map +1 -1
  170. package/dist/lifecycle/run-ledger.js +9 -0
  171. package/dist/op/activities/activity-contracts.d.ts +1 -0
  172. package/dist/op/activities/activity-contracts.d.ts.map +1 -1
  173. package/dist/op/activities/activity-contracts.js +1 -0
  174. package/dist/op/activities/shell.d.ts +6 -0
  175. package/dist/op/activities/shell.d.ts.map +1 -1
  176. package/dist/op/activities/shell.js +1 -1
  177. package/dist/op/local-executor.d.ts +23 -1
  178. package/dist/op/local-executor.d.ts.map +1 -1
  179. package/dist/op/local-executor.js +9 -3
  180. package/dist/op/runtime.d.ts +27 -0
  181. package/dist/op/runtime.d.ts.map +1 -1
  182. package/dist/op/runtime.js +20 -0
  183. package/dist/plan-summary.d.ts.map +1 -1
  184. package/dist/plan-summary.js +8 -2
  185. package/dist/pr-forge.d.ts +23 -0
  186. package/dist/pr-forge.d.ts.map +1 -1
  187. package/dist/pr-forge.js +44 -0
  188. package/dist/pr-loop.d.ts +17 -0
  189. package/dist/pr-loop.d.ts.map +1 -1
  190. package/dist/pr-loop.js +30 -4
  191. package/dist/pr-report-url.d.ts +82 -0
  192. package/dist/pr-report-url.d.ts.map +1 -0
  193. package/dist/pr-report-url.js +174 -0
  194. package/dist/provenance.d.ts +2 -2
  195. package/dist/provenance.d.ts.map +1 -1
  196. package/dist/run-event-store.d.ts +29 -2
  197. package/dist/run-event-store.d.ts.map +1 -1
  198. package/dist/run-event-store.js +50 -3
  199. package/dist/run-event-stream.d.ts +4 -3
  200. package/dist/run-event-stream.d.ts.map +1 -1
  201. package/dist/run-event-stream.js +7 -3
  202. package/dist/run-event.d.ts +34 -1
  203. package/dist/run-event.d.ts.map +1 -1
  204. package/dist/run-event.js +4 -0
  205. package/dist/wave-runtime.mjs +260 -229
  206. package/dist/workspace/__fixtures__/flag-workspace.d.ts +31 -0
  207. package/dist/workspace/__fixtures__/flag-workspace.d.ts.map +1 -0
  208. package/dist/workspace/__fixtures__/flag-workspace.js +114 -0
  209. package/dist/workspace/change-set.schema.json +5 -1
  210. package/dist/workspace/check.schema.json +4 -2
  211. package/dist/workspace/checks/records.d.ts +9 -1
  212. package/dist/workspace/checks/records.d.ts.map +1 -1
  213. package/dist/workspace/checks/records.js +35 -1
  214. package/dist/workspace/checks.d.ts +1 -0
  215. package/dist/workspace/checks.d.ts.map +1 -1
  216. package/dist/workspace/checks.js +2 -1
  217. package/dist/workspace/ci-green-forge.d.ts +2 -0
  218. package/dist/workspace/ci-green-forge.d.ts.map +1 -1
  219. package/dist/workspace/ci-green.d.ts +10 -0
  220. package/dist/workspace/ci-green.d.ts.map +1 -1
  221. package/dist/workspace/ci-green.js +14 -5
  222. package/dist/workspace/ci-run.d.ts +222 -0
  223. package/dist/workspace/ci-run.d.ts.map +1 -0
  224. package/dist/workspace/ci-run.js +464 -0
  225. package/dist/workspace/ci-serve.d.ts +214 -0
  226. package/dist/workspace/ci-serve.d.ts.map +1 -0
  227. package/dist/workspace/ci-serve.js +412 -0
  228. package/dist/workspace/declaration.d.ts +16 -0
  229. package/dist/workspace/declaration.d.ts.map +1 -1
  230. package/dist/workspace/declaration.js +26 -0
  231. package/dist/workspace/declaration.schema.json +64 -0
  232. package/dist/workspace/declared-kinds.d.ts +16 -0
  233. package/dist/workspace/declared-kinds.d.ts.map +1 -1
  234. package/dist/workspace/declared-kinds.js +25 -0
  235. package/dist/workspace/delivery-metrics.d.ts +91 -0
  236. package/dist/workspace/delivery-metrics.d.ts.map +1 -0
  237. package/dist/workspace/delivery-metrics.js +217 -0
  238. package/dist/workspace/delivery-metrics.schema.json +519 -0
  239. package/dist/workspace/flags-read.d.ts +37 -0
  240. package/dist/workspace/flags-read.d.ts.map +1 -0
  241. package/dist/workspace/flags-read.js +103 -0
  242. package/dist/workspace/flags.d.ts +100 -0
  243. package/dist/workspace/flags.d.ts.map +1 -0
  244. package/dist/workspace/flags.js +98 -0
  245. package/dist/workspace/graph-cli.js +1 -1
  246. package/dist/workspace/intent-cli.d.ts +11 -2
  247. package/dist/workspace/intent-cli.d.ts.map +1 -1
  248. package/dist/workspace/intent-cli.js +54 -5
  249. package/dist/workspace/intent-trace.d.ts +219 -0
  250. package/dist/workspace/intent-trace.d.ts.map +1 -0
  251. package/dist/workspace/intent-trace.js +314 -0
  252. package/dist/workspace/intent.d.ts +30 -6
  253. package/dist/workspace/intent.d.ts.map +1 -1
  254. package/dist/workspace/intent.js +141 -21
  255. package/dist/workspace/intent.schema.json +702 -6
  256. package/dist/workspace/overlap.d.ts +146 -0
  257. package/dist/workspace/overlap.d.ts.map +1 -0
  258. package/dist/workspace/overlap.js +276 -0
  259. package/dist/workspace/pr-report.schema.json +5 -0
  260. package/dist/workspace/reason-codes.d.ts +2 -0
  261. package/dist/workspace/reason-codes.d.ts.map +1 -1
  262. package/dist/workspace/reason-codes.js +3 -0
  263. package/dist/workspace/records.d.ts +15 -2
  264. package/dist/workspace/records.d.ts.map +1 -1
  265. package/dist/workspace/records.js +32 -0
  266. package/dist/workspace/records.schema.json +21 -2
  267. package/dist/workspace/reference-kinds/flag/flag.kind.mjs +32 -0
  268. package/dist/workspace/reference-kinds/flag/flag.schema.json +53 -0
  269. package/dist/workspace/releases.d.ts +9 -0
  270. package/dist/workspace/releases.d.ts.map +1 -1
  271. package/dist/workspace/releases.js +9 -0
  272. package/dist/workspace/releases.schema.json +123 -1
  273. package/dist/workspace/run-event.schema.json +24 -6
  274. package/dist/workspace/status-gates.d.ts +8 -0
  275. package/dist/workspace/status-gates.d.ts.map +1 -1
  276. package/dist/workspace/status-stewards.d.ts +2 -0
  277. package/dist/workspace/status-stewards.d.ts.map +1 -1
  278. package/dist/workspace/status-stewards.js +1 -0
  279. package/dist/workspace/status.d.ts +78 -0
  280. package/dist/workspace/status.d.ts.map +1 -1
  281. package/dist/workspace/status.js +170 -3
  282. package/dist/workspace/status.schema.json +210 -2
  283. package/dist/workspace/wip.d.ts.map +1 -1
  284. package/dist/workspace/wip.js +11 -3
  285. package/package.json +1 -1
  286. package/src/build-params.test.ts +46 -0
  287. package/src/build-params.ts +55 -1
  288. package/src/change-set-graph.ts +10 -2
  289. package/src/change-set.ts +14 -3
  290. package/src/cli/build-params-cli.ts +22 -9
  291. package/src/cli/commands/build.ts +6 -3
  292. package/src/cli/handlers/approve-release.test.ts +5 -1
  293. package/src/cli/handlers/approve-revoked.test.ts +155 -0
  294. package/src/cli/handlers/approve.ts +47 -0
  295. package/src/cli/handlers/build.test.ts +30 -0
  296. package/src/cli/handlers/build.ts +20 -4
  297. package/src/cli/handlers/fan-out.test.ts +262 -1
  298. package/src/cli/handlers/fan-out.ts +72 -8
  299. package/src/cli/handlers/intent-trace.e2e.test.ts +201 -0
  300. package/src/cli/handlers/lifecycle-gc.test.ts +126 -0
  301. package/src/cli/handlers/lifecycle-gc.ts +146 -0
  302. package/src/cli/handlers/pr.test.ts +148 -1
  303. package/src/cli/handlers/pr.ts +144 -28
  304. package/src/cli/handlers/promote.test.ts +280 -2
  305. package/src/cli/handlers/promote.ts +210 -34
  306. package/src/cli/handlers/release-implicit.e2e.test.ts +12 -4
  307. package/src/cli/handlers/release-join.e2e.test.ts +185 -0
  308. package/src/cli/handlers/release-publish-targets.e2e.test.ts +295 -0
  309. package/src/cli/handlers/release-verify.e2e.test.ts +117 -0
  310. package/src/cli/handlers/release-workstation-ci.e2e.test.ts +135 -0
  311. package/src/cli/handlers/release.e2e.test.ts +146 -32
  312. package/src/cli/handlers/release.ts +415 -28
  313. package/src/cli/handlers/run-auto-release.test.ts +9 -0
  314. package/src/cli/handlers/run-release.test.ts +55 -0
  315. package/src/cli/handlers/run.ts +69 -5
  316. package/src/cli/main.test.ts +1 -0
  317. package/src/cli/main.ts +91 -10
  318. package/src/cli/parse-args.ts +54 -2
  319. package/src/cli/registry.ts +32 -4
  320. package/src/cli/run-events.ts +5 -2
  321. package/src/components/auto-release.test.ts +9 -0
  322. package/src/components/auto-release.ts +3 -0
  323. package/src/components/capability.ts +9 -0
  324. package/src/components/driver.test.ts +24 -0
  325. package/src/components/driver.ts +36 -0
  326. package/src/components/fan-out-inputs.test.ts +85 -0
  327. package/src/components/fan-out-inputs.ts +192 -0
  328. package/src/components/fan-out-record.test.ts +10 -0
  329. package/src/components/fan-out-record.ts +19 -0
  330. package/src/components/fan-out-run.ts +48 -0
  331. package/src/components/fan-out.ts +4 -0
  332. package/src/components/pr-pipeline.ts +67 -4
  333. package/src/components/pr-run.test.ts +127 -0
  334. package/src/components/pr-run.ts +32 -12
  335. package/src/components/promote.ts +68 -2
  336. package/src/components/release-compile.ts +17 -3
  337. package/src/components/release-gate.ts +18 -4
  338. package/src/components/wave-plan.ts +45 -2
  339. package/src/config.ts +8 -0
  340. package/src/flag-params.test.ts +144 -0
  341. package/src/flag-params.ts +134 -0
  342. package/src/lifecycle/__fixtures__/publish-fakes.ts +351 -0
  343. package/src/lifecycle/change-set-store.ts +2 -1
  344. package/src/lifecycle/delivery-metrics.ts +263 -0
  345. package/src/lifecycle/deploy-outcome.ts +147 -0
  346. package/src/lifecycle/gate-change-set.ts +37 -6
  347. package/src/lifecycle/gate-ledger.ts +2 -2
  348. package/src/lifecycle/git.ts +61 -8
  349. package/src/lifecycle/index.ts +4 -0
  350. package/src/lifecycle/mixed-environment.test.ts +97 -0
  351. package/src/lifecycle/mixed-environment.ts +204 -0
  352. package/src/lifecycle/publish-attachments.ts +196 -0
  353. package/src/lifecycle/publish-credentials.ts +84 -0
  354. package/src/lifecycle/publish-declaration.ts +95 -0
  355. package/src/lifecycle/publish-forge.ts +325 -0
  356. package/src/lifecycle/publish-npm.ts +259 -0
  357. package/src/lifecycle/publish-oci.ts +396 -0
  358. package/src/lifecycle/publish-record.ts +113 -0
  359. package/src/lifecycle/publish-resume.test.ts +168 -0
  360. package/src/lifecycle/publish-targets.test.ts +494 -0
  361. package/src/lifecycle/publish-targets.ts +100 -0
  362. package/src/lifecycle/release-cut.test.ts +74 -2
  363. package/src/lifecycle/release-cut.ts +158 -22
  364. package/src/lifecycle/release-flag.test.ts +112 -0
  365. package/src/lifecycle/release-join.test.ts +68 -0
  366. package/src/lifecycle/release-join.ts +182 -0
  367. package/src/lifecycle/release-ledger.ts +9 -3
  368. package/src/lifecycle/release-publish.test.ts +225 -0
  369. package/src/lifecycle/release-publish.ts +568 -0
  370. package/src/lifecycle/release-revocation.ts +147 -0
  371. package/src/lifecycle/release-store.ts +15 -4
  372. package/src/lifecycle/release-verify.test.ts +110 -0
  373. package/src/lifecycle/release-verify.ts +120 -0
  374. package/src/lifecycle/release-workstation.test.ts +204 -0
  375. package/src/lifecycle/release-workstation.ts +216 -0
  376. package/src/lifecycle/retention-growth.e2e.test.ts +279 -0
  377. package/src/lifecycle/retention-policy.ts +63 -0
  378. package/src/lifecycle/retention.test.ts +363 -0
  379. package/src/lifecycle/retention.ts +508 -0
  380. package/src/lifecycle/run-ledger.ts +7 -1
  381. package/src/op/activities/activity-contracts.ts +1 -0
  382. package/src/op/activities/shell.ts +7 -1
  383. package/src/op/local-executor.ts +27 -4
  384. package/src/op/runtime.ts +42 -0
  385. package/src/plan-summary.test.ts +20 -0
  386. package/src/plan-summary.ts +8 -1
  387. package/src/pr-forge.test.ts +25 -0
  388. package/src/pr-forge.ts +62 -0
  389. package/src/pr-loop.test.ts +13 -1
  390. package/src/pr-loop.ts +41 -4
  391. package/src/pr-report-url.test.ts +131 -0
  392. package/src/pr-report-url.ts +209 -0
  393. package/src/provenance.ts +2 -2
  394. package/src/run-event-store.ts +63 -3
  395. package/src/run-event-stream.ts +8 -4
  396. package/src/run-event.ts +38 -1
  397. package/src/workspace/__fixtures__/flag-workspace.ts +132 -0
  398. package/src/workspace/__fixtures__/older-records/change-set-984534ea9.json +100 -0
  399. package/src/workspace/__fixtures__/older-records/older-records.json +326 -0
  400. package/src/workspace/change-set.schema.json +5 -1
  401. package/src/workspace/check.schema.json +4 -2
  402. package/src/workspace/checks/records.ts +35 -1
  403. package/src/workspace/checks.ts +2 -1
  404. package/src/workspace/ci-green-forge.ts +2 -0
  405. package/src/workspace/ci-green.ts +20 -5
  406. package/src/workspace/ci-run.test.ts +416 -0
  407. package/src/workspace/ci-run.ts +571 -0
  408. package/src/workspace/ci-serve.test.ts +268 -0
  409. package/src/workspace/ci-serve.ts +521 -0
  410. package/src/workspace/declaration.schema.json +64 -0
  411. package/src/workspace/declaration.test.ts +28 -0
  412. package/src/workspace/declaration.ts +38 -0
  413. package/src/workspace/declared-kinds.ts +40 -1
  414. package/src/workspace/delivery-metrics.schema.json +519 -0
  415. package/src/workspace/delivery-metrics.test.ts +236 -0
  416. package/src/workspace/delivery-metrics.ts +286 -0
  417. package/src/workspace/flags-read.ts +121 -0
  418. package/src/workspace/flags.test.ts +141 -0
  419. package/src/workspace/flags.ts +157 -0
  420. package/src/workspace/graph-cli.ts +1 -1
  421. package/src/workspace/intent-cli.ts +46 -5
  422. package/src/workspace/intent-trace.test.ts +173 -0
  423. package/src/workspace/intent-trace.ts +484 -0
  424. package/src/workspace/intent.schema.json +702 -6
  425. package/src/workspace/intent.ts +148 -25
  426. package/src/workspace/older-records.test.ts +412 -0
  427. package/src/workspace/overlap.test.ts +165 -0
  428. package/src/workspace/overlap.ts +340 -0
  429. package/src/workspace/pr-report.schema.json +5 -0
  430. package/src/workspace/read-contract.e2e.test.ts +2 -1
  431. package/src/workspace/reason-codes.test.ts +5 -0
  432. package/src/workspace/reason-codes.ts +3 -0
  433. package/src/workspace/record-assets.test.ts +2 -1
  434. package/src/workspace/records-contract.e2e.test.ts +2 -1
  435. package/src/workspace/records.schema.json +21 -2
  436. package/src/workspace/records.ts +36 -2
  437. package/src/workspace/reference-kinds/flag/flag.kind.mjs +32 -0
  438. package/src/workspace/reference-kinds/flag/flag.schema.json +53 -0
  439. package/src/workspace/releases.schema.json +123 -1
  440. package/src/workspace/releases.ts +11 -0
  441. package/src/workspace/run-event.schema.json +24 -6
  442. package/src/workspace/status-contract.test.ts +29 -0
  443. package/src/workspace/status-gates.ts +8 -0
  444. package/src/workspace/status-mixed.test.ts +152 -0
  445. package/src/workspace/status-revoked.test.ts +153 -0
  446. package/src/workspace/status-stewards.ts +3 -0
  447. package/src/workspace/status.schema.json +210 -2
  448. package/src/workspace/status.ts +254 -3
  449. package/src/workspace/wip.ts +11 -2
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Where a member declares its publish targets (#4047): `release.publish` in
3
+ * its `chant.config.ts`, a list of targets that `chant release publish` runs
4
+ * in order.
5
+ *
6
+ * ```ts
7
+ * export default {
8
+ * release: {
9
+ * publish: [
10
+ * { type: "npm", packages: ["packages/core", "packages/cli"] },
11
+ * { type: "oci", image: "dist/api.oci.tar", repository: "ghcr.io/acme/api", tags: ["{label}"], usernameEnv: "GITHUB_ACTOR", passwordEnv: "GITHUB_TOKEN" },
12
+ * { type: "forge", forge: "github", repo: "acme/api", assets: ["dist/api-linux-amd64.tar.gz"] },
13
+ * ],
14
+ * },
15
+ * };
16
+ * ```
17
+ *
18
+ * The config is the one at the release's commit: a publish with a target
19
+ * refuses a checkout whose `HEAD` is another commit. Paths are relative to
20
+ * the member's directory. A declaration names the environment variables its
21
+ * credentials are read from, never the credentials.
22
+ *
23
+ * This module imports nothing but zod, so ../config.ts can validate the block.
24
+ */
25
+ import { z } from "zod";
26
+ /** npm: `npm publish` for each package, in the order given. */
27
+ export declare const NpmPublishSchema: z.ZodObject<{
28
+ type: z.ZodLiteral<"npm">;
29
+ packages: z.ZodArray<z.ZodString>;
30
+ registry: z.ZodOptional<z.ZodString>;
31
+ access: z.ZodOptional<z.ZodEnum<{
32
+ public: "public";
33
+ restricted: "restricted";
34
+ }>>;
35
+ sbom: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
36
+ }, z.core.$strict>;
37
+ /** An OCI registry such as GHCR or Docker Hub: the image is pushed by digest, then tagged. */
38
+ export declare const OciPublishSchema: z.ZodObject<{
39
+ type: z.ZodLiteral<"oci">;
40
+ image: z.ZodString;
41
+ repository: z.ZodString;
42
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
43
+ usernameEnv: z.ZodOptional<z.ZodString>;
44
+ passwordEnv: z.ZodOptional<z.ZodString>;
45
+ sbom: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
46
+ }, z.core.$strict>;
47
+ /** Release assets on a GitHub, GitLab or Forgejo release named by the release's tag. */
48
+ export declare const ForgePublishSchema: z.ZodObject<{
49
+ type: z.ZodLiteral<"forge">;
50
+ forge: z.ZodEnum<{
51
+ forgejo: "forgejo";
52
+ github: "github";
53
+ gitlab: "gitlab";
54
+ }>;
55
+ repo: z.ZodString;
56
+ api: z.ZodOptional<z.ZodString>;
57
+ assets: z.ZodArray<z.ZodString>;
58
+ tag: z.ZodOptional<z.ZodString>;
59
+ tokenEnv: z.ZodOptional<z.ZodString>;
60
+ sbom: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
61
+ }, z.core.$strict>;
62
+ export declare const PublishDeclarationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
63
+ type: z.ZodLiteral<"npm">;
64
+ packages: z.ZodArray<z.ZodString>;
65
+ registry: z.ZodOptional<z.ZodString>;
66
+ access: z.ZodOptional<z.ZodEnum<{
67
+ public: "public";
68
+ restricted: "restricted";
69
+ }>>;
70
+ sbom: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
71
+ }, z.core.$strict>, z.ZodObject<{
72
+ type: z.ZodLiteral<"oci">;
73
+ image: z.ZodString;
74
+ repository: z.ZodString;
75
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
76
+ usernameEnv: z.ZodOptional<z.ZodString>;
77
+ passwordEnv: z.ZodOptional<z.ZodString>;
78
+ sbom: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
79
+ }, z.core.$strict>, z.ZodObject<{
80
+ type: z.ZodLiteral<"forge">;
81
+ forge: z.ZodEnum<{
82
+ forgejo: "forgejo";
83
+ github: "github";
84
+ gitlab: "gitlab";
85
+ }>;
86
+ repo: z.ZodString;
87
+ api: z.ZodOptional<z.ZodString>;
88
+ assets: z.ZodArray<z.ZodString>;
89
+ tag: z.ZodOptional<z.ZodString>;
90
+ tokenEnv: z.ZodOptional<z.ZodString>;
91
+ sbom: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
92
+ }, z.core.$strict>], "type">;
93
+ export type NpmPublishDeclaration = z.infer<typeof NpmPublishSchema>;
94
+ export type OciPublishDeclaration = z.infer<typeof OciPublishSchema>;
95
+ export type ForgePublishDeclaration = z.infer<typeof ForgePublishSchema>;
96
+ export type PublishDeclaration = z.infer<typeof PublishDeclarationSchema>;
97
+ //# sourceMappingURL=publish-declaration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-declaration.d.ts","sourceRoot":"","sources":["../../src/lifecycle/publish-declaration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,+DAA+D;AAC/D,eAAO,MAAM,gBAAgB;;;;;;;;;kBAelB,CAAC;AAEZ,8FAA8F;AAC9F,eAAO,MAAM,gBAAgB;;;;;;;;kBAgBlB,CAAC;AAEZ,wFAAwF;AACxF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;kBAiBpB,CAAC;AAEZ,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAAyF,CAAC;AAE/H,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AACrE,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AACrE,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AACzE,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Where a member declares its publish targets (#4047): `release.publish` in
3
+ * its `chant.config.ts`, a list of targets that `chant release publish` runs
4
+ * in order.
5
+ *
6
+ * ```ts
7
+ * export default {
8
+ * release: {
9
+ * publish: [
10
+ * { type: "npm", packages: ["packages/core", "packages/cli"] },
11
+ * { type: "oci", image: "dist/api.oci.tar", repository: "ghcr.io/acme/api", tags: ["{label}"], usernameEnv: "GITHUB_ACTOR", passwordEnv: "GITHUB_TOKEN" },
12
+ * { type: "forge", forge: "github", repo: "acme/api", assets: ["dist/api-linux-amd64.tar.gz"] },
13
+ * ],
14
+ * },
15
+ * };
16
+ * ```
17
+ *
18
+ * The config is the one at the release's commit: a publish with a target
19
+ * refuses a checkout whose `HEAD` is another commit. Paths are relative to
20
+ * the member's directory. A declaration names the environment variables its
21
+ * credentials are read from, never the credentials.
22
+ *
23
+ * This module imports nothing but zod, so ../config.ts can validate the block.
24
+ */
25
+ import { z } from "zod";
26
+ const envName = z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/, "an environment variable name");
27
+ /** An SBOM file, or `false` to publish without one (#4049). */
28
+ const sbomField = z.union([z.string().min(1), z.literal(false)]);
29
+ /** npm: `npm publish` for each package, in the order given. */
30
+ export const NpmPublishSchema = z
31
+ .object({
32
+ type: z.literal("npm"),
33
+ /** Package directories or packed `.tgz` files, relative to the member, published in this order. */
34
+ packages: z.array(z.string().min(1)).min(1),
35
+ /** The registry, else the one npm's own config names. */
36
+ registry: z.string().url().optional(),
37
+ access: z.enum(["public", "restricted"]).optional(),
38
+ /**
39
+ * The SBOM each package carries at its root (#4049), a file name relative
40
+ * to the package. Default: the first of `sbom.spdx.json`, `sbom.cdx.json`,
41
+ * `sbom.cyclonedx.json` it holds. `false` publishes without one.
42
+ */
43
+ sbom: sbomField.optional(),
44
+ })
45
+ .strict();
46
+ /** An OCI registry such as GHCR or Docker Hub: the image is pushed by digest, then tagged. */
47
+ export const OciPublishSchema = z
48
+ .object({
49
+ type: z.literal("oci"),
50
+ /** An OCI image layout, as a directory or a tar file such as `docker save` writes, relative to the member. */
51
+ image: z.string().min(1),
52
+ /** `<registry host>/<name>`, such as `ghcr.io/acme/api` or `docker.io/acme/api`. */
53
+ repository: z.string().min(1),
54
+ /** Tags to point at the pushed digest. `{label}` is the release's label. Default: `["{label}"]`, or none for a release with no label. */
55
+ tags: z.array(z.string().min(1)).optional(),
56
+ /** The variable holding the registry user name. Default `OCI_USERNAME`. */
57
+ usernameEnv: envName.optional(),
58
+ /** The variable holding the registry password or token. Default `OCI_PASSWORD`. */
59
+ passwordEnv: envName.optional(),
60
+ /** The SBOM pushed as a referrer of the image (#4049), relative to the member. Default: one written from the member's lockfile. `false` publishes without one. */
61
+ sbom: sbomField.optional(),
62
+ })
63
+ .strict();
64
+ /** Release assets on a GitHub, GitLab or Forgejo release named by the release's tag. */
65
+ export const ForgePublishSchema = z
66
+ .object({
67
+ type: z.literal("forge"),
68
+ forge: z.enum(["github", "gitlab", "forgejo"]),
69
+ /** `owner/name` on GitHub and Forgejo; the project path or numeric id on GitLab. */
70
+ repo: z.string().min(1),
71
+ /** The API root: default `$GITHUB_API_URL` or `https://api.github.com` on GitHub, `$CI_API_V4_URL` or `https://gitlab.com/api/v4` on GitLab, `$GITHUB_API_URL` on Forgejo, which has no default. */
72
+ api: z.string().url().optional(),
73
+ /** Files to attach, relative to the member. */
74
+ assets: z.array(z.string().min(1)).min(1),
75
+ /** The forge release's tag. Default: the tag the cut made, `release/<label>` or `release/<member>/<label>`. */
76
+ tag: z.string().min(1).optional(),
77
+ /** The variable holding the token. Default `GITHUB_TOKEN`, `GITLAB_TOKEN` (then `CI_JOB_TOKEN`), or `FORGEJO_TOKEN`. */
78
+ tokenEnv: envName.optional(),
79
+ /** The SBOM attached to the release (#4049), relative to the member. Default: one written from the member's lockfile. `false` publishes without one. */
80
+ sbom: sbomField.optional(),
81
+ })
82
+ .strict();
83
+ export const PublishDeclarationSchema = z.discriminatedUnion("type", [NpmPublishSchema, OciPublishSchema, ForgePublishSchema]);
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The forge release-asset target (#4047): files attached to the release a
3
+ * GitHub, GitLab or Forgejo repository has for the release's tag, through
4
+ * each forge's REST API and an injectable `fetch`.
5
+ *
6
+ * The tag is the declaration's `tag`, else the one the cut made
7
+ * (`release/<label>`, or `release/<member>/<label>`), so a release with no
8
+ * label and no declared tag is refused.
9
+ *
10
+ * A publish is two steps (#4048), so a consumer never sees a release with
11
+ * some of its assets:
12
+ *
13
+ * - GitHub and Forgejo stage on a draft release: the draft for the tag that
14
+ * `GET /repos/{repo}/releases` lists, else a new one,
15
+ * `POST /repos/{repo}/releases` with `draft: true` at the release's commit.
16
+ * GitHub uploads each asset to the draft's `upload_url`, Forgejo with a
17
+ * multipart `POST /repos/{repo}/releases/{id}/assets`. The reveal publishes
18
+ * the draft, `PATCH /repos/{repo}/releases/{id}` with `draft: false`, and
19
+ * the forge creates the tag then if it was not pushed.
20
+ * - GitLab has no draft release, so its stage puts each asset in the
21
+ * project's generic package registry (package `release`, version the
22
+ * label) and makes no release. The reveal creates the release at the
23
+ * commit with a link to each asset, in one `POST /projects/{id}/releases`.
24
+ *
25
+ * An asset already on the draft with the same name is left as it is when
26
+ * its `digest` matches (GitHub), so a stage run again uploads only the rest;
27
+ * one that differs, or one on a forge that reports no digest (Forgejo), is
28
+ * refused (`publish-forge-asset-exists`). A release already published for
29
+ * the tag is refused (`publish-forge-release-published`), since assets
30
+ * uploaded to it would show one at a time, unless it already holds every
31
+ * asset, which is what a publish revealed earlier leaves (on Forgejo and
32
+ * GitLab, which report no digest, by name).
33
+ *
34
+ * With the declared assets the stage attaches two more files (#4049): the
35
+ * SBOM (the file `sbom` names, else `sbom.spdx.json` written from the
36
+ * member's lockfile) and `release.intoto.json`, the release's provenance
37
+ * statement over the assets' digests, which carries the cut's signature
38
+ * (./publish-attachments.ts). They go on the draft with the assets, so
39
+ * nothing is visible before they are attached.
40
+ *
41
+ * The token is read from `tokenEnv`, else `GITHUB_TOKEN`, `GITLAB_TOKEN`
42
+ * then `CI_JOB_TOKEN`, or `FORGEJO_TOKEN`, and is masked in all output.
43
+ */
44
+ import type { ForgePublishDeclaration } from "./publish-declaration.js";
45
+ import { type PublishDeps, type PublishTarget } from "./release-publish.js";
46
+ /** The variables a forge's token is read from, in order. */
47
+ export declare function forgeTokenEnv(decl: Pick<ForgePublishDeclaration, "forge" | "tokenEnv">): string[];
48
+ /** The API root a forge is reached at. */
49
+ export declare function forgeApi(decl: Pick<ForgePublishDeclaration, "forge" | "api">, env: NodeJS.ProcessEnv): string | null;
50
+ /** A GitLab generic package version: the label with what GitLab refuses replaced. */
51
+ export declare function gitlabPackageVersion(label: string): string;
52
+ export declare function forgeTarget(decl: ForgePublishDeclaration, deps: PublishDeps): PublishTarget;
53
+ //# sourceMappingURL=publish-forge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-forge.d.ts","sourceRoot":"","sources":["../../src/lifecycle/publish-forge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AAMH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAErE,OAAO,EAA2C,KAAK,WAAW,EAAuC,KAAK,aAAa,EAAqB,MAAM,mBAAmB,CAAC;AAE1K,4DAA4D;AAC5D,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,uBAAuB,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG,MAAM,EAAE,CAKjG;AAED,0CAA0C;AAC1C,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,uBAAuB,EAAE,OAAO,GAAG,KAAK,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,GAAG,IAAI,CAGpH;AAqID,qFAAqF;AACrF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,WAAW,GAAG,aAAa,CA0H3F"}
@@ -0,0 +1,298 @@
1
+ /**
2
+ * The forge release-asset target (#4047): files attached to the release a
3
+ * GitHub, GitLab or Forgejo repository has for the release's tag, through
4
+ * each forge's REST API and an injectable `fetch`.
5
+ *
6
+ * The tag is the declaration's `tag`, else the one the cut made
7
+ * (`release/<label>`, or `release/<member>/<label>`), so a release with no
8
+ * label and no declared tag is refused.
9
+ *
10
+ * A publish is two steps (#4048), so a consumer never sees a release with
11
+ * some of its assets:
12
+ *
13
+ * - GitHub and Forgejo stage on a draft release: the draft for the tag that
14
+ * `GET /repos/{repo}/releases` lists, else a new one,
15
+ * `POST /repos/{repo}/releases` with `draft: true` at the release's commit.
16
+ * GitHub uploads each asset to the draft's `upload_url`, Forgejo with a
17
+ * multipart `POST /repos/{repo}/releases/{id}/assets`. The reveal publishes
18
+ * the draft, `PATCH /repos/{repo}/releases/{id}` with `draft: false`, and
19
+ * the forge creates the tag then if it was not pushed.
20
+ * - GitLab has no draft release, so its stage puts each asset in the
21
+ * project's generic package registry (package `release`, version the
22
+ * label) and makes no release. The reveal creates the release at the
23
+ * commit with a link to each asset, in one `POST /projects/{id}/releases`.
24
+ *
25
+ * An asset already on the draft with the same name is left as it is when
26
+ * its `digest` matches (GitHub), so a stage run again uploads only the rest;
27
+ * one that differs, or one on a forge that reports no digest (Forgejo), is
28
+ * refused (`publish-forge-asset-exists`). A release already published for
29
+ * the tag is refused (`publish-forge-release-published`), since assets
30
+ * uploaded to it would show one at a time, unless it already holds every
31
+ * asset, which is what a publish revealed earlier leaves (on Forgejo and
32
+ * GitLab, which report no digest, by name).
33
+ *
34
+ * With the declared assets the stage attaches two more files (#4049): the
35
+ * SBOM (the file `sbom` names, else `sbom.spdx.json` written from the
36
+ * member's lockfile) and `release.intoto.json`, the release's provenance
37
+ * statement over the assets' digests, which carries the cut's signature
38
+ * (./publish-attachments.ts). They go on the draft with the assets, so
39
+ * nothing is visible before they are attached.
40
+ *
41
+ * The token is read from `tokenEnv`, else `GITHUB_TOKEN`, `GITLAB_TOKEN`
42
+ * then `CI_JOB_TOKEN`, or `FORGEJO_TOKEN`, and is masked in all output.
43
+ */
44
+ import { readFileSync } from "node:fs";
45
+ import { basename } from "node:path";
46
+ import { memberSbom, releaseProvenance } from "./publish-attachments.js";
47
+ import { readCredential } from "./publish-credentials.js";
48
+ import { bytesDigest, checkReleaseDigest, memberFile, publishTargetKey } from "./publish-targets.js";
49
+ import { PublishTargetError } from "./release-publish.js";
50
+ /** The variables a forge's token is read from, in order. */
51
+ export function forgeTokenEnv(decl) {
52
+ if (decl.tokenEnv)
53
+ return [decl.tokenEnv];
54
+ if (decl.forge === "github")
55
+ return ["GITHUB_TOKEN"];
56
+ if (decl.forge === "gitlab")
57
+ return ["GITLAB_TOKEN", "CI_JOB_TOKEN"];
58
+ return ["FORGEJO_TOKEN"];
59
+ }
60
+ /** The API root a forge is reached at. */
61
+ export function forgeApi(decl, env) {
62
+ const root = decl.api ?? (decl.forge === "github" ? (env.GITHUB_API_URL ?? "https://api.github.com") : decl.forge === "gitlab" ? (env.CI_API_V4_URL ?? "https://gitlab.com/api/v4") : (env.GITHUB_API_URL ?? null));
63
+ return root ? root.replace(/\/+$/, "") : null;
64
+ }
65
+ class ForgeClient {
66
+ constructor(decl, api, token, fetch, ctx) {
67
+ this.decl = decl;
68
+ this.api = api;
69
+ this.token = token;
70
+ this.fetch = fetch;
71
+ this.ctx = ctx;
72
+ }
73
+ headers() {
74
+ const t = this.token.value;
75
+ if (this.decl.forge === "github")
76
+ return { authorization: `Bearer ${t}`, accept: "application/vnd.github+json", "user-agent": "chant" };
77
+ if (this.decl.forge === "forgejo")
78
+ return { authorization: `token ${t}`, accept: "application/json" };
79
+ return this.token.from === "CI_JOB_TOKEN" ? { "job-token": t } : { "private-token": t };
80
+ }
81
+ async call(method, url, body, extra = {}) {
82
+ const headers = { ...this.headers(), ...(typeof body === "string" ? { "content-type": "application/json" } : {}), ...extra };
83
+ const res = await this.fetch(url, { method, headers, ...(body !== undefined ? { body } : {}) });
84
+ const text = await res.text();
85
+ let json = null;
86
+ try {
87
+ json = text ? JSON.parse(text) : null;
88
+ }
89
+ catch {
90
+ json = null;
91
+ }
92
+ return { status: res.status, json, text };
93
+ }
94
+ fail(what, status, text) {
95
+ throw new PublishTargetError("publish-forge-failed", this.ctx.redactor.redact(`${what} on ${this.decl.forge} ${this.decl.repo} answered ${status}${text ? `: ${text.slice(0, 300)}` : ""}`));
96
+ }
97
+ get repoPath() {
98
+ return this.decl.forge === "gitlab" ? `${this.api}/projects/${encodeURIComponent(this.decl.repo)}` : `${this.api}/repos/${this.decl.repo}`;
99
+ }
100
+ toRelease(body, tag) {
101
+ const assets = new Map();
102
+ if (this.decl.forge === "gitlab") {
103
+ const links = body.assets?.links ?? [];
104
+ for (const l of links)
105
+ assets.set(l.name, null);
106
+ }
107
+ else {
108
+ for (const a of body.assets ?? [])
109
+ assets.set(a.name, typeof a.digest === "string" ? a.digest : null);
110
+ }
111
+ return { id: String(body.id ?? body.tag_name ?? tag), draft: body.draft === true, assets, ...(typeof body.upload_url === "string" ? { uploadUrl: body.upload_url } : {}) };
112
+ }
113
+ /** The published release for `tag`, or null when the forge has none. A draft is not found here. */
114
+ async published(tag) {
115
+ const enc = encodeURIComponent(tag);
116
+ const found = await this.call("GET", this.decl.forge === "gitlab" ? `${this.repoPath}/releases/${enc}` : `${this.repoPath}/releases/tags/${enc}`);
117
+ if (found.status === 404)
118
+ return null;
119
+ if (found.status !== 200 || !found.json)
120
+ this.fail(`reading release ${tag}`, found.status, found.text);
121
+ return this.toRelease(found.json, tag);
122
+ }
123
+ /** GitHub and Forgejo: the draft release for `tag`, made at `commit` when there is none. */
124
+ async draft(tag, commit, name) {
125
+ const list = await this.call("GET", `${this.repoPath}/releases?per_page=100`);
126
+ if (list.status !== 200)
127
+ this.fail("listing releases", list.status, list.text);
128
+ const drafts = Array.isArray(list.json) ? list.json : [];
129
+ const mine = drafts.find((r) => r.draft === true && r.tag_name === tag);
130
+ if (mine) {
131
+ this.ctx.log(`using the draft ${this.decl.forge} release for ${tag}`);
132
+ return this.toRelease(mine, tag);
133
+ }
134
+ this.ctx.log(`creating a draft ${this.decl.forge} release for ${tag} at ${commit.slice(0, 12)}`);
135
+ const create = await this.call("POST", `${this.repoPath}/releases`, JSON.stringify({ tag_name: tag, target_commitish: commit, name, draft: true }));
136
+ if (create.status !== 201 || !create.json)
137
+ this.fail(`creating a draft release ${tag}`, create.status, create.text);
138
+ return this.toRelease(create.json, tag);
139
+ }
140
+ /** GitHub and Forgejo: publish the draft `id`. */
141
+ async publishDraft(id, tag) {
142
+ const res = await this.call("PATCH", `${this.repoPath}/releases/${id}`, JSON.stringify({ draft: false }));
143
+ if (res.status !== 200)
144
+ this.fail(`publishing the draft release ${tag}`, res.status, res.text);
145
+ }
146
+ /** GitLab: create the release for `tag` at `commit` with a link to each asset. */
147
+ async createWithLinks(tag, commit, name, links) {
148
+ const res = await this.call("POST", `${this.repoPath}/releases`, JSON.stringify({ tag_name: tag, ref: commit, name, assets: { links: links.map((l) => ({ ...l, link_type: "package" })) } }));
149
+ if (res.status !== 201)
150
+ this.fail(`creating release ${tag}`, res.status, res.text);
151
+ }
152
+ /** Upload one asset to `rel`, returning where it can be downloaded. */
153
+ async upload(rel, version, asset) {
154
+ if (this.decl.forge === "github") {
155
+ const base = (rel?.uploadUrl ?? `${this.repoPath}/releases/${rel?.id}/assets`).replace(/\{[^}]*\}$/, "");
156
+ const res = await this.call("POST", `${base}?name=${encodeURIComponent(asset.name)}`, asset.bytes, { "content-type": "application/octet-stream" });
157
+ if (res.status !== 201)
158
+ this.fail(`uploading ${asset.name}`, res.status, res.text);
159
+ return String(res.json?.browser_download_url ?? asset.name);
160
+ }
161
+ if (this.decl.forge === "forgejo") {
162
+ const boundary = `chant-${bytesDigest(asset.bytes).slice(7, 31)}`;
163
+ const head = Buffer.from(`--${boundary}\r\nContent-Disposition: form-data; name="attachment"; filename="${asset.name.replace(/"/g, "")}"\r\nContent-Type: application/octet-stream\r\n\r\n`);
164
+ const tail = Buffer.from(`\r\n--${boundary}--\r\n`);
165
+ const body = new Uint8Array(Buffer.concat([head, Buffer.from(asset.bytes), tail]));
166
+ const res = await this.call("POST", `${this.repoPath}/releases/${rel?.id}/assets?name=${encodeURIComponent(asset.name)}`, body, { "content-type": `multipart/form-data; boundary=${boundary}` });
167
+ if (res.status !== 201)
168
+ this.fail(`uploading ${asset.name}`, res.status, res.text);
169
+ return String(res.json?.browser_download_url ?? asset.name);
170
+ }
171
+ const url = `${this.repoPath}/packages/generic/release/${encodeURIComponent(version)}/${encodeURIComponent(asset.name)}`;
172
+ const put = await this.call("PUT", url, asset.bytes, { "content-type": "application/octet-stream" });
173
+ if (put.status !== 201 && put.status !== 200)
174
+ this.fail(`uploading ${asset.name} to the generic package registry`, put.status, put.text);
175
+ return url;
176
+ }
177
+ }
178
+ /** A GitLab generic package version: the label with what GitLab refuses replaced. */
179
+ export function gitlabPackageVersion(label) {
180
+ return label.replace(/[^0-9A-Za-z.\-_+]/g, "-");
181
+ }
182
+ export function forgeTarget(decl, deps) {
183
+ const fetchImpl = deps.fetch ?? ((url, init) => fetch(url, init));
184
+ const tokenNames = forgeTokenEnv(decl);
185
+ const setup = (ctx) => {
186
+ const tag = decl.tag ?? ctx.releaseTag;
187
+ if (!tag) {
188
+ throw new PublishTargetError("publish-forge-no-tag", `a ${decl.forge} release is named by a tag, and release ${ctx.release.releaseDigest} has no label`, "Cut the release with a label, or set tag in the declaration.");
189
+ }
190
+ const api = forgeApi(decl, ctx.env);
191
+ if (!api)
192
+ throw new PublishTargetError("publish-forge-no-api", "a Forgejo target needs its API root, and neither api nor GITHUB_API_URL is set", "Set api, such as https://forgejo.example/api/v1.");
193
+ const token = readCredential(ctx.env, tokenNames, ctx.redactor);
194
+ if (!token) {
195
+ throw new PublishTargetError("publish-credentials-missing", `the ${decl.forge} target reads its token from ${tokenNames.join(" or ")}, and none is set`, `Set ${tokenNames[0]} in the job's or the shell's environment.`);
196
+ }
197
+ const assets = decl.assets.map((p) => {
198
+ const abs = memberFile(ctx.cwd, p);
199
+ const bytes = new Uint8Array(readFileSync(abs));
200
+ const digest = bytesDigest(bytes);
201
+ checkReleaseDigest(ctx.release, "asset", ctx.cwd, p, [digest]);
202
+ return { path: p, name: basename(p), bytes, digest };
203
+ });
204
+ // #4049: the SBOM and the provenance statement over the assets go on the release with them.
205
+ const sbom = memberSbom(ctx, decl.sbom, `${decl.repo}@${tag}`, `the ${decl.forge} target`);
206
+ const provenance = releaseProvenance(ctx, assets.map((a) => ({ name: a.name, digest: a.digest })));
207
+ for (const a of [sbom, provenance])
208
+ if (a)
209
+ assets.push({ path: a.name, name: a.name, bytes: a.bytes, digest: a.digest, attachment: a.kind });
210
+ const names = new Set();
211
+ for (const a of assets) {
212
+ if (names.has(a.name))
213
+ throw new PublishTargetError("publish-forge-asset-name-taken", `two assets are named ${a.name}, and a release holds one asset per name`);
214
+ names.add(a.name);
215
+ }
216
+ return { tag, api, token, assets };
217
+ };
218
+ const att = (a) => (a.attachment ? { attachment: a.attachment } : {});
219
+ const where = (tag, name) => `${decl.forge} ${decl.repo} release ${tag}, asset ${name}`;
220
+ const exists = (tag, a, theirs, before) => new PublishTargetError("publish-forge-asset-exists", `release ${tag} on ${decl.forge} ${decl.repo} already has an asset named ${a.name}${theirs ? ` with digest ${theirs}, not ${a.digest}` : ", and the forge reports no digest to compare"}${before.length > 0 ? `; ${before.map((i) => i.name).join(", ")} were staged before it` : ""}`, "Delete the asset on the forge, or cut a new release.");
221
+ return {
222
+ kind: "forge",
223
+ name: `${decl.forge} release assets ${decl.repo}`,
224
+ destination: `${decl.forge} ${decl.repo}`,
225
+ credentialEnv: tokenNames,
226
+ key: publishTargetKey(decl),
227
+ async plan(ctx) {
228
+ const { tag, assets } = setup(ctx);
229
+ return assets.map((a) => ({ name: a.path, destination: where(tag, a.name), digest: a.digest, ...att(a) }));
230
+ },
231
+ async stage(ctx) {
232
+ const { tag, api, token, assets } = setup(ctx);
233
+ ctx.log(`using the token from ${token.from}`);
234
+ const client = new ForgeClient(decl, api, token, fetchImpl, ctx);
235
+ const done = (items, state) => ({ target: this.name, destination: this.destination, items, state });
236
+ // A release already published: done when it holds every asset, else refused, since uploads to it would show one at a time.
237
+ const published = await client.published(tag);
238
+ if (published) {
239
+ const items = [];
240
+ for (const a of assets) {
241
+ if (!published.assets.has(a.name)) {
242
+ throw new PublishTargetError("publish-forge-release-published", `release ${tag} on ${decl.forge} ${decl.repo} is already published without ${a.name}, so the assets uploaded to it would show one at a time`, "Delete the forge release so the publish makes it whole, or set tag in the declaration to a tag with no release.");
243
+ }
244
+ const theirs = published.assets.get(a.name);
245
+ if (theirs !== a.digest && !(decl.forge !== "github" && theirs === null))
246
+ throw exists(tag, a, theirs, items);
247
+ items.push({ name: a.path, destination: where(tag, a.name), digest: a.digest, ...att(a), present: true });
248
+ }
249
+ ctx.log(`release ${tag} is already published with every asset`);
250
+ return done(items, { published: "true" });
251
+ }
252
+ const version = gitlabPackageVersion(ctx.label ?? tag);
253
+ if (decl.forge === "gitlab") {
254
+ // No draft on GitLab: the assets go to the package registry, and the release is made at the reveal.
255
+ const items = [];
256
+ for (const a of assets) {
257
+ ctx.log(`uploading ${a.name} (${a.bytes.byteLength} bytes) to the generic package registry`);
258
+ items.push({ name: a.path, destination: await client.upload(null, version, a), digest: a.digest, ...att(a) });
259
+ }
260
+ return done(items, {});
261
+ }
262
+ const rel = await client.draft(tag, ctx.release.commit, ctx.label ?? tag);
263
+ const items = [];
264
+ for (const a of assets) {
265
+ if (rel.assets.has(a.name)) {
266
+ const theirs = rel.assets.get(a.name);
267
+ if (theirs !== a.digest)
268
+ throw exists(tag, a, theirs, items);
269
+ items.push({ name: a.path, destination: where(tag, a.name), digest: a.digest, ...att(a), present: true });
270
+ ctx.log(`${a.name} is already on the draft release ${tag}`);
271
+ continue;
272
+ }
273
+ ctx.log(`uploading ${a.name} (${a.bytes.byteLength} bytes) to the draft`);
274
+ items.push({ name: a.path, destination: await client.upload(rel, version, a), digest: a.digest, ...att(a) });
275
+ }
276
+ return done(items, { releaseId: rel.id });
277
+ },
278
+ async reveal(ctx, staged) {
279
+ const { tag, api, token } = setup(ctx);
280
+ const client = new ForgeClient(decl, api, token, fetchImpl, ctx);
281
+ const items = staged.items.map((i) => ({ name: i.name, destination: i.destination, ...(i.digest ? { digest: i.digest } : {}), ...(i.attachment ? { attachment: i.attachment } : {}) }));
282
+ if (staged.state.published === "true")
283
+ return { target: this.name, destination: this.destination, items: items.map((i) => ({ ...i, present: true })) };
284
+ if (decl.forge === "gitlab") {
285
+ ctx.log(`creating the gitlab release ${tag} at ${ctx.release.commit.slice(0, 12)} with ${items.length} asset link(s)`);
286
+ await client.createWithLinks(tag, ctx.release.commit, ctx.label ?? tag, items.map((i) => ({ name: basename(i.name), url: i.destination })));
287
+ }
288
+ else {
289
+ const id = staged.state.releaseId;
290
+ if (!id)
291
+ throw new PublishTargetError("publish-forge-failed", `the staged ${decl.forge} release for ${tag} has no draft id to publish`);
292
+ ctx.log(`publishing the draft ${decl.forge} release ${tag}`);
293
+ await client.publishDraft(id, tag);
294
+ }
295
+ return { target: this.name, destination: this.destination, items };
296
+ },
297
+ };
298
+ }
@@ -0,0 +1,61 @@
1
+ /**
2
+ * The npm publish target (#4047): `npm publish` for each package the
3
+ * declaration lists, in the order it lists them, so a set of packages that
4
+ * depend on each other goes out dependencies first.
5
+ *
6
+ * Each package is a directory with a `package.json` or a `.tgz` that
7
+ * `npm pack` wrote, relative to the member.
8
+ *
9
+ * A publish is two steps (#4048), as chant's own releases are (#3903):
10
+ *
11
+ * - stage: for each package, `npm view <name>@<version> version` asks the
12
+ * registry whether it already holds the version, and when it does not,
13
+ *
14
+ * npm publish <package> --tag next [--registry <url>] [--access <access>] [--provenance]
15
+ *
16
+ * puts it out under the `next` dist-tag, where nothing that resolves
17
+ * `latest` or a range finds it. A version already there is not published
18
+ * again, so a stage run after a failure publishes only the rest.
19
+ * - reveal: `npm dist-tag add <name>@<version> latest` for each package in
20
+ * the declared order. The first package is the set's core: it moves first,
21
+ * so a consumer never resolves a new package whose new core is not `latest`
22
+ * yet. Order the list core first, then the packages that depend on it.
23
+ * `ctx.tag` names another tag to move in place of `latest`.
24
+ *
25
+ * `--provenance` is passed when the run has an OIDC token (`detectProvenance`
26
+ * in ./release-publish.ts), so a CI publish gets npm provenance, and npm's
27
+ * trusted publishing exchanges that token for its own. With that token, the
28
+ * reveal then checks what it published (#4049): in an empty directory it
29
+ * installs every package at its version with `npm install --ignore-scripts`
30
+ * and runs `npm audit signatures`, which fails on a package whose registry
31
+ * signature or provenance attestation does not verify. From a workstation
32
+ * there is no npm provenance, and the release's signature, which
33
+ * `chant release verify` checks, is the only provenance.
34
+ *
35
+ * Each package carries its SBOM (#4049): npm keeps no file beside a package,
36
+ * so the SBOM is a file at the package's root, the one `sbom` names or the
37
+ * first of `sbom.spdx.json`, `sbom.cdx.json`, `sbom.cyclonedx.json` it holds,
38
+ * such as `npm sbom` writes. A package with none is refused
39
+ * (`publish-sbom-missing`) unless the declaration says `sbom: false`. Moving a dist-tag over
40
+ * OIDC needs "Allow npm dist-tag" on the package's trusted-publisher record.
41
+ * npm makes the first version of a new package `latest` whatever tag it is
42
+ * published under, so a package's first release is visible when it stages.
43
+ *
44
+ * Credentials are npm's own. chant reads no npm token and writes no `.npmrc`:
45
+ * npm authenticates with the registry's `_authToken` in the user's or the
46
+ * CI's npm config (`actions/setup-node` writes one that reads
47
+ * `NODE_AUTH_TOKEN`), or by trusted publishing. npm runs with the run's
48
+ * environment, and everything it prints is redacted before chant prints it.
49
+ */
50
+ import type { NpmPublishDeclaration } from "./publish-declaration.js";
51
+ import { type PublishContext, type PublishDeps, type PublishTarget } from "./release-publish.js";
52
+ /** The arguments of one `npm publish`, which stages under `tag`. */
53
+ export declare function npmPublishArgs(decl: Pick<NpmPublishDeclaration, "registry" | "access">, abs: string, ctx: Pick<PublishContext, "provenance">, tag?: string): string[];
54
+ /** The arguments of the `npm dist-tag add` that reveals a staged version under `tag`. */
55
+ export declare function npmDistTagArgs(decl: Pick<NpmPublishDeclaration, "registry">, name: string, version: string, tag: string): string[];
56
+ /** The arguments of the `npm install` that fetches the published packages into an empty directory for `npm audit signatures`. */
57
+ export declare function npmAuditInstallArgs(decl: Pick<NpmPublishDeclaration, "registry">): string[];
58
+ /** The arguments of `npm audit signatures`. */
59
+ export declare function npmAuditSignaturesArgs(decl: Pick<NpmPublishDeclaration, "registry">): string[];
60
+ export declare function npmTarget(decl: NpmPublishDeclaration, deps: PublishDeps): PublishTarget;
61
+ //# sourceMappingURL=publish-npm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish-npm.d.ts","sourceRoot":"","sources":["../../src/lifecycle/publish-npm.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAOH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EAAqC,KAAK,cAAc,EAAE,KAAK,WAAW,EAAoB,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAiDnJ,oEAAoE;AACpE,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,qBAAqB,EAAE,UAAU,GAAG,QAAQ,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,cAAc,EAAE,YAAY,CAAC,EAAE,GAAG,GAAE,MAAsB,GAAG,MAAM,EAAE,CAUpL;AAED,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,qBAAqB,EAAE,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAElI;AAED,iIAAiI;AACjI,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,qBAAqB,EAAE,UAAU,CAAC,GAAG,MAAM,EAAE,CAE3F;AAED,+CAA+C;AAC/C,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,CAAC,qBAAqB,EAAE,UAAU,CAAC,GAAG,MAAM,EAAE,CAE9F;AAuBD,wBAAgB,SAAS,CAAC,IAAI,EAAE,qBAAqB,EAAE,IAAI,EAAE,WAAW,GAAG,aAAa,CAuGvF"}