@williamthorsen/release-kit 4.5.1 → 4.7.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 +122 -99
- package/LICENSE +4 -4
- package/cliff.toml.template +68 -54
- package/dist/esm/.cache +1 -1
- package/dist/esm/assertCleanWorkingTree.d.ts +1 -0
- package/dist/esm/assertCleanWorkingTree.js +15 -0
- package/dist/esm/bin/release-kit.js +29 -6
- package/dist/esm/changelogJsonUtils.d.ts +4 -0
- package/dist/esm/changelogJsonUtils.js +29 -0
- package/dist/esm/createGithubRelease.d.ts +11 -0
- package/dist/esm/createGithubRelease.js +60 -0
- package/dist/esm/defaults.d.ts +3 -1
- package/dist/esm/defaults.js +14 -0
- package/dist/esm/generateChangelogJson.d.ts +7 -0
- package/dist/esm/generateChangelogJson.js +196 -0
- package/dist/esm/generateChangelogs.js +25 -9
- package/dist/esm/githubReleaseCommand.d.ts +1 -0
- package/dist/esm/githubReleaseCommand.js +35 -0
- package/dist/esm/index.d.ts +11 -3
- package/dist/esm/index.js +27 -3
- package/dist/esm/injectReleaseNotesIntoReadme.d.ts +2 -0
- package/dist/esm/injectReleaseNotesIntoReadme.js +42 -0
- package/dist/esm/injectSection.d.ts +1 -0
- package/dist/esm/injectSection.js +32 -0
- package/dist/esm/loadConfig.js +35 -3
- package/dist/esm/parseCommitMessage.js +1 -1
- package/dist/esm/prepareCommand.d.ts +1 -0
- package/dist/esm/prepareCommand.js +54 -20
- package/dist/esm/publish.d.ts +1 -1
- package/dist/esm/publish.js +7 -26
- package/dist/esm/publishCommand.js +49 -29
- package/dist/esm/releasePrepare.js +12 -1
- package/dist/esm/releasePrepareMono.js +23 -0
- package/dist/esm/renderReleaseNotes.d.ts +8 -0
- package/dist/esm/renderReleaseNotes.js +40 -0
- package/dist/esm/resolveCommandTags.d.ts +2 -0
- package/dist/esm/resolveCommandTags.js +36 -0
- package/dist/esm/resolveReleaseNotesConfig.d.ts +6 -0
- package/dist/esm/resolveReleaseNotesConfig.js +37 -0
- package/dist/esm/sync-labels/generateCommand.d.ts +1 -1
- package/dist/esm/sync-labels/generateCommand.js +12 -6
- package/dist/esm/sync-labels/presets.d.ts +1 -0
- package/dist/esm/sync-labels/presets.js +10 -0
- package/dist/esm/typeGuards.d.ts +1 -0
- package/dist/esm/typeGuards.js +5 -1
- package/dist/esm/types.d.ts +29 -0
- package/dist/esm/validateConfig.d.ts +1 -0
- package/dist/esm/validateConfig.js +89 -6
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +4 -3
- package/presets/labels/common.yaml +43 -0
- package/dist/esm/init/prompt.d.ts +0 -4
- package/dist/esm/init/prompt.js +0 -19
- package/dist/esm/runReleasePrepare.d.ts +0 -10
- package/dist/esm/runReleasePrepare.js +0 -125
- package/dist/esm/sync-labels/scaffold.d.ts +0 -6
- package/dist/esm/sync-labels/scaffold.js +0 -25
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { LabelDefinition } from './types.ts';
|
|
2
2
|
export declare const LABELS_OUTPUT_PATH = ".github/labels.yaml";
|
|
3
|
-
export declare function formatLabelsYaml(labels: LabelDefinition[]): string;
|
|
3
|
+
export declare function formatLabelsYaml(labels: LabelDefinition[], presetHashes: Map<string, string>): string;
|
|
4
4
|
export declare function generateCommand(): Promise<number>;
|
|
@@ -2,14 +2,16 @@ import { mkdirSync, writeFileSync } from "node:fs";
|
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
3
|
import { dump } from "js-yaml";
|
|
4
4
|
import { loadSyncLabelsConfig, SYNC_LABELS_CONFIG_PATH } from "./loadSyncLabelsConfig.js";
|
|
5
|
+
import { hashPresetFile } from "./presets.js";
|
|
5
6
|
import { resolveLabels } from "./resolveLabels.js";
|
|
6
7
|
const LABELS_OUTPUT_PATH = ".github/labels.yaml";
|
|
7
|
-
|
|
8
|
-
# Source: ${SYNC_LABELS_CONFIG_PATH}
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
function formatLabelsYaml(labels, presetHashes) {
|
|
9
|
+
const headerLines = ["# Generated by release-kit sync-labels \u2014 do not edit.", `# Source: ${SYNC_LABELS_CONFIG_PATH}`];
|
|
10
|
+
for (const [name, hash] of [...presetHashes.entries()].sort(([a], [b]) => a.localeCompare(b))) {
|
|
11
|
+
headerLines.push(`# ${name} preset hash: ${hash}`);
|
|
12
|
+
}
|
|
11
13
|
const yamlBody = dump(labels, { quotingType: "'", forceQuotes: false, lineWidth: -1 });
|
|
12
|
-
return
|
|
14
|
+
return headerLines.join("\n") + "\n" + yamlBody;
|
|
13
15
|
}
|
|
14
16
|
async function generateCommand() {
|
|
15
17
|
let config;
|
|
@@ -32,7 +34,11 @@ async function generateCommand() {
|
|
|
32
34
|
console.error(`Error resolving labels: ${message}`);
|
|
33
35
|
return 1;
|
|
34
36
|
}
|
|
35
|
-
const
|
|
37
|
+
const presetHashes = /* @__PURE__ */ new Map();
|
|
38
|
+
for (const presetName of config.presets ?? []) {
|
|
39
|
+
presetHashes.set(presetName, hashPresetFile(presetName));
|
|
40
|
+
}
|
|
41
|
+
const content = formatLabelsYaml(labels, presetHashes);
|
|
36
42
|
try {
|
|
37
43
|
mkdirSync(dirname(LABELS_OUTPUT_PATH), { recursive: true });
|
|
38
44
|
writeFileSync(LABELS_OUTPUT_PATH, content, "utf8");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
3
|
import { resolve } from "node:path";
|
|
3
4
|
import { load } from "js-yaml";
|
|
@@ -7,6 +8,14 @@ function resolvePresetPath(presetName) {
|
|
|
7
8
|
const root = findPackageRoot(import.meta.url);
|
|
8
9
|
return resolve(root, "presets", "labels", `${presetName}.yaml`);
|
|
9
10
|
}
|
|
11
|
+
function hashPresetFile(presetName) {
|
|
12
|
+
const presetPath = resolvePresetPath(presetName);
|
|
13
|
+
if (!existsSync(presetPath)) {
|
|
14
|
+
throw new Error(`Unknown preset "${presetName}". No file found at ${presetPath}`);
|
|
15
|
+
}
|
|
16
|
+
const content = readFileSync(presetPath, "utf8");
|
|
17
|
+
return createHash("sha256").update(content).digest("hex");
|
|
18
|
+
}
|
|
10
19
|
function loadPreset(presetName) {
|
|
11
20
|
const presetPath = resolvePresetPath(presetName);
|
|
12
21
|
if (!existsSync(presetPath)) {
|
|
@@ -36,5 +45,6 @@ function loadPreset(presetName) {
|
|
|
36
45
|
return labels;
|
|
37
46
|
}
|
|
38
47
|
export {
|
|
48
|
+
hashPresetFile,
|
|
39
49
|
loadPreset
|
|
40
50
|
};
|
package/dist/esm/typeGuards.d.ts
CHANGED
package/dist/esm/typeGuards.js
CHANGED
package/dist/esm/types.d.ts
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
export type ReleaseType = 'major' | 'minor' | 'patch';
|
|
2
|
+
export type ChangelogAudience = 'all' | 'dev';
|
|
3
|
+
export interface ChangelogItem {
|
|
4
|
+
description: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ChangelogSection {
|
|
7
|
+
title: string;
|
|
8
|
+
audience: ChangelogAudience;
|
|
9
|
+
items: ChangelogItem[];
|
|
10
|
+
}
|
|
11
|
+
export interface ChangelogEntry {
|
|
12
|
+
version: string;
|
|
13
|
+
date: string;
|
|
14
|
+
sections: ChangelogSection[];
|
|
15
|
+
}
|
|
16
|
+
export interface ChangelogJsonConfig {
|
|
17
|
+
enabled: boolean;
|
|
18
|
+
outputPath: string;
|
|
19
|
+
devOnlySections: string[];
|
|
20
|
+
}
|
|
21
|
+
export interface ReleaseNotesConfig {
|
|
22
|
+
shouldInjectIntoReadme: boolean;
|
|
23
|
+
shouldCreateGithubRelease: boolean;
|
|
24
|
+
}
|
|
2
25
|
export interface PropagationSource {
|
|
3
26
|
packageName: string;
|
|
4
27
|
newVersion: string;
|
|
@@ -51,6 +74,8 @@ export interface ReleaseKitConfig {
|
|
|
51
74
|
formatCommand?: string;
|
|
52
75
|
cliffConfigPath?: string;
|
|
53
76
|
scopeAliases?: Record<string, string>;
|
|
77
|
+
changelogJson?: Partial<ChangelogJsonConfig>;
|
|
78
|
+
releaseNotes?: Partial<ReleaseNotesConfig>;
|
|
54
79
|
}
|
|
55
80
|
export interface ComponentOverride {
|
|
56
81
|
dir: string;
|
|
@@ -82,6 +107,8 @@ export interface MonorepoReleaseConfig {
|
|
|
82
107
|
formatCommand?: string;
|
|
83
108
|
cliffConfigPath?: string;
|
|
84
109
|
scopeAliases?: Record<string, string>;
|
|
110
|
+
changelogJson: ChangelogJsonConfig;
|
|
111
|
+
releaseNotes: ReleaseNotesConfig;
|
|
85
112
|
}
|
|
86
113
|
export interface ReleaseConfig {
|
|
87
114
|
tagPrefix: string;
|
|
@@ -92,4 +119,6 @@ export interface ReleaseConfig {
|
|
|
92
119
|
formatCommand?: string;
|
|
93
120
|
cliffConfigPath?: string;
|
|
94
121
|
scopeAliases?: Record<string, string>;
|
|
122
|
+
changelogJson: ChangelogJsonConfig;
|
|
123
|
+
releaseNotes: ReleaseNotesConfig;
|
|
95
124
|
}
|
|
@@ -2,29 +2,112 @@ import { isRecord } from "./typeGuards.js";
|
|
|
2
2
|
function validateConfig(raw) {
|
|
3
3
|
const errors = [];
|
|
4
4
|
if (!isRecord(raw)) {
|
|
5
|
-
return { config: {}, errors: ["Config must be an object"] };
|
|
5
|
+
return { config: {}, errors: ["Config must be an object"], warnings: [] };
|
|
6
6
|
}
|
|
7
7
|
const config = {};
|
|
8
8
|
const knownFields = /* @__PURE__ */ new Set([
|
|
9
|
+
"changelogJson",
|
|
10
|
+
"cliffConfigPath",
|
|
9
11
|
"components",
|
|
10
|
-
"versionPatterns",
|
|
11
|
-
"workTypes",
|
|
12
12
|
"formatCommand",
|
|
13
|
-
"
|
|
14
|
-
"scopeAliases"
|
|
13
|
+
"releaseNotes",
|
|
14
|
+
"scopeAliases",
|
|
15
|
+
"versionPatterns",
|
|
16
|
+
"workTypes"
|
|
15
17
|
]);
|
|
16
18
|
for (const key of Object.keys(raw)) {
|
|
17
19
|
if (!knownFields.has(key)) {
|
|
18
20
|
errors.push(`Unknown field: '${key}'`);
|
|
19
21
|
}
|
|
20
22
|
}
|
|
23
|
+
validateChangelogJson(raw.changelogJson, config, errors);
|
|
21
24
|
validateComponents(raw.components, config, errors);
|
|
25
|
+
validateReleaseNotes(raw.releaseNotes, config, errors);
|
|
22
26
|
validateVersionPatterns(raw.versionPatterns, config, errors);
|
|
23
27
|
validateWorkTypes(raw.workTypes, config, errors);
|
|
24
28
|
validateStringField("formatCommand", raw.formatCommand, config, errors);
|
|
25
29
|
validateStringField("cliffConfigPath", raw.cliffConfigPath, config, errors);
|
|
26
30
|
validateScopeAliases(raw.scopeAliases, config, errors);
|
|
27
|
-
|
|
31
|
+
const warnings = [];
|
|
32
|
+
const changelogJsonEnabled = config.changelogJson?.enabled ?? true;
|
|
33
|
+
if (!changelogJsonEnabled) {
|
|
34
|
+
if (config.releaseNotes?.shouldCreateGithubRelease) {
|
|
35
|
+
warnings.push(
|
|
36
|
+
"releaseNotes.shouldCreateGithubRelease is enabled but changelogJson.enabled is false; GitHub Releases will be skipped at runtime"
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
if (config.releaseNotes?.shouldInjectIntoReadme) {
|
|
40
|
+
warnings.push(
|
|
41
|
+
"releaseNotes.shouldInjectIntoReadme is enabled but changelogJson.enabled is false; README injection will be skipped at runtime"
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return { config, errors, warnings };
|
|
46
|
+
}
|
|
47
|
+
function validateChangelogJson(value, config, errors) {
|
|
48
|
+
if (value === void 0) return;
|
|
49
|
+
if (!isRecord(value)) {
|
|
50
|
+
errors.push("'changelogJson' must be an object");
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const knownChangelogJsonFields = /* @__PURE__ */ new Set(["enabled", "outputPath", "devOnlySections"]);
|
|
54
|
+
for (const key of Object.keys(value)) {
|
|
55
|
+
if (!knownChangelogJsonFields.has(key)) {
|
|
56
|
+
errors.push(`changelogJson: unknown field '${key}'`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const result = {};
|
|
60
|
+
if (value.enabled !== void 0) {
|
|
61
|
+
if (typeof value.enabled === "boolean") {
|
|
62
|
+
result.enabled = value.enabled;
|
|
63
|
+
} else {
|
|
64
|
+
errors.push("changelogJson.enabled: must be a boolean");
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (value.outputPath !== void 0) {
|
|
68
|
+
if (typeof value.outputPath === "string") {
|
|
69
|
+
result.outputPath = value.outputPath;
|
|
70
|
+
} else {
|
|
71
|
+
errors.push("changelogJson.outputPath: must be a string");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
if (value.devOnlySections !== void 0) {
|
|
75
|
+
if (isStringArray(value.devOnlySections)) {
|
|
76
|
+
result.devOnlySections = value.devOnlySections;
|
|
77
|
+
} else {
|
|
78
|
+
errors.push("changelogJson.devOnlySections: must be a string array");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
config.changelogJson = result;
|
|
82
|
+
}
|
|
83
|
+
function validateReleaseNotes(value, config, errors) {
|
|
84
|
+
if (value === void 0) return;
|
|
85
|
+
if (!isRecord(value)) {
|
|
86
|
+
errors.push("'releaseNotes' must be an object");
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const knownReleaseNotesFields = /* @__PURE__ */ new Set(["shouldInjectIntoReadme", "shouldCreateGithubRelease"]);
|
|
90
|
+
for (const key of Object.keys(value)) {
|
|
91
|
+
if (!knownReleaseNotesFields.has(key)) {
|
|
92
|
+
errors.push(`releaseNotes: unknown field '${key}'`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const result = {};
|
|
96
|
+
if (value.shouldInjectIntoReadme !== void 0) {
|
|
97
|
+
if (typeof value.shouldInjectIntoReadme === "boolean") {
|
|
98
|
+
result.shouldInjectIntoReadme = value.shouldInjectIntoReadme;
|
|
99
|
+
} else {
|
|
100
|
+
errors.push("releaseNotes.shouldInjectIntoReadme: must be a boolean");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (value.shouldCreateGithubRelease !== void 0) {
|
|
104
|
+
if (typeof value.shouldCreateGithubRelease === "boolean") {
|
|
105
|
+
result.shouldCreateGithubRelease = value.shouldCreateGithubRelease;
|
|
106
|
+
} else {
|
|
107
|
+
errors.push("releaseNotes.shouldCreateGithubRelease: must be a boolean");
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
config.releaseNotes = result;
|
|
28
111
|
}
|
|
29
112
|
function isStringArray(value) {
|
|
30
113
|
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
package/dist/esm/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "4.
|
|
1
|
+
export declare const VERSION = "4.7.0";
|
package/dist/esm/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@williamthorsen/release-kit",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.7.0",
|
|
4
4
|
"description": "Version-bumping and changelog-generation toolkit for release workflows",
|
|
5
5
|
"keywords": [],
|
|
6
6
|
"homepage": "https://github.com/williamthorsen/node-monorepo-tools/tree/main/packages/release-kit#readme",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"url": "https://github.com/williamthorsen/node-monorepo-tools.git",
|
|
13
13
|
"directory": "packages/release-kit"
|
|
14
14
|
},
|
|
15
|
-
"license": "
|
|
15
|
+
"license": "ISC",
|
|
16
16
|
"author": "William Thorsen <william@thorsen.dev> (https://github.com/williamthorsen)",
|
|
17
17
|
"type": "module",
|
|
18
18
|
"exports": {
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"glob": "13.0.6",
|
|
35
35
|
"jiti": "2.6.1",
|
|
36
36
|
"js-yaml": "4.1.1",
|
|
37
|
-
"
|
|
37
|
+
"json-stringify-pretty-compact": "4.0.0",
|
|
38
|
+
"@williamthorsen/node-monorepo-core": "0.2.6"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
40
41
|
"@types/js-yaml": "4.0.9",
|
|
@@ -11,9 +11,21 @@
|
|
|
11
11
|
- name: documentation
|
|
12
12
|
color: a2eeef
|
|
13
13
|
description: Improvements or additions to documentation
|
|
14
|
+
- name: deprecation
|
|
15
|
+
color: fbca04
|
|
16
|
+
description: Marks functionality for future removal
|
|
14
17
|
- name: feature
|
|
15
18
|
color: '0075ca'
|
|
16
19
|
description: Added or improved external functionality
|
|
20
|
+
- name: fix
|
|
21
|
+
color: d73a4a
|
|
22
|
+
description: Fixes a bug
|
|
23
|
+
- name: performance
|
|
24
|
+
color: '0075ca'
|
|
25
|
+
description: Improves performance without changing behavior
|
|
26
|
+
- name: security
|
|
27
|
+
color: b60205
|
|
28
|
+
description: Security vulnerability or hardening
|
|
17
29
|
- name: spike
|
|
18
30
|
color: '000000'
|
|
19
31
|
description: Investigation
|
|
@@ -30,6 +42,9 @@
|
|
|
30
42
|
description: Further information is needed
|
|
31
43
|
|
|
32
44
|
# Refactoring
|
|
45
|
+
- name: ci
|
|
46
|
+
color: edc287
|
|
47
|
+
description: CI/CD tooling & configuration
|
|
33
48
|
- name: dependencies
|
|
34
49
|
color: edc287
|
|
35
50
|
description: Change to dependencies
|
|
@@ -46,6 +61,34 @@
|
|
|
46
61
|
color: 1d76db
|
|
47
62
|
description: Changed internal functionality
|
|
48
63
|
|
|
64
|
+
# Priority
|
|
65
|
+
- name: 'priority:critical'
|
|
66
|
+
color: b60205
|
|
67
|
+
description: Demands immediate attention
|
|
68
|
+
- name: 'priority:high'
|
|
69
|
+
color: d93f0b
|
|
70
|
+
description: Address soon
|
|
71
|
+
- name: 'priority:medium'
|
|
72
|
+
color: fbca04
|
|
73
|
+
description: No rush but don't forget
|
|
74
|
+
- name: 'priority:low'
|
|
75
|
+
color: cfd3d7
|
|
76
|
+
description: Get to it eventually
|
|
77
|
+
|
|
78
|
+
# Value
|
|
79
|
+
- name: 'value:must-have'
|
|
80
|
+
color: 7057ff
|
|
81
|
+
description: Essential for the application to fulfill its purpose
|
|
82
|
+
- name: 'value:should-have'
|
|
83
|
+
color: 8d83fc
|
|
84
|
+
description: Important but the application is usable without it
|
|
85
|
+
- name: 'value:nice-to-have'
|
|
86
|
+
color: a8b2f8
|
|
87
|
+
description: A nice-to-have enhancement
|
|
88
|
+
- name: 'value:questionable'
|
|
89
|
+
color: c5def5
|
|
90
|
+
description: Decision needed on whether this would add sufficient value
|
|
91
|
+
|
|
49
92
|
# Triage
|
|
50
93
|
- name: duplicate
|
|
51
94
|
color: cfd3d7
|
package/dist/esm/init/prompt.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
function printStep(message) {
|
|
2
|
-
console.info(`
|
|
3
|
-
> ${message}`);
|
|
4
|
-
}
|
|
5
|
-
function printSuccess(message) {
|
|
6
|
-
console.info(` \u2705 ${message}`);
|
|
7
|
-
}
|
|
8
|
-
function printSkip(message) {
|
|
9
|
-
console.info(` \u26A0\uFE0F ${message}`);
|
|
10
|
-
}
|
|
11
|
-
function printError(message) {
|
|
12
|
-
console.error(` \u274C ${message}`);
|
|
13
|
-
}
|
|
14
|
-
export {
|
|
15
|
-
printError,
|
|
16
|
-
printSkip,
|
|
17
|
-
printStep,
|
|
18
|
-
printSuccess
|
|
19
|
-
};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { MonorepoReleaseConfig, ReleaseConfig, ReleaseType } from './types.ts';
|
|
2
|
-
export declare const RELEASE_TAGS_FILE = "tmp/.release-tags";
|
|
3
|
-
export declare function parseArgs(argv: string[]): {
|
|
4
|
-
dryRun: boolean;
|
|
5
|
-
force: boolean;
|
|
6
|
-
bumpOverride: ReleaseType | undefined;
|
|
7
|
-
only: string[] | undefined;
|
|
8
|
-
};
|
|
9
|
-
export declare function runReleasePrepare(config: MonorepoReleaseConfig | ReleaseConfig): void;
|
|
10
|
-
export declare function writeReleaseTags(tags: string[], dryRun: boolean): void;
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { dirname } from "node:path";
|
|
3
|
-
import { dim } from "./format.js";
|
|
4
|
-
import { releasePrepare } from "./releasePrepare.js";
|
|
5
|
-
import { releasePrepareMono } from "./releasePrepareMono.js";
|
|
6
|
-
const RELEASE_TAGS_FILE = "tmp/.release-tags";
|
|
7
|
-
const VALID_BUMP_TYPES = ["major", "minor", "patch"];
|
|
8
|
-
function isReleaseType(value) {
|
|
9
|
-
return VALID_BUMP_TYPES.includes(value);
|
|
10
|
-
}
|
|
11
|
-
function isMonorepoConfig(config) {
|
|
12
|
-
return "components" in config;
|
|
13
|
-
}
|
|
14
|
-
function showHelp() {
|
|
15
|
-
console.info(`
|
|
16
|
-
Usage: runReleasePrepare [options]
|
|
17
|
-
|
|
18
|
-
Legacy entry point for release preparation. Prefer the CLI:
|
|
19
|
-
npx @williamthorsen/release-kit prepare
|
|
20
|
-
|
|
21
|
-
Options:
|
|
22
|
-
--dry-run Run without modifying any files
|
|
23
|
-
--bump=major|minor|patch Override the bump type for all components
|
|
24
|
-
--force Bypass the "no commits since last tag" check (monorepo only, requires --bump)
|
|
25
|
-
--only=name1,name2 Only process the named components (comma-separated, monorepo only)
|
|
26
|
-
--help Show this help message
|
|
27
|
-
`);
|
|
28
|
-
}
|
|
29
|
-
function parseArgs(argv) {
|
|
30
|
-
let dryRun = false;
|
|
31
|
-
let force = false;
|
|
32
|
-
let bumpOverride;
|
|
33
|
-
let only;
|
|
34
|
-
for (const arg of argv) {
|
|
35
|
-
if (arg === "--dry-run") {
|
|
36
|
-
dryRun = true;
|
|
37
|
-
} else if (arg === "--force") {
|
|
38
|
-
force = true;
|
|
39
|
-
} else if (arg.startsWith("--bump=")) {
|
|
40
|
-
const value = arg.slice("--bump=".length);
|
|
41
|
-
if (!isReleaseType(value)) {
|
|
42
|
-
console.error(`Error: Invalid bump type "${value}". Must be one of: ${VALID_BUMP_TYPES.join(", ")}`);
|
|
43
|
-
process.exit(1);
|
|
44
|
-
}
|
|
45
|
-
bumpOverride = value;
|
|
46
|
-
} else if (arg.startsWith("--only=")) {
|
|
47
|
-
const value = arg.slice("--only=".length);
|
|
48
|
-
if (!value) {
|
|
49
|
-
console.error("Error: --only requires a comma-separated list of component names");
|
|
50
|
-
process.exit(1);
|
|
51
|
-
}
|
|
52
|
-
only = value.split(",");
|
|
53
|
-
} else if (arg === "--help" || arg === "-h") {
|
|
54
|
-
showHelp();
|
|
55
|
-
process.exit(0);
|
|
56
|
-
} else {
|
|
57
|
-
console.error(`Error: Unknown argument: ${arg}`);
|
|
58
|
-
process.exit(1);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (force && bumpOverride === void 0) {
|
|
62
|
-
console.error("Error: --force requires --bump to specify the version bump type");
|
|
63
|
-
process.exit(1);
|
|
64
|
-
}
|
|
65
|
-
return { dryRun, force, bumpOverride, only };
|
|
66
|
-
}
|
|
67
|
-
function runReleasePrepare(config) {
|
|
68
|
-
const { dryRun, force, bumpOverride, only } = parseArgs(process.argv.slice(2));
|
|
69
|
-
const options = {
|
|
70
|
-
dryRun,
|
|
71
|
-
force,
|
|
72
|
-
...bumpOverride === void 0 ? {} : { bumpOverride }
|
|
73
|
-
};
|
|
74
|
-
if (!isMonorepoConfig(config)) {
|
|
75
|
-
if (only !== void 0) {
|
|
76
|
-
console.error("Error: --only is only supported for monorepo configurations");
|
|
77
|
-
process.exit(1);
|
|
78
|
-
}
|
|
79
|
-
try {
|
|
80
|
-
const tags = releasePrepare(config, options);
|
|
81
|
-
writeReleaseTags(tags, dryRun);
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.error("Error preparing release:", error instanceof Error ? error.message : String(error));
|
|
84
|
-
process.exit(1);
|
|
85
|
-
}
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
let effectiveConfig = config;
|
|
89
|
-
if (only !== void 0) {
|
|
90
|
-
const knownNames = config.components.map((c) => c.dir);
|
|
91
|
-
for (const name of only) {
|
|
92
|
-
if (!knownNames.includes(name)) {
|
|
93
|
-
console.error(`Error: Unknown component "${name}". Known components: ${knownNames.join(", ")}`);
|
|
94
|
-
process.exit(1);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
const filtered = config.components.filter((c) => only.includes(c.dir));
|
|
98
|
-
effectiveConfig = { ...config, components: filtered };
|
|
99
|
-
}
|
|
100
|
-
try {
|
|
101
|
-
const tags = releasePrepareMono(effectiveConfig, options);
|
|
102
|
-
writeReleaseTags(tags, dryRun);
|
|
103
|
-
} catch (error) {
|
|
104
|
-
console.error("Error preparing release:", error instanceof Error ? error.message : String(error));
|
|
105
|
-
process.exit(1);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
function writeReleaseTags(tags, dryRun) {
|
|
109
|
-
if (tags.length === 0) {
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
if (dryRun) {
|
|
113
|
-
console.info(dim(` [dry-run] Would write ${RELEASE_TAGS_FILE}: ${tags.join(" ")}`));
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
mkdirSync(dirname(RELEASE_TAGS_FILE), { recursive: true });
|
|
117
|
-
writeFileSync(RELEASE_TAGS_FILE, tags.join("\n"), "utf8");
|
|
118
|
-
console.info(dim(` Wrote ${RELEASE_TAGS_FILE}: ${tags.join(" ")}`));
|
|
119
|
-
}
|
|
120
|
-
export {
|
|
121
|
-
RELEASE_TAGS_FILE,
|
|
122
|
-
parseArgs,
|
|
123
|
-
runReleasePrepare,
|
|
124
|
-
writeReleaseTags
|
|
125
|
-
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { dirname } from "node:path";
|
|
3
|
-
function writeIfAbsent(filePath, content, dryRun, overwrite) {
|
|
4
|
-
if (existsSync(filePath) && !overwrite) {
|
|
5
|
-
console.info(` Skipped ${filePath} (already exists)`);
|
|
6
|
-
return { action: "skipped", filePath };
|
|
7
|
-
}
|
|
8
|
-
if (dryRun) {
|
|
9
|
-
console.info(` [dry-run] Would create ${filePath}`);
|
|
10
|
-
return { action: "dry-run", filePath };
|
|
11
|
-
}
|
|
12
|
-
try {
|
|
13
|
-
mkdirSync(dirname(filePath), { recursive: true });
|
|
14
|
-
writeFileSync(filePath, content, "utf8");
|
|
15
|
-
} catch (error) {
|
|
16
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
17
|
-
console.error(` Failed to write ${filePath}: ${message}`);
|
|
18
|
-
return { action: "failed", filePath };
|
|
19
|
-
}
|
|
20
|
-
console.info(` Created ${filePath}`);
|
|
21
|
-
return { action: "created", filePath };
|
|
22
|
-
}
|
|
23
|
-
export {
|
|
24
|
-
writeIfAbsent
|
|
25
|
-
};
|