@williamthorsen/release-kit 15.0.3 → 16.1.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/.meta/changelog.json +93 -0
- package/.readyup/kits/default.js +14 -14
- package/.readyup/kits/npm-auto-publish.js +4 -4
- package/.readyup/manifest.json +13 -13
- package/CHANGELOG.md +27 -0
- package/README.md +12 -3
- package/dist/esm/applyChangelogOverrides.js +6 -6
- package/dist/esm/assertReleasesOnNpm.js +11 -11
- package/dist/esm/assertTaggedBaseline.js +5 -5
- package/dist/esm/assertTarballsComplete.d.ts +9 -0
- package/dist/esm/assertTarballsComplete.js +52 -0
- package/dist/esm/bin/release-kit.js +16 -16
- package/dist/esm/buildChangelogEntries.d.ts +19 -19
- package/dist/esm/buildChangelogEntries.js +40 -36
- package/dist/esm/buildChangelogItem.js +24 -24
- package/dist/esm/buildDependencyGraph.js +23 -23
- package/dist/esm/buildReleasedResult.js +21 -19
- package/dist/esm/buildSyntheticChangelogEntry.js +2 -2
- package/dist/esm/bumpVersion.js +8 -8
- package/dist/esm/changelogArchive.d.ts +1 -1
- package/dist/esm/changelogArchive.js +2 -2
- package/dist/esm/changelogJsonFile.js +5 -5
- package/dist/esm/changelogJsonUtils.js +3 -3
- package/dist/esm/changelogOverrides.d.ts +5 -5
- package/dist/esm/changelogOverrides.js +23 -23
- package/dist/esm/classifyChangelogCommit.js +4 -4
- package/dist/esm/commitCommand.js +3 -3
- package/dist/esm/compareVersions.js +13 -13
- package/dist/esm/configSchema.d.ts +3 -2
- package/dist/esm/configSchema.js +2 -1
- package/dist/esm/createGithubRelease.d.ts +4 -4
- package/dist/esm/createGithubRelease.js +10 -10
- package/dist/esm/createGithubReleaseCommand.js +9 -9
- package/dist/esm/createTags.d.ts +2 -2
- package/dist/esm/createTags.js +8 -8
- package/dist/esm/decideDirectReleases.d.ts +5 -5
- package/dist/esm/decideDirectReleases.js +25 -25
- package/dist/esm/decideRelease.d.ts +1 -1
- package/dist/esm/decideRelease.js +2 -2
- package/dist/esm/deriveDirectoryConfig.d.ts +1 -1
- package/dist/esm/deriveDirectoryConfig.js +18 -18
- package/dist/esm/deriveWorkspaceConfig.js +4 -4
- package/dist/esm/detectPackageManager.d.ts +2 -0
- package/dist/esm/detectPackageManager.js +8 -5
- package/dist/esm/detectUndeclaredTagPrefixes.js +6 -6
- package/dist/esm/enumerateReleaseWindows.d.ts +1 -1
- package/dist/esm/enumerateReleaseWindows.js +7 -7
- package/dist/esm/findMissingManifestPaths.d.ts +14 -0
- package/dist/esm/findMissingManifestPaths.js +90 -0
- package/dist/esm/findTransitiveDependents.js +5 -5
- package/dist/esm/findUnroutedEntryScopes.js +11 -11
- package/dist/esm/format.d.ts +1 -1
- package/dist/esm/format.js +1 -1
- package/dist/esm/formatPrepareFiles.d.ts +3 -3
- package/dist/esm/formatPrepareFiles.js +10 -10
- package/dist/esm/formatPrepareWarnings.js +6 -6
- package/dist/esm/hasPrettierConfig.js +2 -2
- package/dist/esm/init/checks.js +5 -3
- package/dist/esm/init/detectRepoType.js +3 -3
- package/dist/esm/init/initCommand.d.ts +4 -4
- package/dist/esm/init/initCommand.js +7 -7
- package/dist/esm/init/parseJsonRecord.d.ts +1 -1
- package/dist/esm/init/parseJsonRecord.js +4 -4
- package/dist/esm/init/scaffold.d.ts +4 -4
- package/dist/esm/init/scaffold.js +15 -15
- package/dist/esm/init/templates.d.ts +10 -10
- package/dist/esm/init/templates.js +5 -5
- package/dist/esm/init/updateTemplatesCommand.d.ts +2 -2
- package/dist/esm/init/updateTemplatesCommand.js +14 -12
- package/dist/esm/injectReleaseNotesIntoReadme.d.ts +1 -1
- package/dist/esm/injectReleaseNotesIntoReadme.js +6 -6
- package/dist/esm/injectSection.js +8 -8
- package/dist/esm/loadChangelogOverrides.d.ts +1 -1
- package/dist/esm/loadChangelogOverrides.js +9 -9
- package/dist/esm/loadConfig.d.ts +3 -3
- package/dist/esm/loadConfig.js +10 -10
- package/dist/esm/loadValidatedConfig.js +4 -4
- package/dist/esm/mergeConfig.d.ts +1 -1
- package/dist/esm/mergeConfig.js +27 -27
- package/dist/esm/monorepoConfigAssertions.js +15 -15
- package/dist/esm/npmRegistry.js +4 -4
- package/dist/esm/packFromCleanCheckout.d.ts +11 -0
- package/dist/esm/packFromCleanCheckout.js +81 -0
- package/dist/esm/packsPath.js +3 -3
- package/dist/esm/parseChangeRecordBlock.js +33 -33
- package/dist/esm/parseCommitMessage.js +5 -5
- package/dist/esm/planChangelogFiles.js +8 -8
- package/dist/esm/planReleaseNotesPreviews.js +10 -10
- package/dist/esm/planVersionBump.js +24 -16
- package/dist/esm/prepareArgs.d.ts +9 -9
- package/dist/esm/prepareArgs.js +11 -11
- package/dist/esm/prepareCommand.js +27 -24
- package/dist/esm/prepareComposite.d.ts +4 -4
- package/dist/esm/prepareComposite.js +16 -16
- package/dist/esm/{releasePrepareTargets.d.ts → prepareReleaseTargets.d.ts} +9 -9
- package/dist/esm/{releasePrepareTargets.js → prepareReleaseTargets.js} +40 -40
- package/dist/esm/prepareRunContext.d.ts +1 -1
- package/dist/esm/prepareRunContext.js +5 -5
- package/dist/esm/prepareTarget.d.ts +3 -3
- package/dist/esm/prepareTarget.js +41 -39
- package/dist/esm/previewTagPrefixes.js +19 -19
- package/dist/esm/propagateBumps.js +8 -8
- package/dist/esm/publish.d.ts +3 -3
- package/dist/esm/publish.js +6 -11
- package/dist/esm/publishCommand.d.ts +3 -3
- package/dist/esm/publishCommand.js +28 -20
- package/dist/esm/pushCommand.js +8 -8
- package/dist/esm/pushRelease.d.ts +1 -1
- package/dist/esm/pushRelease.js +2 -2
- package/dist/esm/readChangelogSections.d.ts +1 -1
- package/dist/esm/readChangelogSections.js +16 -16
- package/dist/esm/releasePlan.js +25 -25
- package/dist/esm/renderChangelogMarkdown.d.ts +4 -4
- package/dist/esm/renderChangelogMarkdown.js +18 -15
- package/dist/esm/renderReleaseNotes.d.ts +1 -1
- package/dist/esm/renderReleaseNotes.js +16 -16
- package/dist/esm/reportPrepare.js +34 -34
- package/dist/esm/resolveCommandTags.js +9 -9
- package/dist/esm/resolveReleaseDeclaration.d.ts +2 -2
- package/dist/esm/resolveReleaseDeclaration.js +22 -22
- package/dist/esm/resolveReleaseTags.js +17 -15
- package/dist/esm/resolveReleaseTargets.js +2 -2
- package/dist/esm/showTagPrefixesCommand.js +4 -4
- package/dist/esm/sync-labels/generateCommand.d.ts +3 -3
- package/dist/esm/sync-labels/generateCommand.js +10 -10
- package/dist/esm/sync-labels/initCommand.d.ts +3 -3
- package/dist/esm/sync-labels/initCommand.js +15 -15
- package/dist/esm/sync-labels/presets.js +3 -3
- package/dist/esm/sync-labels/resolveLabels.js +13 -13
- package/dist/esm/sync-labels/templates.d.ts +2 -2
- package/dist/esm/sync-labels/templates.js +1 -1
- package/dist/esm/tagCommand.js +4 -4
- package/dist/esm/topologicalSort.d.ts +2 -2
- package/dist/esm/topologicalSort.js +7 -7
- package/dist/esm/types.d.ts +3 -3
- package/dist/esm/validateAllChangelogOverrides.js +9 -9
- package/dist/esm/validateConfig.d.ts +1 -1
- package/dist/esm/validateConfig.js +60 -50
- package/dist/esm/validateOverridesCommand.js +2 -2
- package/docs/changelogs.md +5 -5
- package/docs/configuration.md +16 -15
- package/docs/publishing.md +4 -0
- package/docs/releasing.md +6 -0
- package/docs/work-types.md +1 -1
- package/package.json +2 -2
- package/presets/labels/common.yaml +3 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { formatGlyphLine, formatStatusLine, measureGlyphColumn, STATUS_GLYPHS, } from '@williamthorsen/nmr-core';
|
|
2
|
-
import { bold, dim,
|
|
2
|
+
import { bold, dim, renderSectionHeader } from "./format.js";
|
|
3
3
|
import { formatBumpFiles, formatChangelogFiles, formatPreviewFiles } from "./formatPrepareFiles.js";
|
|
4
4
|
import { formatChangeRecordWarnings, formatPolicyViolations, formatUnparseableWarning, formatWarnings, } from "./formatPrepareWarnings.js";
|
|
5
5
|
import { RELEASE_GLYPHS } from "./glyphs.js";
|
|
@@ -12,15 +12,15 @@ export function reportPrepare(plan, options) {
|
|
|
12
12
|
return formatSingleWorkspace(plan, options);
|
|
13
13
|
}
|
|
14
14
|
function formatSingleWorkspace(result, options) {
|
|
15
|
-
const
|
|
15
|
+
const isDryRun = !options.applied;
|
|
16
16
|
const { style } = options;
|
|
17
17
|
const lines = [];
|
|
18
18
|
const workspace = result.targets[0];
|
|
19
19
|
if (workspace === undefined || workspace.kind === 'composite') {
|
|
20
20
|
return '';
|
|
21
21
|
}
|
|
22
|
-
const
|
|
23
|
-
lines.push(dim(`Found ${workspace.commitCount} commits since ${
|
|
22
|
+
const sinceLabel = workspace.previousTag === undefined ? 'the beginning' : workspace.previousTag;
|
|
23
|
+
lines.push(dim(`Found ${workspace.commitCount} commits since ${sinceLabel}`));
|
|
24
24
|
if (workspace.parsedCommitCount !== undefined) {
|
|
25
25
|
lines.push(dim(` Parsed ${workspace.parsedCommitCount} typed commits`));
|
|
26
26
|
}
|
|
@@ -32,8 +32,8 @@ function formatSingleWorkspace(result, options) {
|
|
|
32
32
|
formatWarnings(lines, result, style);
|
|
33
33
|
return lines.join('\n');
|
|
34
34
|
}
|
|
35
|
-
if (workspace.
|
|
36
|
-
lines.push(` Using version override: ${workspace.
|
|
35
|
+
if (workspace.versionOverride !== undefined) {
|
|
36
|
+
lines.push(` Using version override: ${workspace.versionOverride}`);
|
|
37
37
|
}
|
|
38
38
|
else if (workspace.bumpOverride !== undefined) {
|
|
39
39
|
lines.push(` Using bump override: ${workspace.bumpOverride}`);
|
|
@@ -41,35 +41,35 @@ function formatSingleWorkspace(result, options) {
|
|
|
41
41
|
if (workspace.releaseType !== undefined) {
|
|
42
42
|
lines.push(dim(`Bumping versions (${workspace.releaseType})...`));
|
|
43
43
|
}
|
|
44
|
-
else if (workspace.
|
|
44
|
+
else if (workspace.versionOverride !== undefined) {
|
|
45
45
|
lines.push(dim(`Bumping versions (version override)...`));
|
|
46
46
|
}
|
|
47
|
-
if (workspace.
|
|
47
|
+
if (workspace.versionOverride !== undefined) {
|
|
48
48
|
lines.push(formatGlyphLine(RELEASE_GLYPHS, style, 'bump', `${workspace.currentVersion} → ${bold(workspace.newVersion)} (version override)`));
|
|
49
49
|
}
|
|
50
50
|
else if (workspace.releaseType !== undefined) {
|
|
51
51
|
lines.push(formatGlyphLine(RELEASE_GLYPHS, style, 'bump', `${workspace.currentVersion} → ${bold(workspace.newVersion)} (${workspace.releaseType})`));
|
|
52
52
|
}
|
|
53
53
|
formatChangeRecordWarnings(lines, workspace, style);
|
|
54
|
-
formatBumpFiles(lines, workspace,
|
|
54
|
+
formatBumpFiles(lines, workspace, isDryRun);
|
|
55
55
|
lines.push(dim('Generating changelogs...'));
|
|
56
|
-
formatChangelogFiles(lines, workspace,
|
|
57
|
-
formatPreviewFiles(lines, workspace,
|
|
56
|
+
formatChangelogFiles(lines, workspace, isDryRun, style);
|
|
57
|
+
formatPreviewFiles(lines, workspace, isDryRun);
|
|
58
58
|
formatFormatCommand(lines, result, options);
|
|
59
59
|
formatWarnings(lines, result, style);
|
|
60
60
|
lines.push(formatStatusLine(style, 'passed', 'Release preparation complete.'), ` ${formatGlyphLine(RELEASE_GLYPHS, style, 'tag', bold(workspace.tag))}`);
|
|
61
61
|
return lines.join('\n');
|
|
62
62
|
}
|
|
63
63
|
function formatMultiWorkspace(result, options) {
|
|
64
|
-
const
|
|
64
|
+
const isDryRun = !options.applied;
|
|
65
65
|
const { style } = options;
|
|
66
66
|
const lines = [];
|
|
67
67
|
for (const target of result.targets) {
|
|
68
68
|
if (target.kind === 'composite') {
|
|
69
|
-
formatProjectSection(lines, target,
|
|
69
|
+
formatProjectSection(lines, target, isDryRun, style);
|
|
70
70
|
}
|
|
71
71
|
else {
|
|
72
|
-
formatWorkspaceSection(lines, target,
|
|
72
|
+
formatWorkspaceSection(lines, target, isDryRun, style);
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
formatFormatCommand(lines, result, options);
|
|
@@ -85,10 +85,10 @@ function formatMultiWorkspace(result, options) {
|
|
|
85
85
|
}
|
|
86
86
|
return lines.join('\n');
|
|
87
87
|
}
|
|
88
|
-
function formatProjectSection(lines, project,
|
|
89
|
-
lines.push(`\n${
|
|
90
|
-
const
|
|
91
|
-
lines.push(dim(` Found ${project.commitCount} commits ${
|
|
88
|
+
function formatProjectSection(lines, project, isDryRun, style) {
|
|
89
|
+
lines.push(`\n${renderSectionHeader(project.targetId === PROJECT_TARGET_ID ? 'project' : project.targetId)}`);
|
|
90
|
+
const sinceLabel = project.previousTag === undefined ? '(no previous release found)' : `since ${project.previousTag}`;
|
|
91
|
+
lines.push(dim(` Found ${project.commitCount} commits ${sinceLabel}`));
|
|
92
92
|
formatPolicyViolations(lines, project.policyViolations, style, ' ');
|
|
93
93
|
if (project.status === 'skipped') {
|
|
94
94
|
formatUnparseableWarning(lines, project, style, ' ');
|
|
@@ -107,7 +107,7 @@ function formatProjectSection(lines, project, dryRun, style) {
|
|
|
107
107
|
formatChangeRecordWarnings(lines, project, style, ' ');
|
|
108
108
|
lines.push(dim(` Bumping versions (${releaseType})...`), ` ${formatGlyphLine(RELEASE_GLYPHS, style, 'bump', `${currentVersion} → ${bold(newVersion)} (${releaseType})`)}`);
|
|
109
109
|
for (const file of project.bumpedFiles) {
|
|
110
|
-
if (
|
|
110
|
+
if (isDryRun) {
|
|
111
111
|
lines.push(dim(` [dry-run] Would bump ${file}`));
|
|
112
112
|
}
|
|
113
113
|
else {
|
|
@@ -115,16 +115,16 @@ function formatProjectSection(lines, project, dryRun, style) {
|
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
lines.push(dim(' Generating changelogs...'));
|
|
118
|
-
formatChangelogFiles(lines, project,
|
|
119
|
-
formatPreviewFiles(lines, project,
|
|
118
|
+
formatChangelogFiles(lines, project, isDryRun, style, ' ');
|
|
119
|
+
formatPreviewFiles(lines, project, isDryRun, ' ');
|
|
120
120
|
lines.push(` ${formatGlyphLine(RELEASE_GLYPHS, style, 'tag', bold(tag))}`);
|
|
121
121
|
}
|
|
122
|
-
function formatWorkspaceSection(lines, workspace,
|
|
122
|
+
function formatWorkspaceSection(lines, workspace, isDryRun, style) {
|
|
123
123
|
if (workspace.name !== undefined) {
|
|
124
|
-
lines.push(`\n${
|
|
124
|
+
lines.push(`\n${renderSectionHeader(workspace.name)}`);
|
|
125
125
|
}
|
|
126
|
-
const
|
|
127
|
-
lines.push(dim(` Found ${workspace.commitCount} commits ${
|
|
126
|
+
const sinceLabel = workspace.previousTag === undefined ? '(no previous release found)' : `since ${workspace.previousTag}`;
|
|
127
|
+
lines.push(dim(` Found ${workspace.commitCount} commits ${sinceLabel}`));
|
|
128
128
|
if (workspace.status === 'skipped') {
|
|
129
129
|
formatUnparseableWarning(lines, workspace, style, ' ');
|
|
130
130
|
formatPolicyViolations(lines, workspace.policyViolations, style, ' ');
|
|
@@ -140,24 +140,24 @@ function formatWorkspaceSection(lines, workspace, dryRun, style) {
|
|
|
140
140
|
formatChangeRecordWarnings(lines, workspace, style, ' ');
|
|
141
141
|
formatBumpLabels(lines, workspace, isPropagatedOnly);
|
|
142
142
|
formatVersionLine(lines, workspace, propagatedFrom, isPropagatedOnly, style);
|
|
143
|
-
formatBumpFiles(lines, workspace,
|
|
143
|
+
formatBumpFiles(lines, workspace, isDryRun, ' ');
|
|
144
144
|
lines.push(dim(' Generating changelogs...'));
|
|
145
|
-
formatChangelogFiles(lines, workspace,
|
|
146
|
-
formatPreviewFiles(lines, workspace,
|
|
145
|
+
formatChangelogFiles(lines, workspace, isDryRun, style, ' ');
|
|
146
|
+
formatPreviewFiles(lines, workspace, isDryRun, ' ');
|
|
147
147
|
lines.push(` ${formatGlyphLine(RELEASE_GLYPHS, style, 'tag', bold(workspace.tag))}`);
|
|
148
148
|
}
|
|
149
149
|
function formatCommitSummary(lines, workspace, propagatedFrom, isPropagatedOnly) {
|
|
150
150
|
if (isPropagatedOnly && propagatedFrom !== undefined) {
|
|
151
|
-
const
|
|
152
|
-
lines.push(dim(` Bumped via dependency: ${
|
|
151
|
+
const dependencyNames = propagatedFrom.map((p) => p.packageName).join(', ');
|
|
152
|
+
lines.push(dim(` Bumped via dependency: ${dependencyNames}`));
|
|
153
153
|
}
|
|
154
154
|
else if (workspace.parsedCommitCount !== undefined && workspace.parsedCommitCount > 0) {
|
|
155
155
|
lines.push(dim(` Parsed ${workspace.parsedCommitCount} typed commits`));
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
function formatBumpLabels(lines, workspace, isPropagatedOnly) {
|
|
159
|
-
if (workspace.
|
|
160
|
-
lines.push(` Using version override: ${workspace.
|
|
159
|
+
if (workspace.versionOverride !== undefined) {
|
|
160
|
+
lines.push(` Using version override: ${workspace.versionOverride}`);
|
|
161
161
|
}
|
|
162
162
|
else if (workspace.bumpOverride !== undefined && !isPropagatedOnly) {
|
|
163
163
|
lines.push(` Using bump override: ${workspace.bumpOverride}`);
|
|
@@ -165,13 +165,13 @@ function formatBumpLabels(lines, workspace, isPropagatedOnly) {
|
|
|
165
165
|
if (workspace.releaseType !== undefined) {
|
|
166
166
|
lines.push(dim(` Bumping versions (${workspace.releaseType})...`));
|
|
167
167
|
}
|
|
168
|
-
else if (workspace.
|
|
168
|
+
else if (workspace.versionOverride !== undefined) {
|
|
169
169
|
lines.push(dim(` Bumping versions (version override)...`));
|
|
170
170
|
}
|
|
171
171
|
}
|
|
172
172
|
function formatVersionLine(lines, workspace, propagatedFrom, isPropagatedOnly, style) {
|
|
173
173
|
const versions = `${workspace.currentVersion} → ${bold(workspace.newVersion)}`;
|
|
174
|
-
if (workspace.
|
|
174
|
+
if (workspace.versionOverride !== undefined) {
|
|
175
175
|
lines.push(` ${formatGlyphLine(RELEASE_GLYPHS, style, 'bump', `${versions} (version override)`)}`);
|
|
176
176
|
}
|
|
177
177
|
else if (workspace.releaseType !== undefined) {
|
|
@@ -29,12 +29,12 @@ export function resolveCommandTags(tags, userConfig) {
|
|
|
29
29
|
singleWorkspace = deriveWorkspaceConfig('.');
|
|
30
30
|
}
|
|
31
31
|
else {
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
workspaces = [...
|
|
35
|
-
directories =
|
|
36
|
-
project =
|
|
37
|
-
excludedPaths = new Set(
|
|
32
|
+
const mergedConfig = mergeMonorepoConfig(workspace.packageDirs, userConfig, readRootPackageVersion());
|
|
33
|
+
const excludedWorkspaces = mergedConfig.excludedWorkspaces ?? [];
|
|
34
|
+
workspaces = [...mergedConfig.workspaces, ...excludedWorkspaces];
|
|
35
|
+
directories = mergedConfig.directories ?? [];
|
|
36
|
+
project = mergedConfig.project;
|
|
37
|
+
excludedPaths = new Set(excludedWorkspaces.map((excludedWorkspace) => excludedWorkspace.workspacePath));
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
catch (error) {
|
|
@@ -69,15 +69,15 @@ export function resolveCommandTags(tags, userConfig) {
|
|
|
69
69
|
return dropExcludedTags(resolvedTags, excludedPaths, userConfig?.releases === undefined ? 'legacy' : 'releases');
|
|
70
70
|
}
|
|
71
71
|
function dropExcludedTags(resolvedTags, excludedPaths, surface) {
|
|
72
|
-
const
|
|
72
|
+
const retainedTags = [];
|
|
73
73
|
for (const resolvedTag of resolvedTags) {
|
|
74
74
|
if (resolvedTag.kind === 'package' && excludedPaths.has(resolvedTag.workspacePath)) {
|
|
75
75
|
const setting = surface === 'releases' ? `releases.${resolvedTag.dir}: false` : undefined;
|
|
76
76
|
console.warn(formatExcludedSkip(resolvedTag, setting));
|
|
77
77
|
}
|
|
78
78
|
else {
|
|
79
|
-
|
|
79
|
+
retainedTags.push(resolvedTag);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
return
|
|
82
|
+
return retainedTags;
|
|
83
83
|
}
|
|
@@ -24,9 +24,9 @@ export interface DeclaredDirectory {
|
|
|
24
24
|
/** The release targets that a config declares over the discovered workspaces. */
|
|
25
25
|
export interface ReleaseDeclaration {
|
|
26
26
|
/** Retained workspaces in discovery order, each with its target name and legacy identities applied. */
|
|
27
|
-
|
|
27
|
+
retainedWorkspaces: WorkspaceConfig[];
|
|
28
28
|
/** Discovered workspaces that the config excludes, in discovery order. */
|
|
29
|
-
|
|
29
|
+
excludedWorkspaces: WorkspaceConfig[];
|
|
30
30
|
/** Directories that `releases` entries declare as targets, in config order. */
|
|
31
31
|
directories: DeclaredDirectory[];
|
|
32
32
|
composite?: DeclaredComposite;
|
|
@@ -3,8 +3,8 @@ export function getTargetName(workspace) {
|
|
|
3
3
|
return workspace.targetName ?? workspace.dir;
|
|
4
4
|
}
|
|
5
5
|
export function normalizeWorkspacePath(configuredPath) {
|
|
6
|
-
const
|
|
7
|
-
return
|
|
6
|
+
const normalizedPath = path.posix.normalize(configuredPath.replaceAll('\\', '/'));
|
|
7
|
+
return normalizedPath.replace(/^\.\//, '').replace(/\/+$/, '');
|
|
8
8
|
}
|
|
9
9
|
export function resolveReleaseDeclaration(workspaces, userConfig) {
|
|
10
10
|
if (userConfig?.releases !== undefined) {
|
|
@@ -19,9 +19,9 @@ function applyLegacyIdentities(workspace, legacyIdentities) {
|
|
|
19
19
|
return { ...workspace, legacyIdentities: legacyIdentities.map((identity) => ({ ...identity })) };
|
|
20
20
|
}
|
|
21
21
|
function claimPath(entryByPath, name, claimedPath, kind) {
|
|
22
|
-
const
|
|
23
|
-
if (
|
|
24
|
-
throw new Error(`releases.${name}: ${kind} '${claimedPath}' is already declared by releases.${
|
|
22
|
+
const claimingEntryName = entryByPath.get(claimedPath);
|
|
23
|
+
if (claimingEntryName !== undefined) {
|
|
24
|
+
throw new Error(`releases.${name}: ${kind} '${claimedPath}' is already declared by releases.${claimingEntryName}; declare each ${kind} once`);
|
|
25
25
|
}
|
|
26
26
|
entryByPath.set(claimedPath, name);
|
|
27
27
|
}
|
|
@@ -40,9 +40,9 @@ function declareDirectory(name, entry, normalizedPath) {
|
|
|
40
40
|
}),
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
|
-
function resolveCompositeMembers(composite,
|
|
43
|
+
function resolveCompositeMembers(composite, retainedWorkspaces, excludedWorkspaces, directories) {
|
|
44
44
|
const membersByName = new Map([
|
|
45
|
-
...
|
|
45
|
+
...retainedWorkspaces.map((workspace) => [getTargetName(workspace), { name: getTargetName(workspace), paths: workspace.paths }]),
|
|
46
46
|
...directories.map((directory) => [directory.name, { name: directory.name, paths: directory.paths }]),
|
|
47
47
|
]);
|
|
48
48
|
return composite.includes.map((memberName) => {
|
|
@@ -54,7 +54,7 @@ function resolveCompositeMembers(composite, retained, excluded, directories) {
|
|
|
54
54
|
if (memberName === composite.name) {
|
|
55
55
|
throw new Error(`${label} is the composite itself; a composite includes package and directory targets only`);
|
|
56
56
|
}
|
|
57
|
-
if (
|
|
57
|
+
if (excludedWorkspaces.some((workspace) => workspace.dir === memberName)) {
|
|
58
58
|
throw new Error(`${label} is excluded, so the composite cannot include it`);
|
|
59
59
|
}
|
|
60
60
|
throw new Error(`${label} is not a release target. Known targets: ${membersByName.keys().toArray().join(', ')}`);
|
|
@@ -62,18 +62,18 @@ function resolveCompositeMembers(composite, retained, excluded, directories) {
|
|
|
62
62
|
}
|
|
63
63
|
function resolveLegacyBlocks(workspaces, overrides, project) {
|
|
64
64
|
const overridesByDir = new Map(overrides.map((override) => [override.dir, override]));
|
|
65
|
-
const
|
|
66
|
-
const
|
|
65
|
+
const retainedWorkspaces = [];
|
|
66
|
+
const excludedWorkspaces = [];
|
|
67
67
|
for (const workspace of workspaces) {
|
|
68
68
|
const override = overridesByDir.get(workspace.dir);
|
|
69
69
|
if (override?.shouldExclude === true) {
|
|
70
|
-
|
|
70
|
+
excludedWorkspaces.push(workspace);
|
|
71
71
|
}
|
|
72
72
|
else {
|
|
73
|
-
|
|
73
|
+
retainedWorkspaces.push(applyLegacyIdentities(workspace, override?.legacyIdentities));
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
-
const declaration = {
|
|
76
|
+
const declaration = { retainedWorkspaces, excludedWorkspaces, directories: [] };
|
|
77
77
|
if (project !== undefined) {
|
|
78
78
|
declaration.composite = {
|
|
79
79
|
...(project.paths !== undefined && { paths: [...project.paths] }),
|
|
@@ -87,7 +87,7 @@ function resolveReleasesBlock(workspaces, releases) {
|
|
|
87
87
|
const workspaceByDir = new Map(workspaces.map((workspace) => [workspace.dir, workspace]));
|
|
88
88
|
const entryByPath = new Map();
|
|
89
89
|
const excludedPaths = new Set();
|
|
90
|
-
const
|
|
90
|
+
const renamedWorkspaces = new Map();
|
|
91
91
|
const directories = [];
|
|
92
92
|
let composite;
|
|
93
93
|
for (const [name, entry] of Object.entries(releases)) {
|
|
@@ -126,22 +126,22 @@ function resolveReleasesBlock(workspaces, releases) {
|
|
|
126
126
|
"whose tag prefix derives from its package name; declare the workspace's earlier prefixes in legacyIdentities");
|
|
127
127
|
}
|
|
128
128
|
claimPath(entryByPath, name, workspace.workspacePath, 'workspace');
|
|
129
|
-
const
|
|
130
|
-
|
|
129
|
+
const identifiedWorkspace = applyLegacyIdentities(workspace, entry.legacyIdentities);
|
|
130
|
+
renamedWorkspaces.set(workspace.workspacePath, name === workspace.dir ? identifiedWorkspace : { ...identifiedWorkspace, targetName: name });
|
|
131
131
|
}
|
|
132
|
-
const
|
|
133
|
-
const
|
|
132
|
+
const retainedWorkspaces = [];
|
|
133
|
+
const excludedWorkspaces = [];
|
|
134
134
|
for (const workspace of workspaces) {
|
|
135
135
|
if (excludedPaths.has(workspace.workspacePath)) {
|
|
136
|
-
|
|
136
|
+
excludedWorkspaces.push(workspace);
|
|
137
137
|
}
|
|
138
138
|
else {
|
|
139
|
-
|
|
139
|
+
retainedWorkspaces.push(renamedWorkspaces.get(workspace.workspacePath) ?? workspace);
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
|
-
const declaration = {
|
|
142
|
+
const declaration = { retainedWorkspaces, excludedWorkspaces, directories };
|
|
143
143
|
if (composite !== undefined) {
|
|
144
|
-
const members = resolveCompositeMembers(composite,
|
|
144
|
+
const members = resolveCompositeMembers(composite, retainedWorkspaces, excludedWorkspaces, directories);
|
|
145
145
|
declaration.composite = {
|
|
146
146
|
name: composite.name,
|
|
147
147
|
members: members.map((member) => member.name),
|
|
@@ -22,32 +22,34 @@ export function resolveReleaseTags(args) {
|
|
|
22
22
|
return resolveSinglePackageTags(tags, args.singleWorkspace);
|
|
23
23
|
}
|
|
24
24
|
function resolveSinglePackageTags(tags, singleWorkspace) {
|
|
25
|
-
const
|
|
25
|
+
const matchedTags = tags.filter((tag) => VERSION_PATTERN.test(tag));
|
|
26
26
|
const isPublishable = singleWorkspace?.isPublishable ?? true;
|
|
27
|
-
if (
|
|
28
|
-
console.warn(`Warning: Multiple version tags found on HEAD: ${
|
|
27
|
+
if (matchedTags.length > 1) {
|
|
28
|
+
console.warn(`Warning: Multiple version tags found on HEAD: ${matchedTags.join(', ')}. ` +
|
|
29
29
|
`Publishing the same package multiple times is almost certainly unintended. Using only the first tag.`);
|
|
30
|
-
return
|
|
30
|
+
return matchedTags
|
|
31
|
+
.slice(0, 1)
|
|
32
|
+
.map((tag) => ({ tag, kind: 'package', dir: '.', workspacePath: '.', isPublishable }));
|
|
31
33
|
}
|
|
32
|
-
return
|
|
34
|
+
return matchedTags.map((tag) => ({ tag, kind: 'package', dir: '.', workspacePath: '.', isPublishable }));
|
|
33
35
|
}
|
|
34
36
|
function resolveMonorepoTags(tags, workspaces, directories, project) {
|
|
35
37
|
const sortedWorkspaces = workspaces.toSorted((a, b) => b.tagPrefix.length - a.tagPrefix.length);
|
|
36
|
-
const
|
|
38
|
+
const resolvedTags = [];
|
|
37
39
|
for (const tag of tags) {
|
|
38
|
-
const
|
|
40
|
+
const matchedWorkspace = findMatchingWorkspace(tag, sortedWorkspaces);
|
|
39
41
|
const directory = directories.find((candidate) => hasVersionAfterPrefix(tag, candidate.tagPrefix));
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
+
if (matchedWorkspace !== undefined) {
|
|
43
|
+
resolvedTags.push({
|
|
42
44
|
tag,
|
|
43
45
|
kind: 'package',
|
|
44
|
-
dir: getTargetName(
|
|
45
|
-
workspacePath:
|
|
46
|
-
isPublishable:
|
|
46
|
+
dir: getTargetName(matchedWorkspace),
|
|
47
|
+
workspacePath: matchedWorkspace.workspacePath,
|
|
48
|
+
isPublishable: matchedWorkspace.isPublishable,
|
|
47
49
|
});
|
|
48
50
|
}
|
|
49
51
|
else if (directory !== undefined) {
|
|
50
|
-
|
|
52
|
+
resolvedTags.push({
|
|
51
53
|
tag,
|
|
52
54
|
kind: 'directory',
|
|
53
55
|
dir: directory.name,
|
|
@@ -56,7 +58,7 @@ function resolveMonorepoTags(tags, workspaces, directories, project) {
|
|
|
56
58
|
});
|
|
57
59
|
}
|
|
58
60
|
else if (project !== undefined && hasVersionAfterPrefix(tag, project.tagPrefix)) {
|
|
59
|
-
|
|
61
|
+
resolvedTags.push({
|
|
60
62
|
tag,
|
|
61
63
|
kind: 'project',
|
|
62
64
|
dir: project.name ?? PROJECT_TARGET_ID,
|
|
@@ -65,7 +67,7 @@ function resolveMonorepoTags(tags, workspaces, directories, project) {
|
|
|
65
67
|
});
|
|
66
68
|
}
|
|
67
69
|
}
|
|
68
|
-
return
|
|
70
|
+
return resolvedTags;
|
|
69
71
|
}
|
|
70
72
|
function findMatchingWorkspace(tag, sortedWorkspaces) {
|
|
71
73
|
return sortedWorkspaces.find((workspace) => hasVersionAfterPrefix(tag, workspace.tagPrefix));
|
|
@@ -13,8 +13,8 @@ export function resolveReleaseTargets(userConfig, discovery) {
|
|
|
13
13
|
return projectMonorepoConfig(mergeMonorepoConfig(discovery.packageDirs, userConfig, readRootPackageVersion()));
|
|
14
14
|
}
|
|
15
15
|
export function isSinglePackageTargets(targets) {
|
|
16
|
-
const [
|
|
17
|
-
return targets.length === 1 &&
|
|
16
|
+
const [onlyTarget] = targets;
|
|
17
|
+
return targets.length === 1 && onlyTarget?.kind === 'package' && !onlyTarget.isWorkspace;
|
|
18
18
|
}
|
|
19
19
|
export function projectMonorepoConfig(config) {
|
|
20
20
|
const targets = [
|
|
@@ -59,12 +59,12 @@ function renderWorkspaceRow(row, style) {
|
|
|
59
59
|
lines.push(` ${row.workspacePath}: derived prefix '${row.derivedPrefix}', ${statusMarker}`);
|
|
60
60
|
for (const entry of row.legacyEntries) {
|
|
61
61
|
if (entry.tagCount > 0) {
|
|
62
|
-
const
|
|
63
|
-
lines.push(` ${formatStatusLine(style, 'passed',
|
|
62
|
+
const recognizedMessage = `${entry.tagCount} legacy tags with '${entry.prefix}' prefix (recognized)`;
|
|
63
|
+
lines.push(` ${formatStatusLine(style, 'passed', recognizedMessage)}`);
|
|
64
64
|
}
|
|
65
65
|
else {
|
|
66
|
-
const
|
|
67
|
-
lines.push(` ${formatStatusLine(style, 'warning',
|
|
66
|
+
const taglessMessage = `recorded legacy prefix '${entry.prefix}' does not have any tags`;
|
|
67
|
+
lines.push(` ${formatStatusLine(style, 'warning', taglessMessage)}`);
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
return lines;
|
|
@@ -20,7 +20,7 @@ export declare function loadRepoLabelsConfig(stderrStyle: OutputStyle, configPat
|
|
|
20
20
|
/** Options for the `sync-labels generate` subcommand. */
|
|
21
21
|
interface GenerateOptions {
|
|
22
22
|
/** Compares the regenerated content against the committed file instead of writing. */
|
|
23
|
-
|
|
23
|
+
shouldCheck?: boolean;
|
|
24
24
|
/** Config file to read, relative to the working directory. Defaults to `CONFIG_FILE_PATH`. */
|
|
25
25
|
configPath?: string;
|
|
26
26
|
styles: StreamStyles;
|
|
@@ -28,11 +28,11 @@ interface GenerateOptions {
|
|
|
28
28
|
/**
|
|
29
29
|
* Runs the `sync-labels generate` command and returns the process exit code.
|
|
30
30
|
*
|
|
31
|
-
* Writes `.github/labels.yaml` from the config's `repoLabels` block, or, with `
|
|
31
|
+
* Writes `.github/labels.yaml` from the config's `repoLabels` block, or, with `shouldCheck`, reports whether the committed
|
|
32
32
|
* file is stale and writes nothing.
|
|
33
33
|
*
|
|
34
34
|
* The header names the config by its POSIX path relative to the working directory, the repo root, so that the file
|
|
35
35
|
* does not depend on the invocation directory or on the machine on which the command ran.
|
|
36
36
|
*/
|
|
37
|
-
export declare function generateCommand({
|
|
37
|
+
export declare function generateCommand({ shouldCheck, configPath, styles }: GenerateOptions): Promise<number>;
|
|
38
38
|
export {};
|
|
@@ -15,14 +15,14 @@ export function formatLabelsYaml(labels, presetHashes, configFilePath = CONFIG_F
|
|
|
15
15
|
for (const [name, hash] of sortedPresetHashes) {
|
|
16
16
|
headerLines.push(`# ${name} preset hash: ${hash}`);
|
|
17
17
|
}
|
|
18
|
-
const
|
|
18
|
+
const declaredLabels = labels.map(({ aliases, archived, color, description, name }) => ({
|
|
19
19
|
name,
|
|
20
20
|
color,
|
|
21
21
|
description: description ?? '',
|
|
22
22
|
...(aliases !== undefined && { aliases }),
|
|
23
23
|
...(archived !== undefined && { archived }),
|
|
24
24
|
}));
|
|
25
|
-
const yamlBody = stringify(
|
|
25
|
+
const yamlBody = stringify(declaredLabels, { singleQuote: true, lineWidth: 0 });
|
|
26
26
|
return headerLines.join('\n') + '\n' + yamlBody;
|
|
27
27
|
}
|
|
28
28
|
export async function loadRepoLabelsConfig(stderrStyle, configPath) {
|
|
@@ -41,7 +41,7 @@ export async function loadRepoLabelsConfig(stderrStyle, configPath) {
|
|
|
41
41
|
}
|
|
42
42
|
return result.config.repoLabels;
|
|
43
43
|
}
|
|
44
|
-
export async function generateCommand({
|
|
44
|
+
export async function generateCommand({ shouldCheck = false, configPath, styles }) {
|
|
45
45
|
if (checkRetiredSyncLabelsConfig(configPath)) {
|
|
46
46
|
return 1;
|
|
47
47
|
}
|
|
@@ -63,8 +63,8 @@ export async function generateCommand({ check = false, configPath, styles }) {
|
|
|
63
63
|
for (const presetName of presetNames) {
|
|
64
64
|
presetHashes.set(presetName, hashPreset(presetName));
|
|
65
65
|
}
|
|
66
|
-
const content = formatLabelsYaml(labels, presetHashes,
|
|
67
|
-
if (
|
|
66
|
+
const content = formatLabelsYaml(labels, presetHashes, convertToRootRelativePosixPath(configPath ?? CONFIG_FILE_PATH));
|
|
67
|
+
if (shouldCheck) {
|
|
68
68
|
return compareAgainstCommittedFile(content);
|
|
69
69
|
}
|
|
70
70
|
try {
|
|
@@ -79,22 +79,22 @@ export async function generateCommand({ check = false, configPath, styles }) {
|
|
|
79
79
|
console.info(`Generated ${LABELS_OUTPUT_PATH} with ${String(labels.length)} labels.`);
|
|
80
80
|
return 0;
|
|
81
81
|
}
|
|
82
|
-
function compareAgainstCommittedFile(
|
|
83
|
-
let
|
|
82
|
+
function compareAgainstCommittedFile(expectedContent) {
|
|
83
|
+
let existingContent;
|
|
84
84
|
try {
|
|
85
|
-
|
|
85
|
+
existingContent = readFileSync(LABELS_OUTPUT_PATH, 'utf8');
|
|
86
86
|
}
|
|
87
87
|
catch {
|
|
88
88
|
reportError(`${LABELS_OUTPUT_PATH} is missing. Run \`release-kit sync-labels generate\` and commit the result.`);
|
|
89
89
|
return 1;
|
|
90
90
|
}
|
|
91
|
-
if (
|
|
91
|
+
if (existingContent !== expectedContent) {
|
|
92
92
|
reportError(`${LABELS_OUTPUT_PATH} is stale. Run \`release-kit sync-labels generate\` and commit the result.`);
|
|
93
93
|
return 1;
|
|
94
94
|
}
|
|
95
95
|
console.info(`${LABELS_OUTPUT_PATH} is up to date.`);
|
|
96
96
|
return 0;
|
|
97
97
|
}
|
|
98
|
-
function
|
|
98
|
+
function convertToRootRelativePosixPath(filePath) {
|
|
99
99
|
return path.relative(process.cwd(), path.resolve(filePath)).split(path.sep).join('/');
|
|
100
100
|
}
|
|
@@ -3,8 +3,8 @@ import { type StreamStyles } from '@williamthorsen/nmr-core';
|
|
|
3
3
|
interface InitOptions {
|
|
4
4
|
/** Config file to read, relative to the working directory. Defaults to `CONFIG_FILE_PATH`. */
|
|
5
5
|
configPath?: string;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
isDryRun: boolean;
|
|
7
|
+
shouldForce: boolean;
|
|
8
8
|
styles: StreamStyles;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
@@ -17,5 +17,5 @@ interface InitOptions {
|
|
|
17
17
|
* `configPath` names the config to read. Because the command fails when the named config does not exist, it
|
|
18
18
|
* reaches the scaffolding branch only under the default path, and that branch always writes to `CONFIG_FILE_PATH`.
|
|
19
19
|
*/
|
|
20
|
-
export declare function syncLabelsInitCommand({ configPath,
|
|
20
|
+
export declare function syncLabelsInitCommand({ configPath, isDryRun, shouldForce, styles, }: InitOptions): Promise<number>;
|
|
21
21
|
export {};
|
|
@@ -6,14 +6,14 @@ import { CONFIG_FILE_PATH } from "../loadConfig.js";
|
|
|
6
6
|
import { loadValidatedConfig, reportConfigProblem } from "../loadValidatedConfig.js";
|
|
7
7
|
import { generateCommand, LABELS_OUTPUT_PATH } from "./generateCommand.js";
|
|
8
8
|
import { checkRetiredSyncLabelsConfig } from "./retiredConfig.js";
|
|
9
|
-
import { buildScopeLabels, readSyncLabelsWorkflowTemplate, renderRepoLabelsBlock,
|
|
9
|
+
import { buildScopeLabels, readSyncLabelsWorkflowTemplate, renderRepoLabelsBlock, renderRepoLabelsConfigScript, } from "./templates.js";
|
|
10
10
|
const WORKFLOW_PATH = '.github/workflows/sync-labels.yaml';
|
|
11
|
-
export async function syncLabelsInitCommand({ configPath,
|
|
11
|
+
export async function syncLabelsInitCommand({ configPath, isDryRun, shouldForce, styles, }) {
|
|
12
12
|
const configFilePath = configPath ?? CONFIG_FILE_PATH;
|
|
13
13
|
if (checkRetiredSyncLabelsConfig(configPath)) {
|
|
14
14
|
return 1;
|
|
15
15
|
}
|
|
16
|
-
if (
|
|
16
|
+
if (isDryRun) {
|
|
17
17
|
console.info('[dry-run mode]');
|
|
18
18
|
}
|
|
19
19
|
console.info('\n> Discovering workspaces');
|
|
@@ -36,8 +36,8 @@ export async function syncLabelsInitCommand({ configPath, dryRun, force, styles
|
|
|
36
36
|
else {
|
|
37
37
|
console.info(` Found ${String(workspace.packageDirs.length)} workspaces`);
|
|
38
38
|
}
|
|
39
|
-
const
|
|
40
|
-
const retiredNames =
|
|
39
|
+
const doesConfigExist = configPath !== undefined || existsSync(CONFIG_FILE_PATH);
|
|
40
|
+
const retiredNames = doesConfigExist ? await loadRetiredPackageNames(styles, configPath) : [];
|
|
41
41
|
if (retiredNames === undefined) {
|
|
42
42
|
return 1;
|
|
43
43
|
}
|
|
@@ -51,9 +51,9 @@ export async function syncLabelsInitCommand({ configPath, dryRun, force, styles
|
|
|
51
51
|
process.stderr.write(` ${describeError(error)}\n`);
|
|
52
52
|
return 1;
|
|
53
53
|
}
|
|
54
|
-
const workflowResult = writeFileWithCheck(WORKFLOW_PATH, workflow, { isDryRun
|
|
55
|
-
reportWriteResult(workflowResult,
|
|
56
|
-
if (
|
|
54
|
+
const workflowResult = writeFileWithCheck(WORKFLOW_PATH, workflow, { isDryRun, shouldOverwrite: shouldForce });
|
|
55
|
+
reportWriteResult(workflowResult, isDryRun, styles);
|
|
56
|
+
if (doesConfigExist) {
|
|
57
57
|
console.info(`\n> ${configFilePath} already exists; add this block to the object passed to defineConfig:\n`);
|
|
58
58
|
console.info(renderRepoLabelsBlock(scopeLabels));
|
|
59
59
|
if (workflowResult.outcome === 'failed') {
|
|
@@ -69,16 +69,16 @@ export async function syncLabelsInitCommand({ configPath, dryRun, force, styles
|
|
|
69
69
|
`);
|
|
70
70
|
return 0;
|
|
71
71
|
}
|
|
72
|
-
const configResult = writeFileWithCheck(CONFIG_FILE_PATH,
|
|
73
|
-
isDryRun
|
|
74
|
-
shouldOverwrite:
|
|
72
|
+
const configResult = writeFileWithCheck(CONFIG_FILE_PATH, renderRepoLabelsConfigScript(scopeLabels), {
|
|
73
|
+
isDryRun,
|
|
74
|
+
shouldOverwrite: shouldForce,
|
|
75
75
|
});
|
|
76
|
-
reportWriteResult(configResult,
|
|
76
|
+
reportWriteResult(configResult, isDryRun, styles);
|
|
77
77
|
if (workflowResult.outcome === 'failed' || configResult.outcome === 'failed') {
|
|
78
78
|
process.stderr.write('Failed to scaffold one or more files.\n');
|
|
79
79
|
return 1;
|
|
80
80
|
}
|
|
81
|
-
if (
|
|
81
|
+
if (isDryRun) {
|
|
82
82
|
console.info(`\n> [dry-run] Would generate ${LABELS_OUTPUT_PATH}`);
|
|
83
83
|
}
|
|
84
84
|
else {
|
|
@@ -109,8 +109,8 @@ async function loadRetiredPackageNames(styles, configPath) {
|
|
|
109
109
|
if (result.status === 'missing') {
|
|
110
110
|
return [];
|
|
111
111
|
}
|
|
112
|
-
return (result.config.retiredPackages ?? []).map((retired) =>
|
|
112
|
+
return (result.config.retiredPackages ?? []).map((retired) => stripNpmScope(retired.name));
|
|
113
113
|
}
|
|
114
|
-
function
|
|
114
|
+
function stripNpmScope(name) {
|
|
115
115
|
return name.startsWith('@') ? name.slice(name.indexOf('/') + 1) : name;
|
|
116
116
|
}
|
|
@@ -25,12 +25,12 @@ export function loadPreset(presetName) {
|
|
|
25
25
|
catch (error) {
|
|
26
26
|
throw chainError(`Failed to read preset "${presetName}"`, error);
|
|
27
27
|
}
|
|
28
|
-
const
|
|
29
|
-
if (!Array.isArray(
|
|
28
|
+
const parsedYaml = parse(content);
|
|
29
|
+
if (!Array.isArray(parsedYaml)) {
|
|
30
30
|
throw new TypeError(`Preset "${presetName}" must be a YAML array of label definitions`);
|
|
31
31
|
}
|
|
32
32
|
const labels = [];
|
|
33
|
-
for (const entry of
|
|
33
|
+
for (const entry of parsedYaml) {
|
|
34
34
|
if (!isRecord(entry)) {
|
|
35
35
|
throw new Error(`Preset "${presetName}" contains an invalid label entry: ${JSON.stringify(entry)}`);
|
|
36
36
|
}
|