@williamthorsen/release-kit 4.7.0 → 4.8.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/CHANGELOG.md +18 -8
- package/dist/esm/.cache +1 -1
- package/dist/esm/bin/release-kit.js +24 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/init/detectRepoType.js +1 -2
- package/dist/esm/init/templates.js +7 -7
- package/dist/esm/prepareCommand.js +1 -1
- package/dist/esm/pushCommand.d.ts +1 -0
- package/dist/esm/pushCommand.js +46 -0
- package/dist/esm/pushRelease.d.ts +11 -0
- package/dist/esm/pushRelease.js +26 -0
- package/dist/esm/sync-labels/templates.js +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [release-kit-v4.8.0] - 2026-04-17
|
|
6
|
+
|
|
7
|
+
### Bug fixes
|
|
8
|
+
|
|
9
|
+
- Replace broad catch with `existsSync` guard in `detectRepoType` (#229)
|
|
10
|
+
|
|
11
|
+
Fixes silent swallowing of unexpected filesystem errors in `detectRepoType`. Previously, errors like `EACCES` (permission denied) or `EMFILE` (too many open files) when reading `package.json` were caught and discarded, causing the function to silently return `'single-package'` instead of surfacing the problem.
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
- Add `push` command for safe tag pushing (#243)
|
|
16
|
+
|
|
17
|
+
Adds a `release-kit push` command that safely pushes the release commit and each tag individually, ensuring GitHub Actions fires a separate workflow run per tag. The command performs a `1 + N` push sequence: one branch push followed by one `git push --no-follow-tags origin <tag>` per resolved tag. Supports `--dry-run` (preview without pushing), `--only` (filter tags by package name), and `--tags-only` (skip the branch push).
|
|
18
|
+
|
|
5
19
|
## [release-kit-v4.7.0] - 2026-04-16
|
|
6
20
|
|
|
7
21
|
### Features
|
|
@@ -227,6 +241,10 @@ All notable changes to this project will be documented in this file.
|
|
|
227
241
|
|
|
228
242
|
### Features
|
|
229
243
|
|
|
244
|
+
- Migrate release-kit from toolbelt (#18)
|
|
245
|
+
|
|
246
|
+
Migrates the complete `@williamthorsen/release-kit` package (v1.0.1) from `williamthorsen/toolbelt` into `packages/release-kit/`, adds shebang preservation to the shared esbuild plugin for CLI binaries, and sets up dogfooding infrastructure so this monorepo uses release-kit for its own releases.
|
|
247
|
+
|
|
230
248
|
- Slim down release workflow by removing unnecessary pnpm install (#21)
|
|
231
249
|
|
|
232
250
|
Make release-kit self-contained by invoking git-cliff via `npx --yes` instead of requiring it on PATH, and by appending modified file paths to the format command so lightweight formatters like `npx prettier --write` work without a full `pnpm install`. Update init templates, README, and consuming repo config/workflow to reference workflow v3.
|
|
@@ -249,12 +267,4 @@ All notable changes to this project will be documented in this file.
|
|
|
249
267
|
|
|
250
268
|
Addresses five code quality issues and a test coverage gap identified during the release-kit migration (#5). Extracts a duplicated `isRecord` type guard into a shared module, eliminates a double-read in `bumpAllVersions`, improves error handling in `usesPnpm` by replacing a silent catch with a structured error boundary, removes an unreachable `'feature'` pattern from version defaults, and adds an integration test for scaffold template path resolution.
|
|
251
269
|
|
|
252
|
-
## [release-kit-v1.0.1] - 2026-03-14
|
|
253
|
-
|
|
254
|
-
### Features
|
|
255
|
-
|
|
256
|
-
- Migrate release-kit from toolbelt (#18)
|
|
257
|
-
|
|
258
|
-
Migrates the complete `@williamthorsen/release-kit` package (v1.0.1) from `williamthorsen/toolbelt` into `packages/release-kit/`, adds shebang preservation to the shared esbuild plugin for CLI binaries, and sets up dogfooding infrastructure so this monorepo uses release-kit for its own releases.
|
|
259
|
-
|
|
260
270
|
<!-- generated by git-cliff -->
|
package/dist/esm/.cache
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
d6a6d71f34f00ba31c3dca3b32657832693ff9c12de118fafa96fc3554835ecc
|
|
@@ -5,6 +5,7 @@ import { githubReleaseCommand } from "../githubReleaseCommand.js";
|
|
|
5
5
|
import { initCommand } from "../init/initCommand.js";
|
|
6
6
|
import { prepareCommand } from "../prepareCommand.js";
|
|
7
7
|
import { publishCommand } from "../publishCommand.js";
|
|
8
|
+
import { pushCommand } from "../pushCommand.js";
|
|
8
9
|
import { generateCommand } from "../sync-labels/generateCommand.js";
|
|
9
10
|
import { syncLabelsInitCommand } from "../sync-labels/initCommand.js";
|
|
10
11
|
import { syncLabelsCommand } from "../sync-labels/syncCommand.js";
|
|
@@ -18,6 +19,7 @@ Commands:
|
|
|
18
19
|
prepare Run release preparation (auto-discovers workspaces)
|
|
19
20
|
commit Stage changes and create the release commit
|
|
20
21
|
tag Create annotated git tags from the tags file
|
|
22
|
+
push Push release commit and tags (one push per tag)
|
|
21
23
|
publish Publish packages with release tags on HEAD
|
|
22
24
|
github-release Create GitHub Releases from changelog.json for tags on HEAD
|
|
23
25
|
init Initialize release-kit in the current repository
|
|
@@ -128,6 +130,20 @@ Options:
|
|
|
128
130
|
--help, -h Show this help message
|
|
129
131
|
`);
|
|
130
132
|
}
|
|
133
|
+
function showPushHelp() {
|
|
134
|
+
console.info(`
|
|
135
|
+
Usage: release-kit push [options]
|
|
136
|
+
|
|
137
|
+
Push the release commit and each tag individually, ensuring GitHub Actions
|
|
138
|
+
fires a separate workflow run per tag.
|
|
139
|
+
|
|
140
|
+
Options:
|
|
141
|
+
--dry-run Preview without pushing
|
|
142
|
+
--only=name1,name2 Only push tags for the named packages (comma-separated, monorepo only)
|
|
143
|
+
--tags-only Skip the branch push (push tags only)
|
|
144
|
+
--help, -h Show this help message
|
|
145
|
+
`);
|
|
146
|
+
}
|
|
131
147
|
function showGithubReleaseHelp() {
|
|
132
148
|
console.info(`
|
|
133
149
|
Usage: release-kit github-release [options]
|
|
@@ -194,6 +210,14 @@ if (command === "tag") {
|
|
|
194
210
|
tagCommand(flags);
|
|
195
211
|
process.exit(0);
|
|
196
212
|
}
|
|
213
|
+
if (command === "push") {
|
|
214
|
+
if (flags.some((f) => f === "--help" || f === "-h")) {
|
|
215
|
+
showPushHelp();
|
|
216
|
+
process.exit(0);
|
|
217
|
+
}
|
|
218
|
+
await pushCommand(flags);
|
|
219
|
+
process.exit(0);
|
|
220
|
+
}
|
|
197
221
|
if (command === "github-release") {
|
|
198
222
|
if (flags.some((f) => f === "--help" || f === "-h")) {
|
|
199
223
|
showGithubReleaseHelp();
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -27,6 +27,8 @@ export { injectSection } from './injectSection.ts';
|
|
|
27
27
|
export { COMMIT_PREPROCESSOR_PATTERNS, parseCommitMessage } from './parseCommitMessage.ts';
|
|
28
28
|
export { RELEASE_SUMMARY_FILE, RELEASE_TAGS_FILE, writeReleaseTags } from './prepareCommand.ts';
|
|
29
29
|
export { publishPackage } from './publish.ts';
|
|
30
|
+
export type { PushReleaseOptions } from './pushRelease.ts';
|
|
31
|
+
export { pushRelease } from './pushRelease.ts';
|
|
30
32
|
export { releasePrepare } from './releasePrepare.ts';
|
|
31
33
|
export { releasePrepareMono } from './releasePrepareMono.ts';
|
|
32
34
|
export type { RenderOptions } from './renderReleaseNotes.ts';
|
package/dist/esm/index.js
CHANGED
|
@@ -23,6 +23,7 @@ import { injectSection } from "./injectSection.js";
|
|
|
23
23
|
import { COMMIT_PREPROCESSOR_PATTERNS, parseCommitMessage } from "./parseCommitMessage.js";
|
|
24
24
|
import { RELEASE_SUMMARY_FILE, RELEASE_TAGS_FILE, writeReleaseTags } from "./prepareCommand.js";
|
|
25
25
|
import { publishPackage } from "./publish.js";
|
|
26
|
+
import { pushRelease } from "./pushRelease.js";
|
|
26
27
|
import { releasePrepare } from "./releasePrepare.js";
|
|
27
28
|
import { releasePrepareMono } from "./releasePrepareMono.js";
|
|
28
29
|
import { matchesAudience, renderReleaseNotesMulti, renderReleaseNotesSingle } from "./renderReleaseNotes.js";
|
|
@@ -60,6 +61,7 @@ export {
|
|
|
60
61
|
matchesAudience,
|
|
61
62
|
parseCommitMessage,
|
|
62
63
|
publishPackage,
|
|
64
|
+
pushRelease,
|
|
63
65
|
releasePrepare,
|
|
64
66
|
releasePrepareMono,
|
|
65
67
|
renderReleaseNotesMulti,
|
|
@@ -4,13 +4,12 @@ function detectRepoType() {
|
|
|
4
4
|
if (existsSync("pnpm-workspace.yaml")) {
|
|
5
5
|
return "monorepo";
|
|
6
6
|
}
|
|
7
|
-
|
|
7
|
+
if (existsSync("package.json")) {
|
|
8
8
|
const raw = readFileSync("package.json", "utf8");
|
|
9
9
|
const pkg = parseJsonRecord(raw);
|
|
10
10
|
if (pkg !== void 0 && Array.isArray(pkg.workspaces)) {
|
|
11
11
|
return "monorepo";
|
|
12
12
|
}
|
|
13
|
-
} catch {
|
|
14
13
|
}
|
|
15
14
|
return "single-package";
|
|
16
15
|
}
|
|
@@ -36,7 +36,7 @@ export default config;
|
|
|
36
36
|
`;
|
|
37
37
|
}
|
|
38
38
|
function publishWorkflow(repoType) {
|
|
39
|
-
const tagPattern = repoType === "monorepo" ? "'*-v[0-9]*'" : "'v[0-9]*'";
|
|
39
|
+
const tagPattern = repoType === "monorepo" ? "'*-v[0-9]*.[0-9]*.[0-9]*'" : "'v[0-9]*.[0-9]*.[0-9]*'";
|
|
40
40
|
return `# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
|
41
41
|
name: Publish
|
|
42
42
|
|
|
@@ -51,9 +51,9 @@ permissions:
|
|
|
51
51
|
|
|
52
52
|
jobs:
|
|
53
53
|
publish:
|
|
54
|
-
uses: williamthorsen/node-monorepo-tools/.github/workflows/publish.reusable.yaml@publish-
|
|
54
|
+
uses: williamthorsen/node-monorepo-tools/.github/workflows/publish.reusable.yaml@workflow/publish-v1
|
|
55
55
|
with:
|
|
56
|
-
provenance:
|
|
56
|
+
provenance: true
|
|
57
57
|
`;
|
|
58
58
|
}
|
|
59
59
|
function releaseWorkflow(repoType) {
|
|
@@ -78,7 +78,7 @@ on:
|
|
|
78
78
|
- minor
|
|
79
79
|
- major
|
|
80
80
|
force:
|
|
81
|
-
description: 'Force a
|
|
81
|
+
description: 'Force a release even when there are no commits since the last tag (requires --bump)'
|
|
82
82
|
required: false
|
|
83
83
|
type: boolean
|
|
84
84
|
default: false
|
|
@@ -89,7 +89,7 @@ permissions:
|
|
|
89
89
|
|
|
90
90
|
jobs:
|
|
91
91
|
release:
|
|
92
|
-
uses: williamthorsen/node-monorepo-tools/.github/workflows/release.reusable.yaml@release-
|
|
92
|
+
uses: williamthorsen/node-monorepo-tools/.github/workflows/release.reusable.yaml@workflow/release-v1
|
|
93
93
|
with:
|
|
94
94
|
only: \${{ inputs.only }}
|
|
95
95
|
bump: \${{ inputs.bump }}
|
|
@@ -112,7 +112,7 @@ on:
|
|
|
112
112
|
- minor
|
|
113
113
|
- major
|
|
114
114
|
force:
|
|
115
|
-
description: 'Force a
|
|
115
|
+
description: 'Force a release even when there are no commits since the last tag (requires --bump)'
|
|
116
116
|
required: false
|
|
117
117
|
type: boolean
|
|
118
118
|
default: false
|
|
@@ -123,7 +123,7 @@ permissions:
|
|
|
123
123
|
|
|
124
124
|
jobs:
|
|
125
125
|
release:
|
|
126
|
-
uses: williamthorsen/node-monorepo-tools/.github/workflows/release.reusable.yaml@release-
|
|
126
|
+
uses: williamthorsen/node-monorepo-tools/.github/workflows/release.reusable.yaml@workflow/release-v1
|
|
127
127
|
with:
|
|
128
128
|
bump: \${{ inputs.bump }}
|
|
129
129
|
force: \${{ inputs.force }}
|
|
@@ -25,7 +25,7 @@ Usage: npx @williamthorsen/release-kit prepare [options]
|
|
|
25
25
|
Options:
|
|
26
26
|
--dry-run Run without modifying any files
|
|
27
27
|
--bump=major|minor|patch Override the bump type for all components
|
|
28
|
-
--force
|
|
28
|
+
--force Force a release even when there are no commits since the last tag (requires --bump)
|
|
29
29
|
--no-git-checks, -n Skip the clean-working-tree check
|
|
30
30
|
--only=name1,name2 Only process the named components (comma-separated, monorepo only)
|
|
31
31
|
--help Show this help message
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function pushCommand(argv: string[]): Promise<void>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { parseArgs, translateParseError } from "@williamthorsen/node-monorepo-core";
|
|
2
|
+
import { pushRelease } from "./pushRelease.js";
|
|
3
|
+
import { resolveCommandTags } from "./resolveCommandTags.js";
|
|
4
|
+
const pushFlagSchema = {
|
|
5
|
+
dryRun: { long: "--dry-run", type: "boolean" },
|
|
6
|
+
only: { long: "--only", type: "string" },
|
|
7
|
+
tagsOnly: { long: "--tags-only", type: "boolean" }
|
|
8
|
+
};
|
|
9
|
+
async function pushCommand(argv) {
|
|
10
|
+
let parsed;
|
|
11
|
+
try {
|
|
12
|
+
parsed = parseArgs(argv, pushFlagSchema);
|
|
13
|
+
} catch (error) {
|
|
14
|
+
console.error(`Error: ${translateParseError(error)}`);
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
const { dryRun, tagsOnly } = parsed.flags;
|
|
18
|
+
const only = parsed.flags.only?.split(",");
|
|
19
|
+
const resolvedTags = await resolveCommandTags(only);
|
|
20
|
+
if (resolvedTags.length === 0) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const prefix = dryRun ? "[dry-run] Would push" : "Pushing";
|
|
24
|
+
if (!tagsOnly) {
|
|
25
|
+
console.info(`${prefix} branch and ${resolvedTags.length} tag(s):`);
|
|
26
|
+
} else {
|
|
27
|
+
console.info(`${prefix} ${resolvedTags.length} tag(s):`);
|
|
28
|
+
}
|
|
29
|
+
for (const { tag } of resolvedTags) {
|
|
30
|
+
console.info(` ${tag}`);
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const steps = pushRelease(resolvedTags, { dryRun, tagsOnly });
|
|
34
|
+
if (dryRun) {
|
|
35
|
+
for (const step of steps) {
|
|
36
|
+
console.info(`[dry-run] ${step.command.join(" ")}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
pushCommand
|
|
46
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ResolvedTag } from './resolveReleaseTags.ts';
|
|
2
|
+
export interface PushReleaseOptions {
|
|
3
|
+
dryRun?: boolean;
|
|
4
|
+
tagsOnly?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface PushStep {
|
|
7
|
+
type: 'branch' | 'tag';
|
|
8
|
+
ref: string;
|
|
9
|
+
command: readonly [string, ...string[]];
|
|
10
|
+
}
|
|
11
|
+
export declare function pushRelease(resolvedTags: ResolvedTag[], options?: PushReleaseOptions): PushStep[];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
function pushRelease(resolvedTags, options = {}) {
|
|
3
|
+
const { dryRun = false, tagsOnly = false } = options;
|
|
4
|
+
const steps = [];
|
|
5
|
+
if (!tagsOnly) {
|
|
6
|
+
const branch = execFileSync("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
7
|
+
encoding: "utf8",
|
|
8
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
9
|
+
}).trim();
|
|
10
|
+
const command = ["git", "push", "origin", branch];
|
|
11
|
+
steps.push({ type: "branch", ref: branch, command });
|
|
12
|
+
}
|
|
13
|
+
for (const { tag } of resolvedTags) {
|
|
14
|
+
const command = ["git", "push", "--no-follow-tags", "origin", tag];
|
|
15
|
+
steps.push({ type: "tag", ref: tag, command });
|
|
16
|
+
}
|
|
17
|
+
if (!dryRun) {
|
|
18
|
+
for (const step of steps) {
|
|
19
|
+
execFileSync(step.command[0], step.command.slice(1), { stdio: "inherit" });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return steps;
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
pushRelease
|
|
26
|
+
};
|
|
@@ -12,7 +12,7 @@ permissions:
|
|
|
12
12
|
|
|
13
13
|
jobs:
|
|
14
14
|
sync:
|
|
15
|
-
uses: williamthorsen/node-monorepo-tools/.github/workflows/sync-labels.reusable.yaml@sync-labels-
|
|
15
|
+
uses: williamthorsen/node-monorepo-tools/.github/workflows/sync-labels.reusable.yaml@workflow/sync-labels-v1
|
|
16
16
|
`;
|
|
17
17
|
}
|
|
18
18
|
function buildScopeLabels(workspacePaths) {
|
package/dist/esm/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "4.
|
|
1
|
+
export declare const VERSION = "4.8.0";
|
package/dist/esm/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@williamthorsen/release-kit",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.8.0",
|
|
4
4
|
"description": "Version-bumping and changelog-generation toolkit for release workflows",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"homepage": "https://github.com/williamthorsen/node-monorepo-tools/tree/main/packages/release-kit#readme",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"jiti": "2.6.1",
|
|
36
36
|
"js-yaml": "4.1.1",
|
|
37
37
|
"json-stringify-pretty-compact": "4.0.0",
|
|
38
|
-
"@williamthorsen/node-monorepo-core": "0.2.
|
|
38
|
+
"@williamthorsen/node-monorepo-core": "0.2.7"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/js-yaml": "4.0.9",
|