@williamthorsen/release-kit 17.0.0 → 18.0.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.
@@ -1,4 +1,51 @@
1
1
  [
2
+ {
3
+ "version": "18.0.0",
4
+ "date": "2026-11-10",
5
+ "sections": [
6
+ {
7
+ "title": "🎉 Features",
8
+ "audience": "all",
9
+ "items": [
10
+ {
11
+ "description": "Renames the `common` label preset's `priority:critical`, `priority:high`, `priority:medium`, and `priority:low` labels to `urgency:*`, and declares each old name as an alias so that `release-kit sync-labels` renames a repository's existing labels in place and keeps them on their issues and pull requests. (#1270)",
12
+ "breaking": true,
13
+ "migration": "Replace each `priority:*` name in the `repoLabels.labels` record and in any tool that reads labels by name with its `urgency:*` counterpart, then run `release-kit sync-labels generate`; a `priority:*` entry set to `null` now fails generation as a dangling `null`, and a `labels` entry that restates an `urgency:*` label without `aliases` stops the rename.",
14
+ "hash": "c3da65d2eef59ae0ce5a9087bddbc6bea888c771",
15
+ "entry": 1
16
+ }
17
+ ]
18
+ },
19
+ {
20
+ "title": "♻️ Refactoring",
21
+ "audience": "dev",
22
+ "items": [
23
+ {
24
+ "description": "Replaces the duplicate `resolveStyles` modules in `release-kit` and `v11y-check` with `resolveCliStyles` from `@williamthorsen/nmr-core/cli`, which each package's `route.ts` calls with its own output-style environment variable. (#1248)",
25
+ "hash": "c5f4ac68360ce550a7e53006a2a633b79f179f5f",
26
+ "entry": 1
27
+ }
28
+ ]
29
+ }
30
+ ]
31
+ },
32
+ {
33
+ "version": "17.0.1",
34
+ "date": "2026-11-08",
35
+ "sections": [
36
+ {
37
+ "title": "🐛 Bug fixes",
38
+ "audience": "all",
39
+ "items": [
40
+ {
41
+ "description": "Fixes the issue that `release-kit` did not match a change-record entry's type to a configured work-type key or alias that contains an uppercase letter. (#1216)",
42
+ "hash": "78108625e45ee74cb473b9a15104ef4d58698f5b",
43
+ "entry": 1
44
+ }
45
+ ]
46
+ }
47
+ ]
48
+ },
2
49
  {
3
50
  "version": "17.0.0",
4
51
  "date": "2026-11-08",
@@ -223,7 +223,7 @@ function stripYamlQuotes(value) {
223
223
  }
224
224
 
225
225
  // .readyup/lib/workflow-hashes.ts
226
- var COMMON_PRESET_HASH = "5c6d7efcc8744d9d30720d24e345b04e03f2b28677ad0c6782020d91731b8aa4";
226
+ var COMMON_PRESET_HASH = "83c27890ea984711d33c7d4ea86c755869f091f9f3414f02ef8a3f9d305db490";
227
227
  var SYNC_LABELS_WORKFLOW_HASH = "0a88829d154c0de7cdd4246fede99e9311a89ab4199034dbe601663d641ab1e4";
228
228
  var RELEASE_WORKFLOW_HASH_MONOREPO = "f63f4cabb57f94ee6550f17a9874c7a346d46554595ddbcd46fdd3208d613437";
229
229
  var RELEASE_WORKFLOW_HASH_SINGLE = "d26dd4ca186632b388ea46bd885721124c03d19918e511baa40821d2d760da69";
@@ -234,7 +234,7 @@ var CREATE_GITHUB_RELEASE_WORKFLOW_HASH_SINGLE = "d6de961de913c67b08dfa7e07f7349
234
234
 
235
235
  // .readyup/kits/default.ts
236
236
  function getMinVersion() {
237
- const picked = { "version": "17.0.0" };
237
+ const picked = { "version": "18.0.0" };
238
238
  if (typeof picked["version"] !== "string") {
239
239
  throw new TypeError("release-kit/package.json: 'version' must be a string");
240
240
  }
@@ -3,10 +3,10 @@
3
3
  "kits": [
4
4
  {
5
5
  "bundledDependencies": {
6
- "@williamthorsen/toolbelt.datetime": "4.1.0",
6
+ "@williamthorsen/toolbelt.datetime": "4.1.1",
7
7
  "@williamthorsen/toolbelt.errors": "0.9.0",
8
8
  "@williamthorsen/toolbelt.filesystem": "0.10.0",
9
- "@williamthorsen/toolbelt.numbers": "7.3.0",
9
+ "@williamthorsen/toolbelt.numbers": "7.3.1",
10
10
  "@williamthorsen/toolbelt.objects": "4.4.0",
11
11
  "@williamthorsen/toolbelt.packaging": "0.7.0",
12
12
  "@williamthorsen/toolbelt.terminal": "0.3.0",
@@ -26,7 +26,7 @@
26
26
  "checklist": "release-kit",
27
27
  "checks": [
28
28
  "@williamthorsen/release-kit in devDependencies",
29
- "@williamthorsen/release-kit >= 17.0.0",
29
+ "@williamthorsen/release-kit >= 18.0.0",
30
30
  "release.yaml workflow exists",
31
31
  "release.yaml matches template",
32
32
  "release.yaml does not reference deprecated tag ref",
@@ -157,12 +157,12 @@
157
157
  "path": "lib/config-checks.ts"
158
158
  },
159
159
  {
160
- "hash": "f652dae3",
160
+ "hash": "70e95528",
161
161
  "kind": "module",
162
162
  "path": "lib/workflow-hashes.ts"
163
163
  },
164
164
  {
165
- "hash": "8df94cba",
165
+ "hash": "f79c1319",
166
166
  "kind": "inline",
167
167
  "path": "../package.json",
168
168
  "paths": [
@@ -195,14 +195,14 @@
195
195
  "readyupVersion": "0.45.0",
196
196
  "source": "kits/default.ts",
197
197
  "sourceHash": "56566d0b",
198
- "targetHash": "060f7720"
198
+ "targetHash": "f1bc2e7d"
199
199
  },
200
200
  {
201
201
  "bundledDependencies": {
202
- "@williamthorsen/toolbelt.datetime": "4.1.0",
202
+ "@williamthorsen/toolbelt.datetime": "4.1.1",
203
203
  "@williamthorsen/toolbelt.errors": "0.9.0",
204
204
  "@williamthorsen/toolbelt.filesystem": "0.10.0",
205
- "@williamthorsen/toolbelt.numbers": "7.3.0",
205
+ "@williamthorsen/toolbelt.numbers": "7.3.1",
206
206
  "@williamthorsen/toolbelt.objects": "4.4.0",
207
207
  "@williamthorsen/toolbelt.packaging": "0.7.0",
208
208
  "@williamthorsen/toolbelt.terminal": "0.3.0",
package/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 18.0.0 — 2026-11-10
6
+
7
+ ### 🎉 Features
8
+
9
+ - 🚨 **Breaking:** Renames the `common` label preset's `priority:critical`, `priority:high`, `priority:medium`, and `priority:low` labels to `urgency:*`, and declares each old name as an alias so that `release-kit sync-labels` renames a repository's existing labels in place and keeps them on their issues and pull requests. (#1270)
10
+
11
+ ### ♻️ Refactoring
12
+
13
+ - Replaces the duplicate `resolveStyles` modules in `release-kit` and `v11y-check` with `resolveCliStyles` from `@williamthorsen/nmr-core/cli`, which each package's `route.ts` calls with its own output-style environment variable. (#1248)
14
+
15
+ ## 17.0.1 — 2026-11-08
16
+
17
+ ### 🐛 Bug fixes
18
+
19
+ - Fixes the issue that `release-kit` did not match a change-record entry's type to a configured work-type key or alias that contains an uppercase letter. (#1216)
20
+
5
21
  ## 17.0.0 — 2026-11-08
6
22
 
7
23
  ### 🎉 Features
package/README.md CHANGED
@@ -7,16 +7,11 @@ Version-bumping and changelog-generation toolkit for release workflows.
7
7
  Provides a self-contained CLI that auto-discovers workspaces from `pnpm-workspace.yaml`, parses conventional commits, determines version bumps, updates `package.json` files, and generates changelogs from the same commit history that decides each bump (with optional [editorial overrides](docs/editorial-overrides.md)).
8
8
 
9
9
  <!-- section:release-notes -->
10
- ## Release notes — v17.0.0 (2026-11-08)
10
+ ## Release notes — v18.0.0 (2026-11-10)
11
11
 
12
12
  ### 🎉 Features
13
13
 
14
- - 🚨 **Breaking:** Routes `release-kit` commands through the `toolbelt.cli` command parser, which renders help from each command's options and makes a usage error, such as an invalid `RELEASE_KIT_OUTPUT_STYLE` or a stray argument to `sync-labels sync`, exit 2 with a `Try` line instead of exit 1, and makes a bare `release-kit`, `release-kit overrides`, or `release-kit sync-labels` exit 2 instead of printing help and exiting 0. (#1186)
15
- - Prefixes each handled error line written by `nmr` and its other bins, `release-kit`, and `v11y-check` with the name of the program that wrote it, as `<bin>: <message>` in place of `Error: <message>`, for usage errors such as an unknown command or option as well, and names `v11y` for both of the bins in `v11y-check`. (#1190)
16
-
17
- ### 🐛 Bug fixes
18
-
19
- - Fixes the issue that the tarball refusal from `release-kit prepare` and `release-kit publish` pointed to a `prepack` script, even though the check builds the package through its `prepublishOnly` script, and makes the refusal and `docs/releasing.md` name `"prepublishOnly": "nmr build"` instead. (#1193)
14
+ - 🚨 **Breaking:** Renames the `common` label preset's `priority:critical`, `priority:high`, `priority:medium`, and `priority:low` labels to `urgency:*`, and declares each old name as an alias so that `release-kit sync-labels` renames a repository's existing labels in place and keeps them on their issues and pull requests. (#1270)
20
15
  <!-- /section:release-notes -->
21
16
 
22
17
  ## Installation
@@ -55,7 +55,5 @@ export interface BreakingPolicyInputs {
55
55
  * commit still parses.
56
56
  */
57
57
  export declare function evaluateBreakingPolicy(inputs: BreakingPolicyInputs): boolean;
58
- /**
59
- * Resolves a raw type string to its canonical type name using the record keys and aliases.
60
- */
58
+ /** Resolves a raw type string to its canonical type name through change-grammar, ignoring case on both sides. */
61
59
  export declare function resolveType(rawType: string, workTypes: Record<string, WorkTypeConfig>): string | undefined;
@@ -1,4 +1,4 @@
1
- import { compileTemplate, parse, TEMPLATE_CATALOGUE, } from '@williamthorsen/change-grammar';
1
+ import { canonicalizeType, compileTemplate, parse, TEMPLATE_CATALOGUE, } from '@williamthorsen/change-grammar';
2
2
  const SUBJECT_TEMPLATES = [
3
3
  compileTemplate(TEMPLATE_CATALOGUE.pipedScope),
4
4
  compileTemplate(TEMPLATE_CATALOGUE.conventionalCommits),
@@ -54,20 +54,7 @@ export function evaluateBreakingPolicy(inputs) {
54
54
  return hasPrefixBreaking || hasFooterBreaking;
55
55
  }
56
56
  export function resolveType(rawType, workTypes) {
57
- const loweredType = rawType.toLowerCase();
58
- for (const [key, config] of Object.entries(workTypes)) {
59
- if (key === loweredType) {
60
- return key;
61
- }
62
- if (config.aliases !== undefined) {
63
- for (const alias of config.aliases) {
64
- if (alias === loweredType) {
65
- return key;
66
- }
67
- }
68
- }
69
- }
70
- return undefined;
57
+ return canonicalizeType(rawType, adaptToTaxonomy(workTypes));
71
58
  }
72
59
  function adaptToTaxonomy(workTypes) {
73
60
  return {
package/dist/esm/route.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import process from 'node:process';
2
2
  import { resolveSelfVersion } from '@williamthorsen/nmr-core';
3
- import { createCli, runCli } from '@williamthorsen/nmr-core/cli';
3
+ import { createCli, resolveCliStyles, runCli } from '@williamthorsen/nmr-core/cli';
4
4
  import { BIN } from "./bin.js";
5
5
  import { init, overrides, showTagPrefixes, syncLabels, updateTemplates } from "./cli/maintenanceCommands.js";
6
6
  import { commit, createGithubRelease, prepare, publish, push, tag } from "./cli/releaseCommands.js";
7
- import { OUTPUT_STYLE_ENV_VAR, resolveStyles } from "./resolveStyles.js";
8
7
  const VERSION = resolveSelfVersion(import.meta.url);
8
+ const OUTPUT_STYLE_ENV_VAR = 'RELEASE_KIT_OUTPUT_STYLE';
9
9
  export async function routeCommand(args) {
10
10
  return runCli(args, ROOT, {
11
11
  name: BIN,
@@ -18,7 +18,9 @@ export async function routeCommand(args) {
18
18
  const { defineGroup } = createCli();
19
19
  const ROOT = defineGroup({
20
20
  summary: 'Version-bumping and changelog-generation toolkit for release workflows',
21
- deriveContext: (_flags, context) => ({ styles: resolveStyles(context) }),
21
+ deriveContext: (_flags, context) => ({
22
+ styles: resolveCliStyles({ ...context, envVar: OUTPUT_STYLE_ENV_VAR }),
23
+ }),
22
24
  commands: {
23
25
  prepare,
24
26
  commit,
@@ -3,7 +3,8 @@ import type { LabelDefinition } from './types.js';
3
3
  export declare function hashPreset(presetName: string): string;
4
4
  /**
5
5
  * Loads a named preset from the bundled YAML files. The `common` preset also defines the label of every work type in
6
- * change-grammar's taxonomy, ahead of the labels in its file.
6
+ * change-grammar's taxonomy, ahead of the labels in its file. An entry may declare `aliases`, the old names that the
7
+ * sync renames to the label.
7
8
  *
8
9
  * Throws if the preset does not exist or has invalid content.
9
10
  */
@@ -4,6 +4,7 @@ import { resolve } from 'node:path';
4
4
  import { CANONICAL_TAXONOMY } from '@williamthorsen/change-grammar';
5
5
  import { findPackageRoot, isRecord, UserError } from '@williamthorsen/nmr-core';
6
6
  import { parse } from 'yaml';
7
+ import { labelSpecSchema } from "../configSchema.js";
7
8
  import { chainUserError } from "../user-error-chaining.js";
8
9
  import { deriveTypeLabels } from "./typeLabels.js";
9
10
  const TYPE_LABELS_PRESET = 'common';
@@ -33,13 +34,21 @@ export function loadPreset(presetName) {
33
34
  if (!isRecord(entry)) {
34
35
  throw new UserError(`Preset "${presetName}" contains an invalid label entry: ${JSON.stringify(entry)}`);
35
36
  }
36
- const { color, description, name } = entry;
37
+ const { aliases: rawAliases, color, description, name } = entry;
38
+ const aliasesResult = labelSpecSchema.shape.aliases.safeParse(rawAliases);
37
39
  if (typeof name !== 'string' ||
38
40
  typeof color !== 'string' ||
39
- (description !== undefined && typeof description !== 'string')) {
41
+ (description !== undefined && typeof description !== 'string') ||
42
+ !aliasesResult.success) {
40
43
  throw new UserError(`Preset "${presetName}" contains a label with invalid fields: ${JSON.stringify(entry)}`);
41
44
  }
42
- labels.push({ name, color, ...(description !== undefined && { description }) });
45
+ const aliases = aliasesResult.data;
46
+ labels.push({
47
+ name,
48
+ color,
49
+ ...(description !== undefined && { description }),
50
+ ...(aliases !== undefined && { aliases }),
51
+ });
43
52
  }
44
53
  return presetName === TYPE_LABELS_PRESET ? [...deriveTypeLabels(CANONICAL_TAXONOMY), ...labels] : labels;
45
54
  }
package/docs/labels.md CHANGED
@@ -38,6 +38,8 @@ The `common` preset defines a label for every work type in change-grammar's taxo
38
38
 
39
39
  The bundled file's `confidence:` family grades how advisable a recommendation is, for example one that a triage of spike findings turns into a ticket: `confidence:high` is clearly worth doing, `confidence:medium` is worth doing but arguable, and `confidence:low` is not worth a ticket now.
40
40
 
41
+ The `urgency:` family states how soon an item needs attention, apart from how valuable it is, which the `value:` family states. Its labels replace the earlier `priority:` family and name the old labels in `aliases`, so a repository that has `priority:` labels has them renamed in place by the first sync after it regenerates `.github/labels.yaml` (see [Renaming a label](#renaming-a-label)).
42
+
41
43
  Names match case-insensitively, as GitHub matches them: `Bug` in the `labels` record replaces a preset's `bug`, and `Bug: null` removes it. A label takes the spelling of the last layer to write it.
42
44
 
43
45
  `description` is optional throughout, in a preset as in the `labels` record, and `sync-labels init` generates none for a scope label. The generated file spells an absent description `''` because `github-label-sync` reads an omitted description as "leave the label's current one alone"; the empty form clears it. Because a scope label without a description groups compactly in GitHub's label list, release-kit's readyup kit warns about each `scope:` label in the generated file that has one.
@@ -70,7 +72,7 @@ labels: {
70
72
 
71
73
  The sync renames an existing label that an alias names, in place, rather than deleting it and creating a new one, so the label stays on the issues and pull requests that have it. The dry-run **Label diff** lists the rename. When the repository has both the old name and the new one, the sync adds the new label to every issue and pull request that has the old one, then deletes the old label. A label that an alias names is not reported as undeclared.
72
74
 
73
- `aliases` is set only in the `labels` record, not in a preset, and it takes at least one name. Names match case-insensitively. An alias must not name a label that the config resolves, including the label that declares it, and must not appear twice: Either would make the sync merge one declared label into another and delete it. To rename a preset's label, remove it with `null` and alias it from the new entry:
75
+ `aliases` is set in a preset or in the `labels` record, and it takes at least one name. A `labels` entry that replaces a preset's label replaces its aliases too, so an entry that restates such a label without them stops the rename. Names match case-insensitively. An alias must not name a label that the config resolves, including the label that declares it, and must not appear twice: Either would make the sync merge one declared label into another and delete it. To rename a preset's label, remove it with `null` and alias it from the new entry:
74
76
 
75
77
  ```typescript
76
78
  labels: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@williamthorsen/release-kit",
3
- "version": "17.0.0",
3
+ "version": "18.0.0",
4
4
  "description": "Version-bumping and changelog-generation toolkit for release workflows",
5
5
  "keywords": [
6
6
  "changelog",
@@ -51,8 +51,8 @@
51
51
  "templates"
52
52
  ],
53
53
  "dependencies": {
54
- "@williamthorsen/change-grammar": "0.3.1",
55
- "@williamthorsen/nmr-core": "0.16.0",
54
+ "@williamthorsen/change-grammar": "0.4.0",
55
+ "@williamthorsen/nmr-core": "0.16.1",
56
56
  "@williamthorsen/toolbelt.errors": "0.9.0",
57
57
  "json-stringify-pretty-compact": "4.0.0",
58
58
  "semver": "7.8.6",
@@ -63,7 +63,7 @@
63
63
  "@types/semver": "7.8.0",
64
64
  "@williamthorsen/toolbelt.filesystem": "0.10.0",
65
65
  "@williamthorsen/toolbelt.testing": "0.8.0",
66
- "@williamthorsen/toolbelt.vitest": "0.13.1",
66
+ "@williamthorsen/toolbelt.vitest": "0.13.2",
67
67
  "actionlint": "2.0.6",
68
68
  "esbuild": "0.28.2",
69
69
  "readyup": "0.45.0",
@@ -30,15 +30,19 @@
30
30
  color: fbca04
31
31
  description: Further information is needed
32
32
 
33
- # Priority
34
- - name: 'priority:critical'
33
+ # Urgency
34
+ - name: 'urgency:critical'
35
35
  color: b60205
36
- - name: 'priority:high'
36
+ aliases: ['priority:critical']
37
+ - name: 'urgency:high'
37
38
  color: d93f0b
38
- - name: 'priority:medium'
39
+ aliases: ['priority:high']
40
+ - name: 'urgency:medium'
39
41
  color: fbca04
40
- - name: 'priority:low'
42
+ aliases: ['priority:medium']
43
+ - name: 'urgency:low'
41
44
  color: cfd3d7
45
+ aliases: ['priority:low']
42
46
 
43
47
  # Status
44
48
  - name: 'status:blocked'
@@ -1,10 +0,0 @@
1
- import { type StreamStyles } from '@williamthorsen/nmr-core';
2
- /** The environment variable that sets the caller's standing style preference: `auto`, `plain`, or `rich`. */
3
- export declare const OUTPUT_STYLE_ENV_VAR = "RELEASE_KIT_OUTPUT_STYLE";
4
- export interface ResolveStylesOptions {
5
- readonly env: Readonly<Record<string, string | undefined>>;
6
- readonly stderrIsTty: boolean;
7
- readonly stdoutIsTty: boolean;
8
- }
9
- /** Resolves the style of each output stream, throwing a `UsageError` when the variable doesn't name a setting. */
10
- export declare function resolveStyles(options: ResolveStylesOptions): StreamStyles;
@@ -1,10 +0,0 @@
1
- import { describeInvalidOutputStyle, resolveStreamStyles } from '@williamthorsen/nmr-core';
2
- import { UsageError } from '@williamthorsen/nmr-core/cli';
3
- export const OUTPUT_STYLE_ENV_VAR = 'RELEASE_KIT_OUTPUT_STYLE';
4
- export function resolveStyles(options) {
5
- const { invalid, styles } = resolveStreamStyles({ ...options, envVar: OUTPUT_STYLE_ENV_VAR });
6
- if (invalid !== undefined) {
7
- throw new UsageError(describeInvalidOutputStyle(invalid));
8
- }
9
- return styles;
10
- }