@williamthorsen/release-kit 0.2.3 → 1.0.1

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/CHANGELOG.md CHANGED
@@ -2,7 +2,51 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- ## [release-kit-v0.2.3] - 2026-03-10
5
+ ## [release-kit-v1.0.1] - 2026-03-12
6
+
7
+ ### Bug fixes
8
+
9
+ - #34 release-kit|fix: Fix failure to find consumer's config (#35)
10
+
11
+ Resolves the config file path to an absolute path using `process.cwd()` before passing it to both `existsSync` and `jiti.import()`. Previously, `jiti.import()` received a bare relative path which it resolved against `import.meta.url` (the package's install location), making it impossible for consumers to load their config files. Also fixes root tsconfig includes to cover `.config/` and removes a stale duplicate comment.
12
+
13
+ ## [release-kit-v1.0.0] - 2026-03-12
14
+
15
+ ### Features
16
+
17
+ - #28 release-kit|feat!: Migrate to CLI-driven release preparation with auto-discovery (#31)
18
+
19
+ Replaces release-kit's script-based release preparation with a self-contained CLI (`npx @williamthorsen/release-kit prepare`) that auto-discovers workspaces from `pnpm-workspace.yaml`. Adds workspace auto-discovery, TypeScript config loading via jiti, config validation, and a `component()` factory that accepts full workspace-relative paths. Refactors the type system: `WorkTypeConfig` becomes a record keyed by type name, version-bump rules move to a separate `VersionPatterns` structure, and `ComponentConfig` gains a `dir` field for canonical directory identity.
20
+
21
+ ### Refactoring
22
+
23
+ - #28 release-kit|refactor: Adjust location of config & tags file
24
+
25
+ ### Tooling
26
+
27
+ - #28 release-kit|tooling: Remove legacy release-kit scripts
28
+
29
+ ## [release-kit-v0.3.0] - 2026-03-11
30
+
31
+ ### Features
32
+
33
+ - Release-kit|feat: Extract CLI runner into release-kit and co-locate scripts with workflow
34
+
35
+ Move release script logic (arg parsing, validation, component filtering) into a reusable `runReleasePrepare` function in the release-kit package. Consuming repos now provide only their config and call `runReleasePrepare(config)`.
36
+
37
+ Relocate release-prepare.ts and release.config.ts from scripts/ to .github/scripts/ so they live alongside the workflow they serve.
38
+
39
+ - #20 release-kit|feat: Add release-kit init CLI command for automated repo setup (#22)
40
+
41
+ Add an interactive `npx release-kit init` CLI command that checks repo eligibility, detects monorepo vs single-package layout, scaffolds workflow/scripts/config files, and updates `package.json` with release scripts.
42
+
43
+ Also expand `runReleasePrepare` to polymorphically handle both `MonorepoReleaseConfig` and `ReleaseConfig`, and update the esbuild plugin to preserve shebangs during compilation.
44
+
45
+ - #24 release-kit|feat: Return computed tags from release prepare and write .release-tags (#27)
46
+
47
+ `releasePrepare` and `releasePrepareMono` now return `string[]` of computed tag names instead of `void`. `runReleasePrepare` writes these tags to a `.release-tags` file (one tag per line) so the CI workflow can read them instead of independently deriving tag names from `git diff`. In dry-run mode the file is not written. This makes `tagPrefix` the single source of truth for tag names, eliminating the mismatch between TypeScript-computed tags and workflow-derived tags.
48
+
49
+ ## [strings-v3.1.1] - 2026-03-10
6
50
 
7
51
  ### Tooling
8
52
 
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Version-bumping and changelog-generation toolkit for release workflows.
4
4
 
5
- This package extracts the shared release-preparation logic from the `skypilot-site` and `devtools/afg` repositories into a reusable library. It provides functions for parsing commits, determining version bumps, updating `package.json` files, and generating changelogs with `git-cliff`.
5
+ 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 with `git-cliff`.
6
6
 
7
7
  ## Installation
8
8
 
@@ -12,246 +12,193 @@ pnpm add -D @williamthorsen/release-kit git-cliff
12
12
 
13
13
  ## Quick start
14
14
 
15
- 1. Install `@williamthorsen/release-kit` and `git-cliff` as dev dependencies
16
- 2. Create `scripts/release-prepare.ts` and `scripts/release.config.ts` (see examples below)
17
- 3. Add `release:prepare` scripts to `package.json`
18
- 4. Copy `cliff.toml.template` to your repo root as `cliff.toml`
19
- 5. Add the GitHub Actions release workflow
15
+ ```bash
16
+ # 1. Set up release-kit in your repo (scaffolds workflow + optional config)
17
+ npx @williamthorsen/release-kit init
20
18
 
21
- ## Configuration
19
+ # 2. Preview what a release would do
20
+ npx @williamthorsen/release-kit prepare --dry-run
22
21
 
23
- ### Single-package repo
22
+ # 3. Copy cliff.toml.template to your repo root (if init didn't create one)
23
+ cp node_modules/@williamthorsen/release-kit/cliff.toml.template cliff.toml
24
+ ```
24
25
 
25
- Create `scripts/release.config.ts`:
26
+ That's it for most repos. The CLI auto-discovers workspaces and applies sensible defaults. Customize only what you need via `.config/release-kit.config.ts`.
26
27
 
27
- ```typescript
28
- import { DEFAULT_WORK_TYPES } from '@williamthorsen/release-kit';
29
- import type { ReleaseConfig } from '@williamthorsen/release-kit';
30
-
31
- export const config: ReleaseConfig = {
32
- tagPrefix: 'v',
33
- packageFiles: ['package.json'],
34
- changelogPaths: ['.'],
35
- workTypes: [...DEFAULT_WORK_TYPES],
36
- formatCommand: 'pnpm run fmt',
37
- };
38
- ```
28
+ ## How it works
39
29
 
40
- ### Monorepo
30
+ 1. **Workspace discovery**: reads `pnpm-workspace.yaml` and resolves its `packages` globs to find workspace directories. Each directory containing a `package.json` becomes a component. If no workspace file is found, the repo is treated as a single-package project.
31
+ 2. **Config loading**: loads `.config/release-kit.config.ts` (if present) via [jiti](https://github.com/unjs/jiti) and merges it with discovered defaults.
32
+ 3. **Commit analysis**: for each component, finds commits since the last version tag, parses them for type and scope, and determines the appropriate version bump.
33
+ 4. **Version bump + changelog**: bumps `package.json` versions and generates changelogs via `git-cliff`.
34
+ 5. **Release tags file**: writes computed tags to `/tmp/release-kit/.release-tags` for CI consumption.
41
35
 
42
- Create `scripts/release.config.ts`:
36
+ ## CLI reference
43
37
 
44
- ```typescript
45
- import { DEFAULT_WORK_TYPES } from '@williamthorsen/release-kit';
46
- import type { MonorepoReleaseConfig } from '@williamthorsen/release-kit';
38
+ ### `release-kit prepare`
47
39
 
48
- function component(dir: string) {
49
- return {
50
- tagPrefix: `${dir}-v`,
51
- packageFiles: [`packages/${dir}/package.json`],
52
- changelogPaths: [`packages/${dir}`],
53
- paths: [`packages/${dir}/**`],
54
- };
55
- }
40
+ Run release preparation with automatic workspace discovery.
56
41
 
57
- export const config: MonorepoReleaseConfig = {
58
- components: [component('my-lib'), component('my-cli')],
59
- workTypes: [...DEFAULT_WORK_TYPES],
60
- formatCommand: 'pnpm run fmt',
61
- };
62
42
  ```
43
+ Usage: release-kit prepare [options]
63
44
 
64
- ### ReleaseConfig reference
45
+ Options:
46
+ --dry-run Preview changes without writing files
47
+ --bump=major|minor|patch Override the bump type for all components
48
+ --only=name1,name2 Only process the named components (monorepo only)
49
+ --help, -h Show help
50
+ ```
65
51
 
66
- | Field | Type | Required | Description |
67
- | ----------------- | ------------------ | -------- | ------------------------------------------------------------------ |
68
- | `tagPrefix` | `string` | Yes | Git tag prefix for version tags (e.g., `'v'`) |
69
- | `packageFiles` | `string[]` | Yes | Paths to `package.json` files to bump |
70
- | `changelogPaths` | `string[]` | Yes | Directories in which to generate changelogs |
71
- | `workTypes` | `WorkTypeConfig[]` | Yes | Ordered list of work type configurations for commit categorization |
72
- | `formatCommand` | `string` | No | Shell command to run after changelog generation |
73
- | `cliffConfigPath` | `string` | No | Path to `cliff.toml` (defaults to `'cliff.toml'`) |
52
+ Component names for `--only` match the package directory name (e.g., `arrays`, `release-kit`).
74
53
 
75
- ### MonorepoReleaseConfig reference
54
+ **Self-hosting note**: in a repo where `release-kit` is a workspace package (e.g., this monorepo), `npx` and `pnpm exec` may not resolve the binary. Run the built entry point directly:
76
55
 
77
- | Field | Type | Required | Description |
78
- | --------------- | ------------------- | -------- | ----------------------------------------------------- |
79
- | `components` | `ComponentConfig[]` | Yes | Per-component config (tagPrefix, packageFiles, paths) |
80
- | `workTypes` | `WorkTypeConfig[]` | Yes | Shared work type configurations |
81
- | `formatCommand` | `string` | No | Shell command to run after changelog generation |
56
+ ```bash
57
+ node packages/release-kit/dist/esm/bin/release-kit.js prepare --dry-run
58
+ ```
82
59
 
83
- ## Release script
60
+ ### `release-kit init`
84
61
 
85
- Create `scripts/release-prepare.ts`:
62
+ Initialize release-kit in the current repository. Scaffolds a GitHub Actions workflow and an optional config file.
86
63
 
87
- ### Single-package version
64
+ ```
65
+ Usage: release-kit init [options]
88
66
 
89
- ```typescript
90
- import { releasePrepare } from '@williamthorsen/release-kit';
91
- import type { ReleaseType } from '@williamthorsen/release-kit';
92
- import { config } from './release.config.ts';
67
+ Options:
68
+ --dry-run Preview changes without writing files
69
+ --help, -h Show help
70
+ ```
93
71
 
94
- const VALID_BUMP_TYPES: readonly string[] = ['major', 'minor', 'patch'];
95
-
96
- function parseArgs(): { dryRun: boolean; bumpOverride?: ReleaseType } {
97
- const args = process.argv.slice(2);
98
- let dryRun = false;
99
- let bumpOverride: ReleaseType | undefined;
100
-
101
- for (const arg of args) {
102
- if (arg === '--dry-run') dryRun = true;
103
- else if (arg.startsWith('--bump=')) {
104
- const value = arg.slice('--bump='.length);
105
- if (!VALID_BUMP_TYPES.includes(value)) {
106
- console.error(`Invalid bump type "${value}". Must be: ${VALID_BUMP_TYPES.join(', ')}`);
107
- process.exit(1);
108
- }
109
- bumpOverride = value as ReleaseType;
110
- }
111
- }
112
-
113
- return { dryRun, bumpOverride };
114
- }
72
+ Scaffolded files:
115
73
 
116
- const { dryRun, bumpOverride } = parseArgs();
117
- releasePrepare(config, { dryRun, ...(bumpOverride ? { bumpOverride } : {}) });
118
- ```
74
+ - `.config/release-kit.config.ts` starter config with commented-out customization examples
75
+ - `.github/workflows/release.yaml` workflow that delegates to a reusable release workflow
76
+ - `cliff.toml` — copied from the bundled template (prompted if missing)
119
77
 
120
- ### Monorepo version
78
+ ## Configuration
79
+
80
+ Configuration is optional. The CLI works out of the box by auto-discovering workspaces and applying defaults. Create `.config/release-kit.config.ts` only when you need to customize behavior.
81
+
82
+ ### Config file
121
83
 
122
84
  ```typescript
123
- import { releasePrepareMono } from '@williamthorsen/release-kit';
124
- import type { ReleaseType } from '@williamthorsen/release-kit';
125
- import { config } from './release.config.ts';
85
+ import type { ReleaseKitConfig } from '@williamthorsen/release-kit';
126
86
 
127
- const VALID_BUMP_TYPES: readonly string[] = ['major', 'minor', 'patch'];
128
-
129
- function parseArgs(): { dryRun: boolean; bumpOverride?: ReleaseType; only?: string[] } {
130
- const args = process.argv.slice(2);
131
- let dryRun = false;
132
- let bumpOverride: ReleaseType | undefined;
133
- let only: string[] | undefined;
134
-
135
- for (const arg of args) {
136
- if (arg === '--dry-run') dryRun = true;
137
- else if (arg.startsWith('--bump=')) {
138
- const value = arg.slice('--bump='.length);
139
- if (!VALID_BUMP_TYPES.includes(value)) {
140
- console.error(`Invalid bump type "${value}". Must be: ${VALID_BUMP_TYPES.join(', ')}`);
141
- process.exit(1);
142
- }
143
- bumpOverride = value as ReleaseType;
144
- } else if (arg.startsWith('--only=')) {
145
- only = arg.slice('--only='.length).split(',');
146
- }
147
- }
148
-
149
- return { dryRun, bumpOverride, only };
150
- }
87
+ const config: ReleaseKitConfig = {
88
+ // Exclude a component from release processing
89
+ components: [{ dir: 'internal-tools', shouldExclude: true }],
90
+
91
+ // Run a formatter after changelog generation
92
+ formatCommand: 'pnpm run fmt',
151
93
 
152
- const { dryRun, bumpOverride, only } = parseArgs();
94
+ // Override the default version patterns
95
+ versionPatterns: { major: ['!'], minor: ['feat', 'feature'] },
153
96
 
154
- let effectiveConfig = config;
155
- if (only) {
156
- const filtered = config.components.filter((c) => {
157
- const name = c.tagPrefix.replace(/-v$/, '');
158
- return only.includes(name);
159
- });
160
- effectiveConfig = { ...config, components: filtered };
161
- }
97
+ // Add or override work types (merged with defaults by key)
98
+ workTypes: { perf: { header: 'Performance' } },
99
+ };
162
100
 
163
- releasePrepareMono(effectiveConfig, { dryRun, ...(bumpOverride ? { bumpOverride } : {}) });
101
+ export default config;
164
102
  ```
165
103
 
166
- ### package.json scripts
104
+ The config file supports both `export default config` and `export const config = { ... }`.
105
+
106
+ ### `ReleaseKitConfig` reference
107
+
108
+ | Field | Type | Description |
109
+ | ------------------ | -------------------------------- | ------------------------------------------------------------ |
110
+ | `cliffConfigPath` | `string` | Path to `cliff.toml` (defaults to `'cliff.toml'`) |
111
+ | `components` | `ComponentOverride[]` | Override or exclude discovered components (matched by `dir`) |
112
+ | `formatCommand` | `string` | Shell command to run after changelog generation |
113
+ | `versionPatterns` | `VersionPatterns` | Rules for which commit types trigger major/minor bumps |
114
+ | `workspaceAliases` | `Record<string, string>` | Maps shorthand workspace names to canonical names in commits |
115
+ | `workTypes` | `Record<string, WorkTypeConfig>` | Work type definitions, merged with defaults by key |
116
+
117
+ All fields are optional.
118
+
119
+ ### `ComponentOverride`
167
120
 
168
- ```json
169
- {
170
- "scripts": {
171
- "release:prepare": "tsx scripts/release-prepare.ts",
172
- "release:prepare:dry": "tsx scripts/release-prepare.ts --dry-run"
173
- }
121
+ ```typescript
122
+ interface ComponentOverride {
123
+ dir: string; // Package directory name (e.g., 'arrays')
124
+ tagPrefix?: string; // Custom git tag prefix (defaults to '${dir}-v')
125
+ shouldExclude?: boolean; // If true, exclude from release processing
174
126
  }
175
127
  ```
176
128
 
177
- ## GitHub Actions workflow
129
+ ### `VersionPatterns`
178
130
 
179
- ### Single-package repo
131
+ Defines which commit types trigger major or minor bumps. Any recognized type not listed defaults to a patch bump.
180
132
 
181
- ```yaml
182
- # .github/workflows/release.yaml
183
- name: Release
133
+ ```typescript
134
+ interface VersionPatterns {
135
+ major: string[]; // Patterns triggering a major bump ('!' = any breaking change)
136
+ minor: string[]; // Commit types triggering a minor bump
137
+ }
138
+ ```
184
139
 
185
- on:
186
- workflow_dispatch:
187
- inputs:
188
- bump:
189
- description: 'Override bump type (leave empty to auto-detect)'
190
- required: false
191
- type: choice
192
- options:
193
- - ''
194
- - patch
195
- - minor
196
- - major
140
+ Default: `{ major: ['!'], minor: ['feat', 'feature'] }`
197
141
 
198
- permissions:
199
- contents: write
142
+ ### Default work types
200
143
 
201
- jobs:
202
- release:
203
- runs-on: ubuntu-latest
204
- steps:
205
- - uses: actions/checkout@v4
206
- with:
207
- fetch-depth: 0
208
- token: ${{ secrets.GITHUB_TOKEN }}
144
+ | Key | Header | Aliases |
145
+ | ---------- | ------------- | --------- |
146
+ | `fix` | Bug fixes | `bugfix` |
147
+ | `feat` | Features | `feature` |
148
+ | `internal` | Internal | |
149
+ | `refactor` | Refactoring | |
150
+ | `tests` | Tests | `test` |
151
+ | `tooling` | Tooling | |
152
+ | `ci` | CI | |
153
+ | `deps` | Dependencies | `dep` |
154
+ | `docs` | Documentation | `doc` |
155
+ | `fmt` | Formatting | |
209
156
 
210
- - uses: pnpm/action-setup@v4
157
+ Work types from your config are merged with these defaults by key — your entries override or extend, they don't replace the full set.
211
158
 
212
- - uses: actions/setup-node@v4
213
- with:
214
- node-version: '24'
215
- cache: 'pnpm'
159
+ ## Commit format
216
160
 
217
- - run: pnpm install
161
+ release-kit parses commits in these formats:
218
162
 
219
- - name: Run release preparation
220
- id: prepare
221
- run: |
222
- ARGS=""
223
- if [ -n "${{ inputs.bump }}" ]; then
224
- ARGS="--bump=${{ inputs.bump }}"
225
- fi
226
- pnpm run release:prepare $ARGS
227
- VERSION=$(node -p "require('./package.json').version")
228
- echo "version=$VERSION" >> "$GITHUB_OUTPUT"
163
+ ```
164
+ type: description # e.g., feat: add utility
165
+ type(scope): description # e.g., fix(parser): handle edge case
166
+ workspace|type: description # e.g., arrays|feat: add compact function
167
+ !type: description # breaking change (triggers major bump)
168
+ ```
229
169
 
230
- - name: Check for changes
231
- id: check
232
- run: |
233
- if git diff --quiet; then
234
- echo "changed=false" >> "$GITHUB_OUTPUT"
235
- echo "No release-worthy changes found."
236
- else
237
- echo "changed=true" >> "$GITHUB_OUTPUT"
238
- fi
170
+ 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.
239
171
 
240
- - name: Commit, tag, and push
241
- if: steps.check.outputs.changed == 'true'
242
- run: |
243
- git config user.name "github-actions[bot]"
244
- git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
245
- git add -A
246
- git commit -m "release: v${{ steps.prepare.outputs.version }}"
247
- git tag "v${{ steps.prepare.outputs.version }}"
248
- git push origin main "v${{ steps.prepare.outputs.version }}"
172
+ ## Using `component()` for manual configuration
173
+
174
+ 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:
175
+
176
+ ```typescript
177
+ import { component } from '@williamthorsen/release-kit';
178
+
179
+ // Accepts the full workspace-relative path
180
+ component('packages/arrays');
181
+ // => {
182
+ // dir: 'arrays',
183
+ // tagPrefix: 'arrays-v',
184
+ // packageFiles: ['packages/arrays/package.json'],
185
+ // changelogPaths: ['packages/arrays'],
186
+ // paths: ['packages/arrays/**'],
187
+ // }
188
+
189
+ // Custom tag prefix
190
+ component('libs/core', 'core-v');
249
191
  ```
250
192
 
193
+ The `dir` field is derived from `path.basename()`, so `packages/arrays` and `libs/arrays` both produce `dir: 'arrays'`.
194
+
195
+ ## GitHub Actions workflow
196
+
197
+ The `init` command scaffolds a workflow that delegates to a reusable release workflow. For repos that need a self-contained workflow:
198
+
251
199
  ### Monorepo
252
200
 
253
201
  ```yaml
254
- # .github/workflows/release.yaml
255
202
  name: Release
256
203
 
257
204
  on:
@@ -287,7 +234,7 @@ jobs:
287
234
 
288
235
  - uses: actions/setup-node@v4
289
236
  with:
290
- node-version: '24'
237
+ node-version: '22'
291
238
  cache: 'pnpm'
292
239
 
293
240
  - run: pnpm install
@@ -301,7 +248,7 @@ jobs:
301
248
  if [ -n "${{ inputs.bump }}" ]; then
302
249
  ARGS="$ARGS --bump=${{ inputs.bump }}"
303
250
  fi
304
- pnpm run release:prepare $ARGS
251
+ npx @williamthorsen/release-kit prepare $ARGS
305
252
 
306
253
  - name: Check for changes
307
254
  id: check
@@ -313,18 +260,13 @@ jobs:
313
260
  echo "changed=true" >> "$GITHUB_OUTPUT"
314
261
  fi
315
262
 
316
- - name: Determine release tags
263
+ - name: Read release tags
317
264
  if: steps.check.outputs.changed == 'true'
318
265
  id: tags
319
266
  run: |
320
- TAGS=""
321
- for pkg in $(git diff --name-only -- 'packages/*/package.json'); do
322
- DIR=$(echo "$pkg" | cut -d/ -f2)
323
- VERSION=$(node -p "require('./$pkg').version")
324
- TAGS="$TAGS ${DIR}-v${VERSION}"
325
- done
267
+ TAGS=$(cat /tmp/release-kit/.release-tags | tr '\n' ' ')
326
268
  echo "tags=$TAGS" >> "$GITHUB_OUTPUT"
327
- echo "Releasing:$TAGS"
269
+ echo "Releasing: $TAGS"
328
270
 
329
271
  - name: Commit, tag, and push
330
272
  if: steps.check.outputs.changed == 'true'
@@ -339,21 +281,44 @@ jobs:
339
281
  git push origin main ${{ steps.tags.outputs.tags }}
340
282
  ```
341
283
 
284
+ ### Single-package repo
285
+
286
+ The same workflow without the `only` input. Replace the prepare step with:
287
+
288
+ ```yaml
289
+ - name: Run release preparation
290
+ run: |
291
+ ARGS=""
292
+ if [ -n "${{ inputs.bump }}" ]; then
293
+ ARGS="--bump=${{ inputs.bump }}"
294
+ fi
295
+ npx @williamthorsen/release-kit prepare $ARGS
296
+ ```
297
+
298
+ And the tag step with:
299
+
300
+ ```yaml
301
+ - name: Read release tag
302
+ if: steps.check.outputs.changed == 'true'
303
+ id: tags
304
+ run: |
305
+ TAG=$(cat /tmp/release-kit/.release-tags)
306
+ echo "tag=$TAG" >> "$GITHUB_OUTPUT"
307
+ ```
308
+
342
309
  ## Triggering a release
343
310
 
344
311
  ```sh
345
- # Single-package repo
346
- gh workflow run release.yaml
347
- gh workflow run release.yaml -f bump=minor
348
-
349
- # Monorepo: all components
312
+ # All components
350
313
  gh workflow run release.yaml
351
314
 
352
- # Monorepo: specific component(s)
353
- gh workflow run release.yaml -f only=my-lib
354
- gh workflow run release.yaml -f only=my-lib,my-cli -f bump=minor
315
+ # Specific component(s)
316
+ gh workflow run release.yaml -f only=arrays
317
+ gh workflow run release.yaml -f only=arrays,strings -f bump=minor
355
318
  ```
356
319
 
320
+ Or use the GitHub UI: Actions > Release > Run workflow.
321
+
357
322
  ## cliff.toml setup
358
323
 
359
324
  The package includes a `cliff.toml.template` with a generic git-cliff configuration that:
@@ -377,13 +342,37 @@ This package shells out to two external tools:
377
342
  - **`git`** — must be available on `PATH`. Used to find tags and retrieve commit history.
378
343
  - **`git-cliff`** — must be available on `PATH`. Add `git-cliff` as a dev dependency to make it available in CI.
379
344
 
345
+ ## Legacy script-based approach
346
+
347
+ 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.
348
+
349
+ ```typescript
350
+ // .github/scripts/release.config.ts
351
+ import type { MonorepoReleaseConfig } from '@williamthorsen/release-kit';
352
+ import { component } from '@williamthorsen/release-kit';
353
+
354
+ export const config: MonorepoReleaseConfig = {
355
+ components: [component('packages/arrays'), component('packages/strings')],
356
+ formatCommand: 'pnpm run fmt',
357
+ };
358
+ ```
359
+
360
+ ```typescript
361
+ // .github/scripts/release-prepare.ts
362
+ import { runReleasePrepare } from '@williamthorsen/release-kit';
363
+ import { config } from './release.config.ts';
364
+
365
+ runReleasePrepare(config);
366
+ ```
367
+
368
+ The key difference: the script-based approach requires manually listing every component, while the CLI auto-discovers them from `pnpm-workspace.yaml`.
369
+
380
370
  ## Migration from changesets
381
371
 
382
372
  1. Add `@williamthorsen/release-kit` and `git-cliff` as dev dependencies.
383
373
  2. Remove `@changesets/cli` from dev dependencies.
384
374
  3. Delete the `.changeset/` directory.
385
- 4. Create `scripts/release-prepare.ts` and `scripts/release.config.ts` (see examples above).
386
- 5. Replace `changeset:*` scripts in `package.json` with `release:prepare` scripts.
387
- 6. Copy `cliff.toml.template` to your repo root as `cliff.toml`.
388
- 7. Add the GitHub Actions release workflow.
389
- 8. Create an initial version tag for each package (e.g., `git tag v1.0.0` or `git tag my-lib-v1.0.0`).
375
+ 4. Run `npx @williamthorsen/release-kit init` to scaffold workflow and config files.
376
+ 5. Remove `changeset:*` scripts from `package.json` (no replacement needed — the CLI handles everything).
377
+ 6. Copy `cliff.toml.template` to your repo root as `cliff.toml` (if `init` didn't create one).
378
+ 7. Create an initial version tag for each package (e.g., `git tag v1.0.0` or `git tag arrays-v1.0.0`).
package/dist/esm/.cache CHANGED
@@ -1 +1 @@
1
- a92e7a81da1b36a5b37ad22914e14f9d8c0b5333f34c869fc1b0c1c601ab9e81
1
+ 0ede8bfb18cd7eb611431537e6a16d4476ee70169599c97626bb6f6fc4349bbf
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { initCommand } from "../init/initCommand.js";
3
+ import { prepareCommand } from "../prepareCommand.js";
3
4
  function showUsage() {
4
5
  console.info(`
5
6
  Usage: release-kit <command> [options]
6
7
 
7
8
  Commands:
9
+ prepare Run release preparation (auto-discovers workspaces)
8
10
  init Initialize release-kit in the current repository
9
11
 
10
12
  Options:
@@ -17,13 +19,26 @@ function showInitHelp() {
17
19
  Usage: release-kit init [options]
18
20
 
19
21
  Initialize release-kit in the current repository.
20
- Scaffolds workflow, scripts, and config files.
22
+ Scaffolds workflow and config files.
21
23
 
22
24
  Options:
23
25
  --dry-run Preview changes without writing files
24
26
  --help, -h Show this help message
25
27
  `);
26
28
  }
29
+ function showPrepareHelp() {
30
+ console.info(`
31
+ Usage: release-kit prepare [options]
32
+
33
+ Run release preparation with automatic workspace discovery.
34
+
35
+ Options:
36
+ --dry-run Run without modifying any files
37
+ --bump=major|minor|patch Override the bump type for all components
38
+ --only=name1,name2 Only process the named components (comma-separated, monorepo only)
39
+ --help, -h Show this help message
40
+ `);
41
+ }
27
42
  const args = process.argv.slice(2);
28
43
  const command = args[0];
29
44
  const flags = args.slice(1);
@@ -31,6 +46,14 @@ if (command === "--help" || command === "-h" || command === void 0) {
31
46
  showUsage();
32
47
  process.exit(0);
33
48
  }
49
+ if (command === "prepare") {
50
+ if (flags.some((f) => f === "--help" || f === "-h")) {
51
+ showPrepareHelp();
52
+ process.exit(0);
53
+ }
54
+ await prepareCommand(flags);
55
+ process.exit(0);
56
+ }
34
57
  if (command === "init") {
35
58
  if (flags.some((f) => f === "--help" || f === "-h")) {
36
59
  showInitHelp();
@@ -0,0 +1,2 @@
1
+ import type { ComponentConfig } from './types.ts';
2
+ export declare function component(workspacePath: string, tagPrefix?: string): ComponentConfig;
@@ -0,0 +1,15 @@
1
+ import { basename } from "node:path";
2
+ function component(workspacePath, tagPrefix) {
3
+ const dir = basename(workspacePath);
4
+ const prefix = tagPrefix ?? `${dir}-v`;
5
+ return {
6
+ dir,
7
+ tagPrefix: prefix,
8
+ packageFiles: [`${workspacePath}/package.json`],
9
+ changelogPaths: [workspacePath],
10
+ paths: [`${workspacePath}/**`]
11
+ };
12
+ }
13
+ export {
14
+ component
15
+ };