@williamthorsen/release-kit 2.3.2 → 4.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +90 -24
- package/README.md +123 -173
- package/bin/release-kit.js +10 -1
- package/cliff.toml.template +13 -12
- package/dist/esm/.cache +1 -1
- package/dist/esm/bin/release-kit.js +55 -13
- package/dist/esm/buildDependencyGraph.d.ts +7 -0
- package/dist/esm/buildDependencyGraph.js +59 -0
- package/dist/esm/buildReleaseSummary.d.ts +2 -0
- package/dist/esm/buildReleaseSummary.js +22 -0
- package/dist/esm/commitCommand.d.ts +1 -0
- package/dist/esm/commitCommand.js +60 -0
- package/dist/esm/createTags.js +5 -13
- package/dist/esm/deleteFileIfExists.d.ts +1 -0
- package/dist/esm/deleteFileIfExists.js +14 -0
- package/dist/esm/determineBumpFromCommits.d.ts +1 -1
- package/dist/esm/determineBumpFromCommits.js +2 -2
- package/dist/esm/generateChangelogs.d.ts +2 -0
- package/dist/esm/generateChangelogs.js +9 -1
- package/dist/esm/index.d.ts +5 -1
- package/dist/esm/index.js +10 -1
- package/dist/esm/init/initCommand.js +4 -2
- package/dist/esm/init/scaffold.js +3 -2
- package/dist/esm/init/templates.d.ts +1 -0
- package/dist/esm/init/templates.js +24 -2
- package/dist/esm/loadConfig.js +6 -6
- package/dist/esm/parseCommitMessage.d.ts +1 -1
- package/dist/esm/parseCommitMessage.js +9 -7
- package/dist/esm/prepareCommand.d.ts +1 -0
- package/dist/esm/prepareCommand.js +64 -34
- package/dist/esm/propagateBumps.d.ts +8 -0
- package/dist/esm/propagateBumps.js +54 -0
- package/dist/esm/publish.d.ts +1 -0
- package/dist/esm/publish.js +6 -3
- package/dist/esm/publishCommand.js +15 -9
- package/dist/esm/releasePrepare.js +2 -1
- package/dist/esm/releasePrepareMono.js +237 -48
- package/dist/esm/reportPrepare.js +29 -3
- package/dist/esm/stripScope.d.ts +1 -0
- package/dist/esm/stripScope.js +24 -0
- package/dist/esm/sync-labels/templates.js +1 -1
- package/dist/esm/tagCommand.js +11 -6
- package/dist/esm/types.d.ts +11 -4
- package/dist/esm/validateConfig.js +6 -6
- package/dist/esm/version.d.ts +1 -0
- package/dist/esm/version.js +4 -0
- package/dist/esm/writeSyntheticChangelog.d.ts +9 -0
- package/dist/esm/writeSyntheticChangelog.js +27 -0
- package/package.json +2 -2
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { parseArgs, translateParseError } from "@williamthorsen/node-monorepo-core";
|
|
3
|
+
import { commitCommand } from "../commitCommand.js";
|
|
2
4
|
import { initCommand } from "../init/initCommand.js";
|
|
3
5
|
import { prepareCommand } from "../prepareCommand.js";
|
|
4
6
|
import { publishCommand } from "../publishCommand.js";
|
|
@@ -6,12 +8,14 @@ import { generateCommand } from "../sync-labels/generateCommand.js";
|
|
|
6
8
|
import { syncLabelsInitCommand } from "../sync-labels/initCommand.js";
|
|
7
9
|
import { syncLabelsCommand } from "../sync-labels/syncCommand.js";
|
|
8
10
|
import { tagCommand } from "../tagCommand.js";
|
|
11
|
+
import { VERSION } from "../version.js";
|
|
9
12
|
function showUsage() {
|
|
10
13
|
console.info(`
|
|
11
14
|
Usage: release-kit <command> [options]
|
|
12
15
|
|
|
13
16
|
Commands:
|
|
14
17
|
prepare Run release preparation (auto-discovers workspaces)
|
|
18
|
+
commit Stage changes and create the release commit
|
|
15
19
|
tag Create annotated git tags from the tags file
|
|
16
20
|
publish Publish packages with release tags on HEAD
|
|
17
21
|
init Initialize release-kit in the current repository
|
|
@@ -97,6 +101,18 @@ Options:
|
|
|
97
101
|
--help, -h Show this help message
|
|
98
102
|
`);
|
|
99
103
|
}
|
|
104
|
+
function showCommitHelp() {
|
|
105
|
+
console.info(`
|
|
106
|
+
Usage: release-kit commit [options]
|
|
107
|
+
|
|
108
|
+
Stage all changes and create the release commit using tags and summary
|
|
109
|
+
produced by \`prepare\`.
|
|
110
|
+
|
|
111
|
+
Options:
|
|
112
|
+
--dry-run Preview the commit message without creating it
|
|
113
|
+
--help, -h Show this help message
|
|
114
|
+
`);
|
|
115
|
+
}
|
|
100
116
|
function showTagHelp() {
|
|
101
117
|
console.info(`
|
|
102
118
|
Usage: release-kit tag [options]
|
|
@@ -119,12 +135,17 @@ Options:
|
|
|
119
135
|
--dry-run Preview without publishing
|
|
120
136
|
--no-git-checks Skip git checks (pnpm only)
|
|
121
137
|
--only=name1,name2 Only publish the named packages (comma-separated, monorepo only)
|
|
138
|
+
--provenance Generate provenance statement (requires OIDC, not supported by classic yarn)
|
|
122
139
|
--help, -h Show this help message
|
|
123
140
|
`);
|
|
124
141
|
}
|
|
125
142
|
const args = process.argv.slice(2);
|
|
126
143
|
const command = args[0];
|
|
127
144
|
const flags = args.slice(1);
|
|
145
|
+
if (command === "--version" || command === "-V") {
|
|
146
|
+
console.info(VERSION);
|
|
147
|
+
process.exit(0);
|
|
148
|
+
}
|
|
128
149
|
if (command === "--help" || command === "-h" || command === void 0) {
|
|
129
150
|
showUsage();
|
|
130
151
|
process.exit(0);
|
|
@@ -137,6 +158,19 @@ if (command === "prepare") {
|
|
|
137
158
|
await prepareCommand(flags);
|
|
138
159
|
process.exit(0);
|
|
139
160
|
}
|
|
161
|
+
if (command === "commit") {
|
|
162
|
+
if (flags.some((f) => f === "--help" || f === "-h")) {
|
|
163
|
+
showCommitHelp();
|
|
164
|
+
process.exit(0);
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
commitCommand(flags);
|
|
168
|
+
} catch (error) {
|
|
169
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
process.exit(0);
|
|
173
|
+
}
|
|
140
174
|
if (command === "tag") {
|
|
141
175
|
if (flags.some((f) => f === "--help" || f === "-h")) {
|
|
142
176
|
showTagHelp();
|
|
@@ -158,15 +192,19 @@ if (command === "init") {
|
|
|
158
192
|
showInitHelp();
|
|
159
193
|
process.exit(0);
|
|
160
194
|
}
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
195
|
+
const initFlagSchema = {
|
|
196
|
+
dryRun: { long: "--dry-run", type: "boolean" },
|
|
197
|
+
force: { long: "--force", type: "boolean" },
|
|
198
|
+
withConfig: { long: "--with-config", type: "boolean" }
|
|
199
|
+
};
|
|
200
|
+
let parsed;
|
|
201
|
+
try {
|
|
202
|
+
parsed = parseArgs(flags, initFlagSchema);
|
|
203
|
+
} catch (error) {
|
|
204
|
+
console.error(`Error: ${translateParseError(error)}`);
|
|
165
205
|
process.exit(1);
|
|
166
206
|
}
|
|
167
|
-
const dryRun = flags
|
|
168
|
-
const force = flags.includes("--force");
|
|
169
|
-
const withConfig = flags.includes("--with-config");
|
|
207
|
+
const { dryRun, force, withConfig } = parsed.flags;
|
|
170
208
|
const exitCode = initCommand({ dryRun, force, withConfig });
|
|
171
209
|
process.exit(exitCode);
|
|
172
210
|
}
|
|
@@ -182,14 +220,18 @@ if (command === "sync-labels") {
|
|
|
182
220
|
showSyncLabelsInitHelp();
|
|
183
221
|
process.exit(0);
|
|
184
222
|
}
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
223
|
+
const syncLabelsInitFlagSchema = {
|
|
224
|
+
dryRun: { long: "--dry-run", type: "boolean" },
|
|
225
|
+
force: { long: "--force", type: "boolean" }
|
|
226
|
+
};
|
|
227
|
+
let syncParsed;
|
|
228
|
+
try {
|
|
229
|
+
syncParsed = parseArgs(subflags, syncLabelsInitFlagSchema);
|
|
230
|
+
} catch (error) {
|
|
231
|
+
console.error(`Error: ${translateParseError(error)}`);
|
|
189
232
|
process.exit(1);
|
|
190
233
|
}
|
|
191
|
-
const dryRun =
|
|
192
|
-
const force = subflags.includes("--force");
|
|
234
|
+
const { dryRun, force } = syncParsed.flags;
|
|
193
235
|
const exitCode = await syncLabelsInitCommand({ dryRun, force });
|
|
194
236
|
process.exit(exitCode);
|
|
195
237
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ComponentConfig } from './types.ts';
|
|
2
|
+
export interface DependencyGraph {
|
|
3
|
+
packageNameToDir: Map<string, string>;
|
|
4
|
+
dirToPackageName: Map<string, string>;
|
|
5
|
+
dependentsOf: Map<string, ComponentConfig[]>;
|
|
6
|
+
}
|
|
7
|
+
export declare function buildDependencyGraph(components: readonly ComponentConfig[]): DependencyGraph;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
function isPackageJsonSubset(value) {
|
|
3
|
+
return typeof value === "object" && value !== null;
|
|
4
|
+
}
|
|
5
|
+
function buildDependencyGraph(components) {
|
|
6
|
+
const packageNameToDir = /* @__PURE__ */ new Map();
|
|
7
|
+
const dirToPackageName = /* @__PURE__ */ new Map();
|
|
8
|
+
const dependentsOf = /* @__PURE__ */ new Map();
|
|
9
|
+
const componentPackages = /* @__PURE__ */ new Map();
|
|
10
|
+
for (const component of components) {
|
|
11
|
+
const primaryPackageFile = component.packageFiles[0];
|
|
12
|
+
if (primaryPackageFile === void 0) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
const pkg = readPackageJsonSubset(primaryPackageFile);
|
|
16
|
+
componentPackages.set(component, pkg);
|
|
17
|
+
if (pkg.name === void 0) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
packageNameToDir.set(pkg.name, component.dir);
|
|
21
|
+
dirToPackageName.set(component.dir, pkg.name);
|
|
22
|
+
}
|
|
23
|
+
for (const [component, pkg] of componentPackages) {
|
|
24
|
+
const allDeps = { ...pkg.dependencies, ...pkg.peerDependencies };
|
|
25
|
+
for (const [depName, depVersion] of Object.entries(allDeps)) {
|
|
26
|
+
if (typeof depVersion !== "string" || !depVersion.startsWith("workspace:")) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const existing = dependentsOf.get(depName);
|
|
30
|
+
if (existing === void 0) {
|
|
31
|
+
dependentsOf.set(depName, [component]);
|
|
32
|
+
} else {
|
|
33
|
+
existing.push(component);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { packageNameToDir, dirToPackageName, dependentsOf };
|
|
38
|
+
}
|
|
39
|
+
function readPackageJsonSubset(filePath) {
|
|
40
|
+
let content;
|
|
41
|
+
try {
|
|
42
|
+
content = readFileSync(filePath, "utf8");
|
|
43
|
+
} catch (error) {
|
|
44
|
+
throw new Error(`Failed to read ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
45
|
+
}
|
|
46
|
+
let parsed;
|
|
47
|
+
try {
|
|
48
|
+
parsed = JSON.parse(content);
|
|
49
|
+
} catch (error) {
|
|
50
|
+
throw new Error(`Failed to parse JSON in ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
51
|
+
}
|
|
52
|
+
if (!isPackageJsonSubset(parsed)) {
|
|
53
|
+
throw new Error(`Invalid package.json at ${filePath}`);
|
|
54
|
+
}
|
|
55
|
+
return parsed;
|
|
56
|
+
}
|
|
57
|
+
export {
|
|
58
|
+
buildDependencyGraph
|
|
59
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { stripScope } from "./stripScope.js";
|
|
2
|
+
function buildReleaseSummary(result) {
|
|
3
|
+
const sections = [];
|
|
4
|
+
for (const component of result.components) {
|
|
5
|
+
if (component.status !== "released" || component.tag === void 0) {
|
|
6
|
+
continue;
|
|
7
|
+
}
|
|
8
|
+
const commits = component.commits;
|
|
9
|
+
if (commits === void 0 || commits.length === 0) {
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
const lines = [component.tag];
|
|
13
|
+
for (const commit of commits) {
|
|
14
|
+
lines.push(`- ${stripScope(commit.message)}`);
|
|
15
|
+
}
|
|
16
|
+
sections.push(lines.join("\n"));
|
|
17
|
+
}
|
|
18
|
+
return sections.join("\n\n");
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
buildReleaseSummary
|
|
22
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function commitCommand(argv: string[]): void;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { parseArgs, translateParseError } from "@williamthorsen/node-monorepo-core";
|
|
4
|
+
import { RELEASE_SUMMARY_FILE, RELEASE_TAGS_FILE } from "./prepareCommand.js";
|
|
5
|
+
const commitFlagSchema = {
|
|
6
|
+
dryRun: { long: "--dry-run", type: "boolean" }
|
|
7
|
+
};
|
|
8
|
+
function commitCommand(argv) {
|
|
9
|
+
let parsed;
|
|
10
|
+
try {
|
|
11
|
+
parsed = parseArgs(argv, commitFlagSchema);
|
|
12
|
+
} catch (error) {
|
|
13
|
+
console.error(`Error: ${translateParseError(error)}`);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
const dryRun = parsed.flags.dryRun;
|
|
17
|
+
let tagsContent;
|
|
18
|
+
try {
|
|
19
|
+
tagsContent = readFileSync(RELEASE_TAGS_FILE, "utf8");
|
|
20
|
+
} catch {
|
|
21
|
+
throw new Error("No tags file found. Run `release-kit prepare` first.");
|
|
22
|
+
}
|
|
23
|
+
const tags = tagsContent.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
24
|
+
if (tags.length === 0) {
|
|
25
|
+
throw new Error("Tags file is empty. Run `release-kit prepare` first.");
|
|
26
|
+
}
|
|
27
|
+
let summary = "";
|
|
28
|
+
try {
|
|
29
|
+
summary = readFileSync(RELEASE_SUMMARY_FILE, "utf8").trim();
|
|
30
|
+
} catch (error) {
|
|
31
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
32
|
+
} else {
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const title = `release: ${tags.join(" ")}`;
|
|
37
|
+
const message = summary.length > 0 ? `${title}
|
|
38
|
+
|
|
39
|
+
${summary}` : title;
|
|
40
|
+
if (dryRun) {
|
|
41
|
+
console.info("[dry-run] Would create commit with message:\n");
|
|
42
|
+
console.info(message);
|
|
43
|
+
try {
|
|
44
|
+
const status = execFileSync("git", ["status", "--porcelain"], { encoding: "utf8" });
|
|
45
|
+
if (status.trim().length > 0) {
|
|
46
|
+
console.info("\nUncommitted changes:");
|
|
47
|
+
console.info(status.trimEnd());
|
|
48
|
+
}
|
|
49
|
+
} catch {
|
|
50
|
+
console.info("(Could not determine uncommitted changes)");
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
execFileSync("git", ["add", "-A"]);
|
|
55
|
+
execFileSync("git", ["commit", "-m", message]);
|
|
56
|
+
console.info(`Created release commit: ${title}`);
|
|
57
|
+
}
|
|
58
|
+
export {
|
|
59
|
+
commitCommand
|
|
60
|
+
};
|
package/dist/esm/createTags.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
|
-
import { readFileSync
|
|
3
|
-
import {
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { deleteFileIfExists } from "./deleteFileIfExists.js";
|
|
4
|
+
import { RELEASE_SUMMARY_FILE, RELEASE_TAGS_FILE } from "./prepareCommand.js";
|
|
4
5
|
function createTags(options) {
|
|
5
6
|
const { dryRun, noGitChecks } = options;
|
|
6
7
|
let content;
|
|
@@ -42,19 +43,10 @@ function createTags(options) {
|
|
|
42
43
|
for (const tag of tags) {
|
|
43
44
|
console.info(`\u{1F3F7}\uFE0F ${tag}`);
|
|
44
45
|
}
|
|
45
|
-
|
|
46
|
+
deleteFileIfExists(RELEASE_TAGS_FILE);
|
|
47
|
+
deleteFileIfExists(RELEASE_SUMMARY_FILE);
|
|
46
48
|
return tags;
|
|
47
49
|
}
|
|
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
50
|
function assertCleanWorkingTree() {
|
|
59
51
|
try {
|
|
60
52
|
execFileSync("git", ["diff", "--quiet"]);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function deleteFileIfExists(filePath: string): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { unlinkSync } from "node:fs";
|
|
2
|
+
function deleteFileIfExists(filePath) {
|
|
3
|
+
try {
|
|
4
|
+
unlinkSync(filePath);
|
|
5
|
+
} catch (error) {
|
|
6
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
throw error;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export {
|
|
13
|
+
deleteFileIfExists
|
|
14
|
+
};
|
|
@@ -4,4 +4,4 @@ export interface BumpDetermination {
|
|
|
4
4
|
parsedCommitCount: number;
|
|
5
5
|
unparseableCommits: Commit[] | undefined;
|
|
6
6
|
}
|
|
7
|
-
export declare function determineBumpFromCommits(commits: Commit[], workTypes: Record<string, WorkTypeConfig>, versionPatterns: VersionPatterns,
|
|
7
|
+
export declare function determineBumpFromCommits(commits: Commit[], workTypes: Record<string, WorkTypeConfig>, versionPatterns: VersionPatterns, scopeAliases: Record<string, string> | undefined): BumpDetermination;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { determineBumpType } from "./determineBumpType.js";
|
|
2
2
|
import { parseCommitMessage } from "./parseCommitMessage.js";
|
|
3
|
-
function determineBumpFromCommits(commits, workTypes, versionPatterns,
|
|
3
|
+
function determineBumpFromCommits(commits, workTypes, versionPatterns, scopeAliases) {
|
|
4
4
|
const parsedCommits = [];
|
|
5
5
|
const unparseable = [];
|
|
6
6
|
for (const commit of commits) {
|
|
7
|
-
const parsed = parseCommitMessage(commit.message, commit.hash, workTypes,
|
|
7
|
+
const parsed = parseCommitMessage(commit.message, commit.hash, workTypes, scopeAliases);
|
|
8
8
|
if (parsed === void 0) {
|
|
9
9
|
unparseable.push(commit);
|
|
10
10
|
} else {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ReleaseConfig } from './types.ts';
|
|
2
|
+
export declare function buildTagPattern(tagPrefix: string): string;
|
|
2
3
|
export interface GenerateChangelogOptions {
|
|
4
|
+
tagPattern?: string;
|
|
3
5
|
includePaths?: string[];
|
|
4
6
|
}
|
|
5
7
|
export declare function generateChangelog(config: Pick<ReleaseConfig, 'cliffConfigPath'>, changelogPath: string, tag: string, dryRun: boolean, options?: GenerateChangelogOptions): string[];
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
2
|
import { resolveCliffConfigPath } from "./resolveCliffConfigPath.js";
|
|
3
|
+
function buildTagPattern(tagPrefix) {
|
|
4
|
+
return `${tagPrefix}[0-9].*`;
|
|
5
|
+
}
|
|
3
6
|
function generateChangelog(config, changelogPath, tag, dryRun, options) {
|
|
4
7
|
const cliffConfigPath = resolveCliffConfigPath(config.cliffConfigPath, import.meta.url);
|
|
5
8
|
const outputFile = `${changelogPath}/CHANGELOG.md`;
|
|
6
9
|
const args = ["--config", cliffConfigPath, "--output", outputFile, "--tag", tag];
|
|
10
|
+
if (options?.tagPattern !== void 0) {
|
|
11
|
+
args.push("--tag-pattern", options.tagPattern);
|
|
12
|
+
}
|
|
7
13
|
for (const includePath of options?.includePaths ?? []) {
|
|
8
14
|
args.push("--include-path", includePath);
|
|
9
15
|
}
|
|
@@ -19,13 +25,15 @@ function generateChangelog(config, changelogPath, tag, dryRun, options) {
|
|
|
19
25
|
return [outputFile];
|
|
20
26
|
}
|
|
21
27
|
function generateChangelogs(config, tag, dryRun) {
|
|
28
|
+
const tagPattern = buildTagPattern(config.tagPrefix);
|
|
22
29
|
const results = [];
|
|
23
30
|
for (const changelogPath of config.changelogPaths) {
|
|
24
|
-
results.push(...generateChangelog(config, changelogPath, tag, dryRun));
|
|
31
|
+
results.push(...generateChangelog(config, changelogPath, tag, dryRun, { tagPattern }));
|
|
25
32
|
}
|
|
26
33
|
return results;
|
|
27
34
|
}
|
|
28
35
|
export {
|
|
36
|
+
buildTagPattern,
|
|
29
37
|
generateChangelog,
|
|
30
38
|
generateChangelogs
|
|
31
39
|
};
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -7,19 +7,23 @@ export type { ResolvedTag } from './resolveReleaseTags.ts';
|
|
|
7
7
|
export type { LabelDefinition, SyncLabelsConfig } from './sync-labels/types.ts';
|
|
8
8
|
export type { BumpResult, Commit, ComponentConfig, ComponentOverride, ComponentPrepareResult, MonorepoReleaseConfig, ParsedCommit, PrepareResult, ReleaseConfig, ReleaseKitConfig, ReleaseType, VersionPatterns, WorkTypeConfig, } from './types.ts';
|
|
9
9
|
export { DEFAULT_VERSION_PATTERNS, DEFAULT_WORK_TYPES } from './defaults.ts';
|
|
10
|
+
export { buildReleaseSummary } from './buildReleaseSummary.ts';
|
|
10
11
|
export { bumpAllVersions } from './bumpAllVersions.ts';
|
|
11
12
|
export { bumpVersion } from './bumpVersion.ts';
|
|
13
|
+
export { commitCommand } from './commitCommand.ts';
|
|
12
14
|
export { component } from './component.ts';
|
|
13
15
|
export { createTags } from './createTags.ts';
|
|
16
|
+
export { deleteFileIfExists } from './deleteFileIfExists.ts';
|
|
14
17
|
export { detectPackageManager } from './detectPackageManager.ts';
|
|
15
18
|
export { determineBumpType } from './determineBumpType.ts';
|
|
16
19
|
export { discoverWorkspaces } from './discoverWorkspaces.ts';
|
|
17
20
|
export { generateChangelog, generateChangelogs } from './generateChangelogs.ts';
|
|
18
21
|
export { getCommitsSinceTarget } from './getCommitsSinceTarget.ts';
|
|
19
22
|
export { COMMIT_PREPROCESSOR_PATTERNS, parseCommitMessage } from './parseCommitMessage.ts';
|
|
20
|
-
export { RELEASE_TAGS_FILE, writeReleaseTags } from './prepareCommand.ts';
|
|
23
|
+
export { RELEASE_SUMMARY_FILE, RELEASE_TAGS_FILE, writeReleaseTags } from './prepareCommand.ts';
|
|
21
24
|
export { publish } from './publish.ts';
|
|
22
25
|
export { releasePrepare } from './releasePrepare.ts';
|
|
23
26
|
export { releasePrepareMono } from './releasePrepareMono.ts';
|
|
24
27
|
export { reportPrepare } from './reportPrepare.ts';
|
|
25
28
|
export { resolveReleaseTags } from './resolveReleaseTags.ts';
|
|
29
|
+
export { stripScope } from './stripScope.ts';
|
package/dist/esm/index.js
CHANGED
|
@@ -1,29 +1,37 @@
|
|
|
1
1
|
import { DEFAULT_VERSION_PATTERNS, DEFAULT_WORK_TYPES } from "./defaults.js";
|
|
2
|
+
import { buildReleaseSummary } from "./buildReleaseSummary.js";
|
|
2
3
|
import { bumpAllVersions } from "./bumpAllVersions.js";
|
|
3
4
|
import { bumpVersion } from "./bumpVersion.js";
|
|
5
|
+
import { commitCommand } from "./commitCommand.js";
|
|
4
6
|
import { component } from "./component.js";
|
|
5
7
|
import { createTags } from "./createTags.js";
|
|
8
|
+
import { deleteFileIfExists } from "./deleteFileIfExists.js";
|
|
6
9
|
import { detectPackageManager } from "./detectPackageManager.js";
|
|
7
10
|
import { determineBumpType } from "./determineBumpType.js";
|
|
8
11
|
import { discoverWorkspaces } from "./discoverWorkspaces.js";
|
|
9
12
|
import { generateChangelog, generateChangelogs } from "./generateChangelogs.js";
|
|
10
13
|
import { getCommitsSinceTarget } from "./getCommitsSinceTarget.js";
|
|
11
14
|
import { COMMIT_PREPROCESSOR_PATTERNS, parseCommitMessage } from "./parseCommitMessage.js";
|
|
12
|
-
import { RELEASE_TAGS_FILE, writeReleaseTags } from "./prepareCommand.js";
|
|
15
|
+
import { RELEASE_SUMMARY_FILE, RELEASE_TAGS_FILE, writeReleaseTags } from "./prepareCommand.js";
|
|
13
16
|
import { publish } from "./publish.js";
|
|
14
17
|
import { releasePrepare } from "./releasePrepare.js";
|
|
15
18
|
import { releasePrepareMono } from "./releasePrepareMono.js";
|
|
16
19
|
import { reportPrepare } from "./reportPrepare.js";
|
|
17
20
|
import { resolveReleaseTags } from "./resolveReleaseTags.js";
|
|
21
|
+
import { stripScope } from "./stripScope.js";
|
|
18
22
|
export {
|
|
19
23
|
COMMIT_PREPROCESSOR_PATTERNS,
|
|
20
24
|
DEFAULT_VERSION_PATTERNS,
|
|
21
25
|
DEFAULT_WORK_TYPES,
|
|
26
|
+
RELEASE_SUMMARY_FILE,
|
|
22
27
|
RELEASE_TAGS_FILE,
|
|
28
|
+
buildReleaseSummary,
|
|
23
29
|
bumpAllVersions,
|
|
24
30
|
bumpVersion,
|
|
31
|
+
commitCommand,
|
|
25
32
|
component,
|
|
26
33
|
createTags,
|
|
34
|
+
deleteFileIfExists,
|
|
27
35
|
detectPackageManager,
|
|
28
36
|
determineBumpType,
|
|
29
37
|
discoverWorkspaces,
|
|
@@ -36,5 +44,6 @@ export {
|
|
|
36
44
|
releasePrepareMono,
|
|
37
45
|
reportPrepare,
|
|
38
46
|
resolveReleaseTags,
|
|
47
|
+
stripScope,
|
|
39
48
|
writeReleaseTags
|
|
40
49
|
};
|
|
@@ -56,8 +56,10 @@ function initCommand({ dryRun, force, withConfig }) {
|
|
|
56
56
|
const configHint = withConfig ? "1. (Optional) Customize .config/release-kit.config.ts and .config/git-cliff.toml." : "1. (Optional) Run again with --with-config to scaffold config files.";
|
|
57
57
|
console.info(`
|
|
58
58
|
${configHint}
|
|
59
|
-
2.
|
|
60
|
-
3.
|
|
59
|
+
2. If this is a public repo, set provenance: true in .github/workflows/publish.yaml.
|
|
60
|
+
3. Test by running: npx @williamthorsen/release-kit prepare --dry-run
|
|
61
|
+
4. Commit the generated files.
|
|
62
|
+
5. Register each package as a trusted publisher on npmjs.com.
|
|
61
63
|
`);
|
|
62
64
|
return 0;
|
|
63
65
|
}
|
|
@@ -2,7 +2,7 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { writeFileWithCheck } from "@williamthorsen/node-monorepo-core";
|
|
4
4
|
import { findPackageRoot } from "../findPackageRoot.js";
|
|
5
|
-
import { releaseConfigScript, releaseWorkflow } from "./templates.js";
|
|
5
|
+
import { publishWorkflow, releaseConfigScript, releaseWorkflow } from "./templates.js";
|
|
6
6
|
function copyCliffTemplate(dryRun, overwrite) {
|
|
7
7
|
const destPath = ".config/git-cliff.toml";
|
|
8
8
|
const root = findPackageRoot(import.meta.url);
|
|
@@ -21,7 +21,8 @@ function copyCliffTemplate(dryRun, overwrite) {
|
|
|
21
21
|
}
|
|
22
22
|
function scaffoldFiles({ repoType, dryRun, overwrite, withConfig }) {
|
|
23
23
|
const results = [
|
|
24
|
-
writeFileWithCheck(".github/workflows/release.yaml", releaseWorkflow(repoType), { dryRun, overwrite })
|
|
24
|
+
writeFileWithCheck(".github/workflows/release.yaml", releaseWorkflow(repoType), { dryRun, overwrite }),
|
|
25
|
+
writeFileWithCheck(".github/workflows/publish.yaml", publishWorkflow(repoType), { dryRun, overwrite })
|
|
25
26
|
];
|
|
26
27
|
if (withConfig) {
|
|
27
28
|
results.push(
|
|
@@ -35,6 +35,27 @@ const config: ReleaseKitConfig = {
|
|
|
35
35
|
export default config;
|
|
36
36
|
`;
|
|
37
37
|
}
|
|
38
|
+
function publishWorkflow(repoType) {
|
|
39
|
+
const tagPattern = repoType === "monorepo" ? "'*-v[0-9]*'" : "'v[0-9]*'";
|
|
40
|
+
return `# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
|
41
|
+
name: Publish
|
|
42
|
+
|
|
43
|
+
on:
|
|
44
|
+
push:
|
|
45
|
+
tags:
|
|
46
|
+
- ${tagPattern}
|
|
47
|
+
|
|
48
|
+
permissions:
|
|
49
|
+
id-token: write
|
|
50
|
+
contents: read
|
|
51
|
+
|
|
52
|
+
jobs:
|
|
53
|
+
publish:
|
|
54
|
+
uses: williamthorsen/node-monorepo-tools/.github/workflows/publish.reusable.yaml@publish-workflow-v1
|
|
55
|
+
with:
|
|
56
|
+
provenance: false # Set to true for public repos to generate npm provenance attestations
|
|
57
|
+
`;
|
|
58
|
+
}
|
|
38
59
|
function releaseWorkflow(repoType) {
|
|
39
60
|
if (repoType === "monorepo") {
|
|
40
61
|
return `# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
|
@@ -68,7 +89,7 @@ permissions:
|
|
|
68
89
|
|
|
69
90
|
jobs:
|
|
70
91
|
release:
|
|
71
|
-
uses: williamthorsen/node-monorepo-tools/.github/workflows/release
|
|
92
|
+
uses: williamthorsen/node-monorepo-tools/.github/workflows/release.reusable.yaml@release-workflow-v1
|
|
72
93
|
with:
|
|
73
94
|
only: \${{ inputs.only }}
|
|
74
95
|
bump: \${{ inputs.bump }}
|
|
@@ -102,13 +123,14 @@ permissions:
|
|
|
102
123
|
|
|
103
124
|
jobs:
|
|
104
125
|
release:
|
|
105
|
-
uses: williamthorsen/node-monorepo-tools/.github/workflows/release
|
|
126
|
+
uses: williamthorsen/node-monorepo-tools/.github/workflows/release.reusable.yaml@release-workflow-v1
|
|
106
127
|
with:
|
|
107
128
|
bump: \${{ inputs.bump }}
|
|
108
129
|
force: \${{ inputs.force }}
|
|
109
130
|
`;
|
|
110
131
|
}
|
|
111
132
|
export {
|
|
133
|
+
publishWorkflow,
|
|
112
134
|
releaseConfigScript,
|
|
113
135
|
releaseWorkflow
|
|
114
136
|
};
|
package/dist/esm/loadConfig.js
CHANGED
|
@@ -47,9 +47,9 @@ function mergeMonorepoConfig(discoveredPaths, userConfig) {
|
|
|
47
47
|
if (cliffConfigPath !== void 0) {
|
|
48
48
|
result.cliffConfigPath = cliffConfigPath;
|
|
49
49
|
}
|
|
50
|
-
const
|
|
51
|
-
if (
|
|
52
|
-
result.
|
|
50
|
+
const scopeAliases = userConfig?.scopeAliases;
|
|
51
|
+
if (scopeAliases !== void 0) {
|
|
52
|
+
result.scopeAliases = scopeAliases;
|
|
53
53
|
}
|
|
54
54
|
return result;
|
|
55
55
|
}
|
|
@@ -71,9 +71,9 @@ function mergeSinglePackageConfig(userConfig) {
|
|
|
71
71
|
if (cliffConfigPath !== void 0) {
|
|
72
72
|
result.cliffConfigPath = cliffConfigPath;
|
|
73
73
|
}
|
|
74
|
-
const
|
|
75
|
-
if (
|
|
76
|
-
result.
|
|
74
|
+
const scopeAliases = userConfig?.scopeAliases;
|
|
75
|
+
if (scopeAliases !== void 0) {
|
|
76
|
+
result.scopeAliases = scopeAliases;
|
|
77
77
|
}
|
|
78
78
|
return result;
|
|
79
79
|
}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ParsedCommit, WorkTypeConfig } from './types.ts';
|
|
2
2
|
export declare const COMMIT_PREPROCESSOR_PATTERNS: readonly RegExp[];
|
|
3
|
-
export declare function parseCommitMessage(message: string, hash: string, workTypes: Record<string, WorkTypeConfig>,
|
|
3
|
+
export declare function parseCommitMessage(message: string, hash: string, workTypes: Record<string, WorkTypeConfig>, scopeAliases?: Record<string, string>): ParsedCommit | undefined;
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
const COMMIT_PREPROCESSOR_PATTERNS = [/^#\d+\s+/, /^[A-Z]+-\d+\s+/];
|
|
2
|
-
function parseCommitMessage(message, hash, workTypes,
|
|
2
|
+
function parseCommitMessage(message, hash, workTypes, scopeAliases) {
|
|
3
3
|
const stripped = stripTicketPrefix(message);
|
|
4
|
-
const match = stripped.match(/^(?:([^|]+)\|)?(\w+)(!)?:\s*(.*)$/);
|
|
4
|
+
const match = stripped.match(/^(?:([^|]+)\|)?(\w+)(?:\(([^)]+)\))?(!)?:\s*(.*)$/);
|
|
5
5
|
if (!match) {
|
|
6
6
|
return void 0;
|
|
7
7
|
}
|
|
8
|
-
const
|
|
8
|
+
const pipeScope = match[1];
|
|
9
9
|
const rawType = match[2];
|
|
10
|
-
const
|
|
11
|
-
const
|
|
10
|
+
const parenthesizedScope = match[3];
|
|
11
|
+
const breakingMarker = match[4];
|
|
12
|
+
const description = match[5];
|
|
12
13
|
if (rawType === void 0 || description === void 0) {
|
|
13
14
|
return void 0;
|
|
14
15
|
}
|
|
@@ -17,14 +18,15 @@ function parseCommitMessage(message, hash, workTypes, workspaceAliases) {
|
|
|
17
18
|
return void 0;
|
|
18
19
|
}
|
|
19
20
|
const breaking = breakingMarker === "!" || message.includes("BREAKING CHANGE:");
|
|
20
|
-
const
|
|
21
|
+
const rawScope = pipeScope ?? parenthesizedScope;
|
|
22
|
+
const resolvedScope = rawScope !== void 0 && scopeAliases !== void 0 ? scopeAliases[rawScope] ?? rawScope : rawScope;
|
|
21
23
|
return {
|
|
22
24
|
message,
|
|
23
25
|
hash,
|
|
24
26
|
type: resolvedType,
|
|
25
27
|
description,
|
|
26
28
|
breaking,
|
|
27
|
-
...
|
|
29
|
+
...resolvedScope !== void 0 && { scope: resolvedScope }
|
|
28
30
|
};
|
|
29
31
|
}
|
|
30
32
|
function resolveType(rawType, workTypes) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { WriteResult } from '@williamthorsen/node-monorepo-core';
|
|
2
2
|
import type { ReleaseType } from './types.ts';
|
|
3
3
|
export declare const RELEASE_TAGS_FILE = "tmp/.release-tags";
|
|
4
|
+
export declare const RELEASE_SUMMARY_FILE = "tmp/.release-summary";
|
|
4
5
|
export declare function parseArgs(argv: string[]): {
|
|
5
6
|
dryRun: boolean;
|
|
6
7
|
force: boolean;
|