@williamthorsen/release-kit 10.5.0 โ†’ 10.7.0

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 (44) hide show
  1. package/.meta/changelog.json +1570 -0
  2. package/.readyup/kits/default.js +127 -4
  3. package/.readyup/kits/npm-auto-publish.js +87 -23
  4. package/.readyup/manifest.json +14 -9
  5. package/CHANGELOG.md +83 -0
  6. package/README.md +68 -963
  7. package/dist/esm/bin/release-kit.js +4 -3
  8. package/dist/esm/buildChangelogEntries.js +5 -0
  9. package/dist/esm/buildDependencyGraph.d.ts +6 -5
  10. package/dist/esm/buildDependencyGraph.js +5 -1
  11. package/dist/esm/changelogJsonUtils.d.ts +5 -7
  12. package/dist/esm/changelogJsonUtils.js +0 -13
  13. package/dist/esm/changelogOverrides.js +8 -0
  14. package/dist/esm/extractMigration.d.ts +14 -0
  15. package/dist/esm/extractMigration.js +18 -0
  16. package/dist/esm/init/scaffold.js +14 -6
  17. package/dist/esm/packsPath.d.ts +15 -0
  18. package/dist/esm/packsPath.js +47 -0
  19. package/dist/esm/planVersionBump.d.ts +2 -1
  20. package/dist/esm/planVersionBump.js +4 -0
  21. package/dist/esm/propagateBumps.d.ts +1 -3
  22. package/dist/esm/propagateBumps.js +2 -2
  23. package/dist/esm/releasePrepare.js +0 -16
  24. package/dist/esm/releasePrepareMono.js +3 -24
  25. package/dist/esm/reportPrepare.js +4 -2
  26. package/dist/esm/runGitCliff.d.ts +16 -23
  27. package/dist/esm/runGitCliff.js +4 -10
  28. package/dist/esm/sync-labels/resolveLabels.d.ts +5 -3
  29. package/dist/esm/sync-labels/resolveLabels.js +21 -6
  30. package/dist/esm/types.d.ts +13 -2
  31. package/dist/esm/validateConfig.js +1 -1
  32. package/docs/api.md +73 -0
  33. package/docs/changelogs.md +70 -0
  34. package/docs/configuration.md +105 -0
  35. package/docs/editorial-overrides.md +144 -0
  36. package/docs/labels.md +83 -0
  37. package/docs/project-releases.md +74 -0
  38. package/docs/publishing.md +30 -0
  39. package/docs/readiness-checks.md +18 -0
  40. package/docs/releasing.md +108 -0
  41. package/docs/work-types.md +121 -0
  42. package/package.json +16 -12
  43. package/dist/esm/readCurrentVersion.d.ts +0 -2
  44. package/dist/esm/readCurrentVersion.js +0 -18
@@ -1,6 +1,6 @@
1
1
  /** @noformat -- @generated. Do not edit. Compiled by rdy. */
2
2
  /* eslint-disable */
3
- export const __readyupVersion = "0.35.0";
3
+ export const __readyupVersion = "0.36.0";
4
4
 
5
5
 
6
6
  // .readyup/kits/default.ts
@@ -50,9 +50,55 @@ function detectRepoType() {
50
50
  return "single-package";
51
51
  }
52
52
 
