@releasekit/release 0.3.0 → 0.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.
package/dist/cli.js CHANGED
@@ -1 +1,59 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ createReleaseCommand
4
+ } from "./chunk-WNKYXS62.js";
5
+ import {
6
+ runPreview
7
+ } from "./chunk-I5CGC253.js";
8
+ import {
9
+ EXIT_CODES,
10
+ readPackageVersion
11
+ } from "./chunk-YZHGXRG6.js";
12
+
13
+ // src/cli.ts
14
+ import { realpathSync } from "fs";
15
+ import { fileURLToPath } from "url";
16
+ import { Command as Command2 } from "commander";
17
+
18
+ // src/preview-command.ts
19
+ import { Command } from "commander";
20
+ function createPreviewCommand() {
21
+ return new Command("preview").description("Post a release preview comment on the current pull request").option("-c, --config <path>", "Path to config file").option("--project-dir <path>", "Project directory", process.cwd()).option("--pr <number>", "PR number (auto-detected from GitHub Actions)").option("--repo <owner/repo>", "Repository (auto-detected from GITHUB_REPOSITORY)").option("-p, --prerelease [identifier]", "Force prerelease preview (auto-detected by default)").option("--stable", "Force stable release preview (graduation from prerelease)", false).option(
22
+ "-d, --dry-run",
23
+ "Print the comment to stdout without posting (GitHub context not available in dry-run mode)",
24
+ false
25
+ ).action(async (opts) => {
26
+ try {
27
+ await runPreview({
28
+ config: opts.config,
29
+ projectDir: opts.projectDir,
30
+ pr: opts.pr,
31
+ repo: opts.repo,
32
+ prerelease: opts.prerelease,
33
+ stable: opts.stable,
34
+ dryRun: opts.dryRun
35
+ });
36
+ } catch (error) {
37
+ console.error(error instanceof Error ? error.message : String(error));
38
+ process.exit(EXIT_CODES.GENERAL_ERROR);
39
+ }
40
+ });
41
+ }
42
+
43
+ // src/cli.ts
44
+ function createReleaseProgram() {
45
+ return new Command2().name("releasekit-release").description("Unified release pipeline: version, changelog, and publish").version(readPackageVersion(import.meta.url)).addCommand(createReleaseCommand(), { isDefault: true }).addCommand(createPreviewCommand());
46
+ }
47
+ var isMain = (() => {
48
+ try {
49
+ return process.argv[1] ? realpathSync(process.argv[1]) === fileURLToPath(import.meta.url) : false;
50
+ } catch {
51
+ return false;
52
+ }
53
+ })();
54
+ if (isMain) {
55
+ createReleaseProgram().parse();
56
+ }
57
+ export {
58
+ createReleaseProgram
59
+ };
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from 'commander';
3
+
4
+ declare function createDispatcherProgram(): Command;
5
+
6
+ export { createDispatcherProgram };
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ createReleaseCommand
4
+ } from "./chunk-WNKYXS62.js";
5
+ import {
6
+ EXIT_CODES,
7
+ error,
8
+ info,
9
+ readPackageVersion,
10
+ success
11
+ } from "./chunk-YZHGXRG6.js";
12
+
13
+ // src/dispatcher.ts
14
+ import { realpathSync } from "fs";
15
+ import { fileURLToPath } from "url";
16
+ import { createNotesCommand } from "@releasekit/notes/cli";
17
+ import { createPublishCommand } from "@releasekit/publish/cli";
18
+ import { createVersionCommand } from "@releasekit/version/cli";
19
+ import { Command as Command2 } from "commander";
20
+
21
+ // src/init-command.ts
22
+ import * as fs from "fs";
23
+ import { detectMonorepo } from "@releasekit/notes";
24
+ import { Command } from "commander";
25
+ function createInitCommand() {
26
+ return new Command("init").description("Create a default releasekit.config.json").option("-f, --force", "Overwrite existing config").action((options) => {
27
+ const configPath = "releasekit.config.json";
28
+ if (fs.existsSync(configPath) && !options.force) {
29
+ error(`Config file already exists at ${configPath}. Use --force to overwrite.`);
30
+ process.exit(EXIT_CODES.GENERAL_ERROR);
31
+ } else {
32
+ let changelogMode;
33
+ try {
34
+ const detected = detectMonorepo(process.cwd());
35
+ changelogMode = detected.isMonorepo ? "packages" : "root";
36
+ info(
37
+ detected.isMonorepo ? "Monorepo detected \u2014 using mode: packages" : "Single-package repo detected \u2014 using mode: root"
38
+ );
39
+ } catch {
40
+ changelogMode = "root";
41
+ info("Could not detect project type \u2014 using mode: root");
42
+ }
43
+ let packageName;
44
+ try {
45
+ const pkg = JSON.parse(fs.readFileSync("package.json", "utf-8"));
46
+ packageName = pkg.name;
47
+ } catch {
48
+ }
49
+ const isScoped = packageName?.startsWith("@") ?? false;
50
+ const defaultConfig = {
51
+ $schema: "https://goosewobbler.github.io/releasekit/schema.json",
52
+ notes: {
53
+ changelog: {
54
+ mode: changelogMode
55
+ }
56
+ },
57
+ publish: {
58
+ npm: {
59
+ enabled: true,
60
+ ...isScoped ? { access: "public" } : {}
61
+ }
62
+ }
63
+ };
64
+ fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2), "utf-8");
65
+ success(`Created ${configPath}`);
66
+ }
67
+ });
68
+ }
69
+
70
+ // src/dispatcher.ts
71
+ function createDispatcherProgram() {
72
+ const program = new Command2().name("releasekit").description("Unified release pipeline: version, changelog, and publish").version(readPackageVersion(import.meta.url));
73
+ program.addCommand(createReleaseCommand(), { isDefault: true });
74
+ program.addCommand(createInitCommand());
75
+ program.addCommand(createVersionCommand());
76
+ program.addCommand(createNotesCommand());
77
+ program.addCommand(createPublishCommand());
78
+ return program;
79
+ }
80
+ var isMain = (() => {
81
+ try {
82
+ return process.argv[1] ? realpathSync(process.argv[1]) === fileURLToPath(import.meta.url) : false;
83
+ } catch {
84
+ return false;
85
+ }
86
+ })();
87
+ if (isMain) {
88
+ createDispatcherProgram().parse();
89
+ }
90
+ export {
91
+ createDispatcherProgram
92
+ };
@@ -0,0 +1,3 @@
1
+ export { PreviewOptions, runPreview } from './preview.ts';
2
+ export { runRelease } from './release.ts';
3
+ export { ReleaseOptions, ReleaseOutput } from './types.ts';
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ import {
2
+ runPreview
3
+ } from "./chunk-I5CGC253.js";
4
+ import {
5
+ runRelease
6
+ } from "./chunk-YZHGXRG6.js";
7
+ export {
8
+ runPreview,
9
+ runRelease
10
+ };
@@ -0,0 +1,266 @@
1
+ # CI Setup
2
+
3
+ This guide covers common GitHub Actions patterns for automating releases with `@releasekit/release`.
4
+
5
+ ## Prerequisites
6
+
7
+ All workflows require:
8
+
9
+ - `fetch-depth: 0` on checkout — ReleaseKit reads git history to determine version bumps
10
+ - A `GITHUB_TOKEN` with `contents: write` permission for tagging and GitHub Releases
11
+ - Node.js 20+
12
+
13
+ ---
14
+
15
+ ## Minimal Setup (push to main)
16
+
17
+ Trigger a release on every push to `main`. If there are no releasable commits, the command exits cleanly with code 0 and does nothing.
18
+
19
+ ```yaml
20
+ # .github/workflows/release.yml
21
+ name: Release
22
+
23
+ on:
24
+ push:
25
+ branches: [main]
26
+
27
+ permissions:
28
+ contents: write
29
+ id-token: write # for npm OIDC trusted publishing
30
+
31
+ jobs:
32
+ release:
33
+ runs-on: ubuntu-latest
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+ with:
37
+ fetch-depth: 0
38
+
39
+ - uses: actions/setup-node@v4
40
+ with:
41
+ node-version: '20'
42
+ registry-url: 'https://registry.npmjs.org'
43
+
44
+ - run: npm ci
45
+
46
+ - run: npx releasekit release
47
+ env:
48
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
49
+ # For OIDC trusted publishing (recommended) — no NPM_TOKEN needed.
50
+ # For token-based publishing: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Label-Based Trigger
56
+
57
+ Only release when a PR is merged with a release label. Conventional commits determine the changelog entries; the label controls whether and at what level to bump.
58
+
59
+ **Required labels** (customisable in config):
60
+
61
+ | Label | Effect |
62
+ |-------|--------|
63
+ | `release:patch` | Bump patch version |
64
+ | `release:minor` | Bump minor version |
65
+ | `release:major` | Bump major version |
66
+ | `release:stable` | Graduate a prerelease to stable |
67
+ | `release:prerelease` | Create a prerelease |
68
+ | `release:skip` | Suppress release on this PR |
69
+
70
+ ```yaml
71
+ # .github/workflows/release.yml
72
+ name: Release
73
+
74
+ on:
75
+ push:
76
+ branches: [main]
77
+
78
+ permissions:
79
+ contents: write
80
+ id-token: write
81
+ pull-requests: read
82
+
83
+ jobs:
84
+ release:
85
+ runs-on: ubuntu-latest
86
+ steps:
87
+ - uses: actions/checkout@v4
88
+ with:
89
+ fetch-depth: 0
90
+
91
+ - uses: actions/setup-node@v4
92
+ with:
93
+ node-version: '20'
94
+ registry-url: 'https://registry.npmjs.org'
95
+
96
+ - run: npm ci
97
+
98
+ - run: npx releasekit release
99
+ env:
100
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
101
+ ```
102
+
103
+ Configure the trigger in `releasekit.config.json`:
104
+
105
+ ```json
106
+ {
107
+ "ci": {
108
+ "releaseTrigger": "label",
109
+ "labels": {
110
+ "major": "release:major",
111
+ "minor": "release:minor",
112
+ "patch": "release:patch",
113
+ "skip": "release:skip"
114
+ }
115
+ }
116
+ }
117
+ ```
118
+
119
+ Without a `release:patch/minor/major` label on the merged PR, no release is triggered. The `labels` block shown above reflects the defaults — omit it if your repository already uses those label names.
120
+
121
+ See [@releasekit/release — CI Configuration](../README.md#ci-configuration) for all `ci.*` options.
122
+
123
+ ---
124
+
125
+ ## PR Preview Comments
126
+
127
+ Post a comment on every PR showing what would be released if merged. Requires `pull-requests: write`.
128
+
129
+ ```yaml
130
+ # .github/workflows/release-preview.yml
131
+ name: Release Preview
132
+
133
+ on:
134
+ pull_request:
135
+ branches: [main]
136
+ types: [opened, synchronize, labeled, unlabeled]
137
+
138
+ concurrency:
139
+ group: release-preview-${{ github.event.pull_request.number }}
140
+ cancel-in-progress: true
141
+
142
+ permissions:
143
+ pull-requests: write
144
+ contents: read
145
+
146
+ jobs:
147
+ preview:
148
+ runs-on: ubuntu-latest
149
+ steps:
150
+ - uses: actions/checkout@v4
151
+ with:
152
+ fetch-depth: 0
153
+
154
+ - uses: actions/setup-node@v4
155
+ with:
156
+ node-version: '20'
157
+
158
+ - run: npm ci
159
+
160
+ - run: npx releasekit preview
161
+ env:
162
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
163
+ ```
164
+
165
+ A ready-to-use template is available at [`templates/workflows/release-preview.yml`](../../../templates/workflows/release-preview.yml).
166
+
167
+ ---
168
+
169
+ ## npm OIDC Trusted Publishing (Recommended)
170
+
171
+ With OIDC, no `NPM_TOKEN` secret is required. The workflow exchanges a GitHub-issued OIDC token for a short-lived npm token at publish time.
172
+
173
+ **Requirements:**
174
+ - npm `>=9.5.0`
175
+ - Each package must have an **Automation policy** configured at npmjs.com (Settings → Automation policies → add a GitHub Actions OIDC publisher for your repo and workflow)
176
+
177
+ **Important:** `actions/setup-node` with `registry-url` writes a project `.npmrc` that injects `_authToken=${NODE_AUTH_TOKEN}`. When `NODE_AUTH_TOKEN` is unset, npm resolves this to an empty token and fails with `ENEEDAUTH` instead of falling through to the OIDC exchange. Delete the file before publishing:
178
+
179
+ ```yaml
180
+ permissions:
181
+ contents: write
182
+ id-token: write # grants the OIDC token
183
+
184
+ steps:
185
+ - uses: actions/setup-node@v4
186
+ with:
187
+ node-version: '20'
188
+ registry-url: 'https://registry.npmjs.org'
189
+
190
+ - run: npx releasekit release
191
+ env:
192
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
193
+ # No NPM_TOKEN needed with OIDC
194
+ ```
195
+
196
+ ReleaseKit detects OIDC availability automatically (`npm-auth: auto`). To force it:
197
+
198
+ ```json
199
+ {
200
+ "publish": {
201
+ "npm": { "auth": "oidc" }
202
+ }
203
+ }
204
+ ```
205
+
206
+ ---
207
+
208
+ ## Prerelease Workflow
209
+
210
+ ```yaml
211
+ # Manual dispatch for prereleases
212
+ on:
213
+ workflow_dispatch:
214
+ inputs:
215
+ prerelease:
216
+ description: 'Prerelease identifier (e.g. beta, rc)'
217
+ required: true
218
+ default: 'beta'
219
+
220
+ jobs:
221
+ prerelease:
222
+ runs-on: ubuntu-latest
223
+ steps:
224
+ - uses: actions/checkout@v4
225
+ with:
226
+ fetch-depth: 0
227
+
228
+ - uses: actions/setup-node@v4
229
+ with:
230
+ node-version: '20'
231
+ registry-url: 'https://registry.npmjs.org'
232
+
233
+ - run: npm ci
234
+
235
+ - run: npx releasekit release --prerelease ${{ inputs.prerelease }}
236
+ env:
237
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
238
+ ```
239
+
240
+ ---
241
+
242
+ ## Monorepo Targeted Release
243
+
244
+ Release only specific packages:
245
+
246
+ ```bash
247
+ npx releasekit release --target @myorg/core,@myorg/cli
248
+ ```
249
+
250
+ Or version all packages together:
251
+
252
+ ```bash
253
+ npx releasekit release --sync
254
+ ```
255
+
256
+ ---
257
+
258
+ ## Dry Run in CI
259
+
260
+ Useful for verifying pipeline setup before enabling real releases:
261
+
262
+ ```yaml
263
+ - run: npx releasekit release --dry-run --json
264
+ ```
265
+
266
+ `--dry-run` prints what would happen without modifying any files, creating tags, or publishing packages. `--json` emits structured output for inspection.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@releasekit/release",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Unified release pipeline: version, changelog, and publish in a single command",
5
5
  "type": "module",
6
6
  "module": "./dist/index.js",
@@ -37,6 +37,7 @@
37
37
  "license": "MIT",
38
38
  "files": [
39
39
  "dist",
40
+ "docs",
40
41
  "README.md",
41
42
  "LICENSE"
42
43
  ],
@@ -49,9 +50,9 @@
49
50
  "commander": "^14.0.3",
50
51
  "smol-toml": "^1.6.1",
51
52
  "zod": "^4.3.6",
52
- "@releasekit/notes": "0.3.0",
53
- "@releasekit/version": "0.3.0",
54
- "@releasekit/publish": "0.3.0"
53
+ "@releasekit/notes": "0.4.0",
54
+ "@releasekit/publish": "0.4.0",
55
+ "@releasekit/version": "0.4.0"
55
56
  },
56
57
  "devDependencies": {
57
58
  "@biomejs/biome": "^2.4.6",
@@ -61,8 +62,8 @@
61
62
  "tsup": "^8.5.1",
62
63
  "typescript": "^5.9.3",
63
64
  "vitest": "^4.1.0",
64
- "@releasekit/core": "0.0.0",
65
- "@releasekit/config": "0.0.0"
65
+ "@releasekit/config": "0.0.0",
66
+ "@releasekit/core": "0.0.0"
66
67
  },
67
68
  "engines": {
68
69
  "node": ">=20"