@williamthorsen/release-kit 2.1.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +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/dist/esm/index.d.ts
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
|
+
export type { CreateTagsOptions } from './createTags.ts';
|
|
2
|
+
export type { PackageManager } from './detectPackageManager.ts';
|
|
1
3
|
export type { GenerateChangelogOptions } from './generateChangelogs.ts';
|
|
4
|
+
export type { PublishOptions } from './publish.ts';
|
|
2
5
|
export type { ReleasePrepareOptions } from './releasePrepare.ts';
|
|
3
|
-
export type {
|
|
6
|
+
export type { ResolvedTag } from './resolveReleaseTags.ts';
|
|
7
|
+
export type { LabelDefinition, SyncLabelsConfig } from './sync-labels/types.ts';
|
|
8
|
+
export type { BumpResult, Commit, ComponentConfig, ComponentOverride, ComponentPrepareResult, MonorepoReleaseConfig, ParsedCommit, PrepareResult, ReleaseConfig, ReleaseKitConfig, ReleaseType, VersionPatterns, WorkTypeConfig, } from './types.ts';
|
|
4
9
|
export { DEFAULT_VERSION_PATTERNS, DEFAULT_WORK_TYPES } from './defaults.ts';
|
|
5
10
|
export { bumpAllVersions } from './bumpAllVersions.ts';
|
|
6
11
|
export { bumpVersion } from './bumpVersion.ts';
|
|
7
12
|
export { component } from './component.ts';
|
|
13
|
+
export { createTags } from './createTags.ts';
|
|
14
|
+
export { detectPackageManager } from './detectPackageManager.ts';
|
|
8
15
|
export { determineBumpType } from './determineBumpType.ts';
|
|
9
16
|
export { discoverWorkspaces } from './discoverWorkspaces.ts';
|
|
10
17
|
export { generateChangelog, generateChangelogs } from './generateChangelogs.ts';
|
|
11
18
|
export { getCommitsSinceTarget } from './getCommitsSinceTarget.ts';
|
|
12
19
|
export { parseCommitMessage } from './parseCommitMessage.ts';
|
|
20
|
+
export { RELEASE_TAGS_FILE, writeReleaseTags } from './prepareCommand.ts';
|
|
21
|
+
export { publish } from './publish.ts';
|
|
13
22
|
export { releasePrepare } from './releasePrepare.ts';
|
|
14
23
|
export { releasePrepareMono } from './releasePrepareMono.ts';
|
|
15
|
-
export {
|
|
24
|
+
export { reportPrepare } from './reportPrepare.ts';
|
|
25
|
+
export { resolveReleaseTags } from './resolveReleaseTags.ts';
|
package/dist/esm/index.js
CHANGED
|
@@ -2,14 +2,19 @@ import { DEFAULT_VERSION_PATTERNS, DEFAULT_WORK_TYPES } from "./defaults.js";
|
|
|
2
2
|
import { bumpAllVersions } from "./bumpAllVersions.js";
|
|
3
3
|
import { bumpVersion } from "./bumpVersion.js";
|
|
4
4
|
import { component } from "./component.js";
|
|
5
|
+
import { createTags } from "./createTags.js";
|
|
6
|
+
import { detectPackageManager } from "./detectPackageManager.js";
|
|
5
7
|
import { determineBumpType } from "./determineBumpType.js";
|
|
6
8
|
import { discoverWorkspaces } from "./discoverWorkspaces.js";
|
|
7
9
|
import { generateChangelog, generateChangelogs } from "./generateChangelogs.js";
|
|
8
10
|
import { getCommitsSinceTarget } from "./getCommitsSinceTarget.js";
|
|
9
11
|
import { parseCommitMessage } from "./parseCommitMessage.js";
|
|
12
|
+
import { RELEASE_TAGS_FILE, writeReleaseTags } from "./prepareCommand.js";
|
|
13
|
+
import { publish } from "./publish.js";
|
|
10
14
|
import { releasePrepare } from "./releasePrepare.js";
|
|
11
15
|
import { releasePrepareMono } from "./releasePrepareMono.js";
|
|
12
|
-
import {
|
|
16
|
+
import { reportPrepare } from "./reportPrepare.js";
|
|
17
|
+
import { resolveReleaseTags } from "./resolveReleaseTags.js";
|
|
13
18
|
export {
|
|
14
19
|
DEFAULT_VERSION_PATTERNS,
|
|
15
20
|
DEFAULT_WORK_TYPES,
|
|
@@ -17,14 +22,18 @@ export {
|
|
|
17
22
|
bumpAllVersions,
|
|
18
23
|
bumpVersion,
|
|
19
24
|
component,
|
|
25
|
+
createTags,
|
|
26
|
+
detectPackageManager,
|
|
20
27
|
determineBumpType,
|
|
21
28
|
discoverWorkspaces,
|
|
22
29
|
generateChangelog,
|
|
23
30
|
generateChangelogs,
|
|
24
31
|
getCommitsSinceTarget,
|
|
25
32
|
parseCommitMessage,
|
|
33
|
+
publish,
|
|
26
34
|
releasePrepare,
|
|
27
35
|
releasePrepareMono,
|
|
28
|
-
|
|
36
|
+
reportPrepare,
|
|
37
|
+
resolveReleaseTags,
|
|
29
38
|
writeReleaseTags
|
|
30
39
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { printError, printStep, printSuccess, reportWriteResult } from "@williamthorsen/node-monorepo-core";
|
|
1
2
|
import { hasPackageJson, isGitRepo, usesPnpm } from "./checks.js";
|
|
2
3
|
import { detectRepoType } from "./detectRepoType.js";
|
|
3
|
-
import { printError, printStep, printSuccess } from "./prompt.js";
|
|
4
4
|
import { scaffoldFiles } from "./scaffold.js";
|
|
5
5
|
function runRequiredCheck(label, result) {
|
|
6
6
|
if (result.ok) {
|
|
@@ -39,12 +39,19 @@ function initCommand({ dryRun, force, withConfig }) {
|
|
|
39
39
|
}
|
|
40
40
|
printSuccess(`Detected: ${repoType}`);
|
|
41
41
|
printStep("Scaffolding files");
|
|
42
|
+
let results;
|
|
42
43
|
try {
|
|
43
|
-
scaffoldFiles({ repoType, dryRun, overwrite: force, withConfig });
|
|
44
|
+
results = scaffoldFiles({ repoType, dryRun, overwrite: force, withConfig });
|
|
44
45
|
} catch (error) {
|
|
45
46
|
printError(`Failed to scaffold files: ${error instanceof Error ? error.message : String(error)}`);
|
|
46
47
|
return 1;
|
|
47
48
|
}
|
|
49
|
+
for (const result of results) {
|
|
50
|
+
reportWriteResult(result, dryRun);
|
|
51
|
+
}
|
|
52
|
+
if (results.some((r) => r.outcome === "failed")) {
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
48
55
|
printStep("Next steps");
|
|
49
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.";
|
|
50
57
|
console.info(`
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { WriteResult } from '@williamthorsen/node-monorepo-core';
|
|
1
2
|
import type { RepoType } from './detectRepoType.ts';
|
|
2
3
|
interface ScaffoldOptions {
|
|
3
4
|
repoType: RepoType;
|
|
@@ -5,6 +6,6 @@ interface ScaffoldOptions {
|
|
|
5
6
|
overwrite: boolean;
|
|
6
7
|
withConfig: boolean;
|
|
7
8
|
}
|
|
8
|
-
export declare function copyCliffTemplate(dryRun: boolean, overwrite: boolean):
|
|
9
|
-
export declare function scaffoldFiles({ repoType, dryRun, overwrite, withConfig }: ScaffoldOptions):
|
|
9
|
+
export declare function copyCliffTemplate(dryRun: boolean, overwrite: boolean): WriteResult;
|
|
10
|
+
export declare function scaffoldFiles({ repoType, dryRun, overwrite, withConfig }: ScaffoldOptions): WriteResult[];
|
|
10
11
|
export {};
|
|
@@ -1,61 +1,35 @@
|
|
|
1
|
-
import { existsSync,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { writeFileWithCheck } from "@williamthorsen/node-monorepo-core";
|
|
4
|
+
import { findPackageRoot } from "../findPackageRoot.js";
|
|
5
5
|
import { releaseConfigScript, releaseWorkflow } from "./templates.js";
|
|
6
|
-
function tryWriteFile(filePath, content) {
|
|
7
|
-
try {
|
|
8
|
-
writeFileSync(filePath, content, "utf8");
|
|
9
|
-
return true;
|
|
10
|
-
} catch (error) {
|
|
11
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
12
|
-
printError(`Failed to write ${filePath}: ${message}`);
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
function writeIfAbsent(filePath, content, dryRun, overwrite) {
|
|
17
|
-
if (existsSync(filePath) && !overwrite) {
|
|
18
|
-
printSkip(`${filePath} (already exists)`);
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
if (dryRun) {
|
|
22
|
-
printSuccess(`[dry-run] Would create ${filePath}`);
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
try {
|
|
26
|
-
mkdirSync(dirname(filePath), { recursive: true });
|
|
27
|
-
} catch (error) {
|
|
28
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
29
|
-
printError(`Failed to create directory for ${filePath}: ${message}`);
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
if (tryWriteFile(filePath, content)) {
|
|
33
|
-
printSuccess(`Created ${filePath}`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
6
|
function copyCliffTemplate(dryRun, overwrite) {
|
|
37
|
-
const
|
|
38
|
-
const
|
|
7
|
+
const destPath = ".config/git-cliff.toml";
|
|
8
|
+
const root = findPackageRoot(import.meta.url);
|
|
9
|
+
const templatePath = resolve(root, "cliff.toml.template");
|
|
39
10
|
if (!existsSync(templatePath)) {
|
|
40
|
-
|
|
41
|
-
return;
|
|
11
|
+
return { filePath: destPath, outcome: "failed", error: `Could not find bundled template at ${templatePath}` };
|
|
42
12
|
}
|
|
43
13
|
let content;
|
|
44
14
|
try {
|
|
45
15
|
content = readFileSync(templatePath, "utf8");
|
|
46
16
|
} catch (error) {
|
|
47
17
|
const message = error instanceof Error ? error.message : String(error);
|
|
48
|
-
|
|
49
|
-
return;
|
|
18
|
+
return { filePath: destPath, outcome: "failed", error: `Failed to read template ${templatePath}: ${message}` };
|
|
50
19
|
}
|
|
51
|
-
|
|
20
|
+
return writeFileWithCheck(destPath, content, { dryRun, overwrite });
|
|
52
21
|
}
|
|
53
22
|
function scaffoldFiles({ repoType, dryRun, overwrite, withConfig }) {
|
|
54
|
-
|
|
23
|
+
const results = [
|
|
24
|
+
writeFileWithCheck(".github/workflows/release.yaml", releaseWorkflow(repoType), { dryRun, overwrite })
|
|
25
|
+
];
|
|
55
26
|
if (withConfig) {
|
|
56
|
-
|
|
57
|
-
|
|
27
|
+
results.push(
|
|
28
|
+
writeFileWithCheck(".config/release-kit.config.ts", releaseConfigScript(repoType), { dryRun, overwrite }),
|
|
29
|
+
copyCliffTemplate(dryRun, overwrite)
|
|
30
|
+
);
|
|
58
31
|
}
|
|
32
|
+
return results;
|
|
59
33
|
}
|
|
60
34
|
export {
|
|
61
35
|
copyCliffTemplate,
|
|
@@ -8,8 +8,7 @@ const config: ReleaseKitConfig = {
|
|
|
8
8
|
// { dir: 'my-package', shouldExclude: true },
|
|
9
9
|
// ],
|
|
10
10
|
|
|
11
|
-
//
|
|
12
|
-
// formatCommand: 'npx prettier --write',
|
|
11
|
+
// Formatting: prettier is auto-detected. Set formatCommand to override.
|
|
13
12
|
|
|
14
13
|
// Uncomment to override the default version patterns:
|
|
15
14
|
// versionPatterns: { major: ['!'], minor: ['feat', 'feature'] },
|
|
@@ -24,8 +23,7 @@ export default config;
|
|
|
24
23
|
return `import type { ReleaseKitConfig } from '@williamthorsen/release-kit';
|
|
25
24
|
|
|
26
25
|
const config: ReleaseKitConfig = {
|
|
27
|
-
//
|
|
28
|
-
// formatCommand: 'npx prettier --write',
|
|
26
|
+
// Formatting: prettier is auto-detected. Set formatCommand to override.
|
|
29
27
|
|
|
30
28
|
// Uncomment to override the default version patterns:
|
|
31
29
|
// versionPatterns: { major: ['!'], minor: ['feat', 'feature'] },
|
|
@@ -58,6 +56,11 @@ on:
|
|
|
58
56
|
- patch
|
|
59
57
|
- minor
|
|
60
58
|
- major
|
|
59
|
+
force:
|
|
60
|
+
description: 'Force a version bump even when there are no release-worthy changes'
|
|
61
|
+
required: false
|
|
62
|
+
type: boolean
|
|
63
|
+
default: false
|
|
61
64
|
|
|
62
65
|
permissions:
|
|
63
66
|
contents: write
|
|
@@ -69,6 +72,7 @@ jobs:
|
|
|
69
72
|
with:
|
|
70
73
|
only: \${{ inputs.only }}
|
|
71
74
|
bump: \${{ inputs.bump }}
|
|
75
|
+
force: \${{ inputs.force }}
|
|
72
76
|
`;
|
|
73
77
|
}
|
|
74
78
|
return `# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
|
@@ -86,6 +90,11 @@ on:
|
|
|
86
90
|
- patch
|
|
87
91
|
- minor
|
|
88
92
|
- major
|
|
93
|
+
force:
|
|
94
|
+
description: 'Force a version bump even when there are no release-worthy changes'
|
|
95
|
+
required: false
|
|
96
|
+
type: boolean
|
|
97
|
+
default: false
|
|
89
98
|
|
|
90
99
|
permissions:
|
|
91
100
|
contents: write
|
|
@@ -96,6 +105,7 @@ jobs:
|
|
|
96
105
|
uses: williamthorsen/node-monorepo-tools/.github/workflows/release-workflow.yaml@release-workflow-v1
|
|
97
106
|
with:
|
|
98
107
|
bump: \${{ inputs.bump }}
|
|
108
|
+
force: \${{ inputs.force }}
|
|
99
109
|
`;
|
|
100
110
|
}
|
|
101
111
|
export {
|
package/dist/esm/loadConfig.js
CHANGED
|
@@ -30,12 +30,6 @@ function mergeMonorepoConfig(discoveredPaths, userConfig) {
|
|
|
30
30
|
components = components.filter((c) => {
|
|
31
31
|
const override = overrides.get(c.dir);
|
|
32
32
|
return override?.shouldExclude !== true;
|
|
33
|
-
}).map((c) => {
|
|
34
|
-
const override = overrides.get(c.dir);
|
|
35
|
-
if (override?.tagPrefix !== void 0) {
|
|
36
|
-
return { ...c, tagPrefix: override.tagPrefix };
|
|
37
|
-
}
|
|
38
|
-
return c;
|
|
39
33
|
});
|
|
40
34
|
}
|
|
41
35
|
const workTypes = userConfig?.workTypes === void 0 ? { ...DEFAULT_WORK_TYPES } : { ...DEFAULT_WORK_TYPES, ...userConfig.workTypes };
|
|
@@ -1 +1,11 @@
|
|
|
1
|
+
import type { WriteResult } from '@williamthorsen/node-monorepo-core';
|
|
2
|
+
import type { ReleaseType } from './types.ts';
|
|
3
|
+
export declare const RELEASE_TAGS_FILE = "tmp/.release-tags";
|
|
4
|
+
export declare function parseArgs(argv: string[]): {
|
|
5
|
+
dryRun: boolean;
|
|
6
|
+
force: boolean;
|
|
7
|
+
bumpOverride: ReleaseType | undefined;
|
|
8
|
+
only: string[] | undefined;
|
|
9
|
+
};
|
|
10
|
+
export declare function writeReleaseTags(tags: string[], dryRun: boolean): WriteResult | undefined;
|
|
1
11
|
export declare function prepareCommand(argv: string[]): Promise<void>;
|
|
@@ -1,9 +1,72 @@
|
|
|
1
|
+
import { writeFileWithCheck } from "@williamthorsen/node-monorepo-core";
|
|
1
2
|
import { discoverWorkspaces } from "./discoverWorkspaces.js";
|
|
3
|
+
import { dim } from "./format.js";
|
|
2
4
|
import { loadConfig, mergeMonorepoConfig, mergeSinglePackageConfig } from "./loadConfig.js";
|
|
3
5
|
import { releasePrepare } from "./releasePrepare.js";
|
|
4
6
|
import { releasePrepareMono } from "./releasePrepareMono.js";
|
|
5
|
-
import {
|
|
7
|
+
import { reportPrepare } from "./reportPrepare.js";
|
|
6
8
|
import { validateConfig } from "./validateConfig.js";
|
|
9
|
+
const RELEASE_TAGS_FILE = "tmp/.release-tags";
|
|
10
|
+
const VALID_BUMP_TYPES = ["major", "minor", "patch"];
|
|
11
|
+
function isReleaseType(value) {
|
|
12
|
+
return VALID_BUMP_TYPES.includes(value);
|
|
13
|
+
}
|
|
14
|
+
function showHelp() {
|
|
15
|
+
console.info(`
|
|
16
|
+
Usage: npx @williamthorsen/release-kit prepare [options]
|
|
17
|
+
|
|
18
|
+
Options:
|
|
19
|
+
--dry-run Run without modifying any files
|
|
20
|
+
--bump=major|minor|patch Override the bump type for all components
|
|
21
|
+
--force Bypass the "no commits since last tag" check (monorepo only, requires --bump)
|
|
22
|
+
--only=name1,name2 Only process the named components (comma-separated, monorepo only)
|
|
23
|
+
--help Show this help message
|
|
24
|
+
`);
|
|
25
|
+
}
|
|
26
|
+
function parseArgs(argv) {
|
|
27
|
+
let dryRun = false;
|
|
28
|
+
let force = false;
|
|
29
|
+
let bumpOverride;
|
|
30
|
+
let only;
|
|
31
|
+
for (const arg of argv) {
|
|
32
|
+
if (arg === "--dry-run") {
|
|
33
|
+
dryRun = true;
|
|
34
|
+
} else if (arg === "--force") {
|
|
35
|
+
force = true;
|
|
36
|
+
} else if (arg.startsWith("--bump=")) {
|
|
37
|
+
const value = arg.slice("--bump=".length);
|
|
38
|
+
if (!isReleaseType(value)) {
|
|
39
|
+
console.error(`Error: Invalid bump type "${value}". Must be one of: ${VALID_BUMP_TYPES.join(", ")}`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
bumpOverride = value;
|
|
43
|
+
} else if (arg.startsWith("--only=")) {
|
|
44
|
+
const value = arg.slice("--only=".length);
|
|
45
|
+
if (!value) {
|
|
46
|
+
console.error("Error: --only requires a comma-separated list of component names");
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
only = value.split(",");
|
|
50
|
+
} else if (arg === "--help" || arg === "-h") {
|
|
51
|
+
showHelp();
|
|
52
|
+
process.exit(0);
|
|
53
|
+
} else {
|
|
54
|
+
console.error(`Error: Unknown argument: ${arg}`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (force && bumpOverride === void 0) {
|
|
59
|
+
console.error("Error: --force requires --bump to specify the version bump type");
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
return { dryRun, force, bumpOverride, only };
|
|
63
|
+
}
|
|
64
|
+
function writeReleaseTags(tags, dryRun) {
|
|
65
|
+
if (tags.length === 0) {
|
|
66
|
+
return void 0;
|
|
67
|
+
}
|
|
68
|
+
return writeFileWithCheck(RELEASE_TAGS_FILE, tags.join("\n"), { dryRun, overwrite: true });
|
|
69
|
+
}
|
|
7
70
|
async function prepareCommand(argv) {
|
|
8
71
|
const { dryRun, force, bumpOverride, only } = parseArgs(argv);
|
|
9
72
|
const options = {
|
|
@@ -11,6 +74,9 @@ async function prepareCommand(argv) {
|
|
|
11
74
|
force,
|
|
12
75
|
...bumpOverride === void 0 ? {} : { bumpOverride }
|
|
13
76
|
};
|
|
77
|
+
if (dryRun) {
|
|
78
|
+
console.info("\n\u{1F50D} DRY RUN \u2014 no files will be modified\n");
|
|
79
|
+
}
|
|
14
80
|
let rawConfig;
|
|
15
81
|
try {
|
|
16
82
|
rawConfig = await loadConfig();
|
|
@@ -37,20 +103,13 @@ async function prepareCommand(argv) {
|
|
|
37
103
|
console.error(`Error discovering workspaces: ${error instanceof Error ? error.message : String(error)}`);
|
|
38
104
|
process.exit(1);
|
|
39
105
|
}
|
|
40
|
-
let tags = [];
|
|
41
106
|
if (discoveredPaths === void 0) {
|
|
42
107
|
if (only !== void 0) {
|
|
43
108
|
console.error("Error: --only is only supported for monorepo configurations");
|
|
44
109
|
process.exit(1);
|
|
45
110
|
}
|
|
46
111
|
const config = mergeSinglePackageConfig(userConfig);
|
|
47
|
-
|
|
48
|
-
tags = releasePrepare(config, options);
|
|
49
|
-
writeReleaseTags(tags, dryRun);
|
|
50
|
-
} catch (error) {
|
|
51
|
-
console.error("Error preparing release:", error instanceof Error ? error.message : String(error));
|
|
52
|
-
process.exit(1);
|
|
53
|
-
}
|
|
112
|
+
runAndReport(() => releasePrepare(config, options), dryRun);
|
|
54
113
|
} else {
|
|
55
114
|
const config = mergeMonorepoConfig(discoveredPaths, userConfig);
|
|
56
115
|
if (only !== void 0) {
|
|
@@ -63,19 +122,36 @@ async function prepareCommand(argv) {
|
|
|
63
122
|
}
|
|
64
123
|
config.components = config.components.filter((c) => only.includes(c.dir));
|
|
65
124
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
125
|
+
runAndReport(() => releasePrepareMono(config, options), dryRun);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function runAndReport(execute, dryRun) {
|
|
129
|
+
let result;
|
|
130
|
+
try {
|
|
131
|
+
result = execute();
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error("Error preparing release:", error instanceof Error ? error.message : String(error));
|
|
134
|
+
process.exit(1);
|
|
73
135
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
136
|
+
process.stdout.write(reportPrepare(result) + "\n");
|
|
137
|
+
const writeResult = writeReleaseTags(result.tags, dryRun);
|
|
138
|
+
if (writeResult?.outcome === "failed") {
|
|
139
|
+
console.error(`Error writing release tags: ${writeResult.error ?? "unknown error"}`);
|
|
140
|
+
process.exit(1);
|
|
141
|
+
}
|
|
142
|
+
if (writeResult) {
|
|
143
|
+
if (dryRun) {
|
|
144
|
+
console.info(dim(` [dry-run] Would write ${RELEASE_TAGS_FILE}: ${result.tags.join(" ")}`));
|
|
145
|
+
} else {
|
|
146
|
+
console.info(dim(` Wrote ${RELEASE_TAGS_FILE}: ${result.tags.join(" ")}`));
|
|
147
|
+
console.info(dim(`
|
|
148
|
+
Release tags file: ${RELEASE_TAGS_FILE}`));
|
|
149
|
+
}
|
|
77
150
|
}
|
|
78
151
|
}
|
|
79
152
|
export {
|
|
80
|
-
|
|
153
|
+
RELEASE_TAGS_FILE,
|
|
154
|
+
parseArgs,
|
|
155
|
+
prepareCommand,
|
|
156
|
+
writeReleaseTags
|
|
81
157
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { PackageManager } from './detectPackageManager.ts';
|
|
2
|
+
import type { ResolvedTag } from './resolveReleaseTags.ts';
|
|
3
|
+
export interface PublishOptions {
|
|
4
|
+
dryRun: boolean;
|
|
5
|
+
noGitChecks: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function publish(resolvedTags: ResolvedTag[], packageManager: PackageManager, options: PublishOptions): void;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
function publish(resolvedTags, packageManager, options) {
|
|
3
|
+
const { dryRun, noGitChecks } = options;
|
|
4
|
+
if (resolvedTags.length === 0) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
console.info(dryRun ? "[dry-run] Would publish:" : "Publishing:");
|
|
8
|
+
for (const { tag, workspacePath } of resolvedTags) {
|
|
9
|
+
console.info(` ${tag} (${workspacePath})`);
|
|
10
|
+
}
|
|
11
|
+
const published = [];
|
|
12
|
+
for (const { tag, workspacePath } of resolvedTags) {
|
|
13
|
+
const executable = resolveExecutable(packageManager);
|
|
14
|
+
const args = buildPublishArgs(packageManager, { dryRun, noGitChecks });
|
|
15
|
+
try {
|
|
16
|
+
console.info(`
|
|
17
|
+
${dryRun ? "[dry-run] " : ""}Running: ${executable} ${args.join(" ")} (cwd: ${workspacePath})`);
|
|
18
|
+
execFileSync(executable, args, { cwd: workspacePath, stdio: "inherit" });
|
|
19
|
+
published.push(tag);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
if (published.length > 0) {
|
|
22
|
+
console.warn("Packages published before failure:");
|
|
23
|
+
for (const t of published) {
|
|
24
|
+
console.warn(` ${t}`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function resolveExecutable(packageManager) {
|
|
32
|
+
if (packageManager === "yarn-berry") {
|
|
33
|
+
return "yarn";
|
|
34
|
+
}
|
|
35
|
+
return packageManager;
|
|
36
|
+
}
|
|
37
|
+
function buildPublishArgs(packageManager, options) {
|
|
38
|
+
const args = packageManager === "yarn-berry" ? ["npm", "publish"] : ["publish"];
|
|
39
|
+
if (options.dryRun) {
|
|
40
|
+
args.push("--dry-run");
|
|
41
|
+
}
|
|
42
|
+
if (options.noGitChecks && packageManager === "pnpm") {
|
|
43
|
+
args.push("--no-git-checks");
|
|
44
|
+
}
|
|
45
|
+
return args;
|
|
46
|
+
}
|
|
47
|
+
export {
|
|
48
|
+
publish
|
|
49
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function publishCommand(argv: string[]): Promise<void>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
import { detectPackageManager } from "./detectPackageManager.js";
|
|
3
|
+
import { discoverWorkspaces } from "./discoverWorkspaces.js";
|
|
4
|
+
import { publish } from "./publish.js";
|
|
5
|
+
import { resolveReleaseTags } from "./resolveReleaseTags.js";
|
|
6
|
+
async function publishCommand(argv) {
|
|
7
|
+
const knownFlags = /* @__PURE__ */ new Set(["--dry-run", "--no-git-checks"]);
|
|
8
|
+
const unknownFlags = argv.filter((f) => !f.startsWith("--only=") && !knownFlags.has(f));
|
|
9
|
+
if (unknownFlags.length > 0) {
|
|
10
|
+
console.error(`Error: Unknown option: ${unknownFlags[0]}`);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
const dryRun = argv.includes("--dry-run");
|
|
14
|
+
const noGitChecks = argv.includes("--no-git-checks");
|
|
15
|
+
const onlyArg = argv.find((f) => f.startsWith("--only="));
|
|
16
|
+
const only = onlyArg?.slice("--only=".length).split(",");
|
|
17
|
+
let discoveredPaths;
|
|
18
|
+
try {
|
|
19
|
+
discoveredPaths = await discoverWorkspaces();
|
|
20
|
+
} catch (error) {
|
|
21
|
+
console.error(`Error discovering workspaces: ${error instanceof Error ? error.message : String(error)}`);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
if (only !== void 0 && discoveredPaths === void 0) {
|
|
25
|
+
console.error("Error: --only is only supported for monorepo configurations");
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
const workspaceMap = discoveredPaths === void 0 ? void 0 : new Map(discoveredPaths.map((p) => [basename(p), p]));
|
|
29
|
+
let resolvedTags = resolveReleaseTags(workspaceMap);
|
|
30
|
+
if (resolvedTags.length === 0) {
|
|
31
|
+
console.error("Error: No release tags found on HEAD. Create tags with `release-kit tag` first.");
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
if (only !== void 0) {
|
|
35
|
+
const availableNames = resolvedTags.map((t) => t.dir);
|
|
36
|
+
for (const name of only) {
|
|
37
|
+
if (!availableNames.includes(name)) {
|
|
38
|
+
console.error(`Error: Unknown package "${name}" in --only. Available: ${availableNames.join(", ")}`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
resolvedTags = resolvedTags.filter((t) => only.includes(t.dir));
|
|
43
|
+
}
|
|
44
|
+
const packageManager = detectPackageManager();
|
|
45
|
+
try {
|
|
46
|
+
publish(resolvedTags, packageManager, { dryRun, noGitChecks });
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
publishCommand
|
|
54
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { ReleaseConfig, ReleaseType } from './types.ts';
|
|
1
|
+
import type { PrepareResult, ReleaseConfig, ReleaseType } from './types.ts';
|
|
2
2
|
export interface ReleasePrepareOptions {
|
|
3
3
|
dryRun: boolean;
|
|
4
4
|
force?: boolean;
|
|
5
5
|
bumpOverride?: ReleaseType;
|
|
6
6
|
}
|
|
7
|
-
export declare function releasePrepare(config: ReleaseConfig, options: ReleasePrepareOptions):
|
|
7
|
+
export declare function releasePrepare(config: ReleaseConfig, options: ReleasePrepareOptions): PrepareResult;
|
|
@@ -4,39 +4,50 @@ import { DEFAULT_VERSION_PATTERNS, DEFAULT_WORK_TYPES } from "./defaults.js";
|
|
|
4
4
|
import { determineBumpType } from "./determineBumpType.js";
|
|
5
5
|
import { generateChangelogs } from "./generateChangelogs.js";
|
|
6
6
|
import { getCommitsSinceTarget } from "./getCommitsSinceTarget.js";
|
|
7
|
+
import { hasPrettierConfig } from "./hasPrettierConfig.js";
|
|
7
8
|
import { parseCommitMessage } from "./parseCommitMessage.js";
|
|
8
9
|
function releasePrepare(config, options) {
|
|
9
10
|
const { dryRun, bumpOverride } = options;
|
|
10
11
|
const workTypes = config.workTypes ?? { ...DEFAULT_WORK_TYPES };
|
|
11
12
|
const versionPatterns = config.versionPatterns ?? { ...DEFAULT_VERSION_PATTERNS };
|
|
12
|
-
console.info("Finding commits since last release...");
|
|
13
13
|
const { tag, commits } = getCommitsSinceTarget(config.tagPrefix);
|
|
14
|
-
console.info(` Found ${commits.length} commits since ${tag ?? "the beginning"}`);
|
|
15
14
|
let releaseType;
|
|
15
|
+
let parsedCommitCount;
|
|
16
16
|
if (bumpOverride === void 0) {
|
|
17
17
|
const parsedCommits = commits.map((c) => parseCommitMessage(c.message, c.hash, workTypes, config.workspaceAliases)).filter((c) => c !== void 0);
|
|
18
|
-
|
|
18
|
+
parsedCommitCount = parsedCommits.length;
|
|
19
19
|
releaseType = determineBumpType(parsedCommits, workTypes, versionPatterns);
|
|
20
20
|
} else {
|
|
21
21
|
releaseType = bumpOverride;
|
|
22
|
-
console.info(` Using bump override: ${releaseType}`);
|
|
23
22
|
}
|
|
24
23
|
if (releaseType === void 0) {
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
return {
|
|
25
|
+
components: [
|
|
26
|
+
{
|
|
27
|
+
status: "skipped",
|
|
28
|
+
previousTag: tag,
|
|
29
|
+
commitCount: commits.length,
|
|
30
|
+
parsedCommitCount,
|
|
31
|
+
bumpedFiles: [],
|
|
32
|
+
changelogFiles: [],
|
|
33
|
+
skipReason: "No release-worthy changes found. Skipping."
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
tags: [],
|
|
37
|
+
dryRun
|
|
38
|
+
};
|
|
27
39
|
}
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (
|
|
40
|
+
const bump = bumpAllVersions(config.packageFiles, releaseType, dryRun);
|
|
41
|
+
const newTag = `${config.tagPrefix}${bump.newVersion}`;
|
|
42
|
+
const changelogFiles = generateChangelogs(config, newTag, dryRun);
|
|
43
|
+
const formatCommandStr = config.formatCommand ?? (hasPrettierConfig() ? "npx prettier --write" : void 0);
|
|
44
|
+
let formatCommand;
|
|
45
|
+
if (formatCommandStr !== void 0) {
|
|
34
46
|
const modifiedFiles = [...config.packageFiles, ...config.changelogPaths.map((p) => `${p}/CHANGELOG.md`)];
|
|
35
|
-
const fullCommand = `${
|
|
47
|
+
const fullCommand = `${formatCommandStr} ${modifiedFiles.join(" ")}`;
|
|
36
48
|
if (dryRun) {
|
|
37
|
-
|
|
49
|
+
formatCommand = { command: fullCommand, executed: false, files: modifiedFiles };
|
|
38
50
|
} else {
|
|
39
|
-
console.info(` Running format command: ${fullCommand}`);
|
|
40
51
|
try {
|
|
41
52
|
execSync(fullCommand, { stdio: "inherit" });
|
|
42
53
|
} catch (error) {
|
|
@@ -44,10 +55,28 @@ function releasePrepare(config, options) {
|
|
|
44
55
|
`Format command failed ('${fullCommand}'): ${error instanceof Error ? error.message : String(error)}`
|
|
45
56
|
);
|
|
46
57
|
}
|
|
58
|
+
formatCommand = { command: fullCommand, executed: true, files: modifiedFiles };
|
|
47
59
|
}
|
|
48
60
|
}
|
|
49
|
-
|
|
50
|
-
|
|
61
|
+
return {
|
|
62
|
+
components: [
|
|
63
|
+
{
|
|
64
|
+
status: "released",
|
|
65
|
+
previousTag: tag,
|
|
66
|
+
commitCount: commits.length,
|
|
67
|
+
parsedCommitCount,
|
|
68
|
+
releaseType,
|
|
69
|
+
currentVersion: bump.currentVersion,
|
|
70
|
+
newVersion: bump.newVersion,
|
|
71
|
+
tag: newTag,
|
|
72
|
+
bumpedFiles: bump.files,
|
|
73
|
+
changelogFiles
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
tags: [newTag],
|
|
77
|
+
formatCommand,
|
|
78
|
+
dryRun
|
|
79
|
+
};
|
|
51
80
|
}
|
|
52
81
|
export {
|
|
53
82
|
releasePrepare
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ReleasePrepareOptions } from './releasePrepare.ts';
|
|
2
|
-
import type { MonorepoReleaseConfig } from './types.ts';
|
|
3
|
-
export declare function releasePrepareMono(config: MonorepoReleaseConfig, options: ReleasePrepareOptions):
|
|
2
|
+
import type { MonorepoReleaseConfig, PrepareResult } from './types.ts';
|
|
3
|
+
export declare function releasePrepareMono(config: MonorepoReleaseConfig, options: ReleasePrepareOptions): PrepareResult;
|