@williamthorsen/release-kit 2.3.2 → 4.4.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 (49) hide show
  1. package/CHANGELOG.md +90 -24
  2. package/README.md +123 -173
  3. package/bin/release-kit.js +10 -1
  4. package/cliff.toml.template +13 -12
  5. package/dist/esm/.cache +1 -1
  6. package/dist/esm/bin/release-kit.js +55 -13
  7. package/dist/esm/buildDependencyGraph.d.ts +7 -0
  8. package/dist/esm/buildDependencyGraph.js +59 -0
  9. package/dist/esm/buildReleaseSummary.d.ts +2 -0
  10. package/dist/esm/buildReleaseSummary.js +22 -0
  11. package/dist/esm/commitCommand.d.ts +1 -0
  12. package/dist/esm/commitCommand.js +60 -0
  13. package/dist/esm/createTags.js +5 -13
  14. package/dist/esm/deleteFileIfExists.d.ts +1 -0
  15. package/dist/esm/deleteFileIfExists.js +14 -0
  16. package/dist/esm/determineBumpFromCommits.d.ts +1 -1
  17. package/dist/esm/determineBumpFromCommits.js +2 -2
  18. package/dist/esm/generateChangelogs.d.ts +2 -0
  19. package/dist/esm/generateChangelogs.js +9 -1
  20. package/dist/esm/index.d.ts +5 -1
  21. package/dist/esm/index.js +10 -1
  22. package/dist/esm/init/initCommand.js +4 -2
  23. package/dist/esm/init/scaffold.js +3 -2
  24. package/dist/esm/init/templates.d.ts +1 -0
  25. package/dist/esm/init/templates.js +24 -2
  26. package/dist/esm/loadConfig.js +6 -6
  27. package/dist/esm/parseCommitMessage.d.ts +1 -1
  28. package/dist/esm/parseCommitMessage.js +9 -7
  29. package/dist/esm/prepareCommand.d.ts +1 -0
  30. package/dist/esm/prepareCommand.js +64 -34
  31. package/dist/esm/propagateBumps.d.ts +8 -0
  32. package/dist/esm/propagateBumps.js +54 -0
  33. package/dist/esm/publish.d.ts +1 -0
  34. package/dist/esm/publish.js +6 -3
  35. package/dist/esm/publishCommand.js +15 -9
  36. package/dist/esm/releasePrepare.js +2 -1
  37. package/dist/esm/releasePrepareMono.js +237 -48
  38. package/dist/esm/reportPrepare.js +29 -3
  39. package/dist/esm/stripScope.d.ts +1 -0
  40. package/dist/esm/stripScope.js +24 -0
  41. package/dist/esm/sync-labels/templates.js +1 -1
  42. package/dist/esm/tagCommand.js +11 -6
  43. package/dist/esm/types.d.ts +11 -4
  44. package/dist/esm/validateConfig.js +6 -6
  45. package/dist/esm/version.d.ts +1 -0
  46. package/dist/esm/version.js +4 -0
  47. package/dist/esm/writeSyntheticChangelog.d.ts +9 -0
  48. package/dist/esm/writeSyntheticChangelog.js +27 -0
  49. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -2,6 +2,76 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [release-kit-v4.4.0] - 2026-04-04
