@intentius/chant 0.124.34 → 0.124.36

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 (171) 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 +23 -8
  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 +19 -1
  14. package/dist/cli/parse-args.d.ts.map +1 -1
  15. package/dist/cli/parse-args.js +17 -0
  16. package/dist/cli/registry.d.ts +14 -0
  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.d.ts +4 -1
  28. package/dist/components/promote.d.ts.map +1 -1
  29. package/dist/components/promote.js +6 -3
  30. package/dist/components/release-promote.d.ts +9 -0
  31. package/dist/components/release-promote.d.ts.map +1 -1
  32. package/dist/components/release-promote.js +15 -0
  33. package/dist/config.d.ts +3 -0
  34. package/dist/config.d.ts.map +1 -1
  35. package/dist/deep-observation.d.ts +11 -0
  36. package/dist/deep-observation.d.ts.map +1 -1
  37. package/dist/graph-declared.d.ts +5 -1
  38. package/dist/graph-declared.d.ts.map +1 -1
  39. package/dist/graph-declared.js +7 -2
  40. package/dist/graph-detail.d.ts.map +1 -1
  41. package/dist/graph-detail.js +30 -1
  42. package/dist/graph-ir.d.ts.map +1 -1
  43. package/dist/graph-ir.js +13 -2
  44. package/dist/lifecycle/__fixtures__/publish-fakes.d.ts +5 -0
  45. package/dist/lifecycle/__fixtures__/publish-fakes.d.ts.map +1 -1
  46. package/dist/lifecycle/__fixtures__/publish-fakes.js +20 -2
  47. package/dist/lifecycle/compose-refs.d.ts +52 -0
  48. package/dist/lifecycle/compose-refs.d.ts.map +1 -0
  49. package/dist/lifecycle/compose-refs.js +115 -0
  50. package/dist/lifecycle/deep-observe.d.ts.map +1 -1
  51. package/dist/lifecycle/deep-observe.js +3 -2
  52. package/dist/lifecycle/green-apply.d.ts +39 -0
  53. package/dist/lifecycle/green-apply.d.ts.map +1 -0
  54. package/dist/lifecycle/green-apply.js +51 -0
  55. package/dist/lifecycle/publish-declaration.d.ts +6 -0
  56. package/dist/lifecycle/publish-declaration.d.ts.map +1 -1
  57. package/dist/lifecycle/publish-declaration.js +21 -0
  58. package/dist/lifecycle/publish-npm.d.ts +11 -4
  59. package/dist/lifecycle/publish-npm.d.ts.map +1 -1
  60. package/dist/lifecycle/publish-npm.js +104 -14
  61. package/dist/lifecycle/release-compose.d.ts +91 -0
  62. package/dist/lifecycle/release-compose.d.ts.map +1 -0
  63. package/dist/lifecycle/release-compose.js +235 -0
  64. package/dist/lifecycle/release-cut.d.ts +8 -0
  65. package/dist/lifecycle/release-cut.d.ts.map +1 -1
  66. package/dist/lifecycle/release-cut.js +2 -0
  67. package/dist/lifecycle/release-publish.d.ts +6 -0
  68. package/dist/lifecycle/release-publish.d.ts.map +1 -1
  69. package/dist/lifecycle/release-publish.js +2 -1
  70. package/dist/lifecycle/release-store.d.ts +15 -0
  71. package/dist/lifecycle/release-store.d.ts.map +1 -1
  72. package/dist/lifecycle/release-store.js +5 -1
  73. package/dist/wave-runtime.mjs +225 -223
  74. package/dist/workspace/checks/ci-workflow.d.ts.map +1 -1
  75. package/dist/workspace/checks/ci-workflow.js +8 -1
  76. package/dist/workspace/ci-green-cli.d.ts.map +1 -1
  77. package/dist/workspace/ci-green-cli.js +5 -3
  78. package/dist/workspace/ci-green-workflow.d.ts +18 -2
  79. package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
  80. package/dist/workspace/ci-green-workflow.js +27 -5
  81. package/dist/workspace/ci-green.d.ts +31 -0
  82. package/dist/workspace/ci-green.d.ts.map +1 -1
  83. package/dist/workspace/ci-green.js +78 -4
  84. package/dist/workspace/ci-run.d.ts +6 -0
  85. package/dist/workspace/ci-run.d.ts.map +1 -1
  86. package/dist/workspace/ci-run.js +2 -1
  87. package/dist/workspace/ci-serve.d.ts +94 -13
  88. package/dist/workspace/ci-serve.d.ts.map +1 -1
  89. package/dist/workspace/ci-serve.js +248 -30
  90. package/dist/workspace/ci-workflow.d.ts +4 -4
  91. package/dist/workspace/ci-workflow.d.ts.map +1 -1
  92. package/dist/workspace/ci-workflow.js +2 -2
  93. package/dist/workspace/delivery-metrics.d.ts +3 -1
  94. package/dist/workspace/delivery-metrics.d.ts.map +1 -1
  95. package/dist/workspace/delivery-metrics.js +12 -3
  96. package/dist/workspace/member-commands.d.ts.map +1 -1
  97. package/dist/workspace/member-commands.js +4 -0
  98. package/dist/workspace/nested-graph.d.ts.map +1 -1
  99. package/dist/workspace/nested-graph.js +1 -0
  100. package/dist/workspace/release-candidates.d.ts +28 -0
  101. package/dist/workspace/release-candidates.d.ts.map +1 -1
  102. package/dist/workspace/release-candidates.js +38 -2
  103. package/dist/workspace/release-candidates.schema.json +51 -0
  104. package/dist/workspace/releases.schema.json +30 -0
  105. package/package.json +1 -1
  106. package/src/cli/handlers/graph.ts +2 -2
  107. package/src/cli/handlers/pr-green.test.ts +230 -0
  108. package/src/cli/handlers/pr.ts +148 -66
  109. package/src/cli/handlers/promote.test.ts +34 -0
  110. package/src/cli/handlers/promote.ts +22 -8
  111. package/src/cli/handlers/release-compose.e2e.test.ts +133 -0
  112. package/src/cli/handlers/release-publish-targets.e2e.test.ts +4 -1
  113. package/src/cli/handlers/release.ts +112 -10
  114. package/src/cli/handlers/run.ts +12 -1
  115. package/src/cli/main.ts +19 -1
  116. package/src/cli/parse-args.ts +13 -0
  117. package/src/cli/registry.ts +14 -0
  118. package/src/codegen/release-wiring.test.ts +56 -9
  119. package/src/components/auto-release.test.ts +22 -0
  120. package/src/components/auto-release.ts +9 -2
  121. package/src/components/green-cover.test.ts +170 -0
  122. package/src/components/green-cover.ts +186 -0
  123. package/src/components/pr-pipeline.test.ts +14 -4
  124. package/src/components/pr-pipeline.ts +56 -5
  125. package/src/components/promote.test.ts +7 -0
  126. package/src/components/promote.ts +9 -4
  127. package/src/components/release-promote.test.ts +24 -1
  128. package/src/components/release-promote.ts +15 -0
  129. package/src/deep-observation.ts +8 -0
  130. package/src/graph-declared.test.ts +18 -0
  131. package/src/graph-declared.ts +8 -1
  132. package/src/graph-detail.test.ts +68 -1
  133. package/src/graph-detail.ts +29 -1
  134. package/src/graph-ir.ts +12 -4
  135. package/src/lifecycle/__fixtures__/publish-fakes.ts +20 -2
  136. package/src/lifecycle/compose-refs.ts +125 -0
  137. package/src/lifecycle/deep-observe.test.ts +20 -0
  138. package/src/lifecycle/deep-observe.ts +4 -2
  139. package/src/lifecycle/green-apply.ts +71 -0
  140. package/src/lifecycle/publish-declaration.ts +21 -0
  141. package/src/lifecycle/publish-npm.ts +100 -14
  142. package/src/lifecycle/publish-targets.test.ts +108 -0
  143. package/src/lifecycle/release-compose.test.ts +125 -0
  144. package/src/lifecycle/release-compose.ts +312 -0
  145. package/src/lifecycle/release-cut.ts +6 -0
  146. package/src/lifecycle/release-publish.ts +8 -1
  147. package/src/lifecycle/release-store.ts +16 -1
  148. package/src/workspace/checks/ci-workflow.test.ts +12 -2
  149. package/src/workspace/checks/ci-workflow.ts +7 -1
  150. package/src/workspace/ci-green-cli.ts +5 -3
  151. package/src/workspace/ci-green-workflow.test.ts +52 -0
  152. package/src/workspace/ci-green-workflow.ts +34 -5
  153. package/src/workspace/ci-green.test.ts +33 -0
  154. package/src/workspace/ci-green.ts +85 -4
  155. package/src/workspace/ci-run.test.ts +18 -13
  156. package/src/workspace/ci-run.ts +8 -1
  157. package/src/workspace/ci-serve-land.e2e.test.ts +138 -0
  158. package/src/workspace/ci-serve-land.test.ts +176 -0
  159. package/src/workspace/ci-serve.test.ts +77 -43
  160. package/src/workspace/ci-serve.ts +268 -34
  161. package/src/workspace/ci-workflow.ts +4 -4
  162. package/src/workspace/delivery-metrics.ts +12 -3
  163. package/src/workspace/graph-contract.test.ts +3 -2
  164. package/src/workspace/member-commands.test.ts +11 -4
  165. package/src/workspace/member-commands.ts +3 -0
  166. package/src/workspace/nested-graph.test.ts +4 -0
  167. package/src/workspace/nested-graph.ts +1 -0
  168. package/src/workspace/release-candidates.schema.json +51 -0
  169. package/src/workspace/release-candidates.test.ts +30 -3
  170. package/src/workspace/release-candidates.ts +54 -2
  171. package/src/workspace/releases.schema.json +30 -0
