@williamthorsen/release-kit 11.0.0 → 12.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.
- package/.meta/changelog.json +62 -2
- package/.readyup/kits/default.js +1 -17
- package/.readyup/manifest.json +4 -4
- package/CHANGELOG.md +40 -0
- package/README.md +25 -44
- package/dist/esm/attachChangelogDiagnostics.d.ts +4 -0
- package/dist/esm/attachChangelogDiagnostics.js +11 -0
- package/dist/esm/bin/release-kit.js +4 -3
- package/dist/esm/buildChangelogEntries.d.ts +59 -17
- package/dist/esm/buildChangelogEntries.js +194 -111
- package/dist/esm/buildReleaseSummary.js +2 -2
- package/dist/esm/changelogOverrides.d.ts +31 -13
- package/dist/esm/changelogOverrides.js +138 -58
- package/dist/esm/classifyChangelogCommit.d.ts +38 -0
- package/dist/esm/classifyChangelogCommit.js +33 -0
- package/dist/esm/decideRelease.d.ts +11 -37
- package/dist/esm/decideRelease.js +5 -27
- package/dist/esm/defaults.d.ts +1 -1
- package/dist/esm/defaults.js +3 -0
- package/dist/esm/determineBumpType.d.ts +11 -11
- package/dist/esm/determineBumpType.js +6 -7
- package/dist/esm/enumerateReleaseWindows.d.ts +50 -0
- package/dist/esm/enumerateReleaseWindows.js +124 -0
- package/dist/esm/generateChangelogs.d.ts +5 -23
- package/dist/esm/generateChangelogs.js +0 -14
- package/dist/esm/glyphs.d.ts +1 -1
- package/dist/esm/help/prepareHelp.d.ts +1 -1
- package/dist/esm/help/prepareHelp.js +4 -6
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/init/initCommand.js +1 -1
- package/dist/esm/init/scaffold.d.ts +0 -2
- package/dist/esm/init/scaffold.js +2 -30
- package/dist/esm/loadConfig.d.ts +1 -1
- package/dist/esm/loadConfig.js +1 -4
- package/dist/esm/parseChangeRecordBlock.d.ts +37 -0
- package/dist/esm/parseChangeRecordBlock.js +134 -0
- package/dist/esm/parseCommitMessage.d.ts +31 -6
- package/dist/esm/parseCommitMessage.js +6 -5
- package/dist/esm/prepareCommand.js +4 -12
- package/dist/esm/releasePrepare.d.ts +7 -8
- package/dist/esm/releasePrepare.js +53 -73
- package/dist/esm/releasePrepareMono.js +48 -85
- package/dist/esm/releasePrepareProject.d.ts +1 -1
- package/dist/esm/releasePrepareProject.js +19 -37
- package/dist/esm/reportPrepare.js +39 -28
- package/dist/esm/types.d.ts +99 -55
- package/dist/esm/types.js +1 -1
- package/dist/esm/validateConfig.js +4 -0
- package/dist/esm/validateOverridesCommand.d.ts +6 -5
- package/dist/esm/validateOverridesCommand.js +16 -23
- package/docs/changelogs.md +64 -25
- package/docs/configuration.md +2 -3
- package/docs/editorial-overrides.md +75 -16
- package/docs/project-releases.md +4 -4
- package/docs/releasing.md +13 -8
- package/docs/work-types.md +13 -9
- package/package.json +1 -2
- package/schemas/changelog-overrides.json +39 -0
- package/cliff.toml.template +0 -65
- package/dist/esm/collectPolicyViolations.d.ts +0 -15
- package/dist/esm/collectPolicyViolations.js +0 -12
- package/dist/esm/determineBumpFromCommits.d.ts +0 -17
- package/dist/esm/determineBumpFromCommits.js +0 -28
- package/dist/esm/getCommitsSinceTarget.d.ts +0 -21
- package/dist/esm/getCommitsSinceTarget.js +0 -66
- package/dist/esm/resolveCliffConfigPath.d.ts +0 -11
- package/dist/esm/resolveCliffConfigPath.js +0 -20
- package/dist/esm/runGitCliff.d.ts +0 -38
- package/dist/esm/runGitCliff.js +0 -25
package/.meta/changelog.json
CHANGED
|
@@ -1,4 +1,64 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "12.0.0",
|
|
4
|
+
"date": "2026-09-23",
|
|
5
|
+
"sections": [
|
|
6
|
+
{
|
|
7
|
+
"title": "🎉 Features",
|
|
8
|
+
"audience": "all",
|
|
9
|
+
"items": [
|
|
10
|
+
{
|
|
11
|
+
"description": "Assign changelog sections from the work-type taxonomy (#877)",
|
|
12
|
+
"body": "- Adds `excludedFromChangelog` to a `workTypes` entry, which keeps commits of that type out of every changelog while they still count toward the version bump.\n- Fixes the silent omission of a ticketed commit written as `type(scope):` or with a capitalized type such as `FEAT:`, which counted toward the version bump but reached no changelog.\n- Documents that a scaffolded `.config/git-cliff.toml` may vary its enumeration keys alone: a `commit_parsers` entry that skips or narrows drops the commit before classification, with no error.",
|
|
13
|
+
"hash": "52d4ea928d35b99101947e0509da6699f06f821a"
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"description": "Build changelog items from a merge commit's change-record block (#882)",
|
|
17
|
+
"body": "Builds `release-kit` changelog items from a commit's `change-record` block, the fenced YAML block at the end of a squash-merge commit that lists the change's outcomes, so that a merge with several outcomes of different types yields one item per outcome, each under its own type's section. Makes `release-kit prepare` warn about a block that cannot be read, an entry whose type is undeclared, and an entry that violates its type's breaking policy. Keeps reading a commit with no usable block from its title, as before.",
|
|
18
|
+
"hash": "094aac7048a54b6f07d1c97cd37fff570630b936"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"description": "Derive the version bump from the changelog items (#885)",
|
|
22
|
+
"body": "Derives the version bump in every `release-kit prepare` path (single-package, project, and monorepo) from the changelog items of the unreleased commits, so that the bump and the changelog describe the same release. A commit that yields no changelog item no longer bumps, and a `BREAKING CHANGE:` footer no longer raises a major bump. Single-package mode now follows the monorepo rules for `--bump` and `--force`, and the `prepare` report shows the diagnostics of a skipped target.\n\nMigration: Mark a breaking change with a `!` on the commit subject or with `breaking: true` on its change-record entry, because a `BREAKING CHANGE:` footer alone now gets the bump of the commit's type. Give each commit that should bump a ticket-ID prefix and a type that the changelog does not exclude. In single-package mode, add `--force` to a release that used `--bump=X` alone, or that relied on the patch floor, when no commit yields a changelog item; without it, `prepare` skips the release.",
|
|
23
|
+
"breaking": true,
|
|
24
|
+
"migration": "Mark a breaking change with a `!` on the commit subject or with `breaking: true` on its change-record entry, because a `BREAKING CHANGE:` footer alone now gets the bump of the commit's type. Give each commit that should bump a ticket-ID prefix and a type that the changelog does not exclude. In single-package mode, add `--force` to a release that used `--bump=X` alone, or that relied on the patch floor, when no commit yields a changelog item; without it, `prepare` skips the release.",
|
|
25
|
+
"hash": "f3d0d8f01d6cd5b5638012a4798e64ab3a3def6d"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"description": "Key an editorial override to one of several items on a commit (#886)",
|
|
29
|
+
"body": "Adds the `<hash>:<n>` key to `.meta/changelog-overrides.json`. It targets one of the several changelog items that a commit's change-record block yields, while a bare `<hash>` key still targets all of them. Also makes `release-kit prepare` and `release-kit overrides validate` fail when override keys conflict on an item, and publishes a JSON Schema for the override file.\n\nMigration: Replace a bare key that sets `description` or `body` on a commit with several items with one `<hash>:<n>` key per item, as listed by the error message. Where two keys match the same item, such as `abc1234` beside `abc1234:2`, remove one of them. This includes a root-file key that overlaps a workspace-file key, which now fails even though the two files are separate. In each scope passed to `validateAllChangelogOverrides`, rename `hashes` to `items` and pass `OverrideTargetItem` objects (`{ hash, entry? }`) instead of hash strings.",
|
|
30
|
+
"breaking": true,
|
|
31
|
+
"migration": "Replace a bare key that sets `description` or `body` on a commit with several items with one `<hash>:<n>` key per item, as listed by the error message. Where two keys match the same item, such as `abc1234` beside `abc1234:2`, remove one of them. This includes a root-file key that overlaps a workspace-file key, which now fails even though the two files are separate. In each scope passed to `validateAllChangelogOverrides`, rename `hashes` to `items` and pass `OverrideTargetItem` objects (`{ hash, entry? }`) instead of hash strings.",
|
|
32
|
+
"hash": "f90db5596196e501fef1734bcd978d23f9a0540a"
|
|
33
|
+
}
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"title": "🪦 Removed",
|
|
38
|
+
"audience": "all",
|
|
39
|
+
"items": [
|
|
40
|
+
{
|
|
41
|
+
"description": "Build changelogs from release-kit's own enumeration and remove git-cliff (#880)",
|
|
42
|
+
"body": "Removes git-cliff from `@williamthorsen/release-kit`: `prepare` now builds every changelog from the same commit history that decides each version bump, and no longer fetches a git-cliff binary through `npx`. A config that still sets `cliffConfigPath` now fails validation. Two ways in which the changelog and the bump read different commits are gone, affecting single-package repositories with a tag prefix other than `v` and `paths` entries that name a bare directory.\n\nMigration: Remove `cliffConfigPath` from `.config/release-kit.config.ts`, and delete `.config/git-cliff.toml` or `cliff.toml` if the repository has one. Any customization in that file, such as `tag_pattern` or its tag-skipping keys, no longer has an effect: `release-kit` now splits the changelog on the configured tag prefixes alone.",
|
|
43
|
+
"breaking": true,
|
|
44
|
+
"migration": "Remove `cliffConfigPath` from `.config/release-kit.config.ts`, and delete `.config/git-cliff.toml` or `cliff.toml` if the repository has one. Any customization in that file, such as `tag_pattern` or its tag-skipping keys, no longer has an effect: `release-kit` now splits the changelog on the configured tag prefixes alone.",
|
|
45
|
+
"hash": "3dc091ff6067f1c2cbe1576a55114c481294ce22"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"title": "🏗️ Internal features",
|
|
51
|
+
"audience": "dev",
|
|
52
|
+
"items": [
|
|
53
|
+
{
|
|
54
|
+
"description": "Enumerate release windows and read them on the bump path (#879)",
|
|
55
|
+
"body": "Adds `enumerateReleaseWindows`, which splits the history reachable from HEAD into release windows from tag prefixes and a path list, and rebuilds `getCommitsSinceTarget` on the newest of those windows in place of its `git describe` baseline lookup. Leaves the changelog on git-cliff's enumeration.",
|
|
56
|
+
"hash": "30586d1e045ed69dbf81a1c35773c97b89e0c8dc"
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
},
|
|
2
62
|
{
|
|
3
63
|
"version": "11.0.0",
|
|
4
64
|
"date": "2026-09-22",
|
|
@@ -408,7 +468,7 @@
|
|
|
408
468
|
},
|
|
409
469
|
{
|
|
410
470
|
"description": "Adopt `isError` and consolidate errno narrowing on a shared helper (#697)",
|
|
411
|
-
"body": "Replaces every hand-rolled `instanceof Error` narrowing with `hasErrnoCode`, a new predicate exported from `@williamthorsen/nmr-core`, or with `isError` from `@williamthorsen/toolbelt.errors`. Previously the errno question was answered by inline copies alongside two private helpers of differing shape; both helpers are removed.\
|
|
471
|
+
"body": "Replaces every hand-rolled `instanceof Error` narrowing with `hasErrnoCode`, a new predicate exported from `@williamthorsen/nmr-core`, or with `isError` from `@williamthorsen/toolbelt.errors`. Previously the errno question was answered by inline copies alongside two private helpers of differing shape; both helpers are removed.\n\nSeparately, `eslint.config.ts` now bans `instanceof Error` in every position rather than in a ternary alone.",
|
|
412
472
|
"hash": "c5e8e8a5e006b451e8c5aeea75d35772926d503c"
|
|
413
473
|
}
|
|
414
474
|
]
|
|
@@ -529,7 +589,7 @@
|
|
|
529
589
|
},
|
|
530
590
|
{
|
|
531
591
|
"description": "Make prepare all-or-nothing and report the tags file by path (#601)",
|
|
532
|
-
"body": "Fixes an issue where a failed `prepare` could leave the release flow in a broken intermediate state. A release now lands completely or not at all, and a formatting failure no longer discards one that already landed. When a write fails partway, the error names every file that reached disk, every file that did not, and the commands that undo them.\
|
|
592
|
+
"body": "Fixes an issue where a failed `prepare` could leave the release flow in a broken intermediate state. A release now lands completely or not at all, and a formatting failure no longer discards one that already landed. When a write fails partway, the error names every file that reached disk, every file that did not, and the commands that undo them.\n\n`commit` and `tag` now report the full path of the tags file they looked for, and distinguish a missing file from one that could not be read, so that running from the wrong directory or worktree is no longer reported as a release that never happened.\n\nRuns with `--with-release-notes` now list the preview files they write, and `--dry-run` names the ones a real run would write.",
|
|
533
593
|
"hash": "83ac6e45cf9d4b5371650cda42d7830ed4988660"
|
|
534
594
|
}
|
|
535
595
|
]
|
package/.readyup/kits/default.js
CHANGED
|
@@ -98,7 +98,7 @@ function translateGlob(pattern) {
|
|
|
98
98
|
|
|
99
99
|
// .readyup/kits/default.ts
|
|
100
100
|
function getMinVersion() {
|
|
101
|
-
const picked = { "version": "
|
|
101
|
+
const picked = { "version": "12.0.0" };
|
|
102
102
|
if (typeof picked["version"] !== "string") {
|
|
103
103
|
throw new TypeError("release-kit/package.json: 'version' must be a string");
|
|
104
104
|
}
|
|
@@ -114,7 +114,6 @@ var CONFIG_EXPORT_PATTERNS = [
|
|
|
114
114
|
/export\s*\{[^}]*\b(?:config|default)\b[^}]*\}/,
|
|
115
115
|
/export\s*\*/
|
|
116
116
|
];
|
|
117
|
-
var CLIFF_TEMPLATE_HASH = "93b72e0b1393cd6b1fe8e2a0e303cd326fd323435951b0493396b305af32d2ec";
|
|
118
117
|
var COMMON_PRESET_HASH = "8c52654d4eee216c22377dd1e65b89f6bbb0a3478d74379bd28b04a877f0b02a";
|
|
119
118
|
var SYNC_LABELS_WORKFLOW_HASH = "d6e2403fb551d2d415f679125989c92760444eec887644565b2e05c9bf8f4c1e";
|
|
120
119
|
var RELEASE_WORKFLOW_HASH_MONOREPO = "0a9724b7b3c5e24087fd3a8f36fed8e990d699267fcf36028ce048ab40dc2946";
|
|
@@ -296,13 +295,6 @@ var default_default = defineRdyKit({
|
|
|
296
295
|
check: () => fileDoesNotContain(".config/release-kit.config.ts", /shouldCreateGithubRelease/),
|
|
297
296
|
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."
|
|
298
297
|
},
|
|
299
|
-
{
|
|
300
|
-
name: "git-cliff not in devDependencies",
|
|
301
|
-
severity: "recommend",
|
|
302
|
-
quiet: true,
|
|
303
|
-
check: () => !hasDevDependency("git-cliff"),
|
|
304
|
-
fix: "pnpm remove git-cliff \u2014 release-kit handles changelog generation directly"
|
|
305
|
-
},
|
|
306
298
|
{
|
|
307
299
|
name: "@changesets/cli not in devDependencies",
|
|
308
300
|
severity: "recommend",
|
|
@@ -310,13 +302,6 @@ var default_default = defineRdyKit({
|
|
|
310
302
|
check: () => !hasDevDependency("@changesets/cli"),
|
|
311
303
|
fix: "pnpm remove @changesets/cli, then delete .changeset/ and any changeset:* scripts; release-kit supersedes changesets"
|
|
312
304
|
},
|
|
313
|
-
{
|
|
314
|
-
name: ".config/git-cliff.toml matches current template",
|
|
315
|
-
severity: "warn",
|
|
316
|
-
skip: () => !fileExists(".config/git-cliff.toml") ? "no local cliff config (using fallback)" : false,
|
|
317
|
-
check: () => fileMatchesHash(".config/git-cliff.toml", CLIFF_TEMPLATE_HASH),
|
|
318
|
-
fix: "Update .config/git-cliff.toml to match the current cliff.toml.template from release-kit, or delete it to use the bundled fallback"
|
|
319
|
-
},
|
|
320
305
|
{
|
|
321
306
|
name: "sync-labels.yaml workflow exists",
|
|
322
307
|
severity: "warn",
|
|
@@ -425,7 +410,6 @@ function resolveChangelogJsonOutputPath() {
|
|
|
425
410
|
return match?.[1] ?? DEFAULT_CHANGELOG_JSON_PATH;
|
|
426
411
|
}
|
|
427
412
|
export {
|
|
428
|
-
CLIFF_TEMPLATE_HASH,
|
|
429
413
|
COMMON_PRESET_HASH,
|
|
430
414
|
CREATE_GITHUB_RELEASE_WORKFLOW_HASH_MONOREPO,
|
|
431
415
|
CREATE_GITHUB_RELEASE_WORKFLOW_HASH_SINGLE,
|
package/.readyup/manifest.json
CHANGED
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"esbuildVersion": "0.28.2",
|
|
9
9
|
"inputs": [
|
|
10
10
|
{
|
|
11
|
-
"hash": "
|
|
11
|
+
"hash": "07f5fe58",
|
|
12
12
|
"kind": "module",
|
|
13
13
|
"path": "kits/default.ts"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
|
-
"hash": "
|
|
16
|
+
"hash": "54c6b74c",
|
|
17
17
|
"kind": "inline",
|
|
18
18
|
"path": "../package.json",
|
|
19
19
|
"paths": [
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"path": "kits/default.js",
|
|
46
46
|
"readyupVersion": "0.38.0",
|
|
47
47
|
"source": "kits/default.ts",
|
|
48
|
-
"sourceHash": "
|
|
49
|
-
"targetHash": "
|
|
48
|
+
"sourceHash": "07f5fe58",
|
|
49
|
+
"targetHash": "cece8501"
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
52
|
"checklists": [
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,46 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 12.0.0 — 2026-09-23
|
|
6
|
+
|
|
7
|
+
### 🎉 Features
|
|
8
|
+
|
|
9
|
+
- Assign changelog sections from the work-type taxonomy (#877)
|
|
10
|
+
|
|
11
|
+
- Adds `excludedFromChangelog` to a `workTypes` entry, which keeps commits of that type out of every changelog while they still count toward the version bump.
|
|
12
|
+
- Fixes the silent omission of a ticketed commit written as `type(scope):` or with a capitalized type such as `FEAT:`, which counted toward the version bump but reached no changelog.
|
|
13
|
+
- Documents that a scaffolded `.config/git-cliff.toml` may vary its enumeration keys alone: a `commit_parsers` entry that skips or narrows drops the commit before classification, with no error.
|
|
14
|
+
|
|
15
|
+
- Build changelog items from a merge commit's change-record block (#882)
|
|
16
|
+
|
|
17
|
+
Builds `release-kit` changelog items from a commit's `change-record` block, the fenced YAML block at the end of a squash-merge commit that lists the change's outcomes, so that a merge with several outcomes of different types yields one item per outcome, each under its own type's section. Makes `release-kit prepare` warn about a block that cannot be read, an entry whose type is undeclared, and an entry that violates its type's breaking policy. Keeps reading a commit with no usable block from its title, as before.
|
|
18
|
+
|
|
19
|
+
- 🚨 **Breaking:** Derive the version bump from the changelog items (#885)
|
|
20
|
+
|
|
21
|
+
Derives the version bump in every `release-kit prepare` path (single-package, project, and monorepo) from the changelog items of the unreleased commits, so that the bump and the changelog describe the same release. A commit that yields no changelog item no longer bumps, and a `BREAKING CHANGE:` footer no longer raises a major bump. Single-package mode now follows the monorepo rules for `--bump` and `--force`, and the `prepare` report shows the diagnostics of a skipped target.
|
|
22
|
+
|
|
23
|
+
Migration: Mark a breaking change with a `!` on the commit subject or with `breaking: true` on its change-record entry, because a `BREAKING CHANGE:` footer alone now gets the bump of the commit's type. Give each commit that should bump a ticket-ID prefix and a type that the changelog does not exclude. In single-package mode, add `--force` to a release that used `--bump=X` alone, or that relied on the patch floor, when no commit yields a changelog item; without it, `prepare` skips the release.
|
|
24
|
+
|
|
25
|
+
- 🚨 **Breaking:** Key an editorial override to one of several items on a commit (#886)
|
|
26
|
+
|
|
27
|
+
Adds the `<hash>:<n>` key to `.meta/changelog-overrides.json`. It targets one of the several changelog items that a commit's change-record block yields, while a bare `<hash>` key still targets all of them. Also makes `release-kit prepare` and `release-kit overrides validate` fail when override keys conflict on an item, and publishes a JSON Schema for the override file.
|
|
28
|
+
|
|
29
|
+
Migration: Replace a bare key that sets `description` or `body` on a commit with several items with one `<hash>:<n>` key per item, as listed by the error message. Where two keys match the same item, such as `abc1234` beside `abc1234:2`, remove one of them. This includes a root-file key that overlaps a workspace-file key, which now fails even though the two files are separate. In each scope passed to `validateAllChangelogOverrides`, rename `hashes` to `items` and pass `OverrideTargetItem` objects (`{ hash, entry? }`) instead of hash strings.
|
|
30
|
+
|
|
31
|
+
### 🪦 Removed
|
|
32
|
+
|
|
33
|
+
- 🚨 **Breaking:** Build changelogs from release-kit's own enumeration and remove git-cliff (#880)
|
|
34
|
+
|
|
35
|
+
Removes git-cliff from `@williamthorsen/release-kit`: `prepare` now builds every changelog from the same commit history that decides each version bump, and no longer fetches a git-cliff binary through `npx`. A config that still sets `cliffConfigPath` now fails validation. Two ways in which the changelog and the bump read different commits are gone, affecting single-package repositories with a tag prefix other than `v` and `paths` entries that name a bare directory.
|
|
36
|
+
|
|
37
|
+
Migration: Remove `cliffConfigPath` from `.config/release-kit.config.ts`, and delete `.config/git-cliff.toml` or `cliff.toml` if the repository has one. Any customization in that file, such as `tag_pattern` or its tag-skipping keys, no longer has an effect: `release-kit` now splits the changelog on the configured tag prefixes alone.
|
|
38
|
+
|
|
39
|
+
### 🏗️ Internal features
|
|
40
|
+
|
|
41
|
+
- Enumerate release windows and read them on the bump path (#879)
|
|
42
|
+
|
|
43
|
+
Adds `enumerateReleaseWindows`, which splits the history reachable from HEAD into release windows from tag prefixes and a path list, and rebuilds `getCommitsSinceTarget` on the newest of those windows in place of its `git describe` baseline lookup. Leaves the changelog on git-cliff's enumeration.
|
|
44
|
+
|
|
5
45
|
## 11.0.0 — 2026-09-22
|
|
6
46
|
|
|
7
47
|
### 🎉 Features
|
package/README.md
CHANGED
|
@@ -4,56 +4,42 @@
|
|
|
4
4
|
|
|
5
5
|
Version-bumping and changelog-generation toolkit for release workflows.
|
|
6
6
|
|
|
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
|
|
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 —
|
|
10
|
+
## Release notes — v12.0.0 (2026-09-23)
|
|
11
11
|
|
|
12
12
|
### 🎉 Features
|
|
13
13
|
|
|
14
|
-
-
|
|
14
|
+
- Assign changelog sections from the work-type taxonomy (#877)
|
|
15
15
|
|
|
16
|
-
-
|
|
17
|
-
-
|
|
16
|
+
- Adds `excludedFromChangelog` to a `workTypes` entry, which keeps commits of that type out of every changelog while they still count toward the version bump.
|
|
17
|
+
- Fixes the silent omission of a ticketed commit written as `type(scope):` or with a capitalized type such as `FEAT:`, which counted toward the version bump but reached no changelog.
|
|
18
|
+
- Documents that a scaffolded `.config/git-cliff.toml` may vary its enumeration keys alone: a `commit_parsers` entry that skips or narrows drops the commit before classification, with no error.
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
- Build changelog items from a merge commit's change-record block (#882)
|
|
20
21
|
|
|
21
|
-
-
|
|
22
|
+
Builds `release-kit` changelog items from a commit's `change-record` block, the fenced YAML block at the end of a squash-merge commit that lists the change's outcomes, so that a merge with several outcomes of different types yields one item per outcome, each under its own type's section. Makes `release-kit prepare` warn about a block that cannot be read, an entry whose type is undeclared, and an entry that violates its type's breaking policy. Keeps reading a commit with no usable block from its title, as before.
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
- Requires a named `--config` file to exist, failing if it does not; an absent default path continues to mean that the repo declares no config.
|
|
25
|
-
- Confines scaffolding to the default path: `release-kit init` and `sync-labels init` still write `.config/release-kit.config.ts`, and `sync-labels init --config` reads the named file and fails when it is absent.
|
|
24
|
+
- 🚨 **Breaking:** Derive the version bump from the changelog items (#885)
|
|
26
25
|
|
|
27
|
-
-
|
|
26
|
+
Derives the version bump in every `release-kit prepare` path (single-package, project, and monorepo) from the changelog items of the unreleased commits, so that the bump and the changelog describe the same release. A commit that yields no changelog item no longer bumps, and a `BREAKING CHANGE:` footer no longer raises a major bump. Single-package mode now follows the monorepo rules for `--bump` and `--force`, and the `prepare` report shows the diagnostics of a skipped target.
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
- Stops `release-kit` from tagging, publishing, and label-syncing a package that a `!` entry in `pnpm-workspace.yaml` excludes, which its previous `glob`-based resolution could not remove from the match.
|
|
31
|
-
- Replaces the release of the root package alone with a failure naming the condition that emptied the workspace, when `pnpm-workspace.yaml` does not hold valid YAML or declares a workspace that does not resolve to a package.
|
|
32
|
-
- Replaces the `no-pattern` remedy that `nmr` printed for a `pnpm-workspace.yaml` declaring no `packages` list, and for one declaring a `packages` value that is not a list of strings.
|
|
33
|
-
- Raises `engines.node` to `>=24.16.0` in `@williamthorsen/nmr-core` and `@williamthorsen/release-kit`, because Node 24.0 through 24.15 ignores the `followSymlinks` option that the workspace matcher passes to `globSync` and drops a symlinked package directory from the resolution without reporting it.
|
|
28
|
+
Migration: Mark a breaking change with a `!` on the commit subject or with `breaking: true` on its change-record entry, because a `BREAKING CHANGE:` footer alone now gets the bump of the commit's type. Give each commit that should bump a ticket-ID prefix and a type that the changelog does not exclude. In single-package mode, add `--force` to a release that used `--bump=X` alone, or that relied on the patch floor, when no commit yields a changelog item; without it, `prepare` skips the release.
|
|
34
29
|
|
|
35
|
-
|
|
30
|
+
- 🚨 **Breaking:** Key an editorial override to one of several items on a commit (#886)
|
|
36
31
|
|
|
37
|
-
|
|
32
|
+
Adds the `<hash>:<n>` key to `.meta/changelog-overrides.json`. It targets one of the several changelog items that a commit's change-record block yields, while a bare `<hash>` key still targets all of them. Also makes `release-kit prepare` and `release-kit overrides validate` fail when override keys conflict on an item, and publishes a JSON Schema for the override file.
|
|
38
33
|
|
|
39
|
-
|
|
34
|
+
Migration: Replace a bare key that sets `description` or `body` on a commit with several items with one `<hash>:<n>` key per item, as listed by the error message. Where two keys match the same item, such as `abc1234` beside `abc1234:2`, remove one of them. This includes a root-file key that overlaps a workspace-file key, which now fails even though the two files are separate. In each scope passed to `validateAllChangelogOverrides`, rename `hashes` to `items` and pass `OverrideTargetItem` objects (`{ hash, entry? }`) instead of hash strings.
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
- Replaces the `...` marker on a truncated subject with `…`, the default of the width-aware truncation that now does the cutting.
|
|
43
|
-
- Exports `truncateToWidth` and `measureWidth` from `@williamthorsen/nmr-core`, which measure and cut text by display width without splitting a grapheme cluster.
|
|
36
|
+
### 🪦 Removed
|
|
44
37
|
|
|
45
|
-
-
|
|
38
|
+
- 🚨 **Breaking:** Build changelogs from release-kit's own enumeration and remove git-cliff (#880)
|
|
46
39
|
|
|
47
|
-
-
|
|
40
|
+
Removes git-cliff from `@williamthorsen/release-kit`: `prepare` now builds every changelog from the same commit history that decides each version bump, and no longer fetches a git-cliff binary through `npx`. A config that still sets `cliffConfigPath` now fails validation. Two ways in which the changelog and the bump read different commits are gone, affecting single-package repositories with a tag prefix other than `v` and `paths` entries that name a bare directory.
|
|
48
41
|
|
|
49
|
-
-
|
|
50
|
-
|
|
51
|
-
- Fixes `publish` proceeding on derived defaults when the default config file exists and fails to load, which silently dropped a configured `releaseNotes.shouldInjectIntoReadme`, `changelogJson.outputPath`, or `workTypes`; it now reports the failure and exits 1, as every other config-reading subcommand does.
|
|
52
|
-
- Fixes `publish` and `create-github-release` ignoring a broken or invalid default config when every requested tag names a private package, a case in which both commands return before any loader runs.
|
|
53
|
-
|
|
54
|
-
- Strip trailing Change trailers from changelog item bodies (#870)
|
|
55
|
-
|
|
56
|
-
- Fixes a changelog item body that kept a commit's trailing `Change:` trailers, which then appeared verbatim in the rendered release notes, including the notes injected into a README.
|
|
42
|
+
Migration: Remove `cliffConfigPath` from `.config/release-kit.config.ts`, and delete `.config/git-cliff.toml` or `cliff.toml` if the repository has one. Any customization in that file, such as `tag_pattern` or its tag-skipping keys, no longer has an effect: `release-kit` now splits the changelog on the configured tag prefixes alone.
|
|
57
43
|
<!-- /section:release-notes -->
|
|
58
44
|
|
|
59
45
|
## Installation
|
|
@@ -86,7 +72,7 @@ Example output from `prepare --dry-run` in a monorepo whose `arrays` workspace h
|
|
|
86
72
|
📦 1.2.0 → 1.3.0 (minor)
|
|
87
73
|
[dry-run] Would bump packages/arrays/package.json
|
|
88
74
|
Generating changelogs...
|
|
89
|
-
[dry-run] Would
|
|
75
|
+
[dry-run] Would generate changelog: packages/arrays/CHANGELOG.md
|
|
90
76
|
🔖 arrays-v1.3.0
|
|
91
77
|
|
|
92
78
|
✅ Release preparation complete.
|
|
@@ -102,17 +88,17 @@ gh workflow run release.yaml # every workspace with release-wor
|
|
|
102
88
|
gh workflow run release.yaml -f only=arrays # the named workspaces alone
|
|
103
89
|
```
|
|
104
90
|
|
|
105
|
-
The CLI applies defaults to every discovered workspace
|
|
91
|
+
The CLI applies defaults to every discovered workspace. [Releasing](docs/releasing.md) covers `prepare`'s flags, release-notes previews, and the workflow's inputs.
|
|
106
92
|
|
|
107
93
|
## How it works
|
|
108
94
|
|
|
109
95
|
1. **Workspace discovery**: reads `pnpm-workspace.yaml` and resolves its `packages` patterns to find workspace directories, applying pnpm's semantics — a `!`-prefixed entry excludes what it matches, wherever it appears in the list. Each directory containing a `package.json` becomes a workspace. The repo is treated as a single-package project when it holds no workspace file, and when the workspace file declares no `packages` list — a file kept for `catalog:` or `overrides:` alone, which pnpm likewise resolves to the root package. A workspace file that declares patterns resolving to no package is an error naming the condition that emptied it.
|
|
110
96
|
2. **Config loading**: loads `.config/release-kit.config.ts` (if present), or the file named by `--config`, and merges it with discovered defaults.
|
|
111
|
-
3. **Commit analysis**: for each workspace,
|
|
112
|
-
4. **Version bump + changelog**: bumps `package.json` versions, builds structured `ChangelogEntry[]` from
|
|
97
|
+
3. **Commit analysis**: for each workspace, reads the history once, builds the changelog items of the commits since the last version tag, and takes the bump as the highest level that those items call for.
|
|
98
|
+
4. **Version bump + changelog**: bumps `package.json` versions, builds structured `ChangelogEntry[]` from the commits between each pair of release tags, applies any [editorial overrides](docs/editorial-overrides.md) from per-scope `.meta/changelog-overrides.json` files, and renders both `CHANGELOG.md` and `.meta/changelog.json` from that single source, so the two always agree.
|
|
113
99
|
5. **Release tags file**: writes computed tags to `tmp/.release-tags` for the release workflow to read when tagging and pushing.
|
|
114
100
|
|
|
115
|
-
[Changelogs](docs/changelogs.md) covers what reaches a published tarball, the `changelog.json` item schema, and
|
|
101
|
+
[Changelogs](docs/changelogs.md) covers what reaches a published tarball, the `changelog.json` item schema, and which commits reach a changelog.
|
|
116
102
|
|
|
117
103
|
## Commit format
|
|
118
104
|
|
|
@@ -163,10 +149,7 @@ Node loads the file directly, so a relative import inside it needs an explicit f
|
|
|
163
149
|
|
|
164
150
|
## External dependencies
|
|
165
151
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
- **`git`** — must be available on `PATH`. Used to find tags and retrieve commit history.
|
|
169
|
-
- **`git-cliff`** — pinned to an exact version and fetched via `npx` on first invocation, then served from npx's cache. No need to install it as a dev dependency. The pin moves only when a new release-kit version names a newer git-cliff, so two releases cut months apart run the same changelog generator.
|
|
152
|
+
release-kit shells out to `git`, which must be available on `PATH`, to find tags and read commit history.
|
|
170
153
|
|
|
171
154
|
## Readiness checks
|
|
172
155
|
|
|
@@ -198,15 +181,13 @@ rdy run --packages
|
|
|
198
181
|
5. Remove `changeset:*` scripts from `package.json` (no replacement needed — the CLI handles everything).
|
|
199
182
|
6. Create an initial version tag for each package (e.g., `git tag v1.0.0` or `git tag arrays-v1.0.0`).
|
|
200
183
|
|
|
201
|
-
No cliff config copy is needed — the bundled template is used automatically. To customize, run `release-kit init --with-config`.
|
|
202
|
-
|
|
203
184
|
## Documentation
|
|
204
185
|
|
|
205
186
|
- [Configuration](docs/configuration.md): `ReleaseKitConfig` fields, workspace overrides and legacy identities, retired packages, tag prefixes, and version patterns
|
|
206
187
|
- [Project releases](docs/project-releases.md): the `project` block, and how a project release interacts with `prepare`'s flags
|
|
207
188
|
- [Releasing](docs/releasing.md): `init`, `prepare`'s flags and release-notes previews, and the release workflow
|
|
208
189
|
- [Publishing](docs/publishing.md): `publish`, the publishability filter, and `create-github-release`
|
|
209
|
-
- [Changelogs](docs/changelogs.md): the `changelog.json` item schema,
|
|
190
|
+
- [Changelogs](docs/changelogs.md): the `changelog.json` item schema, which commits reach a changelog, and release-notes injection
|
|
210
191
|
- [Editorial overrides](docs/editorial-overrides.md): correcting generated changelog entries, and `overrides validate`
|
|
211
192
|
- [Work types and tiers](docs/work-types.md): tiers, the `!` policy, markers, custom work types, and maintenance of the bundled taxonomy
|
|
212
193
|
- [Labels](docs/labels.md): `sync-labels`, label configuration, the workflow's triggers, and the `label-map.json` schema
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ChangelogDiagnostics } from './buildChangelogEntries.js';
|
|
2
|
+
import type { ReleasedWorkspaceResult } from './types.js';
|
|
3
|
+
/** Attaches a history's diagnostics to a released or skipped result, omitting each empty list. */
|
|
4
|
+
export declare function attachChangelogDiagnostics(result: Pick<ReleasedWorkspaceResult, 'malformedBlocks' | 'policyViolations' | 'undeclaredEntryTypes'>, diagnostics: ChangelogDiagnostics): void;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function attachChangelogDiagnostics(result, diagnostics) {
|
|
2
|
+
if (diagnostics.malformedBlocks.length > 0) {
|
|
3
|
+
result.malformedBlocks = diagnostics.malformedBlocks;
|
|
4
|
+
}
|
|
5
|
+
if (diagnostics.undeclaredEntryTypes.length > 0) {
|
|
6
|
+
result.undeclaredEntryTypes = diagnostics.undeclaredEntryTypes;
|
|
7
|
+
}
|
|
8
|
+
if (diagnostics.policyViolations.length > 0) {
|
|
9
|
+
result.policyViolations = diagnostics.policyViolations;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -105,7 +105,7 @@ Initialize release-kit in the current repository.
|
|
|
105
105
|
By default, scaffolds only the GitHub Actions workflow files.
|
|
106
106
|
|
|
107
107
|
Options:
|
|
108
|
-
--with-config Also scaffold .config/release-kit.config.ts
|
|
108
|
+
--with-config Also scaffold .config/release-kit.config.ts
|
|
109
109
|
--force Overwrite existing files instead of skipping them
|
|
110
110
|
--dry-run Preview changes without writing files
|
|
111
111
|
--help, -h Show this help message
|
|
@@ -195,12 +195,13 @@ function showOverridesValidateHelp() {
|
|
|
195
195
|
Usage: release-kit overrides validate
|
|
196
196
|
|
|
197
197
|
Validate every \`.meta/changelog-overrides.json\` file across the project and per-workspace
|
|
198
|
-
scopes. Reports schema/parse errors, ambiguous-prefix errors,
|
|
198
|
+
scopes. Reports schema/parse errors, ambiguous-prefix errors, conflicting-key errors, and
|
|
199
|
+
stale-key warnings.
|
|
199
200
|
|
|
200
201
|
Exit codes:
|
|
201
202
|
0 Clean — no errors, no stale keys
|
|
202
203
|
1 Stale-key warnings only (no errors)
|
|
203
|
-
2 Schema/parse
|
|
204
|
+
2 Schema/parse, ambiguous-prefix, or conflicting-key errors (errors dominate)
|
|
204
205
|
|
|
205
206
|
Options:
|
|
206
207
|
--config <path> Path to config file (default: .config/release-kit.config.ts)
|
|
@@ -1,26 +1,68 @@
|
|
|
1
|
+
import { type RawCommit } from './enumerateReleaseWindows.js';
|
|
1
2
|
import type { GenerateChangelogOptions } from './generateChangelogs.js';
|
|
2
|
-
import type { ChangelogEntry, ReleaseConfig } from './types.js';
|
|
3
|
+
import type { ChangelogEntry, ChangelogSection, MalformedChangeRecordBlock, PolicyViolation, ReleaseConfig, ReleaseType, UndeclaredEntryType } from './types.js';
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
+
* Strips a section title down to its bare name.
|
|
5
6
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* but downstream consumers that read the raw `group` value (changelog.json titles, the
|
|
10
|
-
* dev-vs-public classifier, the drift test) see the prefix and must strip it. The trailing
|
|
11
|
-
* `stripEmojiPrefix` keeps the helper backward-compatible with consumer overrides written
|
|
12
|
-
* as bare names.
|
|
7
|
+
* A default title carries a leading emoji (e.g. `"🐛 Bug fixes"`), while a consumer's
|
|
8
|
+
* `devOnlySections` or `workTypes` override may be written as a bare name. Comparing both sides
|
|
9
|
+
* through this helper lets the two forms match.
|
|
13
10
|
*/
|
|
14
11
|
export declare function stripGroupDecorations(group: string): string;
|
|
15
12
|
/**
|
|
16
|
-
*
|
|
13
|
+
* Builds structured changelog entries from the release windows of git history, naming the unreleased window `tag`.
|
|
17
14
|
*
|
|
18
|
-
*
|
|
19
|
-
* `
|
|
20
|
-
|
|
15
|
+
* Composes `readReleaseHistory` and `toChangelogEntries` for a caller that knows the tag before it reads. Performs no
|
|
16
|
+
* `changelog.json` I/O; callers persist the entries via `renderChangelogJson`.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildChangelogEntries(config: ReleaseHistoryConfig, tag: string, options: GenerateChangelogOptions): {
|
|
19
|
+
entries: ChangelogEntry[];
|
|
20
|
+
diagnostics: ChangelogDiagnostics;
|
|
21
|
+
};
|
|
22
|
+
/** What reading the unreleased window reports beyond its items. */
|
|
23
|
+
export interface ChangelogDiagnostics {
|
|
24
|
+
malformedBlocks: MalformedChangeRecordBlock[];
|
|
25
|
+
/** Breaking-policy violations of the window's titles and change-record entries. */
|
|
26
|
+
policyViolations: PolicyViolation[];
|
|
27
|
+
undeclaredEntryTypes: UndeclaredEntryType[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Reads a scope's release windows once and returns the changelog items of every window, with what the unreleased
|
|
31
|
+
* window decides: its commits, its bump, and its diagnostics.
|
|
21
32
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
33
|
+
* A commit whose last `change-record` block records entries yields one item per entry; any other commit is
|
|
34
|
+
* classified by its title through `classifyChangelogCommit`. A `release:` or merge subject yields nothing either
|
|
35
|
+
* way. Only the unreleased window records diagnostics, since the released windows were reported when they were
|
|
36
|
+
* prepared.
|
|
25
37
|
*/
|
|
26
|
-
export declare function
|
|
38
|
+
export declare function readReleaseHistory(config: ReleaseHistoryConfig, options: GenerateChangelogOptions): ReleaseHistory;
|
|
39
|
+
/** The configuration that `readReleaseHistory` reads. */
|
|
40
|
+
export type ReleaseHistoryConfig = Pick<ReleaseConfig, 'breakingPolicies' | 'changelogJson' | 'versionPatterns' | 'workTypes'>;
|
|
41
|
+
/** One read of a scope's release windows. */
|
|
42
|
+
export interface ReleaseHistory {
|
|
43
|
+
/** The newest matching tag that HEAD reaches; undefined when none does. */
|
|
44
|
+
previousTag: string | undefined;
|
|
45
|
+
/** Entries of the released windows, newest first; a window that yields no item contributes none. */
|
|
46
|
+
releasedEntries: ChangelogEntry[];
|
|
47
|
+
unreleased: UnreleasedWindowReading;
|
|
48
|
+
}
|
|
49
|
+
/** The unreleased window: its changelog sections and commits, and the bump and diagnostics that they determine. */
|
|
50
|
+
export interface UnreleasedWindowReading {
|
|
51
|
+
/** The highest bump that the window's items call for; undefined when the window yields no item. */
|
|
52
|
+
bump: ReleaseType | undefined;
|
|
53
|
+
/** The window's commits, newest first, without release commits. */
|
|
54
|
+
commits: RawCommit[];
|
|
55
|
+
/** The date of the window's entry, from the time of the read. */
|
|
56
|
+
date: string;
|
|
57
|
+
diagnostics: ChangelogDiagnostics;
|
|
58
|
+
/** The number of commits that yield at least one item. */
|
|
59
|
+
parsedCommitCount: number;
|
|
60
|
+
sections: ChangelogSection[];
|
|
61
|
+
/**
|
|
62
|
+
* Commits that yield no item and that neither an exclusion nor a diagnostic accounts for, newest first; undefined
|
|
63
|
+
* when none.
|
|
64
|
+
*/
|
|
65
|
+
unparseableCommits: RawCommit[] | undefined;
|
|
66
|
+
}
|
|
67
|
+
/** Labels the unreleased window of `history` with `tag` and returns the entries of every window, newest first. */
|
|
68
|
+
export declare function toChangelogEntries(history: ReleaseHistory, tag: string): ChangelogEntry[];
|