6
+
7
+ ### Documentation
8
+
9
+ - #135 release-kit|docs: Refine README to match preflight documentation standard (#138)
10
+
11
+ Restructures the release-kit README to match the documentation standard established by the preflight README (#114). Reorders sections to follow the cross-package convention, converts CLI flag listings from code blocks to tables, adds representative `prepare --dry-run` output to the quick start, and condenses ~90 lines of inline workflow YAML into a summary with an inputs table and trigger examples. Fixes several accuracy gaps found by verifying documentation against source.
12
+
13
+ ### Features
14
+
15
+ - #142 feat: Add --version flag to nmr and release-kit (#143)
16
+
17
+ Adds `--version` / `-V` support to the `nmr` and `release-kit` CLIs, matching the existing `preflight` behavior. Moves the build-time version generation script to the shared `config/` directory so all three packages use a single `generateVersion.ts`.
18
+
19
+ - #150 feat: Detect and report missing build output in bin wrappers (#152)
20
+
21
+ Adds try/catch with `ERR_MODULE_NOT_FOUND` detection to all six bin wrappers across `nmr`, `preflight`, and `release-kit`. Previously, five of the six wrappers used bare `import()` calls that produced cryptic unhandled rejections when `dist/` was missing, and `preflight`'s existing try/catch gave no actionable guidance.
22
+
23
+ ### Refactoring
24
+
25
+ - #88 release-kit|refactor: Extract deleteFileIfExists helper (#136)
26
+
27
+ Replaces the duplicate `deleteTagsFile` and `deleteSummaryFile` functions in `createTags.ts` with a single parameterized `deleteFileIfExists(path)` utility. The new helper lives in its own module and is exported from the package barrel for reuse.
28
+
29
+ - #145 refactor: Extract shared CLI argument-parsing utility into core (#151)
30
+
31
+ Add a schema-driven `parseArgs` function to `@williamthorsen/node-monorepo-core` that handles boolean flags, string flags (both `--flag=value` and `--flag value`), short aliases, positional collection, the `--` delimiter, and unknown-flag errors. Migrate all CLI argument-parsing sites in preflight (3 sites) and release-kit (5 sites) to use it. A companion `translateParseError` helper normalizes internal error messages for consistent user-facing output.
32
+
33
+ ## [release-kit-v4.0.0] - 2026-04-02
34
+
35
+ ### Features
36
+
37
+ - #125 feat: Rename reusable workflows to .reusable.yaml convention (#129)
38
+
39
+ Renames all three reusable GitHub Actions workflow files from the inconsistent `-workflow.yaml`/bare `.yaml` convention to a uniform `.reusable.yaml` suffix. Updates all references across caller workflows, release-kit templates, tests, preflight collection, and documentation. Scaffolds the sync-labels caller workflow and labels file for this repo. Deletes superseded legacy files.
40
+
41
+ ## [release-kit-v3.0.0] - 2026-03-29
42
+
43
+ ### Bug fixes
44
+
45
+ - #68 release-kit|fix: Pass tag pattern to git-cliff based on tagPrefix (#77)
46
+
47
+ Fixes the issue that git-cliff was processing the entire commit history on every run instead of only commits since the last release.
48
+
49
+ Constructs the pattern from `tagPrefix` at invocation time (e.g., `release-kit-v` → `release-kit-v[0-9].*`) and pass it via `--tag-pattern`, which overrides the config file default.
50
+
51
+ - #72 release-kit|fix: Propagate version bumps to workspace dependents (#80)
52
+
53
+ Restructures `releasePrepareMono` from a single-pass loop into a phased pipeline that automatically patch-bumps workspace dependents when a component is released. A reverse dependency graph is built from `workspace:` references in `dependencies` and `peerDependencies`, then BFS propagation walks upward from bumped components to their dependents. Propagated-only components receive synthetic changelog entries instead of git-cliff invocations.
54
+
55
+ ### Features
56
+
57
+ - #73 release-kit|feat!: Support conventional-commit format in commit parsing (#85)
58
+
59
+ Adds support for the conventional commits format (`type(scope): description`) alongside the existing pipe-prefixed format (`scope|type: description`) in release-kit's commit parser. Renames `workspace` to `scope` throughout release-kit types, config, validation, and consumers.
60
+
61
+ - #70 release-kit|feat: Add commit command for local release flow (#89)
62
+
63
+ Adds a `release-kit commit` command that centralizes the release commit step between `prepare` and `tag`. The command reads tag names and a per-component commit summary from temporary files written by `prepare`, stages all changes, and creates a formatted commit. Two new utilities — `stripScope` and `buildReleaseSummary` — support building the commit body by stripping redundant scope indicators and formatting commits under their component headings. The CI workflow is simplified to use `release-kit commit` and `release-kit tag` instead of inline shell logic.
64
+
65
+ - #69 release-kit|feat: Add CI publish workflow with OIDC trusted publishing (#90)
66
+
67
+ Adds automated npm publication via a tag-push-triggered GitHub Actions workflow using OIDC trusted publishing. Extends `release-kit publish` with a `--provenance` flag and `release-kit init` with publish workflow scaffolding.
68
+
69
+ - #91 release-kit|feat: Make --provenance opt-in to support private repos (#94)
70
+
71
+ Adds a `provenance` boolean input (default `false`) to the reusable `publish-workflow.yaml` so private repos using OIDC trusted publishing no longer fail at publish time. The `--provenance` flag is only passed to `release-kit publish` when the caller sets `provenance: true`.
72
+
73
+ Updates the scaffolded `publish.yaml` template to include `provenance: false` with an inline comment guiding public repos to opt in. Expand the `release-kit init` next-steps output with hints about the provenance setting and trusted publisher registration. Set `provenance: true` in this repo's own `publish.yaml` since it is public.
74
+
5
75
  ## [release-kit-v2.3.2] - 2026-03-28
6
76
 
7
77
  ### Bug fixes
@@ -40,8 +110,28 @@ Adds three unit tests to `releasePrepare.unit.test.ts` covering previously untes
40
110
 
41
111
  ## [release-kit-v2.2.0] - 2026-03-27
42
112
 
113
+ ### Dependencies
114
+
115
+ - Root|deps: Add release-kit as root devDependency
116
+
117
+ Make `npx release-kit` and `pnpm exec release-kit` resolve within
118
+ this repo by adding a `workspace:*` dependency that symlinks the bin.
119
+
43
120
  ### Features
44
121
 
122
+ - #23 release-kit|feat: Add sync-labels command (#33)
123
+
124
+ Add a `release-kit sync-labels` command group with three subcommands (`init`, `generate`, `sync`) for declarative GitHub label management in monorepos. Bundle a reusable GitHub Actions workflow and composable label presets with the release-kit package. Introduce a `findPackageRoot` utility to replace fragile hardcoded path resolutions across the codebase.
125
+
126
+ - #34 release-kit|feat: Report up-to-date status for unchanged init files (#35)
127
+
128
+ `release-kit init` now compares existing file content against the default before reporting status. When an existing file is identical to the default (after normalizing trailing whitespace), it reports `✅ (up to date)` instead of the misleading `⚠️ (already exists)`.
129
+
130
+ - Release-workflow|feat: Accept force input
131
+
132
+ Pass `--force` to the prepare command so callers can force a version
133
+ bump even when there are no release-worthy changes.
134
+
45
135
  - #27 release-kit|feat: Auto-detect Prettier for CHANGELOG formatting (#36)
46
136
 
47
137
  When `formatCommand` is not configured, release-kit now auto-detects whether the repo uses Prettier by checking for config files (`.prettierrc*`, `prettier.config.*`) or a `"prettier"` key in root `package.json`. If found, it defaults to `npx prettier --write` on generated files. If not found, formatting is skipped.
@@ -96,30 +186,6 @@ Also adds a `findAllCliffOutputPaths()` test helper that collects the `--output`
96
186
 
97
187
  Replaces the legacy workspace script runner and ~25 root `package.json` scripts with `nmr`, the monorepo's own context-aware script runner. Root scripts are reduced to 4 (`prepare`, `postinstall`, `ci`, `bootstrap`), packages use direct build commands for bootstrap, and release-kit declares tier-3 test overrides for its integration test configs.
98
188
 
99
- ## [release-workflow-v1] - 2026-03-19
100
-
101
- ### Dependencies
102
-
103
- - Root|deps: Add release-kit as root devDependency
104
-
105
- Make `npx release-kit` and `pnpm exec release-kit` resolve within
106
- this repo by adding a `workspace:*` dependency that symlinks the bin.
107
-
108
- ### Features
109
-
110
- - #23 release-kit|feat: Add sync-labels command (#33)
111
-
112
- Add a `release-kit sync-labels` command group with three subcommands (`init`, `generate`, `sync`) for declarative GitHub label management in monorepos. Bundle a reusable GitHub Actions workflow and composable label presets with the release-kit package. Introduce a `findPackageRoot` utility to replace fragile hardcoded path resolutions across the codebase.
113
-
114
- - #34 release-kit|feat: Report up-to-date status for unchanged init files (#35)
115
-
116
- `release-kit init` now compares existing file content against the default before reporting status. When an existing file is identical to the default (after normalizing trailing whitespace), it reports `✅ (up to date)` instead of the misleading `⚠️ (already exists)`.
117
-
118
- - Release-workflow|feat: Accept force input
119
-
120
- Pass `--force` to the prepare command so callers can force a version
121
- bump even when there are no release-worthy changes.
122
-
123
189
  ## [release-kit-v2.1.0] - 2026-03-17
124
190
 
125
191
  ### Features
package/README.md CHANGED
@@ -20,6 +20,36 @@ npx @williamthorsen/release-kit init
20
20
  npx @williamthorsen/release-kit prepare --dry-run
21
21
  ```
22
22
 
23
+ Example output from `prepare --dry-run` in a monorepo:
24
+
25
+ ```
26
+ 🔍 DRY RUN — no files will be modified
27
+
28
+ ── arrays ──────────────────────────────────────
29
+ Found 4 commits since arrays-v1.2.0
30
+ Parsed 3 typed commits
31
+ Bumping versions (minor)...
32
+ 📦 1.2.0 → 1.3.0 (minor)
33
+ [dry-run] Would bump packages/arrays/package.json
34
+ Generating changelogs...
35
+ [dry-run] Would run: npx --yes git-cliff ... --output packages/arrays/CHANGELOG.md
36
+ 🏷️ arrays-v1.3.0
37
+
38
+ ── strings ─────────────────────────────────────
39
+ Found 2 commits since strings-v0.5.1
40
+ Parsed 2 typed commits
41
+ Bumping versions (patch)...
42
+ 📦 0.5.1 → 0.5.2 (patch)
43
+ [dry-run] Would bump packages/strings/package.json
44
+ Generating changelogs...
45
+ [dry-run] Would run: npx --yes git-cliff ... --output packages/strings/CHANGELOG.md
46
+ 🏷️ strings-v0.5.2
47
+
48
+ ✅ Release preparation complete.
49
+ 🏷️ arrays-v1.3.0
50
+ 🏷️ strings-v0.5.2
51
+ ```
52
+
23
53
  That's it for most repos. The CLI auto-discovers workspaces and applies sensible defaults. The bundled `cliff.toml.template` is used automatically — no need to copy it. Customize only what you need via `.config/release-kit.config.ts`.
24
54
 
25
55
  ## How it works
@@ -30,43 +60,20 @@ That's it for most repos. The CLI auto-discovers workspaces and applies sensible
30
60
  4. **Version bump + changelog**: bumps `package.json` versions and generates changelogs via `git-cliff`.
31
61
  5. **Release tags file**: writes computed tags to `tmp/.release-tags` for the release workflow to read when tagging and pushing.
32
62
 
33
- ## CLI reference
34
-
35
- ### `release-kit prepare`
36
-
37
- Run release preparation with automatic workspace discovery.
63
+ ## Commit format
38
64
 
39
- ```
40
- Usage: release-kit prepare [options]
65
+ release-kit parses commits in these formats:
41
66
 
42
- Options:
43
- --dry-run Preview changes without writing files
44
- --bump=major|minor|patch Override the bump type for all components
45
- --only=name1,name2 Only process the named components (monorepo only)
46
- --help, -h Show help
47
67
  ```
48
-
49
- Component names for `--only` match the package directory name (e.g., `arrays`, `release-kit`).
50
-
51
- ### `release-kit init`
52
-
53
- Initialize release-kit in the current repository. By default, scaffolds only the GitHub Actions workflow file. Use `--with-config` to also scaffold configuration files.
54
-
68
+ type: description # e.g., feat: add utility
69
+ scope|type: description # e.g., arrays|feat: add compact function
70
+ type(scope): description # e.g., feat(arrays): add compact function
71
+ type!: description # breaking change (triggers major bump)
72
+ scope|type!: description # scoped breaking change
73
+ type(scope)!: description # conventional scoped breaking change
55
74
  ```
56
- Usage: release-kit init [options]
57
75
 
58
- Options:
59
- --with-config Also scaffold .config/release-kit.config.ts and .config/git-cliff.toml
60
- --force Overwrite existing files instead of skipping them
61
- --dry-run Preview changes without writing files
62
- --help, -h Show help
63
- ```
64
-
65
- Scaffolded files:
66
-
67
- - `.github/workflows/release.yaml` — workflow that delegates to a reusable release workflow
68
- - `.config/release-kit.config.ts` — starter config with commented-out customization examples (with `--with-config`)
69
- - `.config/git-cliff.toml` — copied from the bundled template (with `--with-config`)
76
+ The `scope|type:` format scopes a commit to a specific component in a monorepo. Use `scopeAliases` in your config to map shorthand names to canonical scope names.
70
77
 
71
78
  ## Configuration
72
79
 
@@ -98,14 +105,14 @@ The config file supports both `export default config` and `export const config =
98
105
 
99
106
  ### `ReleaseKitConfig` reference
100
107
 
101
- | Field | Type | Description |
102
- | ------------------ | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
103
- | `cliffConfigPath` | `string` | Explicit path to cliff config. If omitted, resolved automatically: `.config/git-cliff.toml` → `cliff.toml` → bundled template |
104
- | `components` | `ComponentOverride[]` | Override or exclude discovered components (matched by `dir`) |
105
- | `formatCommand` | `string` | Shell command to run after changelog generation; modified file paths are appended as arguments |
106
- | `versionPatterns` | `VersionPatterns` | Rules for which commit types trigger major/minor bumps |
107
- | `workspaceAliases` | `Record<string, string>` | Maps shorthand workspace names to canonical names in commits |
108
- | `workTypes` | `Record<string, WorkTypeConfig>` | Work type definitions, merged with defaults by key |
108
+ | Field | Type | Description |
109
+ | ----------------- | -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
110
+ | `cliffConfigPath` | `string` | Explicit path to cliff config. If omitted, resolved automatically: `.config/git-cliff.toml` → `cliff.toml` → bundled template |
111
+ | `components` | `ComponentOverride[]` | Override or exclude discovered components (matched by `dir`) |
112
+ | `formatCommand` | `string` | Shell command to run after changelog generation; modified file paths are appended as arguments |
113
+ | `versionPatterns` | `VersionPatterns` | Rules for which commit types trigger major/minor bumps |
114
+ | `scopeAliases` | `Record<string, string>` | Maps shorthand scope names to canonical names in commits |
115
+ | `workTypes` | `Record<string, WorkTypeConfig>` | Work type definitions, merged with defaults by key |
109
116
 
110
117
  All fields are optional.
111
118
 
@@ -129,7 +136,7 @@ interface VersionPatterns {
129
136
  }
130
137
  ```
131
138
 
132
- Default: `{ major: ['!'], minor: ['feat', 'feature'] }`
139
+ Default: `{ major: ['!'], minor: ['feat'] }`
133
140
 
134
141
  ### Default work types
135
142
 
@@ -148,149 +155,70 @@ Default: `{ major: ['!'], minor: ['feat', 'feature'] }`
148
155
 
149
156
  Work types from your config are merged with these defaults by key — your entries override or extend, they don't replace the full set.
150
157
 
151
- ## Commit format
158
+ ## CLI reference
152
159
 
153
- release-kit parses commits in these formats:
160
+ ### Global options
154
161
 
155
- ```
156
- type: description # e.g., feat: add utility
157
- type(scope): description # e.g., fix(parser): handle edge case
158
- workspace|type: description # e.g., arrays|feat: add compact function
159
- !type: description # breaking change (triggers major bump)
160
- ```
162
+ | Flag | Description |
163
+ | ----------------- | ------------------- |
164
+ | `--help`, `-h` | Show help message |
165
+ | `--version`, `-V` | Show version number |
161
166
 
162
- The `workspace|type:` format scopes a commit to a specific workspace in a monorepo. Use `workspaceAliases` in your config to map shorthand names to canonical workspace names.
167
+ ### `release-kit prepare`
163
168
 
164
- ## Using `component()` for manual configuration
169
+ Run release preparation with automatic workspace discovery.
165
170
 
166
- If you need to build a `MonorepoReleaseConfig` manually (e.g., for the legacy script-based approach), the exported `component()` helper creates a `ComponentConfig` from a workspace-relative path:
171
+ | Flag | Description |
172
+ | ---------------------------- | ---------------------------------------------------------------- |
173
+ | `--dry-run` | Preview changes without writing files |
174
+ | `--bump=major\|minor\|patch` | Override the bump type for all components |
175
+ | `--force` | Bypass the "no commits since last tag" check (requires `--bump`) |
176
+ | `--only=name1,name2` | Only process the named components (monorepo only) |
177
+ | `--help`, `-h` | Show help |
167
178
 
168
- ```typescript
169
- import { component } from '@williamthorsen/release-kit';
179
+ Component names for `--only` match the package directory name (e.g., `arrays`, `release-kit`).
170
180
 
171
- // Accepts the full workspace-relative path
172
- component('packages/arrays');
173
- // => {
174
- // dir: 'arrays',
175
- // tagPrefix: 'arrays-v',
176
- // packageFiles: ['packages/arrays/package.json'],
177
- // changelogPaths: ['packages/arrays'],
178
- // paths: ['packages/arrays/**'],
179
- // }
180
- ```
181
+ ### `release-kit init`
181
182
 
182
- The `dir` field is derived from `path.basename()`, so `packages/arrays` and `libs/arrays` both produce `dir: 'arrays'`. The `tagPrefix` is always `${dir}-v` it cannot be customized.
183
+ Initialize release-kit in the current repository. By default, scaffolds only the GitHub Actions workflow file. Use `--with-config` to also scaffold configuration files.
183
184
 
184
- ## GitHub Actions workflow
185
+ | Flag | Description |
186
+ | --------------- | -------------------------------------------------------------------------- |
187
+ | `--with-config` | Also scaffold `.config/release-kit.config.ts` and `.config/git-cliff.toml` |
188
+ | `--force` | Overwrite existing files instead of skipping them |
189
+ | `--dry-run` | Preview changes without writing files |
190
+ | `--help`, `-h` | Show help |
185
191
 
186
- The `init` command scaffolds a workflow that delegates to a reusable release workflow. For repos that need a self-contained workflow:
187
-
188
- ### Monorepo
189
-
190
- ```yaml
191
- name: Release
192
-
193
- on:
194
- workflow_dispatch:
195
- inputs:
196
- only:
197
- description: 'Components to release (comma-separated, leave empty for all)'
198
- required: false
199
- type: string
200
- bump:
201
- description: 'Override bump type (leave empty to auto-detect)'
202
- required: false
203
- type: choice
204
- options:
205
- - ''
206
- - patch
207
- - minor
208
- - major
209
-
210
- permissions:
211
- contents: write
212
-
213
- jobs:
214
- release:
215
- runs-on: ubuntu-latest
216
- steps:
217
- - uses: actions/checkout@v4
218
- with:
219
- fetch-depth: 0
220
- token: ${{ secrets.GITHUB_TOKEN }}
221
-
222
- - uses: actions/setup-node@v4
223
- with:
224
- node-version: '24'
225
-
226
- - name: Run release preparation
227
- run: |
228
- ARGS=""
229
- if [ -n "${{ inputs.only }}" ]; then
230
- ARGS="$ARGS --only=${{ inputs.only }}"
231
- fi
232
- if [ -n "${{ inputs.bump }}" ]; then
233
- ARGS="$ARGS --bump=${{ inputs.bump }}"
234
- fi
235
- npx @williamthorsen/release-kit prepare $ARGS
236
-
237
- - name: Check for changes
238
- id: check
239
- run: |
240
- if git diff --quiet; then
241
- echo "changed=false" >> "$GITHUB_OUTPUT"
242
- echo "No release-worthy changes found."
243
- else
244
- echo "changed=true" >> "$GITHUB_OUTPUT"
245
- fi
246
-
247
- - name: Read release tags
248
- if: steps.check.outputs.changed == 'true'
249
- id: tags
250
- run: |
251
- TAGS=$(cat tmp/.release-tags | tr '\n' ' ')
252
- echo "tags=$TAGS" >> "$GITHUB_OUTPUT"
253
- echo "Releasing: $TAGS"
254
-
255
- - name: Commit, tag, and push
256
- if: steps.check.outputs.changed == 'true'
257
- run: |
258
- git config user.name "github-actions[bot]"
259
- git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
260
- git add -A
261
- git commit -m "release: ${{ steps.tags.outputs.tags }}"
262
- for TAG in ${{ steps.tags.outputs.tags }}; do
263
- git tag "$TAG"
264
- done
265
- git push origin main ${{ steps.tags.outputs.tags }}
266
- ```
192
+ Scaffolded files:
267
193
 
268
- ### Single-package repo
194
+ - `.github/workflows/release.yaml` — workflow that delegates to a reusable release workflow
195
+ - `.config/release-kit.config.ts` — starter config with commented-out customization examples (with `--with-config`)
196
+ - `.config/git-cliff.toml` — copied from the bundled template (with `--with-config`)
269
197
 
270
- The same workflow without the `only` input. Replace the prepare step with:
198
+ ### `release-kit sync-labels`
271
199
 
272
- ```yaml
273
- - name: Run release preparation
274
- run: |
275
- ARGS=""
276
- if [ -n "${{ inputs.bump }}" ]; then
277
- ARGS="--bump=${{ inputs.bump }}"
278
- fi
279
- npx @williamthorsen/release-kit prepare $ARGS
280
- ```
200
+ Manage GitHub label definitions via config-driven YAML files.
281
201
 
282
- And the tag step with:
202
+ | Subcommand | Description | Flags |
203
+ | ---------- | -------------------------------------------------------------- | ---------------------- |
204
+ | `init` | Scaffold config, caller workflow, and generate labels | `--dry-run`, `--force` |
205
+ | `generate` | Regenerate `.github/labels.yaml` from config | — |
206
+ | `sync` | Trigger the `sync-labels` GitHub Actions workflow via `gh` CLI | — |
283
207
 
284
- ```yaml
285
- - name: Read release tag
286
- if: steps.check.outputs.changed == 'true'
287
- id: tags
288
- run: |
289
- TAG=$(cat tmp/.release-tags)
290
- echo "tag=$TAG" >> "$GITHUB_OUTPUT"
291
- ```
208
+ `init` scaffolds `.config/sync-labels.config.ts` with auto-detected workspace scope labels and a `.github/workflows/sync-labels.yaml` caller workflow, then generates `.github/labels.yaml`. `generate` reads the config and writes `.github/labels.yaml`. `sync` triggers the workflow remotely — it requires the `gh` CLI and an existing workflow file.
209
+
210
+ ## GitHub Actions workflow
211
+
212
+ The `init` command scaffolds a release workflow at `.github/workflows/release.yaml` that delegates to a reusable release workflow. The scaffolded workflow accepts these inputs:
213
+
214
+ | Input | Type | Description |
215
+ | ------ | ------ | ------------------------------------------------------------------- |
216
+ | `only` | string | Components to release (comma-separated, leave empty for all) |
217
+ | `bump` | choice | Override bump type: `patch`, `minor`, `major` (empty = auto-detect) |
292
218
 
293
- ## Triggering a release
219
+ For repos that need a self-contained workflow instead of the reusable one, the scaffolded file can be expanded. The key steps are: checkout with full history (`fetch-depth: 0`), run `release-kit prepare` with optional `--only` and `--bump` flags, check for changes, read tags from `tmp/.release-tags`, then commit, tag, and push.
220
+
221
+ ### Triggering a release
294
222
 
295
223
  ```sh
296
224
  # All components
@@ -305,12 +233,14 @@ Or use the GitHub UI: Actions > Release > Run workflow.
305
233
 
306
234
  ## cliff.toml setup
307
235
 
308
- The package includes a bundled `cliff.toml.template` that is used automatically when no custom config is found. The resolution order is:
236
+ The package includes a bundled `cliff.toml.template` that is used automatically when no custom config is found. The resolution order:
309
237
 
310
- 1. Explicit `cliffConfigPath` in `.config/release-kit.config.ts`
311
- 2. `.config/git-cliff.toml`
312
- 3. `cliff.toml` (repo root)
313
- 4. Bundled `cliff.toml.template` (automatic fallback)
238
+ | Priority | Path | Notes |
239
+ | -------- | ----------------------------- | ----------------------------------------------- |
240
+ | 1 | `cliffConfigPath` in config | Explicit path, returned without existence check |
241
+ | 2 | `.config/git-cliff.toml` | Project-level override |
242
+ | 3 | `cliff.toml` | Repo root fallback |
243
+ | 4 | Bundled `cliff.toml.template` | Automatic fallback |
314
244
 
315
245
  The bundled template provides a generic git-cliff configuration that:
316
246
 
@@ -327,6 +257,26 @@ This package shells out to two external tools:
327
257
  - **`git`** — must be available on `PATH`. Used to find tags and retrieve commit history.
328
258
  - **`git-cliff`** — automatically downloaded and cached via `npx` on first invocation. No need to install it as a dev dependency.
329
259
 
260
+ ## Using `component()` for manual configuration
261
+
262
+ If you need to build a `MonorepoReleaseConfig` manually (e.g., for the legacy script-based approach), the exported `component()` helper creates a `ComponentConfig` from a workspace-relative path:
263
+
264
+ ```typescript
265
+ import { component } from '@williamthorsen/release-kit';
266
+
267
+ // Accepts the full workspace-relative path
268
+ component('packages/arrays');
269
+ // => {
270
+ // dir: 'arrays',
271
+ // tagPrefix: 'arrays-v',
272
+ // packageFiles: ['packages/arrays/package.json'],
273
+ // changelogPaths: ['packages/arrays'],
274
+ // paths: ['packages/arrays/**'],
275
+ // }
276
+ ```
277
+
278
+ The `dir` field is derived from `path.basename()`, so `packages/arrays` and `libs/arrays` both produce `dir: 'arrays'`. The `tagPrefix` is always `${dir}-v` — it cannot be customized.
279
+
330
280
  ## Legacy script-based approach
331
281
 
332
282
  The CLI-driven approach is recommended for new setups. The script-based approach (using `runReleasePrepare` with a manually maintained config) is still supported for backward compatibility.
@@ -1,2 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import('../dist/esm/bin/release-kit.js');
2
+ try {
3
+ await import('../dist/esm/bin/release-kit.js');
4
+ } catch (error) {
5
+ if (error.code === 'ERR_MODULE_NOT_FOUND') {
6
+ process.stderr.write('release-kit: build output not found — run `pnpm run build` first\n');
7
+ } else {
8
+ process.stderr.write(`release-kit: failed to load: ${error.message}\n`);
9
+ }
10
+ process.exit(1);
11
+ }
@@ -45,19 +45,20 @@ commit_preprocessors = [
45
45
  { pattern = '^[A-Z]+-\d+\s+', replace = "" },
46
46
  ]
47
47
  # regex for parsing and grouping commits
48
- # Supports both "type: description" and "workspace|type: description" formats
48
+ # Supports "type: desc", "scope|type: desc", and "type(scope): desc" formats
49
49
  commit_parsers = [
50
- { message = "^.*\\|?fix(!)?:", group = "Bug fixes" },
51
- { message = "^.*\\|?feat(!)?:", group = "Features" },
52
- { message = "^.*\\|?feature(!)?:", group = "Features" },
53
- { message = "^.*\\|?internal(!)?:", group = "Internal" },
54
- { message = "^.*\\|?refactor(!)?:", group = "Refactoring" },
55
- { message = "^.*\\|?tests?(!)?:", group = "Tests" },
56
- { message = "^.*\\|?tooling(!)?:", group = "Tooling" },
57
- { message = "^.*\\|?ci(!)?:", group = "CI" },
58
- { message = "^.*\\|?deps?(!)?:", group = "Dependencies" },
59
- { message = "^.*\\|?docs?(!)?:", group = "Documentation" },
60
- { message = "^.*\\|?fmt(!)?:", group = "Formatting" },
50
+ { message = "^(.*\\|)?fix(\\(.*\\))?(!)?:", group = "Bug fixes" },
51
+ { message = "^(.*\\|)?bugfix(\\(.*\\))?(!)?:", group = "Bug fixes" },
52
+ { message = "^(.*\\|)?feat(\\(.*\\))?(!)?:", group = "Features" },
53
+ { message = "^(.*\\|)?feature(\\(.*\\))?(!)?:", group = "Features" },
54
+ { message = "^(.*\\|)?internal(\\(.*\\))?(!)?:", group = "Internal" },
55
+ { message = "^(.*\\|)?refactor(\\(.*\\))?(!)?:", group = "Refactoring" },
56
+ { message = "^(.*\\|)?tests?(\\(.*\\))?(!)?:", group = "Tests" },
57
+ { message = "^(.*\\|)?tooling(\\(.*\\))?(!)?:", group = "Tooling" },
58
+ { message = "^(.*\\|)?ci(\\(.*\\))?(!)?:", group = "CI" },
59
+ { message = "^(.*\\|)?deps?(\\(.*\\))?(!)?:", group = "Dependencies" },
60
+ { message = "^(.*\\|)?docs?(\\(.*\\))?(!)?:", group = "Documentation" },
61
+ { message = "^(.*\\|)?fmt(\\(.*\\))?(!)?:", group = "Formatting" },
61
62
  ]
62
63
  # protect breaking changes from being skipped due to matching a skipping commit_parser
63
64
  protect_breaking_commits = false
package/dist/esm/.cache CHANGED
@@ -1 +1 @@
1
- 894421aa6cf2eb13518310f0bb75d5751a6a68ae1fcb068600b25ed30eea9b67
1
+ 89fa3a396cfa2f4f2cf5ce8827dbe171e310519ab3faa7325268a87693116335