@williamthorsen/release-kit 6.0.0 → 7.0.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 +8 -0
- package/README.md +3 -3
- package/dist/esm/.cache +1 -1
- package/dist/esm/assertCleanWorkingTree.js +9 -14
- package/dist/esm/bin/release-kit.js +200 -199
- package/dist/esm/buildChangelogEntries.d.ts +2 -2
- package/dist/esm/buildChangelogEntries.js +142 -149
- package/dist/esm/buildDependencyGraph.d.ts +1 -1
- package/dist/esm/buildDependencyGraph.js +60 -59
- package/dist/esm/buildEmptyReleaseEntry.d.ts +1 -1
- package/dist/esm/buildEmptyReleaseEntry.js +12 -15
- package/dist/esm/buildReleaseSummary.d.ts +1 -1
- package/dist/esm/buildReleaseSummary.js +23 -26
- package/dist/esm/buildSyntheticChangelogEntry.d.ts +1 -1
- package/dist/esm/buildSyntheticChangelogEntry.js +9 -12
- package/dist/esm/bumpAllVersions.d.ts +1 -1
- package/dist/esm/bumpAllVersions.js +51 -52
- package/dist/esm/bumpVersion.d.ts +1 -1
- package/dist/esm/bumpVersion.js +25 -28
- package/dist/esm/changelogJsonFile.d.ts +1 -1
- package/dist/esm/changelogJsonFile.js +59 -62
- package/dist/esm/changelogJsonUtils.d.ts +1 -1
- package/dist/esm/changelogJsonUtils.js +35 -32
- package/dist/esm/changelogOverrides.d.ts +1 -1
- package/dist/esm/changelogOverrides.js +374 -377
- package/dist/esm/checkWorkTypesDrift.js +104 -102
- package/dist/esm/collectPolicyViolations.d.ts +2 -2
- package/dist/esm/collectPolicyViolations.js +11 -14
- package/dist/esm/commitCommand.js +48 -46
- package/dist/esm/compareVersions.js +20 -23
- package/dist/esm/createGithubRelease.js +56 -59
- package/dist/esm/createGithubReleaseCommand.js +21 -23
- package/dist/esm/createTags.js +57 -56
- package/dist/esm/decideRelease.d.ts +2 -2
- package/dist/esm/decideRelease.js +27 -41
- package/dist/esm/defaults.d.ts +3 -3
- package/dist/esm/defaults.js +36 -48
- package/dist/esm/deleteFileIfExists.js +10 -12
- package/dist/esm/deriveWorkspaceConfig.d.ts +1 -1
- package/dist/esm/deriveWorkspaceConfig.js +34 -36
- package/dist/esm/detectPackageManager.js +35 -37
- package/dist/esm/detectUndeclaredTagPrefixes.js +41 -40
- package/dist/esm/determineBumpFromCommits.d.ts +2 -2
- package/dist/esm/determineBumpFromCommits.js +25 -29
- package/dist/esm/determineBumpType.d.ts +1 -1
- package/dist/esm/determineBumpType.js +31 -32
- package/dist/esm/discoverWorkspaces.js +38 -40
- package/dist/esm/format.js +6 -11
- package/dist/esm/generateChangelogs.d.ts +1 -1
- package/dist/esm/generateChangelogs.js +13 -17
- package/dist/esm/getCommitsSinceTarget.d.ts +1 -1
- package/dist/esm/getCommitsSinceTarget.js +54 -55
- package/dist/esm/hasPrettierConfig.js +33 -35
- package/dist/esm/help/prepareHelp.js +4 -8
- package/dist/esm/index.d.ts +4 -4
- package/dist/esm/index.js +2 -8
- package/dist/esm/init/checks.js +28 -32
- package/dist/esm/init/detectRepoType.js +12 -15
- package/dist/esm/init/initCommand.js +60 -54
- package/dist/esm/init/parseJsonRecord.js +9 -11
- package/dist/esm/init/scaffold.d.ts +1 -1
- package/dist/esm/init/scaffold.js +32 -38
- package/dist/esm/init/templates.d.ts +1 -1
- package/dist/esm/init/templates.js +16 -22
- package/dist/esm/injectReleaseNotesIntoReadme.js +42 -49
- package/dist/esm/injectSection.js +17 -27
- package/dist/esm/loadConfig.d.ts +1 -1
- package/dist/esm/loadConfig.js +206 -225
- package/dist/esm/parseCommitMessage.d.ts +1 -1
- package/dist/esm/parseCommitMessage.js +72 -76
- package/dist/esm/parseRequestedTags.js +6 -9
- package/dist/esm/prepareCommand.d.ts +1 -1
- package/dist/esm/prepareCommand.js +225 -235
- package/dist/esm/previewTagPrefixes.d.ts +1 -1
- package/dist/esm/previewTagPrefixes.js +101 -96
- package/dist/esm/propagateBumps.d.ts +2 -2
- package/dist/esm/propagateBumps.js +48 -50
- package/dist/esm/publish.d.ts +2 -2
- package/dist/esm/publish.js +22 -28
- package/dist/esm/publishCommand.js +75 -80
- package/dist/esm/pushCommand.js +33 -34
- package/dist/esm/pushRelease.d.ts +1 -1
- package/dist/esm/pushRelease.js +21 -24
- package/dist/esm/readCurrentVersion.js +13 -17
- package/dist/esm/releasePrepare.d.ts +1 -1
- package/dist/esm/releasePrepare.js +213 -231
- package/dist/esm/releasePrepareMono.d.ts +2 -2
- package/dist/esm/releasePrepareMono.js +434 -494
- package/dist/esm/releasePrepareProject.d.ts +2 -2
- package/dist/esm/releasePrepareProject.js +143 -153
- package/dist/esm/renderChangelogMarkdown.d.ts +1 -1
- package/dist/esm/renderChangelogMarkdown.js +20 -24
- package/dist/esm/renderReleaseNotes.d.ts +1 -1
- package/dist/esm/renderReleaseNotes.js +50 -55
- package/dist/esm/reportPrepare.d.ts +1 -1
- package/dist/esm/reportPrepare.js +230 -231
- package/dist/esm/resolveCliffConfigPath.js +18 -23
- package/dist/esm/resolveCommandTags.d.ts +1 -1
- package/dist/esm/resolveCommandTags.js +47 -45
- package/dist/esm/resolveReleaseNotesConfig.d.ts +1 -1
- package/dist/esm/resolveReleaseNotesConfig.js +39 -43
- package/dist/esm/resolveReleaseTags.d.ts +1 -1
- package/dist/esm/resolveReleaseTags.js +39 -40
- package/dist/esm/runGitCliff.js +27 -30
- package/dist/esm/showTagPrefixesCommand.js +48 -70
- package/dist/esm/stripEmojiPrefix.js +2 -5
- package/dist/esm/stripScope.js +18 -21
- package/dist/esm/sync-labels/generateCommand.d.ts +1 -1
- package/dist/esm/sync-labels/generateCommand.js +51 -53
- package/dist/esm/sync-labels/initCommand.js +46 -48
- package/dist/esm/sync-labels/loadSyncLabelsConfig.d.ts +1 -1
- package/dist/esm/sync-labels/loadSyncLabelsConfig.js +46 -52
- package/dist/esm/sync-labels/presets.d.ts +1 -1
- package/dist/esm/sync-labels/presets.js +40 -43
- package/dist/esm/sync-labels/resolveLabels.d.ts +1 -1
- package/dist/esm/sync-labels/resolveLabels.js +28 -35
- package/dist/esm/sync-labels/syncCommand.js +30 -31
- package/dist/esm/sync-labels/templates.d.ts +1 -1
- package/dist/esm/sync-labels/templates.js +23 -26
- package/dist/esm/sync-labels/types.js +1 -0
- package/dist/esm/syncWorkTypes.js +83 -84
- package/dist/esm/tagCommand.js +12 -14
- package/dist/esm/typeGuards.js +4 -8
- package/dist/esm/types.js +66 -60
- package/dist/esm/validateConfig.d.ts +1 -1
- package/dist/esm/validateConfig.js +109 -115
- package/dist/esm/validateOnlyExcludesStrandedDependents.d.ts +2 -2
- package/dist/esm/validateOnlyExcludesStrandedDependents.js +97 -91
- package/dist/esm/validateOverridesCommand.d.ts +2 -2
- package/dist/esm/validateOverridesCommand.js +110 -111
- package/dist/esm/workTypesData.js +57 -60
- package/dist/esm/workTypesUtils.js +16 -21
- package/dist/esm/writeReleaseNotesPreviews.js +55 -57
- package/package.json +2 -2
|
@@ -1,137 +1,136 @@
|
|
|
1
|
-
import { formatErrorLine } from
|
|
1
|
+
import { formatErrorLine } from '@williamthorsen/nmr-core';
|
|
2
2
|
import { buildChangelogEntries } from "./buildChangelogEntries.js";
|
|
3
|
-
import {
|
|
4
|
-
resolveOverridePath,
|
|
5
|
-
validateAllChangelogOverrides
|
|
6
|
-
} from "./changelogOverrides.js";
|
|
3
|
+
import { resolveOverridePath, validateAllChangelogOverrides, } from "./changelogOverrides.js";
|
|
7
4
|
import { discoverWorkspaces } from "./discoverWorkspaces.js";
|
|
8
5
|
import { buildTagPattern, getAllTagPrefixes } from "./generateChangelogs.js";
|
|
9
6
|
import { loadConfig, mergeMonorepoConfig, mergeSinglePackageConfig, readRootPackageVersion } from "./loadConfig.js";
|
|
10
7
|
import { validateConfig } from "./validateConfig.js";
|
|
11
|
-
const SYNTHETIC_VALIDATE_TAG =
|
|
12
|
-
async function validateOverridesCommand(dependencies = {}) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
discoveredPaths
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
8
|
+
const SYNTHETIC_VALIDATE_TAG = 'validate-only';
|
|
9
|
+
export async function validateOverridesCommand(dependencies = {}) {
|
|
10
|
+
const discover = dependencies.discoverWorkspaces ?? discoverWorkspaces;
|
|
11
|
+
const load = dependencies.loadConfig ?? loadConfig;
|
|
12
|
+
const buildEntries = dependencies.buildEntries ?? defaultBuildEntries;
|
|
13
|
+
const validate = dependencies.validate ?? validateAllChangelogOverrides;
|
|
14
|
+
let rawConfig;
|
|
15
|
+
try {
|
|
16
|
+
rawConfig = await load();
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
return { exitCode: 2, message: formatErrorLine(`Failed to load config: ${errorMessage(error)}`) };
|
|
20
|
+
}
|
|
21
|
+
let userConfig;
|
|
22
|
+
try {
|
|
23
|
+
userConfig = validateLoadedConfig(rawConfig);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
return { exitCode: 2, message: errorMessage(error) };
|
|
27
|
+
}
|
|
28
|
+
let discoveredPaths;
|
|
29
|
+
try {
|
|
30
|
+
discoveredPaths = await discover();
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
return { exitCode: 2, message: formatErrorLine(`Failed to discover workspaces: ${errorMessage(error)}`) };
|
|
34
|
+
}
|
|
35
|
+
let inputs;
|
|
36
|
+
try {
|
|
37
|
+
inputs =
|
|
38
|
+
discoveredPaths === undefined
|
|
39
|
+
? buildSinglePackageInputs(userConfig, buildEntries)
|
|
40
|
+
: buildMonorepoInputs(discoveredPaths, userConfig, buildEntries);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
return { exitCode: 2, message: formatErrorLine(`Failed to resolve overrides scope: ${errorMessage(error)}`) };
|
|
44
|
+
}
|
|
45
|
+
const result = validate(inputs);
|
|
46
|
+
return formatValidateOverridesResult(result);
|
|
43
47
|
}
|
|
44
|
-
function formatValidateOverridesResult(result) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
export function formatValidateOverridesResult(result) {
|
|
49
|
+
const { errors, warnings } = result;
|
|
50
|
+
if (errors.length === 0 && warnings.length === 0) {
|
|
51
|
+
return { exitCode: 0, message: 'All override files are valid (no errors, no stale keys).' };
|
|
52
|
+
}
|
|
53
|
+
const exitCode = errors.length > 0 ? 2 : 1;
|
|
54
|
+
const summary = formatSummaryLine(errors.length, warnings.length);
|
|
55
|
+
const errorLines = errors.map((message) => ` ❌ ${message}`);
|
|
56
|
+
const warningLines = warnings.map((message) => ` ⚠️ ${message}`);
|
|
57
|
+
const message = [summary, '', ...errorLines, ...warningLines].join('\n');
|
|
58
|
+
return { exitCode, message };
|
|
55
59
|
}
|
|
56
60
|
function formatSummaryLine(errorCount, warningCount) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
const parts = [];
|
|
62
|
+
if (errorCount > 0) {
|
|
63
|
+
parts.push(pluralize(errorCount, 'error'));
|
|
64
|
+
}
|
|
65
|
+
if (warningCount > 0) {
|
|
66
|
+
parts.push(pluralize(warningCount, 'warning'));
|
|
67
|
+
}
|
|
68
|
+
return `Found ${parts.join(' and ')}:`;
|
|
65
69
|
}
|
|
66
70
|
function pluralize(count, noun) {
|
|
67
|
-
|
|
71
|
+
return count === 1 ? `${count} ${noun}` : `${count} ${noun}s`;
|
|
68
72
|
}
|
|
69
73
|
function errorMessage(error) {
|
|
70
|
-
|
|
74
|
+
return error instanceof Error ? error.message : String(error);
|
|
71
75
|
}
|
|
72
76
|
function defaultBuildEntries(config, tagPattern, includePaths) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
77
|
+
const options = {};
|
|
78
|
+
if (tagPattern !== undefined) {
|
|
79
|
+
options.tagPattern = tagPattern;
|
|
80
|
+
}
|
|
81
|
+
if (includePaths !== undefined) {
|
|
82
|
+
options.includePaths = includePaths;
|
|
83
|
+
}
|
|
84
|
+
return buildChangelogEntries(config, SYNTHETIC_VALIDATE_TAG, options);
|
|
81
85
|
}
|
|
82
86
|
function flattenEntriesToHashes(entries) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
const hashes = [];
|
|
88
|
+
for (const entry of entries) {
|
|
89
|
+
for (const section of entry.sections) {
|
|
90
|
+
for (const item of section.items) {
|
|
91
|
+
if (item.hash !== undefined) {
|
|
92
|
+
hashes.push(item.hash);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
89
95
|
}
|
|
90
|
-
}
|
|
91
96
|
}
|
|
92
|
-
|
|
93
|
-
return hashes;
|
|
97
|
+
return hashes;
|
|
94
98
|
}
|
|
95
99
|
function validateLoadedConfig(rawConfig) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return config;
|
|
100
|
+
if (rawConfig === undefined) {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
const { config, errors } = validateConfig(rawConfig);
|
|
104
|
+
if (errors.length > 0) {
|
|
105
|
+
throw new Error(`Invalid config:\n - ${errors.join('\n - ')}`);
|
|
106
|
+
}
|
|
107
|
+
return config;
|
|
105
108
|
}
|
|
106
109
|
function buildSinglePackageInputs(userConfig, buildEntries) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
const config = mergeSinglePackageConfig(userConfig);
|
|
111
|
+
const hashes = flattenEntriesToHashes(buildEntries(config));
|
|
112
|
+
return {
|
|
113
|
+
project: { filePath: resolveOverridePath('.'), hashes },
|
|
114
|
+
};
|
|
112
115
|
}
|
|
113
116
|
function buildMonorepoInputs(discoveredPaths, userConfig, buildEntries) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
117
|
+
const rootPackage = readRootPackageVersion();
|
|
118
|
+
const config = mergeMonorepoConfig(discoveredPaths, userConfig, rootPackage);
|
|
119
|
+
const workspaces = config.workspaces.map((workspace) => {
|
|
120
|
+
const tagPattern = buildTagPattern(getAllTagPrefixes(workspace));
|
|
121
|
+
return {
|
|
122
|
+
filePath: resolveOverridePath(workspace.workspacePath),
|
|
123
|
+
hashes: flattenEntriesToHashes(buildEntries(config, tagPattern, workspace.paths)),
|
|
124
|
+
};
|
|
125
|
+
});
|
|
126
|
+
const project = config.project;
|
|
127
|
+
const projectScope = {
|
|
128
|
+
filePath: resolveOverridePath('.'),
|
|
121
129
|
};
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const contributingPaths = config.workspaces.flatMap((workspace) => workspace.paths);
|
|
129
|
-
const projectTagPattern = buildTagPattern([project.tagPrefix]);
|
|
130
|
-
projectScope.hashes = flattenEntriesToHashes(buildEntries(config, projectTagPattern, contributingPaths));
|
|
131
|
-
}
|
|
132
|
-
return { project: projectScope, workspaces };
|
|
130
|
+
if (project !== undefined) {
|
|
131
|
+
const contributingPaths = config.workspaces.flatMap((workspace) => workspace.paths);
|
|
132
|
+
const projectTagPattern = buildTagPattern([project.tagPrefix]);
|
|
133
|
+
projectScope.hashes = flattenEntriesToHashes(buildEntries(config, projectTagPattern, contributingPaths));
|
|
134
|
+
}
|
|
135
|
+
return { project: projectScope, workspaces };
|
|
133
136
|
}
|
|
134
|
-
export {
|
|
135
|
-
formatValidateOverridesResult,
|
|
136
|
-
validateOverridesCommand
|
|
137
|
-
};
|
|
@@ -1,62 +1,59 @@
|
|
|
1
|
-
const WORK_TYPES_DATA = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
export const WORK_TYPES_DATA = {
|
|
2
|
+
tiers: ['public', 'internal', 'process'],
|
|
3
|
+
types: [
|
|
4
|
+
{ tier: 'public', key: 'feat', aliases: ['feature'], emoji: '🎉', label: 'Features', breakingPolicy: 'optional' },
|
|
5
|
+
{ tier: 'public', key: 'drop', aliases: [], emoji: '🪦', label: 'Removed', breakingPolicy: 'required' },
|
|
6
|
+
{ tier: 'public', key: 'deprecate', aliases: [], emoji: '🗑️', label: 'Deprecated', breakingPolicy: 'forbidden' },
|
|
7
|
+
{ tier: 'public', key: 'fix', aliases: ['bugfix'], emoji: '🐛', label: 'Bug fixes', breakingPolicy: 'forbidden' },
|
|
8
|
+
{ tier: 'public', key: 'sec', aliases: ['security'], emoji: '🔒', label: 'Security', breakingPolicy: 'optional' },
|
|
9
|
+
{
|
|
10
|
+
tier: 'public',
|
|
11
|
+
key: 'perf',
|
|
12
|
+
aliases: ['performance'],
|
|
13
|
+
emoji: '⚡',
|
|
14
|
+
label: 'Performance',
|
|
15
|
+
breakingPolicy: 'forbidden',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
tier: 'internal',
|
|
19
|
+
key: 'internal',
|
|
20
|
+
aliases: ['utility'],
|
|
21
|
+
emoji: '🏗️',
|
|
22
|
+
label: 'Internal features',
|
|
23
|
+
breakingPolicy: 'forbidden',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
tier: 'internal',
|
|
27
|
+
key: 'refactor',
|
|
28
|
+
aliases: [],
|
|
29
|
+
emoji: '♻️',
|
|
30
|
+
label: 'Refactoring',
|
|
31
|
+
breakingPolicy: 'forbidden',
|
|
32
|
+
},
|
|
33
|
+
{ tier: 'internal', key: 'tests', aliases: ['test'], emoji: '🧪', label: 'Tests', breakingPolicy: 'forbidden' },
|
|
34
|
+
{ tier: 'process', key: 'tooling', aliases: [], emoji: '⚙️', label: 'Tooling', breakingPolicy: 'forbidden' },
|
|
35
|
+
{ tier: 'process', key: 'ci', aliases: [], emoji: '👷', label: 'CI', breakingPolicy: 'forbidden' },
|
|
36
|
+
{ tier: 'process', key: 'deps', aliases: ['dep'], emoji: '📦', label: 'Dependencies', breakingPolicy: 'forbidden' },
|
|
37
|
+
{ tier: 'process', key: 'ai', aliases: [], emoji: '🤖', label: 'Agentic support', breakingPolicy: 'forbidden' },
|
|
38
|
+
{
|
|
39
|
+
tier: 'process',
|
|
40
|
+
key: 'docs',
|
|
41
|
+
aliases: ['doc'],
|
|
42
|
+
emoji: '📚',
|
|
43
|
+
label: 'Documentation',
|
|
44
|
+
breakingPolicy: 'forbidden',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
tier: 'process',
|
|
48
|
+
key: 'fmt',
|
|
49
|
+
aliases: [],
|
|
50
|
+
emoji: '🎨',
|
|
51
|
+
label: 'Formatting',
|
|
52
|
+
breakingPolicy: 'forbidden',
|
|
53
|
+
excludedFromChangelog: true,
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
markers: {
|
|
57
|
+
breaking: { emoji: '🚨', label: 'Breaking' },
|
|
16
58
|
},
|
|
17
|
-
{
|
|
18
|
-
tier: "internal",
|
|
19
|
-
key: "internal",
|
|
20
|
-
aliases: ["utility"],
|
|
21
|
-
emoji: "\u{1F3D7}\uFE0F",
|
|
22
|
-
label: "Internal features",
|
|
23
|
-
breakingPolicy: "forbidden"
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
tier: "internal",
|
|
27
|
-
key: "refactor",
|
|
28
|
-
aliases: [],
|
|
29
|
-
emoji: "\u267B\uFE0F",
|
|
30
|
-
label: "Refactoring",
|
|
31
|
-
breakingPolicy: "forbidden"
|
|
32
|
-
},
|
|
33
|
-
{ tier: "internal", key: "tests", aliases: ["test"], emoji: "\u{1F9EA}", label: "Tests", breakingPolicy: "forbidden" },
|
|
34
|
-
{ tier: "process", key: "tooling", aliases: [], emoji: "\u2699\uFE0F", label: "Tooling", breakingPolicy: "forbidden" },
|
|
35
|
-
{ tier: "process", key: "ci", aliases: [], emoji: "\u{1F477}", label: "CI", breakingPolicy: "forbidden" },
|
|
36
|
-
{ tier: "process", key: "deps", aliases: ["dep"], emoji: "\u{1F4E6}", label: "Dependencies", breakingPolicy: "forbidden" },
|
|
37
|
-
{ tier: "process", key: "ai", aliases: [], emoji: "\u{1F916}", label: "Agentic support", breakingPolicy: "forbidden" },
|
|
38
|
-
{
|
|
39
|
-
tier: "process",
|
|
40
|
-
key: "docs",
|
|
41
|
-
aliases: ["doc"],
|
|
42
|
-
emoji: "\u{1F4DA}",
|
|
43
|
-
label: "Documentation",
|
|
44
|
-
breakingPolicy: "forbidden"
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
tier: "process",
|
|
48
|
-
key: "fmt",
|
|
49
|
-
aliases: [],
|
|
50
|
-
emoji: "\u{1F3A8}",
|
|
51
|
-
label: "Formatting",
|
|
52
|
-
breakingPolicy: "forbidden",
|
|
53
|
-
excludedFromChangelog: true
|
|
54
|
-
}
|
|
55
|
-
],
|
|
56
|
-
markers: {
|
|
57
|
-
breaking: { emoji: "\u{1F6A8}", label: "Breaking" }
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
export {
|
|
61
|
-
WORK_TYPES_DATA
|
|
62
59
|
};
|
|
@@ -1,24 +1,19 @@
|
|
|
1
|
-
function hasExpectedTopLevelShape(value) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
export function hasExpectedTopLevelShape(value) {
|
|
2
|
+
if (typeof value !== 'object' || value === null) {
|
|
3
|
+
return false;
|
|
4
|
+
}
|
|
5
|
+
if (!('tiers' in value) || !('types' in value)) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
return Array.isArray(value.tiers) && Array.isArray(value.types);
|
|
9
9
|
}
|
|
10
|
-
function errorMessage(error) {
|
|
11
|
-
|
|
10
|
+
export function errorMessage(error) {
|
|
11
|
+
return error instanceof Error ? error.message : String(error);
|
|
12
12
|
}
|
|
13
|
-
function buildFetchInit() {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
export function buildFetchInit() {
|
|
14
|
+
const token = process.env.GITHUB_TOKEN;
|
|
15
|
+
if (token === undefined || token === '') {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
return { headers: { Authorization: `Bearer ${token}` } };
|
|
19
19
|
}
|
|
20
|
-
export {
|
|
21
|
-
buildFetchInit,
|
|
22
|
-
errorMessage,
|
|
23
|
-
hasExpectedTopLevelShape
|
|
24
|
-
};
|
|
@@ -1,65 +1,63 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from
|
|
2
|
-
import path from
|
|
3
|
-
import { reportError, writeFileWithCheck } from
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { reportError, writeFileWithCheck } from '@williamthorsen/nmr-core';
|
|
4
4
|
import { extractVersion } from "./changelogJsonUtils.js";
|
|
5
5
|
import { dim } from "./format.js";
|
|
6
6
|
import { renderInjectedReadme } from "./injectReleaseNotesIntoReadme.js";
|
|
7
|
-
function writeReleaseNotesPreviews(options) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
export function writeReleaseNotesPreviews(options) {
|
|
8
|
+
const { workspacePath, tag, changelogJsonPath, sectionOrder, dryRun } = options;
|
|
9
|
+
const version = extractVersion(tag);
|
|
10
|
+
const readmePath = path.join(workspacePath, 'README.md');
|
|
11
|
+
let readmeExists = existsSync(readmePath);
|
|
12
|
+
let readmeUnreadable = false;
|
|
13
|
+
let readmeContent = '';
|
|
14
|
+
if (readmeExists) {
|
|
15
|
+
try {
|
|
16
|
+
readmeContent = readFileSync(readmePath, 'utf8');
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
20
|
+
console.warn(`Warning: failed to read ${readmePath}: ${message}; skipping injected-README preview`);
|
|
21
|
+
readmeExists = false;
|
|
22
|
+
readmeUnreadable = true;
|
|
23
|
+
}
|
|
22
24
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
return { renderSkipped: true };
|
|
27
|
-
}
|
|
28
|
-
const docsDir = path.join(workspacePath, "docs");
|
|
29
|
-
const readmePreviewPath = path.join(docsDir, `README.v${version}.md`);
|
|
30
|
-
const releaseNotesPreviewPath = path.join(docsDir, `RELEASE_NOTES.v${version}.md`);
|
|
31
|
-
let injectedReadme;
|
|
32
|
-
if (readmeExists) {
|
|
33
|
-
injectedReadme = writePreviewFile(readmePreviewPath, rendered.injectedReadme, dryRun);
|
|
34
|
-
} else {
|
|
35
|
-
if (!readmeUnreadable) {
|
|
36
|
-
console.warn(
|
|
37
|
-
`Warning: ${readmePath} not found; skipping injected-README preview but still writing standalone release notes`
|
|
38
|
-
);
|
|
25
|
+
const rendered = renderInjectedReadme(readmeContent, changelogJsonPath, tag, sectionOrder);
|
|
26
|
+
if (rendered === undefined) {
|
|
27
|
+
return { renderSkipped: true };
|
|
39
28
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
29
|
+
const docsDir = path.join(workspacePath, 'docs');
|
|
30
|
+
const readmePreviewPath = path.join(docsDir, `README.v${version}.md`);
|
|
31
|
+
const releaseNotesPreviewPath = path.join(docsDir, `RELEASE_NOTES.v${version}.md`);
|
|
32
|
+
let injectedReadme;
|
|
33
|
+
if (readmeExists) {
|
|
34
|
+
injectedReadme = writePreviewFile(readmePreviewPath, rendered.injectedReadme, dryRun);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
if (!readmeUnreadable) {
|
|
38
|
+
console.warn(`Warning: ${readmePath} not found; skipping injected-README preview but still writing standalone release notes`);
|
|
39
|
+
}
|
|
40
|
+
injectedReadme = { filePath: readmePreviewPath, outcome: 'skipped-no-readme' };
|
|
41
|
+
}
|
|
42
|
+
const releaseNotesContent = rendered.releaseNotesMarkdown.endsWith('\n')
|
|
43
|
+
? rendered.releaseNotesMarkdown
|
|
44
|
+
: `${rendered.releaseNotesMarkdown}\n`;
|
|
45
|
+
const releaseNotes = writePreviewFile(releaseNotesPreviewPath, releaseNotesContent, dryRun);
|
|
46
|
+
return { injectedReadme, releaseNotes, renderSkipped: false };
|
|
46
47
|
}
|
|
47
48
|
function writePreviewFile(filePath, content, dryRun) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
49
|
+
if (dryRun) {
|
|
50
|
+
console.info(dim(` [dry-run] Would write ${filePath}`));
|
|
51
|
+
return { filePath, outcome: 'dry-run' };
|
|
52
|
+
}
|
|
53
|
+
const result = writeFileWithCheck(filePath, content, { dryRun: false, overwrite: true });
|
|
54
|
+
if (result.outcome === 'failed') {
|
|
55
|
+
reportError(`Failed to write ${filePath}: ${result.error ?? 'unknown error'}`);
|
|
56
|
+
return { filePath, outcome: 'failed', ...(result.error === undefined ? {} : { error: result.error }) };
|
|
57
|
+
}
|
|
58
|
+
if (result.outcome === 'created' || result.outcome === 'overwritten') {
|
|
59
|
+
console.info(dim(` Wrote ${filePath}`));
|
|
60
|
+
return { filePath, outcome: result.outcome };
|
|
61
|
+
}
|
|
62
|
+
return { filePath, outcome: 'failed', error: `unexpected outcome: ${result.outcome}` };
|
|
62
63
|
}
|
|
63
|
-
export {
|
|
64
|
-
writeReleaseNotesPreviews
|
|
65
|
-
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@williamthorsen/release-kit",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.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",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"semver": "7.8.5",
|
|
39
39
|
"yaml": "2.9.0",
|
|
40
40
|
"zod": "4.4.3",
|
|
41
|
-
"@williamthorsen/nmr-core": "0.
|
|
41
|
+
"@williamthorsen/nmr-core": "0.6.0"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/semver": "7.7.1",
|