@williamthorsen/release-kit 4.5.1 → 4.6.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 +115 -100
- package/LICENSE +4 -4
- package/cliff.toml.template +66 -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 +54 -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
|
@@ -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.6.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.6.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
|