@williamthorsen/release-kit 2.1.0 → 2.3.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 +110 -0
- package/README.md +1 -11
- package/bin/release-kit.js +2 -0
- package/dist/esm/.cache +1 -1
- package/dist/esm/bin/release-kit.js +148 -0
- package/dist/esm/bumpAllVersions.d.ts +2 -2
- package/dist/esm/bumpAllVersions.js +1 -4
- package/dist/esm/component.d.ts +1 -1
- package/dist/esm/component.js +2 -3
- package/dist/esm/createTags.d.ts +5 -0
- package/dist/esm/createTags.js +73 -0
- package/dist/esm/detectPackageManager.d.ts +2 -0
- package/dist/esm/detectPackageManager.js +44 -0
- package/dist/esm/findPackageRoot.d.ts +1 -0
- package/dist/esm/findPackageRoot.js +17 -0
- package/dist/esm/format.d.ts +3 -0
- package/dist/esm/format.js +14 -0
- package/dist/esm/generateChangelogs.d.ts +2 -2
- package/dist/esm/generateChangelogs.js +12 -12
- package/dist/esm/hasPrettierConfig.d.ts +1 -0
- package/dist/esm/hasPrettierConfig.js +42 -0
- package/dist/esm/index.d.ts +12 -2
- package/dist/esm/index.js +11 -2
- package/dist/esm/init/initCommand.js +9 -2
- package/dist/esm/init/scaffold.d.ts +3 -2
- package/dist/esm/init/scaffold.js +18 -44
- package/dist/esm/init/templates.js +14 -4
- package/dist/esm/loadConfig.js +0 -6
- package/dist/esm/prepareCommand.d.ts +10 -0
- package/dist/esm/prepareCommand.js +96 -20
- package/dist/esm/publish.d.ts +7 -0
- package/dist/esm/publish.js +49 -0
- package/dist/esm/publishCommand.d.ts +1 -0
- package/dist/esm/publishCommand.js +54 -0
- package/dist/esm/releasePrepare.d.ts +2 -2
- package/dist/esm/releasePrepare.js +46 -17
- package/dist/esm/releasePrepareMono.d.ts +2 -2
- package/dist/esm/releasePrepareMono.js +54 -24
- package/dist/esm/reportPrepare.d.ts +2 -0
- package/dist/esm/reportPrepare.js +120 -0
- package/dist/esm/resolveCliffConfigPath.js +4 -4
- package/dist/esm/resolveReleaseTags.d.ts +6 -0
- package/dist/esm/resolveReleaseTags.js +42 -0
- package/dist/esm/runReleasePrepare.js +3 -2
- package/dist/esm/sync-labels/generateCommand.d.ts +4 -0
- package/dist/esm/sync-labels/generateCommand.js +51 -0
- package/dist/esm/sync-labels/initCommand.d.ts +6 -0
- package/dist/esm/sync-labels/initCommand.js +62 -0
- package/dist/esm/sync-labels/loadSyncLabelsConfig.d.ts +3 -0
- package/dist/esm/sync-labels/loadSyncLabelsConfig.js +59 -0
- package/dist/esm/sync-labels/presets.d.ts +2 -0
- package/dist/esm/sync-labels/presets.js +40 -0
- package/dist/esm/sync-labels/resolveLabels.d.ts +2 -0
- package/dist/esm/sync-labels/resolveLabels.js +43 -0
- package/dist/esm/sync-labels/scaffold.d.ts +6 -0
- package/dist/esm/sync-labels/scaffold.js +25 -0
- package/dist/esm/sync-labels/syncCommand.d.ts +1 -0
- package/dist/esm/sync-labels/syncCommand.js +33 -0
- package/dist/esm/sync-labels/templates.d.ts +4 -0
- package/dist/esm/sync-labels/templates.js +50 -0
- package/dist/esm/sync-labels/types.d.ts +9 -0
- package/dist/esm/sync-labels/types.js +0 -0
- package/dist/esm/tagCommand.d.ts +1 -0
- package/dist/esm/tagCommand.js +20 -0
- package/dist/esm/types.d.ts +29 -1
- package/dist/esm/validateConfig.js +11 -6
- package/package.json +12 -5
- package/presets/labels/common.yaml +52 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,116 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [release-kit-v2.3.0] - 2026-03-28
|
|
6
|
+
|
|
7
|
+
### Features
|
|
8
|
+
|
|
9
|
+
- #8 feat: Add shared writeFileWithCheck utility and overwrite reporting (#66)
|
|
10
|
+
|
|
11
|
+
Extracts three duplicated `writeIfAbsent` implementations and two duplicated terminal helper sets into shared utilities in `@williamthorsen/node-monorepo-core`, then migrates all consumers (`release-kit init`, `preflight init`, `sync-labels`) to use them. All init commands now report which files were created, overwritten, skipped, or failed — including when `--force` replaces existing files.
|
|
12
|
+
|
|
13
|
+
- #11 release-kit|feat: Separate tag-write errors from release preparation errors (#67)
|
|
14
|
+
|
|
15
|
+
When tag-file writing fails, the error message now reads "Error writing release tags:" instead of the misleading "Error preparing release:", which only appeared because both operations shared a single try/catch.
|
|
16
|
+
|
|
17
|
+
Refactors `writeReleaseTags` to use the shared `writeFileWithCheck` utility from `@node-monorepo-tools/core` instead of raw `mkdirSync`/`writeFileSync`. The function now returns a structured `WriteResult` instead of throwing, and contains no `console` calls — all presentation moves to `runAndReport`.
|
|
18
|
+
|
|
19
|
+
### Tests
|
|
20
|
+
|
|
21
|
+
- #14 release-kit|tests: Add eligibility check failure and short-circuit tests (#63)
|
|
22
|
+
|
|
23
|
+
Adds 4 unit tests to `initCommand.unit.test.ts` covering the remaining `checkEligibility` orchestration gaps: individual failure exit codes for `hasPackageJson` and `usesPnpm`, and short-circuit verification ensuring downstream checks are skipped when an earlier check fails.
|
|
24
|
+
|
|
25
|
+
- #13 release-kit|tests: Add cliff.toml.template alignment test (#64)
|
|
26
|
+
|
|
27
|
+
Adds a unit test that enforces bidirectional alignment between `DEFAULT_WORK_TYPES` and the bundled `cliff.toml.template` commit parsers. The test parses the TOML template using `smol-toml`, then verifies that every canonical type name and alias is matched by a parser with the correct group heading, and that every parser group maps to a known work type header.
|
|
28
|
+
|
|
29
|
+
- #12 release-kit|tests: Add releasePrepare coverage for bumpOverride, tagPrefix, and dry-run tags (#65)
|
|
30
|
+
|
|
31
|
+
Adds three unit tests to `releasePrepare.unit.test.ts` covering previously untested code paths: the `bumpOverride` bypass of commit-based bump detection, custom `tagPrefix` propagation into tags, and tag computation in dry-run mode.
|
|
32
|
+
|
|
33
|
+
## [release-kit-v2.2.0] - 2026-03-27
|
|
34
|
+
|
|
35
|
+
### Features
|
|
36
|
+
|
|
37
|
+
- #27 release-kit|feat: Auto-detect Prettier for CHANGELOG formatting (#36)
|
|
38
|
+
|
|
39
|
+
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.
|
|
40
|
+
|
|
41
|
+
- #28 release-kit|feat: Add tag-creation command (#40)
|
|
42
|
+
|
|
43
|
+
Adds a `release-kit tag` CLI command that reads computed tag names from the `tmp/.release-tags` file produced by `prepare` and creates annotated git tags. The command supports `--dry-run` (preview without creating tags) and `--no-git-checks` (skip dirty working tree validation). The `createTags` function and its options type are exported for programmatic use.
|
|
44
|
+
|
|
45
|
+
- #29 release-kit|feat: Add publish command (#42)
|
|
46
|
+
|
|
47
|
+
Adds a `release-kit publish` subcommand that derives packages to publish from git tags on HEAD and delegates to the repo's detected package manager. Also cleans up the `.release-tags` file after tag creation.
|
|
48
|
+
|
|
49
|
+
- #41 release-kit|feat: Remove tagPrefix customization from component config (#49)
|
|
50
|
+
|
|
51
|
+
Removes the ability to customize `tagPrefix` per component, enforcing the deterministic `{dir}-v` convention universally. The internal `tagPrefix` property on `ComponentConfig` and `ReleaseConfig` is preserved — only the override/customization entry points are removed. Existing configs that still include `tagPrefix` now receive a clear deprecation error.
|
|
52
|
+
|
|
53
|
+
- #54 release-kit|feat: Add styled terminal output to prepare command (#55)
|
|
54
|
+
|
|
55
|
+
Adds ANSI formatting and emoji markers to the `release-kit prepare` command output. Progress chatter is dimmed, key results (version bumps, release tags, completion status) are highlighted with bold text and emoji, and monorepo components are separated by box-drawing section headers.
|
|
56
|
+
|
|
57
|
+
- #59 feat: Extract nmr CLI from core package (#61)
|
|
58
|
+
|
|
59
|
+
Extracts all nmr CLI code from `packages/core` into a new `packages/nmr` package (`@williamthorsen/nmr`). Core is reduced to an empty shared-library shell ready for cross-cutting utilities. All internal references are rewired and the full build/test pipeline passes.
|
|
60
|
+
|
|
61
|
+
Scopes: core, nmr
|
|
62
|
+
|
|
63
|
+
### Refactoring
|
|
64
|
+
|
|
65
|
+
- #43 refactor: Replace dist bin targets with thin wrapper scripts (#48)
|
|
66
|
+
|
|
67
|
+
The `bin` entries in `packages/core` and `packages/release-kit` pointed directly into `dist/esm/`, causing `pnpm install` to emit "Failed to create bin" warnings in fresh worktrees where `dist/` does not yet exist. Each bin entry now points to a committed wrapper script in `bin/` that dynamically imports the real entry point. The `files` field in both packages includes `bin` so the wrappers are published.
|
|
68
|
+
|
|
69
|
+
- #53 release-kit|refactor: Separate presentation from logic in prepare workflow (#57)
|
|
70
|
+
|
|
71
|
+
Extracts all `console.info` calls from the prepare workflow's logic functions (`bumpAllVersions`, `generateChangelogs`, `releasePrepare`, `releasePrepareMono`) into a dedicated `reportPrepare` formatter. Logic functions now return structured result types (`BumpResult`, `ComponentPrepareResult`, `PrepareResult`). The legacy `runReleasePrepare` entry point is retired, with its utilities absorbed into `prepareCommand`.
|
|
72
|
+
|
|
73
|
+
### Tests
|
|
74
|
+
|
|
75
|
+
- #17 release-kit|tests: Cover multi-changelogPaths and error paths (#44)
|
|
76
|
+
|
|
77
|
+
Add three tests for previously untested code paths:
|
|
78
|
+
|
|
79
|
+
- `releasePrepareMono`: component with two `changelogPaths` entries, asserting `git-cliff` is invoked once per path with the correct `--output` target.
|
|
80
|
+
- `getCommitsSinceTarget`: `git describe` failure with a non-128 exit status propagates as a wrapped error instead of being swallowed.
|
|
81
|
+
- `getCommitsSinceTarget`: `git log` failure is wrapped and re-thrown with the commit range in the message.
|
|
82
|
+
|
|
83
|
+
Also adds a `findAllCliffOutputPaths()` test helper that collects the `--output` arg from every `git-cliff` mock call.
|
|
84
|
+
|
|
85
|
+
### Tooling
|
|
86
|
+
|
|
87
|
+
- #37 root|tooling: Adopt nmr to run monorepo and workspace scripts (#38)
|
|
88
|
+
|
|
89
|
+
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.
|
|
90
|
+
|
|
91
|
+
## [release-workflow-v1] - 2026-03-19
|
|
92
|
+
|
|
93
|
+
### Dependencies
|
|
94
|
+
|
|
95
|
+
- Root|deps: Add release-kit as root devDependency
|
|
96
|
+
|
|
97
|
+
Make `npx release-kit` and `pnpm exec release-kit` resolve within
|
|
98
|
+
this repo by adding a `workspace:*` dependency that symlinks the bin.
|
|
99
|
+
|
|
100
|
+
### Features
|
|
101
|
+
|
|
102
|
+
- #23 release-kit|feat: Add sync-labels command (#33)
|
|
103
|
+
|
|
104
|
+
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.
|
|
105
|
+
|
|
106
|
+
- #34 release-kit|feat: Report up-to-date status for unchanged init files (#35)
|
|
107
|
+
|
|
108
|
+
`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)`.
|
|
109
|
+
|
|
110
|
+
- Release-workflow|feat: Accept force input
|
|
111
|
+
|
|
112
|
+
Pass `--force` to the prepare command so callers can force a version
|
|
113
|
+
bump even when there are no release-worthy changes.
|
|
114
|
+
|
|
5
115
|
## [release-kit-v2.1.0] - 2026-03-17
|
|
6
116
|
|
|
7
117
|
### Features
|
package/README.md
CHANGED
|
@@ -48,12 +48,6 @@ Options:
|
|
|
48
48
|
|
|
49
49
|
Component names for `--only` match the package directory name (e.g., `arrays`, `release-kit`).
|
|
50
50
|
|
|
51
|
-
**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:
|
|
52
|
-
|
|
53
|
-
```bash
|
|
54
|
-
node packages/release-kit/dist/esm/bin/release-kit.js prepare --dry-run
|
|
55
|
-
```
|
|
56
|
-
|
|
57
51
|
### `release-kit init`
|
|
58
52
|
|
|
59
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.
|
|
@@ -120,7 +114,6 @@ All fields are optional.
|
|
|
120
114
|
```typescript
|
|
121
115
|
interface ComponentOverride {
|
|
122
116
|
dir: string; // Package directory name (e.g., 'arrays')
|
|
123
|
-
tagPrefix?: string; // Custom git tag prefix (defaults to '${dir}-v')
|
|
124
117
|
shouldExclude?: boolean; // If true, exclude from release processing
|
|
125
118
|
}
|
|
126
119
|
```
|
|
@@ -184,12 +177,9 @@ component('packages/arrays');
|
|
|
184
177
|
// changelogPaths: ['packages/arrays'],
|
|
185
178
|
// paths: ['packages/arrays/**'],
|
|
186
179
|
// }
|
|
187
|
-
|
|
188
|
-
// Custom tag prefix
|
|
189
|
-
component('libs/core', 'core-v');
|
|
190
180
|
```
|
|
191
181
|
|
|
192
|
-
The `dir` field is derived from `path.basename()`, so `packages/arrays` and `libs/arrays` both produce `dir: 'arrays'`.
|
|
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.
|
|
193
183
|
|
|
194
184
|
## GitHub Actions workflow
|
|
195
185
|
|
package/dist/esm/.cache
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
a59da8f9c8d7a95b776af266dfb8998307bdabf5e0cb68c9ca2a17b9655a5524
|
|
@@ -1,19 +1,75 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { initCommand } from "../init/initCommand.js";
|
|
3
3
|
import { prepareCommand } from "../prepareCommand.js";
|
|
4
|
+
import { publishCommand } from "../publishCommand.js";
|
|
5
|
+
import { generateCommand } from "../sync-labels/generateCommand.js";
|
|
6
|
+
import { syncLabelsInitCommand } from "../sync-labels/initCommand.js";
|
|
7
|
+
import { syncLabelsCommand } from "../sync-labels/syncCommand.js";
|
|
8
|
+
import { tagCommand } from "../tagCommand.js";
|
|
4
9
|
function showUsage() {
|
|
5
10
|
console.info(`
|
|
6
11
|
Usage: release-kit <command> [options]
|
|
7
12
|
|
|
8
13
|
Commands:
|
|
9
14
|
prepare Run release preparation (auto-discovers workspaces)
|
|
15
|
+
tag Create annotated git tags from the tags file
|
|
16
|
+
publish Publish packages with release tags on HEAD
|
|
10
17
|
init Initialize release-kit in the current repository
|
|
18
|
+
sync-labels Manage GitHub label synchronization
|
|
11
19
|
|
|
12
20
|
Options:
|
|
13
21
|
--dry-run Preview changes without writing files
|
|
14
22
|
--help, -h Show this help message
|
|
15
23
|
`);
|
|
16
24
|
}
|
|
25
|
+
function showSyncLabelsHelp() {
|
|
26
|
+
console.info(`
|
|
27
|
+
Usage: release-kit sync-labels <subcommand> [options]
|
|
28
|
+
|
|
29
|
+
Manage GitHub label synchronization via preset and custom label definitions.
|
|
30
|
+
|
|
31
|
+
Subcommands:
|
|
32
|
+
init Scaffold caller workflow and config, then generate labels
|
|
33
|
+
generate Regenerate .github/labels.yaml from config
|
|
34
|
+
sync Trigger the sync-labels workflow via gh CLI
|
|
35
|
+
|
|
36
|
+
Options:
|
|
37
|
+
--help, -h Show this help message
|
|
38
|
+
`);
|
|
39
|
+
}
|
|
40
|
+
function showSyncLabelsInitHelp() {
|
|
41
|
+
console.info(`
|
|
42
|
+
Usage: release-kit sync-labels init [options]
|
|
43
|
+
|
|
44
|
+
Scaffold the sync-labels caller workflow and config file, auto-discover workspaces
|
|
45
|
+
for scope labels, then generate .github/labels.yaml.
|
|
46
|
+
|
|
47
|
+
Options:
|
|
48
|
+
--dry-run Preview changes without writing files
|
|
49
|
+
--force Overwrite existing files instead of skipping them
|
|
50
|
+
--help, -h Show this help message
|
|
51
|
+
`);
|
|
52
|
+
}
|
|
53
|
+
function showSyncLabelsGenerateHelp() {
|
|
54
|
+
console.info(`
|
|
55
|
+
Usage: release-kit sync-labels generate
|
|
56
|
+
|
|
57
|
+
Regenerate .github/labels.yaml from .config/sync-labels.config.ts.
|
|
58
|
+
|
|
59
|
+
Options:
|
|
60
|
+
--help, -h Show this help message
|
|
61
|
+
`);
|
|
62
|
+
}
|
|
63
|
+
function showSyncLabelsSyncHelp() {
|
|
64
|
+
console.info(`
|
|
65
|
+
Usage: release-kit sync-labels sync
|
|
66
|
+
|
|
67
|
+
Trigger the sync-labels GitHub Actions workflow via the gh CLI.
|
|
68
|
+
|
|
69
|
+
Options:
|
|
70
|
+
--help, -h Show this help message
|
|
71
|
+
`);
|
|
72
|
+
}
|
|
17
73
|
function showInitHelp() {
|
|
18
74
|
console.info(`
|
|
19
75
|
Usage: release-kit init [options]
|
|
@@ -41,6 +97,31 @@ Options:
|
|
|
41
97
|
--help, -h Show this help message
|
|
42
98
|
`);
|
|
43
99
|
}
|
|
100
|
+
function showTagHelp() {
|
|
101
|
+
console.info(`
|
|
102
|
+
Usage: release-kit tag [options]
|
|
103
|
+
|
|
104
|
+
Create annotated git tags from the tags file produced by \`prepare\`.
|
|
105
|
+
|
|
106
|
+
Options:
|
|
107
|
+
--dry-run Preview without creating tags
|
|
108
|
+
--no-git-checks Skip dirty working tree check
|
|
109
|
+
--help, -h Show this help message
|
|
110
|
+
`);
|
|
111
|
+
}
|
|
112
|
+
function showPublishHelp() {
|
|
113
|
+
console.info(`
|
|
114
|
+
Usage: release-kit publish [options]
|
|
115
|
+
|
|
116
|
+
Publish packages that have release tags on HEAD.
|
|
117
|
+
|
|
118
|
+
Options:
|
|
119
|
+
--dry-run Preview without publishing
|
|
120
|
+
--no-git-checks Skip git checks (pnpm only)
|
|
121
|
+
--only=name1,name2 Only publish the named packages (comma-separated, monorepo only)
|
|
122
|
+
--help, -h Show this help message
|
|
123
|
+
`);
|
|
124
|
+
}
|
|
44
125
|
const args = process.argv.slice(2);
|
|
45
126
|
const command = args[0];
|
|
46
127
|
const flags = args.slice(1);
|
|
@@ -56,6 +137,22 @@ if (command === "prepare") {
|
|
|
56
137
|
await prepareCommand(flags);
|
|
57
138
|
process.exit(0);
|
|
58
139
|
}
|
|
140
|
+
if (command === "tag") {
|
|
141
|
+
if (flags.some((f) => f === "--help" || f === "-h")) {
|
|
142
|
+
showTagHelp();
|
|
143
|
+
process.exit(0);
|
|
144
|
+
}
|
|
145
|
+
tagCommand(flags);
|
|
146
|
+
process.exit(0);
|
|
147
|
+
}
|
|
148
|
+
if (command === "publish") {
|
|
149
|
+
if (flags.some((f) => f === "--help" || f === "-h")) {
|
|
150
|
+
showPublishHelp();
|
|
151
|
+
process.exit(0);
|
|
152
|
+
}
|
|
153
|
+
await publishCommand(flags);
|
|
154
|
+
process.exit(0);
|
|
155
|
+
}
|
|
59
156
|
if (command === "init") {
|
|
60
157
|
if (flags.some((f) => f === "--help" || f === "-h")) {
|
|
61
158
|
showInitHelp();
|
|
@@ -73,6 +170,57 @@ if (command === "init") {
|
|
|
73
170
|
const exitCode = initCommand({ dryRun, force, withConfig });
|
|
74
171
|
process.exit(exitCode);
|
|
75
172
|
}
|
|
173
|
+
if (command === "sync-labels") {
|
|
174
|
+
const subcommand = flags[0];
|
|
175
|
+
const subflags = flags.slice(1);
|
|
176
|
+
if (subcommand === "--help" || subcommand === "-h" || subcommand === void 0) {
|
|
177
|
+
showSyncLabelsHelp();
|
|
178
|
+
process.exit(0);
|
|
179
|
+
}
|
|
180
|
+
if (subcommand === "init") {
|
|
181
|
+
if (subflags.some((f) => f === "--help" || f === "-h")) {
|
|
182
|
+
showSyncLabelsInitHelp();
|
|
183
|
+
process.exit(0);
|
|
184
|
+
}
|
|
185
|
+
const knownFlags = /* @__PURE__ */ new Set(["--dry-run", "--force", "--help", "-h"]);
|
|
186
|
+
const unknownFlags = subflags.filter((f) => !knownFlags.has(f));
|
|
187
|
+
if (unknownFlags.length > 0) {
|
|
188
|
+
console.error(`Error: Unknown option: ${unknownFlags[0]}`);
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
const dryRun = subflags.includes("--dry-run");
|
|
192
|
+
const force = subflags.includes("--force");
|
|
193
|
+
const exitCode = await syncLabelsInitCommand({ dryRun, force });
|
|
194
|
+
process.exit(exitCode);
|
|
195
|
+
}
|
|
196
|
+
if (subcommand === "generate") {
|
|
197
|
+
if (subflags.some((f) => f === "--help" || f === "-h")) {
|
|
198
|
+
showSyncLabelsGenerateHelp();
|
|
199
|
+
process.exit(0);
|
|
200
|
+
}
|
|
201
|
+
if (subflags.length > 0) {
|
|
202
|
+
console.error(`Error: Unknown option: ${subflags[0]}`);
|
|
203
|
+
process.exit(1);
|
|
204
|
+
}
|
|
205
|
+
const exitCode = await generateCommand();
|
|
206
|
+
process.exit(exitCode);
|
|
207
|
+
}
|
|
208
|
+
if (subcommand === "sync") {
|
|
209
|
+
if (subflags.some((f) => f === "--help" || f === "-h")) {
|
|
210
|
+
showSyncLabelsSyncHelp();
|
|
211
|
+
process.exit(0);
|
|
212
|
+
}
|
|
213
|
+
if (subflags.length > 0) {
|
|
214
|
+
console.error(`Error: Unknown option: ${subflags[0]}`);
|
|
215
|
+
process.exit(1);
|
|
216
|
+
}
|
|
217
|
+
const exitCode = syncLabelsCommand();
|
|
218
|
+
process.exit(exitCode);
|
|
219
|
+
}
|
|
220
|
+
console.error(`Error: Unknown subcommand: ${subcommand}`);
|
|
221
|
+
showSyncLabelsHelp();
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
76
224
|
console.error(`Error: Unknown command: ${command}`);
|
|
77
225
|
showUsage();
|
|
78
226
|
process.exit(1);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { ReleaseType } from './types.ts';
|
|
2
|
-
export declare function bumpAllVersions(packageFiles: readonly string[], releaseType: ReleaseType, dryRun: boolean):
|
|
1
|
+
import type { BumpResult, ReleaseType } from './types.ts';
|
|
2
|
+
export declare function bumpAllVersions(packageFiles: readonly string[], releaseType: ReleaseType, dryRun: boolean): BumpResult;
|
|
@@ -11,10 +11,8 @@ function bumpAllVersions(packageFiles, releaseType, dryRun) {
|
|
|
11
11
|
const firstPkg = readPackageJson(firstFile);
|
|
12
12
|
const currentVersion = firstPkg.version;
|
|
13
13
|
const newVersion = bumpVersion(currentVersion, releaseType);
|
|
14
|
-
console.info(`Bumping version: ${currentVersion} -> ${newVersion} (${releaseType})`);
|
|
15
14
|
for (const filePath of packageFiles) {
|
|
16
15
|
if (dryRun) {
|
|
17
|
-
console.info(` [dry-run] Would bump ${filePath}`);
|
|
18
16
|
continue;
|
|
19
17
|
}
|
|
20
18
|
const pkg = filePath === firstFile ? firstPkg : readPackageJson(filePath);
|
|
@@ -24,9 +22,8 @@ function bumpAllVersions(packageFiles, releaseType, dryRun) {
|
|
|
24
22
|
} catch (error) {
|
|
25
23
|
throw new Error(`Failed to write ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
26
24
|
}
|
|
27
|
-
console.info(` Bumped ${filePath}`);
|
|
28
25
|
}
|
|
29
|
-
return newVersion;
|
|
26
|
+
return { currentVersion, newVersion, files: [...packageFiles] };
|
|
30
27
|
}
|
|
31
28
|
function readPackageJson(filePath) {
|
|
32
29
|
let content;
|
package/dist/esm/component.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ComponentConfig } from './types.ts';
|
|
2
|
-
export declare function component(workspacePath: string
|
|
2
|
+
export declare function component(workspacePath: string): ComponentConfig;
|
package/dist/esm/component.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { basename } from "node:path";
|
|
2
|
-
function component(workspacePath
|
|
2
|
+
function component(workspacePath) {
|
|
3
3
|
const dir = basename(workspacePath);
|
|
4
|
-
const prefix = tagPrefix ?? `${dir}-v`;
|
|
5
4
|
return {
|
|
6
5
|
dir,
|
|
7
|
-
tagPrefix:
|
|
6
|
+
tagPrefix: `${dir}-v`,
|
|
8
7
|
packageFiles: [`${workspacePath}/package.json`],
|
|
9
8
|
changelogPaths: [workspacePath],
|
|
10
9
|
paths: [`${workspacePath}/**`]
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { readFileSync, unlinkSync } from "node:fs";
|
|
3
|
+
import { RELEASE_TAGS_FILE } from "./prepareCommand.js";
|
|
4
|
+
function createTags(options) {
|
|
5
|
+
const { dryRun, noGitChecks } = options;
|
|
6
|
+
let content;
|
|
7
|
+
try {
|
|
8
|
+
content = readFileSync(RELEASE_TAGS_FILE, "utf8");
|
|
9
|
+
} catch {
|
|
10
|
+
throw new Error("No tags file found. Run `release-kit prepare` first.");
|
|
11
|
+
}
|
|
12
|
+
const tags = content.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
13
|
+
if (tags.length === 0) {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
if (!dryRun && !noGitChecks) {
|
|
17
|
+
assertCleanWorkingTree();
|
|
18
|
+
}
|
|
19
|
+
if (dryRun) {
|
|
20
|
+
console.info("[dry-run] Would create tags:");
|
|
21
|
+
for (const tag of tags) {
|
|
22
|
+
console.info(`\u{1F3F7}\uFE0F ${tag}`);
|
|
23
|
+
}
|
|
24
|
+
return tags;
|
|
25
|
+
}
|
|
26
|
+
const created = [];
|
|
27
|
+
for (const tag of tags) {
|
|
28
|
+
try {
|
|
29
|
+
execFileSync("git", ["tag", "-a", tag, "-m", tag]);
|
|
30
|
+
created.push(tag);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
if (created.length > 0) {
|
|
33
|
+
console.warn("Tags created before failure:");
|
|
34
|
+
for (const t of created) {
|
|
35
|
+
console.warn(` ${t}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
console.info("Created tags:");
|
|
42
|
+
for (const tag of tags) {
|
|
43
|
+
console.info(`\u{1F3F7}\uFE0F ${tag}`);
|
|
44
|
+
}
|
|
45
|
+
deleteTagsFile();
|
|
46
|
+
return tags;
|
|
47
|
+
}
|
|
48
|
+
function deleteTagsFile() {
|
|
49
|
+
try {
|
|
50
|
+
unlinkSync(RELEASE_TAGS_FILE);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function assertCleanWorkingTree() {
|
|
59
|
+
try {
|
|
60
|
+
execFileSync("git", ["diff", "--quiet"]);
|
|
61
|
+
execFileSync("git", ["diff", "--quiet", "--cached"]);
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
throw new Error(
|
|
67
|
+
"Working tree is dirty. Commit or stash changes before tagging, or use `--no-git-checks` to skip this check."
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export {
|
|
72
|
+
createTags
|
|
73
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { isRecord } from "./typeGuards.js";
|
|
4
|
+
function detectPackageManager() {
|
|
5
|
+
const packageJsonPath = join(process.cwd(), "package.json");
|
|
6
|
+
try {
|
|
7
|
+
const content = readFileSync(packageJsonPath, "utf8");
|
|
8
|
+
const parsed = JSON.parse(content);
|
|
9
|
+
if (isRecord(parsed) && typeof parsed.packageManager === "string") {
|
|
10
|
+
const [name, version] = parsed.packageManager.split("@");
|
|
11
|
+
if (name === "pnpm" || name === "npm") {
|
|
12
|
+
return name;
|
|
13
|
+
}
|
|
14
|
+
if (name === "yarn") {
|
|
15
|
+
return isYarnBerry(version) ? "yarn-berry" : "yarn";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
} catch {
|
|
19
|
+
}
|
|
20
|
+
return detectFromLockfile();
|
|
21
|
+
}
|
|
22
|
+
function isYarnBerry(version) {
|
|
23
|
+
if (version === void 0) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const major = Number.parseInt(version, 10);
|
|
27
|
+
return !Number.isNaN(major) && major >= 2;
|
|
28
|
+
}
|
|
29
|
+
function detectFromLockfile() {
|
|
30
|
+
const cwd = process.cwd();
|
|
31
|
+
if (existsSync(join(cwd, "pnpm-lock.yaml"))) {
|
|
32
|
+
return "pnpm";
|
|
33
|
+
}
|
|
34
|
+
if (existsSync(join(cwd, "package-lock.json"))) {
|
|
35
|
+
return "npm";
|
|
36
|
+
}
|
|
37
|
+
if (existsSync(join(cwd, "yarn.lock"))) {
|
|
38
|
+
return "yarn";
|
|
39
|
+
}
|
|
40
|
+
return "npm";
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
detectPackageManager
|
|
44
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function findPackageRoot(fromUrl: string): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
function findPackageRoot(fromUrl) {
|
|
5
|
+
let dir = dirname(fileURLToPath(fromUrl));
|
|
6
|
+
while (!existsSync(resolve(dir, "package.json"))) {
|
|
7
|
+
const parent = dirname(dir);
|
|
8
|
+
if (parent === dir) {
|
|
9
|
+
throw new Error("Could not find package root from " + fromUrl);
|
|
10
|
+
}
|
|
11
|
+
dir = parent;
|
|
12
|
+
}
|
|
13
|
+
return dir;
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
findPackageRoot
|
|
17
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
function bold(text) {
|
|
2
|
+
return `\x1B[1m${text}\x1B[0m`;
|
|
3
|
+
}
|
|
4
|
+
function dim(text) {
|
|
5
|
+
return `\x1B[2m${text}\x1B[0m`;
|
|
6
|
+
}
|
|
7
|
+
function sectionHeader(name) {
|
|
8
|
+
return `\u2501\u2501\u2501 ${name} \u2501\u2501\u2501`;
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
bold,
|
|
12
|
+
dim,
|
|
13
|
+
sectionHeader
|
|
14
|
+
};
|
|
@@ -2,5 +2,5 @@ import type { ReleaseConfig } from './types.ts';
|
|
|
2
2
|
export interface GenerateChangelogOptions {
|
|
3
3
|
includePaths?: string[];
|
|
4
4
|
}
|
|
5
|
-
export declare function generateChangelog(config: Pick<ReleaseConfig, 'cliffConfigPath'>, changelogPath: string, tag: string, dryRun: boolean, options?: GenerateChangelogOptions):
|
|
6
|
-
export declare function generateChangelogs(config: ReleaseConfig, tag: string, dryRun: boolean):
|
|
5
|
+
export declare function generateChangelog(config: Pick<ReleaseConfig, 'cliffConfigPath'>, changelogPath: string, tag: string, dryRun: boolean, options?: GenerateChangelogOptions): string[];
|
|
6
|
+
export declare function generateChangelogs(config: ReleaseConfig, tag: string, dryRun: boolean): string[];
|
|
@@ -7,23 +7,23 @@ function generateChangelog(config, changelogPath, tag, dryRun, options) {
|
|
|
7
7
|
for (const includePath of options?.includePaths ?? []) {
|
|
8
8
|
args.push("--include-path", includePath);
|
|
9
9
|
}
|
|
10
|
-
if (dryRun) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
throw new Error(
|
|
19
|
-
`Failed to generate changelog for ${outputFile}: ${error instanceof Error ? error.message : String(error)}`
|
|
20
|
-
);
|
|
10
|
+
if (!dryRun) {
|
|
11
|
+
try {
|
|
12
|
+
execFileSync("npx", ["--yes", "git-cliff", ...args], { stdio: "inherit" });
|
|
13
|
+
} catch (error) {
|
|
14
|
+
throw new Error(
|
|
15
|
+
`Failed to generate changelog for ${outputFile}: ${error instanceof Error ? error.message : String(error)}`
|
|
16
|
+
);
|
|
17
|
+
}
|
|
21
18
|
}
|
|
19
|
+
return [outputFile];
|
|
22
20
|
}
|
|
23
21
|
function generateChangelogs(config, tag, dryRun) {
|
|
22
|
+
const results = [];
|
|
24
23
|
for (const changelogPath of config.changelogPaths) {
|
|
25
|
-
generateChangelog(config, changelogPath, tag, dryRun);
|
|
24
|
+
results.push(...generateChangelog(config, changelogPath, tag, dryRun));
|
|
26
25
|
}
|
|
26
|
+
return results;
|
|
27
27
|
}
|
|
28
28
|
export {
|
|
29
29
|
generateChangelog,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function hasPrettierConfig(): boolean;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { isRecord } from "./typeGuards.js";
|
|
4
|
+
function hasPrettierConfig() {
|
|
5
|
+
const cwd = process.cwd();
|
|
6
|
+
for (const file of PRETTIER_CONFIG_FILES) {
|
|
7
|
+
if (existsSync(path.join(cwd, file))) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return hasPrettierKeyInPackageJson(path.join(cwd, "package.json"));
|
|
12
|
+
}
|
|
13
|
+
function hasPrettierKeyInPackageJson(packageJsonPath) {
|
|
14
|
+
if (!existsSync(packageJsonPath)) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
19
|
+
return isRecord(parsed) && "prettier" in parsed;
|
|
20
|
+
} catch {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const PRETTIER_CONFIG_FILES = [
|
|
25
|
+
".prettierrc",
|
|
26
|
+
".prettierrc.cjs",
|
|
27
|
+
".prettierrc.js",
|
|
28
|
+
".prettierrc.json",
|
|
29
|
+
".prettierrc.json5",
|
|
30
|
+
".prettierrc.mjs",
|
|
31
|
+
".prettierrc.toml",
|
|
32
|
+
".prettierrc.ts",
|
|
33
|
+
".prettierrc.yaml",
|
|
34
|
+
".prettierrc.yml",
|
|
35
|
+
"prettier.config.cjs",
|
|
36
|
+
"prettier.config.js",
|
|
37
|
+
"prettier.config.mjs",
|
|
38
|
+
"prettier.config.ts"
|
|
39
|
+
];
|
|
40
|
+
export {
|
|
41
|
+
hasPrettierConfig
|
|
42
|
+
};
|