53
+ // src/packsPath.ts
54
+ function packsPath(filesField, path) {
55
+ if (!isStringArray(filesField)) return true;
56
+ const prefixes = listAncestorPrefixes(path);
57
+ return filesField.some((entry) => {
58
+ const pattern = compileEntry(entry);
59
+ return pattern !== void 0 && prefixes.some((prefix) => pattern.test(prefix));
60
+ });
61
+ }
62
+ var GLOB_TOKEN_PATTERN = /\*\*\/|\*\*|\*|\?|[^*?]+/g;
63
+ function compileEntry(entry) {
64
+ if (entry.startsWith("!")) return void 0;
65
+ const normalized = entry.replace(/^\.?\//, "").replace(/\/+$/, "");
66
+ if (normalized === "") return void 0;
67
+ return new RegExp(`^${translateGlob(normalized)}$`);
68
+ }
69
+ function isStringArray(value) {
70
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string");
71
+ }
72
+ function listAncestorPrefixes(path) {
73
+ const segments = path.split("/");
74
+ return segments.map((_segment, index) => segments.slice(0, index + 1).join("/"));
75
+ }
76
+ function translateGlob(pattern) {
77
+ let source = "";
78
+ for (const [token] of pattern.matchAll(GLOB_TOKEN_PATTERN)) {
79
+ switch (token) {
80
+ case "**/":
81
+ source += String.raw`(?:[^/]*\/)*`;
82
+ break;
83
+ case "**":
84
+ source += ".*";
85
+ break;
86
+ case "*":
87
+ source += "[^/]*";
88
+ break;
89
+ case "?":
90
+ source += "[^/]";
91
+ break;
92
+ default:
93
+ source += RegExp.escape(token);
94
+ }
95
+ }
96
+ return source;
97
+ }
98
+
53
99
  // .readyup/kits/default.ts
54
100
  function getMinVersion() {
55
- const picked = { "version": "10.5.0" };
101
+ const picked = { "version": "10.7.0" };
56
102
  if (typeof picked["version"] !== "string") {
57
103
  throw new TypeError("release-kit/package.json: 'version' must be a string");
58
104
  }
@@ -61,6 +107,7 @@ function getMinVersion() {
61
107
  function hasPublishablePackages() {
62
108
  return discoverWorkspaces({ filter: (w) => w.isPackage }).length > 0;
63
109
  }
110
+ var DEFAULT_CHANGELOG_JSON_PATH = ".meta/changelog.json";
64
111
  var CONFIG_EXPORT_PATTERNS = [
65
112
  /export\s+default\b/,
66
113
  /export\s+(?:const|let|var)\s+config\b/,
@@ -74,6 +121,8 @@ var RELEASE_WORKFLOW_HASH_MONOREPO = "0a9724b7b3c5e24087fd3a8f36fed8e990d699267f
74
121
  var RELEASE_WORKFLOW_HASH_SINGLE = "a3d19bbc1ba8bb30622e53c590137b97e3179e80988c0967737b021cdaeab73f";
75
122
  var PUBLISH_WORKFLOW_HASH_MONOREPO = "0afa9ffe914f3dc8f043e68252ebc604c8cc1a953422fcea37a909a4def370ee";
76
123
  var PUBLISH_WORKFLOW_HASH_SINGLE = "6f31183e0a1e66be791a19266c3b028dadbd9fe010f7fc4452f3f8970c937b43";
124
+ var CREATE_GITHUB_RELEASE_WORKFLOW_HASH_MONOREPO = "c455d88c93d855737c96079945ff729a9d094f846519c24afbefe83a425c1d7f";
125
+ var CREATE_GITHUB_RELEASE_WORKFLOW_HASH_SINGLE = "f595831ff28f8b3a01d97e6cb0cfe100262f7a8821091c6c458b0c0224cebba8";
77
126
  var default_default = defineRdyKit({
78
127
  checklists: [
79
128
  {
@@ -148,6 +197,16 @@ var default_default = defineRdyKit({
148
197
  }
149
198
  ]
150
199
  },
200
+ {
201
+ name: "create-github-release.yaml matches template",
202
+ severity: "warn",
203
+ skip: () => !fileExists(".github/workflows/create-github-release.yaml") ? "no create-github-release workflow (GitHub Releases not adopted)" : false,
204
+ check: () => {
205
+ const hash = detectRepoType() === "monorepo" ? CREATE_GITHUB_RELEASE_WORKFLOW_HASH_MONOREPO : CREATE_GITHUB_RELEASE_WORKFLOW_HASH_SINGLE;
206
+ return fileMatchesHash(".github/workflows/create-github-release.yaml", hash);
207
+ },
208
+ fix: "Run `release-kit init --force` to regenerate create-github-release.yaml from the current template"
209
+ },
151
210
  {
152
211
  name: ".config/release-kit.config.ts exports a config",
153
212
  severity: "error",
@@ -204,12 +263,38 @@ var default_default = defineRdyKit({
204
263
  }
205
264
  ]
206
265
  },
266
+ // Deliberately outside the config gate above: that check skips where the config file is absent, and a repo
267
+ // with no config file still defaults `changelogJson.enabled` to true and still publishes tarballs.
268
+ {
269
+ name: "published packages ship CHANGELOG.md",
270
+ severity: "warn",
271
+ skip: () => !hasPublishablePackages() ? "no publishable packages" : false,
272
+ check: () => packagesShipChangelog(),
273
+ fix: 'Add "CHANGELOG.md" to the files field of each affected package.json'
274
+ },
275
+ {
276
+ name: "changelog.json generation is enabled",
277
+ severity: "recommend",
278
+ skip: () => !hasPublishablePackages() ? "no publishable packages" : false,
279
+ check: () => changelogJsonIsEnabled(),
280
+ fix: "Remove changelogJson.enabled: false from .config/release-kit.config.ts so release-kit writes the machine-readable changelog that upgrade tooling reads before CHANGELOG.md",
281
+ checks: [
282
+ {
283
+ name: "published packages ship the changelog JSON",
284
+ severity: "warn",
285
+ check: () => packagesShipChangelogJson(),
286
+ get fix() {
287
+ return `Add "${resolveChangelogJsonOutputPath()}" to the files field of each affected package.json`;
288
+ }
289
+ }
290
+ ]
291
+ },
207
292
  {
208
293
  name: "config does not use removed releaseNotes.shouldCreateGithubRelease",
209
294
  severity: "error",
210
295
  quiet: true,
211
296
  check: () => fileDoesNotContain(".config/release-kit.config.ts", /shouldCreateGithubRelease/),
212
- fix: "Remove 'shouldCreateGithubRelease' from .config/release-kit.config.ts. Adoption of GitHub Releases is now signaled by installing the create-github-release workflow (see release-kit README for setup)."
297
+ fix: "Remove 'shouldCreateGithubRelease' from .config/release-kit.config.ts. Adoption of GitHub Releases is now signaled by installing the create-github-release workflow, which `release-kit init` scaffolds."
213
298
  },
214
299
  {
215
300
  name: "git-cliff not in devDependencies",
@@ -264,6 +349,11 @@ var default_default = defineRdyKit({
264
349
  }
265
350
  ]
266
351
  });
352
+ function changelogJsonIsEnabled() {
353
+ const content = readFile(".config/release-kit.config.ts");
354
+ if (content === void 0) return true;
355
+ return !/changelogJson\s*:\s*\{[^}]*enabled\s*:\s*false/.test(content);
356
+ }
267
357
  function configFileExportsConfig() {
268
358
  const content = readFile(".config/release-kit.config.ts");
269
359
  if (content === void 0) return false;
@@ -276,6 +366,12 @@ function labelsHaveCurrentPresetHash(presetName, expectedHash) {
276
366
  const match = pattern.exec(content);
277
367
  return match !== null && match[1] === expectedHash;
278
368
  }
369
+ function packagesShipChangelog() {
370
+ return reportWorkspacesOmitting("CHANGELOG.md");
371
+ }
372
+ function packagesShipChangelogJson() {
373
+ return reportWorkspacesOmitting(resolveChangelogJsonOutputPath());
374
+ }
279
375
  function readmeHasReleaseNotesMarkers(content) {
280
376
  return content.includes("<!-- section:release-notes -->") && content.includes("<!-- /section:release-notes -->");
281
377
  }
@@ -308,16 +404,43 @@ function releaseNotesInjectsIntoReadme() {
308
404
  if (content === void 0) return false;
309
405
  return /shouldInjectIntoReadme\s*:\s*true/.test(content);
310
406
  }
407
+ function reportWorkspacesOmitting(path) {
408
+ const failing = [];
409
+ const packageWorkspaces = discoverWorkspaces({ filter: (w) => w.isPackage });
410
+ for (const { dir, packageJson } of packageWorkspaces) {
411
+ if (!packsPath(packageJson["files"], path)) {
412
+ failing.push(dir === "." ? "package.json" : `${dir}/package.json`);
413
+ }
414
+ }
415
+ if (failing.length === 0) return true;
416
+ return {
417
+ ok: false,
418
+ detail: `files field omits ${path}: ${failing.join(", ")}`
419
+ };
420
+ }
421
+ function resolveChangelogJsonOutputPath() {
422
+ const content = readFile(".config/release-kit.config.ts");
423
+ if (content === void 0) return DEFAULT_CHANGELOG_JSON_PATH;
424
+ const match = /changelogJson\s*:\s*\{[^}]*outputPath\s*:\s*['"]([^'"]+)['"]/.exec(content);
425
+ return match?.[1] ?? DEFAULT_CHANGELOG_JSON_PATH;
426
+ }
311
427
  export {
312
428
  CLIFF_TEMPLATE_HASH,
313
429
  COMMON_PRESET_HASH,
430
+ CREATE_GITHUB_RELEASE_WORKFLOW_HASH_MONOREPO,
431
+ CREATE_GITHUB_RELEASE_WORKFLOW_HASH_SINGLE,
432
+ DEFAULT_CHANGELOG_JSON_PATH,
314
433
  PUBLISH_WORKFLOW_HASH_MONOREPO,
315
434
  PUBLISH_WORKFLOW_HASH_SINGLE,
316
435
  RELEASE_WORKFLOW_HASH_MONOREPO,
317
436
  RELEASE_WORKFLOW_HASH_SINGLE,
318
437
  SYNC_LABELS_WORKFLOW_HASH,
438
+ changelogJsonIsEnabled,
319
439
  configFileExportsConfig,
320
440
  default_default as default,
441
+ packagesShipChangelog,
442
+ packagesShipChangelogJson,
321
443
  readmeHasReleaseNotesMarkers,
322
- readmesHaveReleaseNotesMarkers
444
+ readmesHaveReleaseNotesMarkers,
445
+ resolveChangelogJsonOutputPath
323
446
  };
@@ -1,6 +1,6 @@
1
1
  /** @noformat -- @generated. Do not edit. Compiled by rdy. */
2
2
  /* eslint-disable */
3
- export const __readyupVersion = "0.35.0";
3
+ export const __readyupVersion = "0.36.0";
4
4
 
5
5
 
6
6
  // .readyup/kits/npm-auto-publish.ts
@@ -18,6 +18,7 @@ import {
18
18
  readJsonFile
19
19
  } from "readyup/check-utils";
20
20
  var AUTH_ERROR_CODES = /* @__PURE__ */ new Set(["E401", "ENEEDAUTH"]);
21
+ var OTP_ERROR_CODE = "EOTP";
21
22
  var PUBLISH_WORKFLOW_FILE = "publish.yaml";
22
23
  var UNREACHABLE_ERROR_CODES = /* @__PURE__ */ new Set([
23
24
  "EAI_AGAIN",
@@ -77,24 +78,19 @@ var packagesChecklist = defineRdyChecklist({
77
78
  fix: "Ensure pnpm-workspace.yaml lists package globs, or that a root package.json exists"
78
79
  }
79
80
  ],
80
- checks: [
81
- {
82
- name: "npm session is usable",
83
- skip: () => skipIfNothingPublishable(),
84
- check: () => {
85
- const auth = getCachedNpmAuthStatus();
86
- return auth.status === "authenticated" ? { ok: true } : { ok: false, detail: auth.detail };
87
- },
88
- // readyup reads `fix` before it consults `skip`, and again when it validates the kit, so a getter here would
89
- // reach the registry on every run regardless of the skip. Per-outcome wording goes in the check's detail.
90
- fix: 'Restore a usable npm session: log in with "npm login", or restore access to the registry, which the trusted-publisher check queries directly',
91
- get checks() {
92
- return discoverWorkspaces({ filter: belongsInPackagesChecklist }).map(
93
- (workspace) => buildWorkspaceCheck(workspace)
94
- );
95
- }
81
+ // The gate stands beside the workspace rows rather than above them, so a session that cannot answer trust queries
82
+ // suppresses the trusted-publisher rows alone and leaves the package.json checks reporting. The rows no longer
83
+ // hang beneath the gate's skip, so a repo that publishes nothing has to be held to its one line here.
84
+ get checks() {
85
+ const sessionCheck = buildSessionCheck();
86
+ if (skipIfNothingPublishable() !== false) {
87
+ return [sessionCheck];
96
88
  }
97
- ]
89
+ return [
90
+ sessionCheck,
91
+ ...discoverWorkspaces({ filter: belongsInPackagesChecklist }).map((workspace) => buildWorkspaceCheck(workspace))
92
+ ];
93
+ }
98
94
  });
99
95
  var npm_auto_publish_default = defineRdyKit({
100
96
  fixLocation: "inline",
@@ -103,6 +99,19 @@ var npm_auto_publish_default = defineRdyKit({
103
99
  function belongsInPackagesChecklist(workspace) {
104
100
  return !workspace.isRoot || workspace.isPackage;
105
101
  }
102
+ function buildSessionCheck() {
103
+ return {
104
+ name: "npm session can answer trust queries",
105
+ skip: () => skipIfNothingPublishable(),
106
+ check: () => {
107
+ const capability = getCachedTrustCapability();
108
+ return capability.ok ? { ok: true } : { ok: false, detail: capability.detail };
109
+ },
110
+ // A plain string rather than a getter, because readyup takes outcome-specific wording in `detail`, which the
111
+ // check above already carries.
112
+ fix: 'Restore a usable npm session: log in with "npm login", supplying the one-time password when prompted, or restore access to the registry, which the trusted-publisher check queries directly'
113
+ };
114
+ }
106
115
  function buildWorkspaceCheck(workspace) {
107
116
  const displayName = workspace.name ?? "(unnamed)";
108
117
  const pkgJsonPath = path.join(workspace.dir, "package.json");
@@ -126,11 +135,22 @@ function buildWorkspaceCheck(workspace) {
126
135
  children.push(
127
136
  {
128
137
  name: "published to npm",
138
+ // `npm view` reads the registry without a session, so a missing login or a missing one-time password leaves
139
+ // this answerable. An unreachable registry does not: the lookup fails for every package, and reporting that
140
+ // as unpublished would advise publishing a package that is already there.
141
+ skip: () => {
142
+ const auth = getCachedNpmAuthStatus();
143
+ return auth.status === "unreachable" ? auth.detail : false;
144
+ },
129
145
  check: () => isPublishedToNpm(displayName),
130
146
  fix: `Run "npm publish --access public" from ${workspace.dir} to bootstrap the package on npm`,
131
147
  checks: [
132
148
  {
133
149
  name: "trusted publisher configured",
150
+ skip: () => {
151
+ const capability = getCachedTrustCapability();
152
+ return capability.ok ? false : capability.detail;
153
+ },
134
154
  check: () => checkTrustedPublisher(displayName),
135
155
  get fix() {
136
156
  return `Run: npm trust github ${displayName} --repo ${getCachedOwnerRepo()} --file ${PUBLISH_WORKFLOW_FILE}`;
@@ -180,11 +200,7 @@ function checkProvenanceMatchesVisibility() {
180
200
  return { ok: true };
181
201
  }
182
202
  function checkTrustedPublisher(packageName) {
183
- const result = classifyTrustQuery(
184
- runNpmJson(`npm trust list ${packageName} --json`),
185
- getCachedOwnerRepo(),
186
- PUBLISH_WORKFLOW_FILE
187
- );
203
+ const result = getTrustQueryResult(packageName);
188
204
  switch (result.status) {
189
205
  case "configured":
190
206
  return { ok: true };
@@ -210,6 +226,12 @@ function classifyNpmAuth(result) {
210
226
  }
211
227
  return { status: "unreachable", detail: `The npm registry query failed (${error.code}): ${error.summary}` };
212
228
  }
229
+ function classifyTrustCapability(auth, probe) {
230
+ if (auth.status !== "authenticated") {
231
+ return { ok: false, detail: auth.detail };
232
+ }
233
+ return probe?.status === "unanswerable" ? { ok: false, detail: probe.detail } : { ok: true };
234
+ }
213
235
  function classifyTrustQuery(result, expectedRepo, expectedFile) {
214
236
  if (!result.exitOk) {
215
237
  const error = readNpmError(result.stdout);
@@ -219,6 +241,15 @@ function classifyTrustQuery(result, expectedRepo, expectedFile) {
219
241
  if (error.code === "E404") {
220
242
  return { status: "not-configured" };
221
243
  }
244
+ if (AUTH_ERROR_CODES.has(error.code) || error.code === OTP_ERROR_CODE) {
245
+ return {
246
+ status: "unanswerable",
247
+ detail: `The npm session cannot answer trust queries (${error.code}): ${error.summary}`
248
+ };
249
+ }
250
+ if (UNREACHABLE_ERROR_CODES.has(error.code)) {
251
+ return { status: "unanswerable", detail: `Cannot reach the npm registry (${error.code})` };
252
+ }
222
253
  return { status: "error", detail: `The npm trust query failed (${error.code}): ${error.summary}` };
223
254
  }
224
255
  const relationships = readTrustRelationships(result.stdout);
@@ -252,6 +283,10 @@ var getCachedOwnerRepo = /* @__PURE__ */ (() => {
252
283
  let cached;
253
284
  return () => cached ??= getOwnerRepo();
254
285
  })();
286
+ var getCachedTrustCapability = /* @__PURE__ */ (() => {
287
+ let cached;
288
+ return () => cached ??= resolveTrustCapability();
289
+ })();
255
290
  function getOwnerRepo() {
256
291
  const url = execSync("git remote get-url origin", {
257
292
  encoding: "utf8"
@@ -266,6 +301,20 @@ function getOwnerRepo() {
266
301
  }
267
302
  throw new Error(`Cannot parse GitHub owner/repo from remote URL: ${url}`);
268
303
  }
304
+ var trustQueryResults = /* @__PURE__ */ new Map();
305
+ function getTrustQueryResult(packageName) {
306
+ const cached = trustQueryResults.get(packageName);
307
+ if (cached !== void 0) {
308
+ return cached;
309
+ }
310
+ const result = classifyTrustQuery(
311
+ runNpmJson(`npm trust list ${packageName} --json`),
312
+ getCachedOwnerRepo(),
313
+ PUBLISH_WORKFLOW_FILE
314
+ );
315
+ trustQueryResults.set(packageName, result);
316
+ return result;
317
+ }
269
318
  function hasTokenReferences() {
270
319
  const workflowDir = path.resolve(process.cwd(), ".github/workflows");
271
320
  if (!existsSync(workflowDir)) {
@@ -301,6 +350,10 @@ function isRepoPrivate() {
301
350
  function parseProvenanceSetting(workflowContent) {
302
351
  return /^[^#]*provenance:\s*['"]?true['"]?/im.test(workflowContent);
303
352
  }
353
+ function probeTrustQuery() {
354
+ const probeName = selectProbeName();
355
+ return probeName === void 0 ? void 0 : getTrustQueryResult(probeName);
356
+ }
304
357
  function readNpmError(stdout) {
305
358
  let parsed;
306
359
  try {
@@ -329,6 +382,10 @@ function readTrustRelationships(stdout) {
329
382
  }
330
383
  return "type" in parsed ? [parsed] : [];
331
384
  }
385
+ function resolveTrustCapability() {
386
+ const auth = getCachedNpmAuthStatus();
387
+ return classifyTrustCapability(auth, auth.status === "authenticated" ? probeTrustQuery() : void 0);
388
+ }
332
389
  function runNpmJson(command) {
333
390
  try {
334
391
  return { exitOk: true, stdout: execSync(command, { encoding: "utf8", stdio: "pipe" }) };
@@ -337,6 +394,11 @@ function runNpmJson(command) {
337
394
  return { exitOk: false, stdout };
338
395
  }
339
396
  }
397
+ function selectProbeName() {
398
+ return discoverWorkspaces({ filter: (workspace) => workspace.isPackage }).find(
399
+ (workspace) => workspace.name !== void 0
400
+ )?.name;
401
+ }
340
402
  function skipIfNothingPublishable() {
341
403
  const publishable = discoverWorkspaces({ filter: (workspace) => workspace.isPackage });
342
404
  return publishable.length > 0 ? false : "no publishable packages";
@@ -347,9 +409,11 @@ function skipIfNotPublishable(workspace) {
347
409
  export {
348
410
  buildWorkspaceCheck,
349
411
  classifyNpmAuth,
412
+ classifyTrustCapability,
350
413
  classifyTrustQuery,
351
414
  npm_auto_publish_default as default,
352
415
  packagesChecklist,
416
+ selectProbeName,
353
417
  skipIfNotPublishable,
354
418
  skipIfNothingPublishable
355
419
  };
@@ -8,12 +8,12 @@
8
8
  "esbuildVersion": "0.28.2",
9
9
  "inputs": [
10
10
  {
11
- "hash": "c948b179",
11
+ "hash": "55ff5731",
12
12
  "kind": "module",
13
13
  "path": "kits/default.ts"
14
14
  },
15
15
  {
16
- "hash": "221d9444",
16
+ "hash": "a373c49d",
17
17
  "kind": "inline",
18
18
  "path": "../package.json",
19
19
  "paths": [
@@ -30,6 +30,11 @@
30
30
  "kind": "module",
31
31
  "path": "../src/init/parseJsonRecord.ts"
32
32
  },
33
+ {
34
+ "hash": "b798d024",
35
+ "kind": "module",
36
+ "path": "../src/packsPath.ts"
37
+ },
33
38
  {
34
39
  "hash": "646fe51b",
35
40
  "kind": "module",
@@ -38,10 +43,10 @@
38
43
  ],
39
44
  "name": "default",
40
45
  "path": "kits/default.js",
41
- "readyupVersion": "0.35.0",
46
+ "readyupVersion": "0.36.0",
42
47
  "source": "kits/default.ts",
43
- "sourceHash": "c948b179",
44
- "targetHash": "08e4eb5a"
48
+ "sourceHash": "55ff5731",
49
+ "targetHash": "68976fc8"
45
50
  },
46
51
  {
47
52
  "checklists": [
@@ -51,17 +56,17 @@
51
56
  "esbuildVersion": "0.28.2",
52
57
  "inputs": [
53
58
  {
54
- "hash": "15641d4a",
59
+ "hash": "2f1fb68c",
55
60
  "kind": "module",
56
61
  "path": "kits/npm-auto-publish.ts"
57
62
  }
58
63
  ],
59
64
  "name": "npm-auto-publish",
60
65
  "path": "kits/npm-auto-publish.js",
61
- "readyupVersion": "0.35.0",
66
+ "readyupVersion": "0.36.0",
62
67
  "source": "kits/npm-auto-publish.ts",
63
- "sourceHash": "15641d4a",
64
- "targetHash": "721e337b"
68
+ "sourceHash": "2f1fb68c",
69
+ "targetHash": "cbabceb3"
65
70
  }
66
71
  ]
67
72
  }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,89 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 10.7.0 โ€” 2026-09-15
6
+
7
+ ### ๐ŸŽ‰ Features
8
+
9
+ - Fix scaffold error handling and cover every scaffolded workflow (#806)
10
+
11
+ - Adds a `create-github-release.yaml matches template` check to release-kit's ReadyUp kit, which warns when `.github/workflows/create-github-release.yaml` differs from the template for the detected repo type and skips in a repo that has not installed that workflow.
12
+ - Stops `v11y init --force` from replacing an existing `.config/v11y-check.config.json` with the defaults, which discarded the repo's thresholds and the allowlist maintained by `v11y sync`.
13
+
14
+ Migration: To reset `.config/v11y-check.config.json` to its defaults, delete the file and run `v11y init`, because `v11y init --force` now overwrites only `.github/workflows/audit.yaml`.
15
+
16
+ ### ๐Ÿ› Bug fixes
17
+
18
+ - Gate the trusted-publisher checks on trust-query capability (#786)
19
+
20
+ - Fixes the issue that the `npm-auto-publish` kit advised `npm trust github โ€ฆ` for every package when the npm session lacked the two-factor authentication that trust queries need.
21
+
22
+ - Treat label names that differ only in case as one label (#808)
23
+
24
+ - Fixes the issue that `sync-labels generate` wrote a preset's `bug` and a local `Bug` to `.github/labels.yaml` as two labels, which made the first sync fail to create the second and every later sync rename the existing label back and forth.
25
+ - Lets a `labels` entry change a preset label's casing: `Bug` replaces a preset's `bug` and appears in the output as `Bug`, and `Bug: null` removes it.
26
+ - Makes `labels` keys that differ only in case a config error that names each group, such as `'bug' and 'Bug'`, since folding them would discard all but one without any sign in the output.
27
+
28
+ Migration: Keep one of any keys in the `labels` record that differ only in case, and delete the others.
29
+
30
+ ### โ™ป๏ธ Refactoring
31
+
32
+ - Remove the redundant, soft-failing version read from release prepare (#811)
33
+
34
+ - Deletes `readCurrentVersion` from `release-kit`, moving into `planVersionSet` the check that a `--set-version` target exceeds the current version and recording each workspace's version in the `DependencyGraph` passed to `propagateBumps`.
35
+ - Stops prepare from printing a warning before it fails on an unreadable `package.json`, and replaces `failed to read current version` for a missing `version` under `--set-version` with an error from `planVersionSet` that reports the missing `version` field.
36
+
37
+ ### โš™๏ธ Tooling
38
+
39
+ - Upgrade eslint-config-typescript to v17 and adopt its ignore lists (#797)
40
+
41
+ - Declares `vitest` as `catalog:` in every workspace that imports it, with the pnpm catalog pinning 4.1.11, because v17 no longer exempts `vitest` from `n/no-extraneous-import`.
42
+ - Builds the global ignores in `eslint.config.ts` from the published `commonIgnores` and `toolIgnores`, which also exclude `pnpm-lock.yaml` and each `.readyup/manifest.json`, so the `eslint --fix` in `nmr lint` can no longer rewrite a kit manifest and make the next build's `rdy verify` fail.
43
+
44
+ ### ๐Ÿ“š Documentation
45
+
46
+ - Trim the release-kit README and move reference detail into shipped docs (#802)
47
+
48
+ - Adds `docs` to the published `files` of `@williamthorsen/release-kit` and a `!docs/*.v*.md` exclusion to both it and `@williamthorsen/nmr`, because `pnpm pack` would otherwise include the release-notes previews that a local checkout holds.
49
+ - Adds `--version` to the options that `release-kit --help` lists, and points the hints for the removed `releaseNotes.shouldCreateGithubRelease` field at `release-kit init` instead of the README.
50
+
51
+ ## 10.6.0 โ€” 2026-09-08
52
+
53
+ ### ๐ŸŽ‰ Features
54
+
55
+ - Report a package whose tarball would omit its changelog (#768)
56
+
57
+ Adds ReadyUp checks to verify that every published package bundles its changelog files: the human-readable `CHANGELOG.md` and the machine-readable `changelog.json`.
58
+
59
+ - Add a migration field to changelog.json items (#770)
60
+
61
+ Adds an optional `migration` field to entries in the `.meta/changelog.json` that `release-kit` generates. If a commit body contains a labeled migration step, that content is copied to the `migration` field.
62
+
63
+ ### ๐Ÿ› Bug fixes
64
+
65
+ - Pin git-cliff and remove the per-run npx cache refresh (#776)
66
+
67
+ Fixes an issue where git-cliff's version was unpinned, resulting in a per-run cache refresh. An exact version is now pinned.
68
+
69
+ Removes the per-run cache refresh, which re-ran `npx` without `--prefer-offline` once per prepare and forced a registry round trip. An exact version leaves npm nothing to revalidate, so a prepare run no longer waits on registry latency.
70
+
71
+ Also silences git-cliff's INFO output, in particular the crates.io update notice.
72
+
73
+ ### โ™ป๏ธ Refactoring
74
+
75
+ - Remove the unwired isChangelogItem type guard (#771)
76
+
77
+ Removes the unused `isChangelogItem` from `release-kit`'s `changelogJsonUtils.ts`, together with its tests.
78
+
79
+ Documentation is updated to record the boundary on `isChangelogEntry`: Entries parsed from `.meta/changelog.json` are shape-checked at the top level only, and strict validation applies only to the human-authored `.meta/changelog-overrides.json`.
80
+
81
+ ### ๐Ÿงช Tests
82
+
83
+ - Read console spy output with listConsoleLines rather than by hand (#781)
84
+
85
+ - Replaces the hand-rolled reads of a console spy's `mock.calls` in the `nmr`, `release-kit`, and `v11y-check` test suites with `listConsoleLines` from `@williamthorsen/toolbelt.vitest/candidate`.
86
+ - Clears the `toolbelt.vitest/no-console-calls-read` recommendation that `rdy run --packages` reported.
87
+
5
88
  ## 10.5.0 โ€” 2026-09-01
6
89
 
7
90
  ### ๐ŸŽ‰ Features