@@ -42,10 +42,13 @@
42
42
  * npm makes the first version of a new package `latest` whatever tag it is
43
43
  * published under, so a package's first release is visible when it stages.
44
44
  *
45
- * Credentials are npm's own. chant reads no npm token and writes no `.npmrc`:
46
- * npm authenticates with the registry's `_authToken` in the user's or the
47
- * CI's npm config (`actions/setup-node` writes one that reads
48
- * `NODE_AUTH_TOKEN`), or by trusted publishing. npm runs with the run's
45
+ * Credentials are npm's own: npm authenticates with the registry's
46
+ * `_authToken` in the user's or the CI's npm config (`actions/setup-node`
47
+ * writes one that reads `NODE_AUTH_TOKEN`), or by trusted publishing. The one
48
+ * exception is `tokenEnv` (#4040): when a publish fails to authenticate, the
49
+ * package is published again with that variable's token in a throwaway npm
50
+ * user config, never on the command line, and without `--provenance` if the
51
+ * registry refuses the attestation on the token path. npm runs with the run's
49
52
  * environment, and everything it prints is redacted before chant prints it.
50
53
  */
51
54
  import { execFileSync, spawn } from "node:child_process";
@@ -55,6 +58,8 @@ import { join } from "node:path";
55
58
  import { packageSbom } from "./publish-attachments.js";
56
59
  import { checkReleaseDigest, fileDigest, isDir, memberFile, publishTargetKey } from "./publish-targets.js";
57
60
  import { NPM_STAGE_TAG, PublishTargetError } from "./release-publish.js";
61
+ /** npm's output when a publish could not authenticate, as publish-packages.sh matches it. */
62
+ const NPM_AUTH_FAILED = /ENEEDAUTH|E401|need auth/;
58
63
  /** Read a package's name and version, from its directory or its packed `.tgz`, and find the SBOM it carries. */
59
64
  function readPackage(ctx, path, sbom) {
60
65
  const abs = memberFile(ctx.cwd, path);
@@ -119,9 +124,9 @@ export function npmAuditInstallArgs(decl) {
119
124
  export function npmAuditSignaturesArgs(decl) {
120
125
  return ["audit", "signatures", ...(decl.registry ? ["--registry", decl.registry] : [])];
121
126
  }
122
- function run(bin, args, ctx, cwd = ctx.cwd) {
127
+ function run(bin, args, ctx, cwd = ctx.cwd, env = ctx.env) {
123
128
  return new Promise((resolvePromise, reject) => {
124
- const child = spawn(bin, args, { cwd, env: ctx.env, stdio: ["ignore", "pipe", "pipe"] });
129
+ const child = spawn(bin, args, { cwd, env, stdio: ["ignore", "pipe", "pipe"] });
125
130
  const output = [];
126
131
  let partial = { out: "", err: "" };
127
132
  const take = (key) => (chunk) => {
@@ -143,14 +148,25 @@ function run(bin, args, ctx, cwd = ctx.cwd) {
143
148
  });
144
149
  });
145
150
  }
151
+ /** Seconds the reveal waits for the registry to serve what it published, by default (#4244). */
152
+ export const NPM_REGISTRY_WAIT_SECONDS = 600;
153
+ /** Between polls of the registry while it waits. */
154
+ export const NPM_REGISTRY_POLL_MS = 10000;
155
+ /** npm's errors for a version the registry does not serve yet. */
156
+ const NPM_NOT_SERVED = /\b(ETARGET|ERESOLVE|notarget)\b|No matching version found/;
146
157
  export function npmTarget(decl, deps) {
147
158
  const bin = deps.npm ?? "npm";
159
+ const sleep = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
160
+ const now = deps.now ?? Date.now;
148
161
  const registry = decl.registry ?? "the registry npm's config names";
149
162
  const shown = (tag) => `${registry}, dist-tag ${tag}`;
150
163
  const revealTag = (ctx) => ctx.tag ?? "latest";
151
- const npm = async (ctx, args, cwd) => {
164
+ // Under `stage: false` a package goes straight to the reveal tag, and the reveal moves no tag (#4040).
165
+ const staging = decl.stage !== false;
166
+ const stageTag = (ctx) => (staging ? NPM_STAGE_TAG : revealTag(ctx));
167
+ const npm = async (ctx, args, cwd, env) => {
152
168
  try {
153
- return await run(bin, args, ctx, cwd);
169
+ return await run(bin, args, ctx, cwd, env);
154
170
  }
155
171
  catch (err) {
156
172
  throw new PublishTargetError("publish-npm-failed", ctx.redactor.redact(`npm could not be run: ${err instanceof Error ? err.message : String(err)}`), "Install npm, or put it on PATH.");
@@ -161,24 +177,90 @@ export function npmTarget(decl, deps) {
161
177
  const r = await npm(ctx, ["view", `${pkg.name}@${pkg.version}`, "version", ...(decl.registry ? ["--registry", decl.registry] : [])]);
162
178
  return r.code === 0 && r.output.some((l) => l.trim() === pkg.version || l.trim() === JSON.stringify(pkg.version));
163
179
  };
180
+ /**
181
+ * The `tokenEnv` retry (#4040): a publish that failed to authenticate runs
182
+ * again with the token in a throwaway user config, and once more without
183
+ * `--provenance` when the token path refuses the attestation.
184
+ */
185
+ const withToken = async (ctx, pkg, args, failed) => {
186
+ const token = decl.tokenEnv ? ctx.env[decl.tokenEnv] : undefined;
187
+ if (!token || !failed.output.some((l) => NPM_AUTH_FAILED.test(l)))
188
+ return failed;
189
+ ctx.log(`${pkg.name}@${pkg.version} could not authenticate; publishing again with ${decl.tokenEnv}`);
190
+ const dir = mkdtempSync(join(tmpdir(), "chant-npm-token-"));
191
+ try {
192
+ const userconfig = join(dir, ".npmrc");
193
+ const host = (decl.registry ?? "https://registry.npmjs.org/").replace(/^https?:/, "").replace(/\/?$/, "/");
194
+ writeFileSync(userconfig, `${host}:_authToken=${token}\n`, { mode: 0o600 });
195
+ const env = { ...ctx.env, NPM_CONFIG_USERCONFIG: userconfig };
196
+ let result = await npm(ctx, args, undefined, env);
197
+ for (const line of result.output)
198
+ ctx.log(` ${line}`);
199
+ if (result.code !== 0 && args.includes("--provenance") && result.output.some((l) => /^npm (error|ERR!).*(provenance|attestation)/i.test(l))) {
200
+ ctx.log(`${pkg.name}@${pkg.version}: the registry refused provenance on the token path; publishing without an attestation`);
201
+ result = await npm(ctx, args.filter((a) => a !== "--provenance"), undefined, env);
202
+ for (const line of result.output)
203
+ ctx.log(` ${line}`);
204
+ }
205
+ return result;
206
+ }
207
+ finally {
208
+ rmSync(dir, { recursive: true, force: true });
209
+ }
210
+ };
164
211
  const read = (ctx) => decl.packages.map((p) => readPackage(ctx, p, decl.sbom));
165
212
  const extra = (pkg) => ({ ...(pkg.digest ? { digest: pkg.digest } : {}), ...(pkg.sbom ? { sbom: pkg.sbom } : {}) });
166
- const plan = async (ctx) => read(ctx).map((pkg) => ({ name: `${pkg.name}@${pkg.version}`, destination: `${shown(NPM_STAGE_TAG)}, then ${revealTag(ctx)}`, ...extra(pkg) }));
213
+ const plan = async (ctx) => read(ctx).map((pkg) => ({ name: `${pkg.name}@${pkg.version}`, destination: staging ? `${shown(NPM_STAGE_TAG)}, then ${revealTag(ctx)}` : shown(revealTag(ctx)), ...extra(pkg) }));
167
214
  /**
168
215
  * In CI, install what was published into an empty directory and run
169
216
  * `npm audit signatures` there (#4049), which checks each package's
170
217
  * registry signature and provenance attestation.
171
218
  */
219
+ /**
220
+ * Wait until the registry serves every version (#4244): npm accepts a
221
+ * publish minutes before `npm view` and `npm install` find it, so an
222
+ * install straight after fails with ETARGET or ERESOLVE.
223
+ */
224
+ const served = async (ctx, pkgs) => {
225
+ const wait = (decl.registryWait ?? NPM_REGISTRY_WAIT_SECONDS) * 1000;
226
+ const start = now();
227
+ let missing = pkgs;
228
+ for (;;) {
229
+ const still = [];
230
+ for (const pkg of missing)
231
+ if (!(await onRegistry(ctx, pkg)))
232
+ still.push(pkg);
233
+ missing = still;
234
+ if (missing.length === 0)
235
+ return;
236
+ const names = missing.map((p) => `${p.name}@${p.version}`).join(", ");
237
+ if (now() - start >= wait) {
238
+ throw new PublishTargetError("publish-npm-not-served", `the registry did not serve ${names} within ${Math.round(wait / 1000)}s of the publish, so nothing was audited`, "Each package was published. Once npm serves them, run the publish again: it publishes nothing twice and audits again. `registryWait` sets the wait.");
239
+ }
240
+ ctx.log(`waiting for the registry to serve ${names}`);
241
+ await sleep(NPM_REGISTRY_POLL_MS);
242
+ }
243
+ };
172
244
  const audit = async (ctx, pkgs) => {
245
+ await served(ctx, pkgs);
173
246
  const dir = mkdtempSync(join(tmpdir(), "chant-npm-audit-"));
174
247
  try {
175
248
  const dependencies = Object.fromEntries(pkgs.map((p) => [p.name, p.version]));
176
249
  writeFileSync(join(dir, "package.json"), `${JSON.stringify({ name: "chant-publish-audit", version: "0.0.0", private: true, dependencies }, null, 2)}\n`);
177
250
  for (const args of [npmAuditInstallArgs(decl), npmAuditSignaturesArgs(decl)]) {
178
251
  ctx.log(`npm ${args.join(" ")}`);
179
- const result = await npm(ctx, args, dir);
252
+ let result = await npm(ctx, args, dir);
180
253
  for (const line of result.output)
181
254
  ctx.log(` ${line}`);
255
+ // `npm view` can answer before every mirror `npm install` reads does: wait once more, then install again.
256
+ if (result.code !== 0 && args[0] === "install" && result.output.some((l) => NPM_NOT_SERVED.test(l))) {
257
+ ctx.log("the registry does not serve every version to an install yet; waiting, then installing again");
258
+ await sleep(NPM_REGISTRY_POLL_MS);
259
+ await served(ctx, pkgs);
260
+ result = await npm(ctx, args, dir);
261
+ for (const line of result.output)
262
+ ctx.log(` ${line}`);
263
+ }
182
264
  if (result.code !== 0) {
183
265
  throw new PublishTargetError("publish-npm-audit-failed", `npm ${args.slice(0, 2).join(" ")} exited ${result.code} for ${pkgs.map((p) => `${p.name}@${p.version}`).join(", ")}, after latest moved: ${result.output.at(-1) ?? "npm printed nothing"}`, "Each package was published; check its signature and provenance on the registry. Running the publish again moves no tag that moved and audits again.");
184
266
  }
@@ -199,20 +281,22 @@ export function npmTarget(decl, deps) {
199
281
  const pkgs = read(ctx);
200
282
  const items = [];
201
283
  for (const pkg of pkgs) {
202
- const item = { name: `${pkg.name}@${pkg.version}`, destination: shown(NPM_STAGE_TAG), ...extra(pkg) };
284
+ const item = { name: `${pkg.name}@${pkg.version}`, destination: shown(stageTag(ctx)), ...extra(pkg) };
203
285
  if (await onRegistry(ctx, pkg)) {
204
286
  ctx.log(`${item.name} is already on the registry; not published again`);
205
287
  items.push({ ...item, present: true });
206
288
  continue;
207
289
  }
208
- const args = npmPublishArgs(decl, pkg.abs, ctx);
290
+ const args = npmPublishArgs(decl, pkg.abs, ctx, stageTag(ctx));
209
291
  ctx.log(`npm publish ${pkg.path} ${args.slice(2).join(" ")}`);
210
- const result = await npm(ctx, args);
292
+ let result = await npm(ctx, args);
211
293
  for (const line of result.output)
212
294
  ctx.log(` ${line}`);
295
+ if (result.code !== 0)
296
+ result = await withToken(ctx, pkg, args, result);
213
297
  if (result.code !== 0) {
214
298
  const done = items.map((i) => i.name);
215
- throw new PublishTargetError("publish-npm-failed", `npm publish of ${item.name} exited ${result.code}${done.length > 0 ? `, after ${done.join(", ")} were staged under ${NPM_STAGE_TAG}` : ", before any package was staged"}: ${result.output.at(-1) ?? "npm printed nothing"}`);
299
+ throw new PublishTargetError("publish-npm-failed", `npm publish of ${item.name} exited ${result.code}${done.length > 0 ? `, after ${done.join(", ")} were ${staging ? "staged" : "published"} under ${stageTag(ctx)}` : `, before any package was ${staging ? "staged" : "published"}`}: ${result.output.at(-1) ?? "npm printed nothing"}`);
216
300
  }
217
301
  items.push(item);
218
302
  }
@@ -222,6 +306,12 @@ export function npmTarget(decl, deps) {
222
306
  const tag = revealTag(ctx);
223
307
  const pkgs = read(ctx);
224
308
  const items = [];
309
+ if (!staging) {
310
+ // Already under the reveal tag since the stage; only the audit is left.
311
+ if (ctx.provenance.oidc)
312
+ await audit(ctx, pkgs);
313
+ return { target: this.name, destination: this.destination, items: pkgs.map((pkg) => ({ name: `${pkg.name}@${pkg.version}`, destination: shown(tag), ...extra(pkg) })) };
314
+ }
225
315
  // The declared order: the first package is the set's core, and its tag moves first.
226
316
  for (const pkg of pkgs) {
227
317
  const args = npmDistTagArgs(decl, pkg.name, pkg.version, tag);
@@ -0,0 +1,91 @@
1
+ /**
2
+ * `chant release compose` (#4168 4.3, mode b): a release of chosen changes
3
+ * on a base, when trunk carries work that is not ready to ship.
4
+ *
5
+ * The changes are named by pull request (`--pr <n>`) or work item
6
+ * (`--work <id>`) and found on trunk's first-parent line after the base:
7
+ * a pull request by the merge record `_merges/<sha>.json` on
8
+ * `chant/lifecycle` (./merge-record.ts) or the squash subject `... (#n)`,
9
+ * a work item by the commit's `Chant-Record: work:<id>` trailers or a merge
10
+ * record that names it. Each commit is cherry-picked in trunk order onto the
11
+ * base, in a temporary detached worktree, with a `Chant-Composed-From: <sha>`
12
+ * trailer, and the result goes on the branch `chant/compose/<name>`, pushed
13
+ * so the forge's CI builds it (decision 6).
14
+ *
15
+ * It only appends. A branch that exists is composed onto from its tip, with
16
+ * the base it already has; a change it already carries is skipped. On a
17
+ * conflict it stops, names the change and the files, and writes nothing: a
18
+ * person resolves it in a pull request to the compose branch.
19
+ *
20
+ * Without `yes` it is a dry run: the picks are made in the temporary
21
+ * worktree, so a conflict shows now, and no ref is moved or pushed.
22
+ */
23
+ export type ComposeCode = "not-a-git-repository" | "compose-name-invalid" | "compose-nothing-chosen" | "compose-base-unknown" | "compose-base-differs" | "compose-branch-diverged" | "compose-source-unknown" | "compose-conflict" | "compose-push-refused";
24
+ export declare class ComposeError extends Error {
25
+ readonly code: ComposeCode;
26
+ readonly fix?: string | undefined;
27
+ /** With `compose-conflict`: the change that did not apply and the files it conflicts in. */
28
+ readonly conflict?: {
29
+ commit: string;
30
+ subject: string;
31
+ files: string[];
32
+ } | undefined;
33
+ constructor(code: ComposeCode, message: string, fix?: string | undefined,
34
+ /** With `compose-conflict`: the change that did not apply and the files it conflicts in. */
35
+ conflict?: {
36
+ commit: string;
37
+ subject: string;
38
+ files: string[];
39
+ } | undefined);
40
+ }
41
+ export interface ComposeRequest {
42
+ cwd: string;
43
+ name: string;
44
+ /** A release label or digest, or a commit. Required when the branch does not exist yet. */
45
+ base?: string;
46
+ prs: readonly number[];
47
+ works: readonly string[];
48
+ /** Move the branch and push it. Otherwise a dry run. */
49
+ yes: boolean;
50
+ /** The trunk branch, `ci.green.branch` as the cut resolves it. */
51
+ trunk: {
52
+ remote: string;
53
+ branch: string;
54
+ };
55
+ /** Push the branch to the trunk's remote with `yes`. Default true. */
56
+ push?: boolean;
57
+ }
58
+ /** One trunk commit a compose picks, and why. */
59
+ export interface ComposeSource {
60
+ commit: string;
61
+ subject: string;
62
+ pr: number | null;
63
+ work: string[];
64
+ /** The `--pr` and `--work` values that chose it. */
65
+ chosenBy: string[];
66
+ }
67
+ export interface ComposeResult {
68
+ name: string;
69
+ branch: string;
70
+ base: string;
71
+ /** The branch's tip before the compose, or null when it is new. */
72
+ from: string | null;
73
+ /** The commits picked now, in trunk order. */
74
+ picked: ComposeSource[];
75
+ /** Chosen commits the branch already carries. */
76
+ already: ComposeSource[];
77
+ /** The branch's tip after the picks. Under a dry run, the tip it would have. */
78
+ tip: string;
79
+ /** Whether the branch was moved here. False under a dry run. */
80
+ written: boolean;
81
+ /** Whether it was pushed. */
82
+ pushed: boolean;
83
+ }
84
+ /** The branch a compose name lives on. */
85
+ export declare function composeBranchName(name: string): string;
86
+ /**
87
+ * Compose the chosen changes onto the base, on `chant/compose/<name>`.
88
+ * Throws {@link ComposeError} before any ref moves.
89
+ */
90
+ export declare function composeRelease(req: ComposeRequest): Promise<ComposeResult>;
91
+ //# sourceMappingURL=release-compose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release-compose.d.ts","sourceRoot":"","sources":["../../src/lifecycle/release-compose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAQH,MAAM,MAAM,WAAW,GACnB,sBAAsB,GACtB,sBAAsB,GACtB,wBAAwB,GACxB,sBAAsB,GACtB,sBAAsB,GACtB,yBAAyB,GACzB,wBAAwB,GACxB,kBAAkB,GAClB,sBAAsB,CAAC;AAE3B,qBAAa,YAAa,SAAQ,KAAK;IAEnC,QAAQ,CAAC,IAAI,EAAE,WAAW;IAE1B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM;IACrB,4FAA4F;IAC5F,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE;IAL1E,YACW,IAAI,EAAE,WAAW,EAC1B,OAAO,EAAE,MAAM,EACN,GAAG,CAAC,EAAE,MAAM,YAAA;IACrB,4FAA4F;IACnF,QAAQ,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAA;KAAE,YAAA,EAIzE;CACF;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,2FAA2F;IAC3F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;IACvB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,wDAAwD;IACxD,GAAG,EAAE,OAAO,CAAC;IACb,kEAAkE;IAClE,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,sEAAsE;IACtE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,iDAAiD;AACjD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,oDAAoD;IACpD,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,mEAAmE;IACnE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,8CAA8C;IAC9C,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,iDAAiD;IACjD,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,OAAO,EAAE,OAAO,CAAC;IACjB,6BAA6B;IAC7B,MAAM,EAAE,OAAO,CAAC;CACjB;AAmBD,0CAA0C;AAC1C,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAsCD;;;GAGG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAkHhF"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * `chant release compose` (#4168 4.3, mode b): a release of chosen changes
3
+ * on a base, when trunk carries work that is not ready to ship.
4
+ *
5
+ * The changes are named by pull request (`--pr <n>`) or work item
6
+ * (`--work <id>`) and found on trunk's first-parent line after the base:
7
+ * a pull request by the merge record `_merges/<sha>.json` on
8
+ * `chant/lifecycle` (./merge-record.ts) or the squash subject `... (#n)`,
9
+ * a work item by the commit's `Chant-Record: work:<id>` trailers or a merge
10
+ * record that names it. Each commit is cherry-picked in trunk order onto the
11
+ * base, in a temporary detached worktree, with a `Chant-Composed-From: <sha>`
12
+ * trailer, and the result goes on the branch `chant/compose/<name>`, pushed
13
+ * so the forge's CI builds it (decision 6).
14
+ *
15
+ * It only appends. A branch that exists is composed onto from its tip, with
16
+ * the base it already has; a change it already carries is skipped. On a
17
+ * conflict it stops, names the change and the files, and writes nothing: a
18
+ * person resolves it in a pull request to the compose branch.
19
+ *
20
+ * Without `yes` it is a dry run: the picks are made in the temporary
21
+ * worktree, so a conflict shows now, and no ref is moved or pushed.
22
+ */
23
+ import { execFileSync, spawnSync } from "node:child_process";
24
+ import { mkdtempSync, realpathSync, rmSync } from "node:fs";
25
+ import { tmpdir } from "node:os";
26
+ import { join } from "node:path";
27
+ import { COMPOSE_BRANCH_PREFIX, COMPOSED_FROM_TRAILER, compositionOnTrunk } from "./compose-refs.js";
28
+ export class ComposeError extends Error {
29
+ constructor(code, message, fix,
30
+ /** With `compose-conflict`: the change that did not apply and the files it conflicts in. */
31
+ conflict) {
32
+ super(message);
33
+ this.code = code;
34
+ this.fix = fix;
35
+ this.conflict = conflict;
36
+ this.name = "ComposeError";
37
+ }
38
+ }
39
+ const NAME = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
40
+ const PR_IN_SUBJECT = /\(#(\d+)\)\s*$/;
41
+ function git(cwd, args, env) {
42
+ return execFileSync("git", args, { cwd, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"], maxBuffer: 64 * 1024 * 1024, ...(env ? { env } : {}) }).trim();
43
+ }
44
+ function tryGit(cwd, args) {
45
+ try {
46
+ return git(cwd, args);
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ }
52
+ const isAncestor = (top, a, b) => spawnSync("git", ["merge-base", "--is-ancestor", a, b], { cwd: top, stdio: "ignore" }).status === 0;
53
+ /** The branch a compose name lives on. */
54
+ export function composeBranchName(name) {
55
+ return `${COMPOSE_BRANCH_PREFIX}${name}`;
56
+ }
57
+ async function resolveBase(top, cwd, ref) {
58
+ const { resolveRelease } = await import("./release-store.js");
59
+ const found = await resolveRelease(ref, { cwd }).catch(() => null);
60
+ if (found)
61
+ return found.release.commit;
62
+ const sha = tryGit(top, ["rev-parse", "--verify", "--quiet", `${ref}^{commit}`]);
63
+ if (!sha) {
64
+ throw new ComposeError("compose-base-unknown", `--base ${ref} names no release of this member and no commit this clone has`, "Name a release label (chant release list) or a commit, after fetching it.");
65
+ }
66
+ return sha;
67
+ }
68
+ /** The merge record of `sha`, as stored, or null. */
69
+ async function mergeRecordOf(cwd, sha) {
70
+ const { readBlobFromPath } = await import("./git.js");
71
+ const text = await readBlobFromPath("_merges", `${sha}.json`, { cwd }).catch(() => null);
72
+ if (text === null)
73
+ return null;
74
+ try {
75
+ const parsed = JSON.parse(text);
76
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
77
+ }
78
+ catch {
79
+ return null;
80
+ }
81
+ }
82
+ /** The pull request and work items a merge record names. */
83
+ function fromMergeRecord(merge) {
84
+ if (!merge)
85
+ return { pr: null, work: [] };
86
+ const source = merge.source;
87
+ const pr = source?.kind === "pull-request" && typeof source.pr === "number" ? source.pr : typeof merge.pr === "number" ? merge.pr : null;
88
+ const work = source?.kind === "work-item" && Array.isArray(source.records)
89
+ ? source.records.filter((r) => !!r && typeof r === "object" && r.kind === "work").map((r) => r.id)
90
+ : [];
91
+ return { pr, work };
92
+ }
93
+ /**
94
+ * Compose the chosen changes onto the base, on `chant/compose/<name>`.
95
+ * Throws {@link ComposeError} before any ref moves.
96
+ */
97
+ export async function composeRelease(req) {
98
+ const top = tryGit(req.cwd, ["rev-parse", "--show-toplevel"]);
99
+ if (!top)
100
+ throw new ComposeError("not-a-git-repository", "a compose picks commits, and this directory is not in a git repository");
101
+ if (!NAME.test(req.name)) {
102
+ throw new ComposeError("compose-name-invalid", `"${req.name}" can't name a compose branch: use letters, digits, dots, dashes and underscores, starting with a letter or digit`);
103
+ }
104
+ if (req.prs.length === 0 && req.works.length === 0) {
105
+ throw new ComposeError("compose-nothing-chosen", "a compose needs the changes it carries", "Name them: --pr <n> or --work <id>, each as often as needed.");
106
+ }
107
+ const { remote } = req.trunk;
108
+ const branch = composeBranchName(req.name);
109
+ const remoteRef = `refs/remotes/${remote}/${branch}`;
110
+ const localRef = `refs/heads/${branch}`;
111
+ // The branch as the remote has it, when the remote is reachable; a new branch is absent there.
112
+ if (tryGit(top, ["remote", "get-url", remote]) !== null)
113
+ tryGit(top, ["fetch", "--quiet", "--no-tags", remote, `+${localRef}:${remoteRef}`]);
114
+ const remoteTip = tryGit(top, ["rev-parse", "--verify", "--quiet", `${remoteRef}^{commit}`]);
115
+ const localTip = tryGit(top, ["rev-parse", "--verify", "--quiet", `${localRef}^{commit}`]);
116
+ if (remoteTip && localTip && !isAncestor(top, localTip, remoteTip) && !isAncestor(top, remoteTip, localTip)) {
117
+ throw new ComposeError("compose-branch-diverged", `${branch} here and on ${remote} have diverged, and a compose only appends`, `Keep the remote's: git branch -f ${branch} ${remote}/${branch}`);
118
+ }
119
+ const from = remoteTip && localTip ? (isAncestor(top, localTip, remoteTip) ? remoteTip : localTip) : (remoteTip ?? localTip);
120
+ const trunkRef = tryGit(top, ["rev-parse", "--verify", "--quiet", `refs/remotes/${remote}/${req.trunk.branch}^{commit}`]) ??
121
+ tryGit(top, ["rev-parse", "--verify", "--quiet", `refs/heads/${req.trunk.branch}^{commit}`]);
122
+ if (!trunkRef)
123
+ throw new ComposeError("compose-source-unknown", `this clone has neither ${remote}/${req.trunk.branch} nor ${req.trunk.branch}, so there is no trunk to pick from`);
124
+ // What the branch carries: back to trunk, past a commit a person made on it, such as a resolved conflict.
125
+ const existing = from ? compositionOnTrunk(top, from, trunkRef, branch) : null;
126
+ let base;
127
+ if (from) {
128
+ base = existing?.base ?? from;
129
+ if (req.base !== undefined) {
130
+ const asked = await resolveBase(top, req.cwd, req.base);
131
+ if (asked !== base) {
132
+ throw new ComposeError("compose-base-differs", `${branch} is composed on ${base.slice(0, 12)}, and --base names ${asked.slice(0, 12)}; a compose only appends to its branch`, `Drop --base to add to ${branch}, or compose under another name.`);
133
+ }
134
+ }
135
+ }
136
+ else {
137
+ if (req.base === undefined)
138
+ throw new ComposeError("compose-base-unknown", `${branch} does not exist yet, so the compose needs --base`, "Name the release or commit to compose on: --base <label|sha>");
139
+ base = await resolveBase(top, req.cwd, req.base);
140
+ }
141
+ // Trunk's first-parent commits after the base, oldest first.
142
+ const line = (tryGit(top, ["rev-list", "--first-parent", "--reverse", trunkRef, `^${base}`]) ?? "").split("\n").filter(Boolean);
143
+ const { commitDetails } = await import("../workspace/intent.js");
144
+ const { recordTrailers } = await import("../workspace/release-candidates.js");
145
+ const details = commitDetails(top, line);
146
+ const chosen = new Map();
147
+ const choose = (sha, by, pr, work) => {
148
+ const entry = chosen.get(sha) ?? { commit: sha, subject: details.get(sha)?.subject ?? "", pr, work, chosenBy: [] };
149
+ if (!entry.chosenBy.includes(by))
150
+ entry.chosenBy.push(by);
151
+ chosen.set(sha, entry);
152
+ };
153
+ const unmatched = new Set([...req.prs.map((n) => `--pr ${n}`), ...req.works.map((w) => `--work ${w}`)]);
154
+ for (const sha of line) {
155
+ const d = details.get(sha);
156
+ const merge = fromMergeRecord(await mergeRecordOf(req.cwd, sha));
157
+ const subjectPr = PR_IN_SUBJECT.exec(d?.subject ?? "");
158
+ const pr = merge.pr ?? (subjectPr ? Number(subjectPr[1]) : null);
159
+ const work = [...new Set([...recordTrailers(d?.trailers ?? {}).work, ...merge.work])];
160
+ for (const n of req.prs) {
161
+ if (pr === n) {
162
+ choose(sha, `--pr ${n}`, pr, work);
163
+ unmatched.delete(`--pr ${n}`);
164
+ }
165
+ }
166
+ for (const w of req.works) {
167
+ if (work.includes(w)) {
168
+ choose(sha, `--work ${w}`, pr, work);
169
+ unmatched.delete(`--work ${w}`);
170
+ }
171
+ }
172
+ }
173
+ if (unmatched.size > 0) {
174
+ throw new ComposeError("compose-source-unknown", `${[...unmatched].join(", ")} names no commit on ${remote}/${req.trunk.branch} after ${base.slice(0, 12)}`, "A pull request is found by its merge record or its squash subject (#n), and a work item by a Chant-Record: work:<id> trailer. Fetch trunk and chant/lifecycle if it merged elsewhere.");
175
+ }
176
+ // Trunk order, and what the branch already carries.
177
+ const carried = new Set(existing?.sources ?? []);
178
+ const ordered = line.filter((sha) => chosen.has(sha)).map((sha) => chosen.get(sha));
179
+ const already = ordered.filter((s) => carried.has(s.commit));
180
+ const picked = ordered.filter((s) => !carried.has(s.commit));
181
+ const tip = picked.length === 0 ? (from ?? base) : pickOnto(top, from ?? base, picked);
182
+ let written = false;
183
+ let pushed = false;
184
+ if (req.yes && picked.length > 0) {
185
+ git(top, ["update-ref", "-m", `chant release compose ${req.name}`, localRef, tip, localTip ?? ""]);
186
+ written = true;
187
+ }
188
+ if (req.yes && (req.push ?? true) && tryGit(top, ["remote", "get-url", remote]) !== null && tip !== remoteTip) {
189
+ try {
190
+ git(top, ["push", "--quiet", remote, `${tip}:${localRef}`]);
191
+ tryGit(top, ["update-ref", remoteRef, tip]);
192
+ pushed = true;
193
+ }
194
+ catch (err) {
195
+ const stderr = err.stderr?.toString().trim() ?? String(err);
196
+ throw new ComposeError("compose-push-refused", `${branch} was composed here at ${tip.slice(0, 12)} and ${remote} refused the push: ${stderr}`, `Push it by hand once the remote allows it: git push ${remote} ${branch}`);
197
+ }
198
+ }
199
+ return { name: req.name, branch, base, from, picked, already, tip, written, pushed };
200
+ }
201
+ /**
202
+ * Cherry-pick `sources` in order onto `start` in a temporary detached
203
+ * worktree, each with its trailer, and return the last commit. Throws
204
+ * `compose-conflict` naming the change and its files when one does not
205
+ * apply. The worktree is removed either way.
206
+ */
207
+ function pickOnto(top, start, sources) {
208
+ const realTop = realpathSync(top);
209
+ const dir = mkdtempSync(join(tmpdir(), "chant-compose-"));
210
+ git(realTop, ["worktree", "add", "--detach", "--quiet", dir, start]);
211
+ try {
212
+ for (const s of sources) {
213
+ const parents = (tryGit(dir, ["rev-list", "--parents", "-n", "1", s.commit]) ?? "").split(" ").length - 1;
214
+ const args = ["cherry-pick", "--allow-empty", "--keep-redundant-commits", ...(parents > 1 ? ["-m", "1"] : []), s.commit];
215
+ const run = spawnSync("git", args, { cwd: dir, encoding: "utf-8" });
216
+ if (run.status !== 0) {
217
+ const files = (tryGit(dir, ["diff", "--name-only", "--diff-filter=U"]) ?? "").split("\n").filter(Boolean);
218
+ tryGit(dir, ["cherry-pick", "--abort"]);
219
+ const what = [s.pr !== null ? `#${s.pr}` : null, ...s.work.map((w) => `work:${w}`)].filter(Boolean).join(", ");
220
+ throw new ComposeError("compose-conflict", `${s.commit.slice(0, 12)} (${s.subject}${what ? `; ${what}` : ""}) does not apply on the composed commits${files.length > 0 ? `: it conflicts in ${files.join(", ")}` : `: ${(run.stderr || run.stdout).trim()}`}. Nothing was written`, "Resolve it by hand in a pull request to the compose branch, or compose without that change.", { commit: s.commit, subject: s.subject, files });
221
+ }
222
+ git(dir, ["commit", "--quiet", "--amend", "--no-edit", "--allow-empty", "--no-verify", "--trailer", `${COMPOSED_FROM_TRAILER}: ${s.commit}`]);
223
+ }
224
+ return git(dir, ["rev-parse", "HEAD"]);
225
+ }
226
+ finally {
227
+ try {
228
+ git(realTop, ["worktree", "remove", "--force", dir]);
229
+ }
230
+ catch {
231
+ rmSync(dir, { recursive: true, force: true });
232
+ tryGit(realTop, ["worktree", "prune"]);
233
+ }
234
+ }
235
+ }
@@ -60,6 +60,14 @@ export interface CutRequest {
60
60
  * must be the principal the signers file lists the key for.
61
61
  */
62
62
  sign?: string | true;
63
+ /** The composition of a composed commit (#4168 4.3), recorded on the cut. */
64
+ composed?: {
65
+ branch: string;
66
+ base: string;
67
+ sources: string[];
68
+ };
69
+ /** The publish channel recorded on the cut (#4168 4.3), in place of `latest`. */
70
+ channel?: string;
63
71
  }
64
72
  export interface CutResult {
65
73
  release: Release;
@@ -1 +1 @@
1
- {"version":3,"file":"release-cut.d.ts","sourceRoot":"","sources":["../../src/lifecycle/release-cut.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"release-cut.d.ts","sourceRoot":"","sources":["../../src/lifecycle/release-cut.ts"],"names":[],"mappings":"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"}
@@ -366,6 +366,8 @@ export async function cutRelease(req) {
366
366
  runId: ci?.runId ?? `local-${Date.parse(timestamp)}`,
367
367
  runOrigin: ci?.runOrigin ?? { forge: "local" },
368
368
  signature,
369
+ ...(req.composed ? { composed: req.composed } : {}),
370
+ ...(req.channel ? { channel: req.channel } : {}),
369
371
  }, { cwd });
370
372
  return {
371
373
  release,
@@ -108,6 +108,10 @@ export interface PublishDeps {
108
108
  fetch?: PublishFetch;
109
109
  /** The npm executable. Default: `npm` on `PATH`. */
110
110
  npm?: string;
111
+ /** How a target waits between polls of a registry (#4244). Default: a timer. */
112
+ sleep?: (ms: number) => Promise<void>;
113
+ /** The clock a target's wait reads (#4244). Default: `Date.now`. */
114
+ now?: () => number;
111
115
  }
112
116
  /** The subset of the WHATWG `fetch` the targets use. */
113
117
  export type PublishFetch = (url: string, init: {
@@ -245,6 +249,8 @@ export interface PublishPlan {
245
249
  redactor: Redactor;
246
250
  /** Whether a target with no SBOM source is refused (`publish-sbom-missing`): the workspace opts into `supply-chain` (#4168). Otherwise it publishes without one. */
247
251
  requireSbom: boolean;
252
+ /** The channel a cut of the release names (#4168 4.3), the tag moved in place of `latest`, or null. */
253
+ channel: string | null;
248
254
  }
249
255
  /**
250
256
  * Resolve `ref` (a label or a digest) in the member at `cwd` and decide
@@ -1 +1 @@
1
- {"version":3,"file":"release-publish.d.ts","sourceRoot":"","sources":["../../src/lifecycle/release-publish.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"release-publish.d.ts","sourceRoot":"","sources":["../../src/lifecycle/release-publish.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAkB,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtE,0FAA0F;AAC1F,MAAM,WAAW,eAAe;IAC9B,6EAA6E;IAC7E,IAAI,EAAE,OAAO,CAAC;IACd,sDAAsD;IACtD,EAAE,EAAE,QAAQ,GAAG,QAAQ,GAAG,IAAI,CAAC;IAC/B,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,eAAe,CAYtF;AAED,mEAAmE;AACnE,MAAM,WAAW,WAAW;IAC1B,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,qFAAqF;IACrF,WAAW,EAAE,MAAM,CAAC;IACpB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kHAAkH;IAClH,UAAU,CAAC,EAAE,MAAM,GAAG,YAAY,CAAC;IACnC,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,6GAA6G;AAC7G,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,+FAA+F;IAC/F,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,iCAAiC;AACjC,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,sCAAsC;IACtC,KAAK,EAAE,WAAW,EAAE,CAAC;CACtB;AAED,iEAAiE;AACjE,MAAM,WAAW,WAAW;IAC1B,kFAAkF;IAClF,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,wDAAwD;AACxD,MAAM,MAAM,YAAY,GAAG,CACzB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,UAAU,GAAG,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAAE,KAClH,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAAC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAA;CAAE,CAAC,CAAC;AAEtH,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,kIAAkI;IAClI,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,eAAe,CAAC;IAC5B,oGAAoG;IACpG,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IACxB,6EAA6E;IAC7E,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,6FAA6F;IAC7F,QAAQ,EAAE,QAAQ,CAAC;IACnB,wDAAwD;IACxD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wEAAwE;AACxE,qBAAa,kBAAmB,SAAQ,KAAK;IAEzC,QAAQ,CAAC,IAAI,EAAE,MAAM;IAErB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM;IAHvB,YACW,IAAI,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACN,GAAG,CAAC,EAAE,MAAM,YAAA,EAItB;CACF;AAED,4HAA4H;AAC5H,eAAO,MAAM,aAAa,SAAS,CAAC;AAEpC;;;;;;;;GAQG;AACH,MAAM,WAAW,aAAa;IAC5B,gCAAgC;IAChC,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,OAAO,CAAC;IAC9B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,kGAAkG;IAClG,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;;OAMG;IACH,IAAI,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAClD;;;;;;;OAOG;IACH,KAAK,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAClD;;;;;;OAMG;IACH,MAAM,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;CAC7E;AAED,iGAAiG;AACjG,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAKzG;AAED,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC7B,IAAI,EACA,mBAAmB,GACnB,iBAAiB,GACjB,kBAAkB,GAClB,8BAA8B,GAC9B,4BAA4B,GAC5B,wBAAwB,GACxB,uBAAuB,GACvB,wBAAwB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,8GAA8G;AAC9G,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,6EAA6E;IAC7E,SAAS,EAAE;QAAE,MAAM,EAAE,UAAU,GAAG,UAAU,GAAG,YAAY,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACxH,UAAU,EAAE,eAAe,CAAC;IAC5B,gIAAgI;IAChI,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,mHAAmH;IACnH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,mGAAmG;IACnG,GAAG,EAAE,UAAU,GAAG,IAAI,CAAC;IACvB,iEAAiE;IACjE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,8DAA8D;IAC9D,QAAQ,EAAE,QAAQ,CAAC;IACnB,oKAAoK;IACpK,WAAW,EAAE,OAAO,CAAC;IACrB,uGAAuG;IACvG,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAAC,GAAG,EAAE;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,GAAG,OAAO,CAAC,WAAW,GAAG;IAAE,OAAO,EAAE,cAAc,CAAA;CAAE,CAAC,CAwGrD;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAmBvG;AAUD,6DAA6D;AAC7D,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,GAAG,cAAc,CAcjK;AAED,mCAAmC;AACnC,MAAM,WAAW,UAAU;IACzB,oDAAoD;IACpD,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,+FAA+F;IAC/F,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,CAAA;KAAE,CAAC,CAAC;IAChE,2GAA2G;IAC3G,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,0GAA0G;AAC1G,qBAAa,eAAgB,SAAQ,kBAAkB;IAKnD,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE;IAN7B,YACE,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GAAG,SAAS,EACd,IAAI,EAAE,OAAO,GAAG,QAAQ,EACxB,MAAM,EAAE,MAAM,EAAE,EAChB,QAAQ,EAAE,MAAM,EAAE,EAI5B;CACF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAClC,GAAG,EAAE,cAAc,CAAC;IACpB,sCAAsC;IACtC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB,GAAG,OAAO,CAAC,UAAU,CAAC,CAiFtB"}
@@ -189,7 +189,8 @@ export async function preparePublish(req) {
189
189
  const member = ledger.members.length > 0 ? ledger.members.join("/") : null;
190
190
  const releaseTag = label !== null ? releaseTagName(member, label) : null;
191
191
  const redactor = createRedactor(env, targets.flatMap((t) => t.credentialEnv));
192
- return { release, label, signature, provenance, warning, signatureWarning, cut, releaseTag, targets, redactor, requireSbom: groups.has("supply-chain") };
192
+ const channel = [...cuts].reverse().find((c) => c.channel)?.channel ?? null;
193
+ return { release, label, signature, provenance, warning, signatureWarning, cut, releaseTag, targets, redactor, requireSbom: groups.has("supply-chain"), channel };
193
194
  }
194
195
  /**
195
196
  * A publish with a target reads files from the checkout it runs in: package