@williamthorsen/release-kit 5.0.0 → 5.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/CHANGELOG.md +60 -0
- package/README.md +137 -43
- package/dist/esm/.cache +1 -1
- package/dist/esm/assertCleanWorkingTree.js +1 -1
- package/dist/esm/bin/release-kit.js +1 -1
- package/dist/esm/buildChangelogEntries.d.ts +3 -0
- package/dist/esm/{generateChangelogJson.js → buildChangelogEntries.js} +7 -80
- package/dist/esm/buildDependencyGraph.d.ts +1 -0
- package/dist/esm/buildDependencyGraph.js +8 -1
- package/dist/esm/buildReleaseSummary.js +9 -1
- package/dist/esm/buildSyntheticChangelogEntry.d.ts +5 -0
- package/dist/esm/buildSyntheticChangelogEntry.js +13 -0
- package/dist/esm/changelogJsonFile.d.ts +4 -0
- package/dist/esm/changelogJsonFile.js +68 -0
- package/dist/esm/decideRelease.d.ts +25 -0
- package/dist/esm/decideRelease.js +28 -0
- package/dist/esm/defaults.d.ts +1 -0
- package/dist/esm/defaults.js +2 -0
- package/dist/esm/index.d.ts +2 -43
- package/dist/esm/index.js +0 -82
- package/dist/esm/init/templates.js +2 -2
- package/dist/esm/loadConfig.d.ts +10 -1
- package/dist/esm/loadConfig.js +96 -2
- package/dist/esm/prepareCommand.js +51 -9
- package/dist/esm/publish.d.ts +0 -1
- package/dist/esm/publish.js +3 -3
- package/dist/esm/publishCommand.js +10 -1
- package/dist/esm/releasePrepare.js +83 -39
- package/dist/esm/releasePrepareMono.js +133 -87
- package/dist/esm/releasePrepareProject.d.ts +9 -0
- package/dist/esm/releasePrepareProject.js +109 -0
- package/dist/esm/reportPrepare.js +70 -24
- package/dist/esm/types.d.ts +57 -14
- package/dist/esm/validateConfig.js +26 -0
- package/dist/esm/validateOnlyExcludesStrandedDependents.d.ts +14 -0
- package/dist/esm/validateOnlyExcludesStrandedDependents.js +109 -0
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +4 -1
- package/presets/labels/common.yaml +9 -6
- package/schemas/label-map.json +24 -0
- package/dist/esm/generateChangelogJson.d.ts +0 -7
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { execSync } from "node:child_process";
|
|
2
|
+
import { buildChangelogEntries } from "./buildChangelogEntries.js";
|
|
2
3
|
import { bumpAllVersions, setAllVersions } from "./bumpAllVersions.js";
|
|
4
|
+
import { resolveChangelogJsonPath, upsertChangelogJson } from "./changelogJsonFile.js";
|
|
3
5
|
import { isForwardVersion } from "./compareVersions.js";
|
|
4
6
|
import { DEFAULT_VERSION_PATTERNS, DEFAULT_WORK_TYPES } from "./defaults.js";
|
|
5
7
|
import { determineBumpFromCommits } from "./determineBumpFromCommits.js";
|
|
6
|
-
import { generateChangelogJson } from "./generateChangelogJson.js";
|
|
7
8
|
import { generateChangelogs } from "./generateChangelogs.js";
|
|
8
9
|
import { getCommitsSinceTarget } from "./getCommitsSinceTarget.js";
|
|
9
10
|
import { hasPrettierConfig } from "./hasPrettierConfig.js";
|
|
@@ -43,19 +44,22 @@ function releasePrepare(config, options) {
|
|
|
43
44
|
releaseType = bumpOverride;
|
|
44
45
|
}
|
|
45
46
|
if (releaseType === void 0) {
|
|
47
|
+
const skipped = {
|
|
48
|
+
status: "skipped",
|
|
49
|
+
commitCount: commits.length,
|
|
50
|
+
skipReason: "No release-worthy changes found. Skipping."
|
|
51
|
+
};
|
|
52
|
+
if (tag !== void 0) {
|
|
53
|
+
skipped.previousTag = tag;
|
|
54
|
+
}
|
|
55
|
+
if (parsedCommitCount !== void 0) {
|
|
56
|
+
skipped.parsedCommitCount = parsedCommitCount;
|
|
57
|
+
}
|
|
58
|
+
if (unparseableCommits !== void 0) {
|
|
59
|
+
skipped.unparseableCommits = unparseableCommits;
|
|
60
|
+
}
|
|
46
61
|
return {
|
|
47
|
-
workspaces: [
|
|
48
|
-
{
|
|
49
|
-
status: "skipped",
|
|
50
|
-
previousTag: tag,
|
|
51
|
-
commitCount: commits.length,
|
|
52
|
-
parsedCommitCount,
|
|
53
|
-
unparseableCommits,
|
|
54
|
-
bumpedFiles: [],
|
|
55
|
-
changelogFiles: [],
|
|
56
|
-
skipReason: "No release-worthy changes found. Skipping."
|
|
57
|
-
}
|
|
58
|
-
],
|
|
62
|
+
workspaces: [skipped],
|
|
59
63
|
tags: [],
|
|
60
64
|
dryRun
|
|
61
65
|
};
|
|
@@ -64,12 +68,7 @@ function releasePrepare(config, options) {
|
|
|
64
68
|
}
|
|
65
69
|
const newTag = `${config.tagPrefix}${bump.newVersion}`;
|
|
66
70
|
const changelogFiles = generateChangelogs(config, newTag, dryRun);
|
|
67
|
-
const changelogJsonFiles = [];
|
|
68
|
-
if (config.changelogJson.enabled) {
|
|
69
|
-
for (const changelogPath of config.changelogPaths) {
|
|
70
|
-
changelogJsonFiles.push(...generateChangelogJson(config, changelogPath, newTag, dryRun));
|
|
71
|
-
}
|
|
72
|
-
}
|
|
71
|
+
const changelogJsonFiles = config.changelogJson.enabled ? buildAndPersistChangelogJson(config, newTag, dryRun) : [];
|
|
73
72
|
maybeWriteSinglePackagePreviews(withReleaseNotes === true, config, newTag, changelogJsonFiles[0], dryRun);
|
|
74
73
|
const formatCommandStr = config.formatCommand ?? (hasPrettierConfig() ? "npx prettier --write" : void 0);
|
|
75
74
|
let formatCommand;
|
|
@@ -86,36 +85,81 @@ function releasePrepare(config, options) {
|
|
|
86
85
|
try {
|
|
87
86
|
execSync(fullCommand, { stdio: "inherit" });
|
|
88
87
|
} catch (error) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
);
|
|
88
|
+
const baseMessage = error instanceof Error ? error.message : String(error);
|
|
89
|
+
throw new Error(`format stage: ${baseMessage} (command: '${fullCommand}')`, { cause: error });
|
|
92
90
|
}
|
|
93
91
|
formatCommand = { command: fullCommand, executed: true, files: modifiedFiles };
|
|
94
92
|
}
|
|
95
93
|
}
|
|
94
|
+
const released = buildReleasedSinglePackage({
|
|
95
|
+
commits,
|
|
96
|
+
bump,
|
|
97
|
+
newTag,
|
|
98
|
+
changelogFiles,
|
|
99
|
+
previousTag: tag,
|
|
100
|
+
parsedCommitCount,
|
|
101
|
+
releaseType,
|
|
102
|
+
unparseableCommits,
|
|
103
|
+
setVersion
|
|
104
|
+
});
|
|
96
105
|
return {
|
|
97
|
-
workspaces: [
|
|
98
|
-
{
|
|
99
|
-
status: "released",
|
|
100
|
-
previousTag: tag,
|
|
101
|
-
commitCount: commits.length,
|
|
102
|
-
parsedCommitCount,
|
|
103
|
-
releaseType,
|
|
104
|
-
currentVersion: bump.currentVersion,
|
|
105
|
-
newVersion: bump.newVersion,
|
|
106
|
-
tag: newTag,
|
|
107
|
-
bumpedFiles: bump.files,
|
|
108
|
-
changelogFiles,
|
|
109
|
-
commits,
|
|
110
|
-
unparseableCommits,
|
|
111
|
-
...setVersion === void 0 ? {} : { setVersion }
|
|
112
|
-
}
|
|
113
|
-
],
|
|
106
|
+
workspaces: [released],
|
|
114
107
|
tags: [newTag],
|
|
115
108
|
formatCommand,
|
|
116
109
|
dryRun
|
|
117
110
|
};
|
|
118
111
|
}
|
|
112
|
+
function buildReleasedSinglePackage(args) {
|
|
113
|
+
const {
|
|
114
|
+
commits,
|
|
115
|
+
bump,
|
|
116
|
+
newTag,
|
|
117
|
+
changelogFiles,
|
|
118
|
+
previousTag,
|
|
119
|
+
parsedCommitCount,
|
|
120
|
+
releaseType,
|
|
121
|
+
unparseableCommits,
|
|
122
|
+
setVersion
|
|
123
|
+
} = args;
|
|
124
|
+
const released = {
|
|
125
|
+
status: "released",
|
|
126
|
+
commitCount: commits.length,
|
|
127
|
+
currentVersion: bump.currentVersion,
|
|
128
|
+
newVersion: bump.newVersion,
|
|
129
|
+
tag: newTag,
|
|
130
|
+
bumpedFiles: bump.files,
|
|
131
|
+
changelogFiles,
|
|
132
|
+
commits
|
|
133
|
+
};
|
|
134
|
+
if (previousTag !== void 0) {
|
|
135
|
+
released.previousTag = previousTag;
|
|
136
|
+
}
|
|
137
|
+
if (parsedCommitCount !== void 0) {
|
|
138
|
+
released.parsedCommitCount = parsedCommitCount;
|
|
139
|
+
}
|
|
140
|
+
if (releaseType !== void 0) {
|
|
141
|
+
released.releaseType = releaseType;
|
|
142
|
+
}
|
|
143
|
+
if (unparseableCommits !== void 0) {
|
|
144
|
+
released.unparseableCommits = unparseableCommits;
|
|
145
|
+
}
|
|
146
|
+
if (setVersion !== void 0) {
|
|
147
|
+
released.setVersion = setVersion;
|
|
148
|
+
}
|
|
149
|
+
return released;
|
|
150
|
+
}
|
|
151
|
+
function buildAndPersistChangelogJson(config, newTag, dryRun) {
|
|
152
|
+
const changelogJsonFiles = [];
|
|
153
|
+
const entries = buildChangelogEntries(config, newTag);
|
|
154
|
+
for (const changelogPath of config.changelogPaths) {
|
|
155
|
+
const jsonPath = resolveChangelogJsonPath(config, changelogPath);
|
|
156
|
+
if (!dryRun) {
|
|
157
|
+
upsertChangelogJson(jsonPath, entries);
|
|
158
|
+
}
|
|
159
|
+
changelogJsonFiles.push(jsonPath);
|
|
160
|
+
}
|
|
161
|
+
return changelogJsonFiles;
|
|
162
|
+
}
|
|
119
163
|
function maybeWriteSinglePackagePreviews(withReleaseNotes, config, newTag, changelogJsonPath, dryRun) {
|
|
120
164
|
if (!withReleaseNotes) {
|
|
121
165
|
return;
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { execSync } from "node:child_process";
|
|
2
|
+
import { buildChangelogEntries } from "./buildChangelogEntries.js";
|
|
2
3
|
import { buildDependencyGraph } from "./buildDependencyGraph.js";
|
|
4
|
+
import { buildSyntheticChangelogEntry } from "./buildSyntheticChangelogEntry.js";
|
|
3
5
|
import { bumpAllVersions, setAllVersions } from "./bumpAllVersions.js";
|
|
6
|
+
import { resolveChangelogJsonPath, upsertChangelogJson } from "./changelogJsonFile.js";
|
|
4
7
|
import { isForwardVersion } from "./compareVersions.js";
|
|
8
|
+
import { decideRelease } from "./decideRelease.js";
|
|
5
9
|
import { DEFAULT_VERSION_PATTERNS, DEFAULT_WORK_TYPES } from "./defaults.js";
|
|
6
10
|
import { detectUndeclaredTagPrefixes } from "./detectUndeclaredTagPrefixes.js";
|
|
7
|
-
import { determineBumpFromCommits } from "./determineBumpFromCommits.js";
|
|
8
|
-
import { generateChangelogJson, generateSyntheticChangelogJson } from "./generateChangelogJson.js";
|
|
9
11
|
import { buildTagPattern, generateChangelog } from "./generateChangelogs.js";
|
|
10
12
|
import { getCommitsSinceTarget } from "./getCommitsSinceTarget.js";
|
|
11
13
|
import { hasPrettierConfig } from "./hasPrettierConfig.js";
|
|
12
14
|
import { resolveWorkTypes } from "./loadConfig.js";
|
|
13
15
|
import { propagateBumps } from "./propagateBumps.js";
|
|
14
16
|
import { readCurrentVersion } from "./readCurrentVersion.js";
|
|
17
|
+
import { releasePrepareProject } from "./releasePrepareProject.js";
|
|
15
18
|
import { deriveSectionOrder } from "./resolveReleaseNotesConfig.js";
|
|
16
19
|
import { writeReleaseNotesPreviews } from "./writeReleaseNotesPreviews.js";
|
|
17
20
|
import { writeSyntheticChangelog } from "./writeSyntheticChangelog.js";
|
|
@@ -59,13 +62,18 @@ function releasePrepareMono(config, options) {
|
|
|
59
62
|
const orderB = configOrder.get(b.name ?? "") ?? 0;
|
|
60
63
|
return orderA - orderB;
|
|
61
64
|
});
|
|
65
|
+
let project;
|
|
66
|
+
if (config.project !== void 0) {
|
|
67
|
+
project = tryStage("project release stage", () => releasePrepareProject({ config, options, modifiedFiles, tags }));
|
|
68
|
+
}
|
|
62
69
|
const formatCommand = runFormatCommand(config, tags, modifiedFiles, dryRun);
|
|
63
70
|
return {
|
|
64
71
|
workspaces,
|
|
65
72
|
tags,
|
|
66
73
|
formatCommand,
|
|
67
74
|
dryRun,
|
|
68
|
-
...warnings.length > 0 ? { warnings } : {}
|
|
75
|
+
...warnings.length > 0 ? { warnings } : {},
|
|
76
|
+
...project === void 0 ? {} : { project }
|
|
69
77
|
};
|
|
70
78
|
}
|
|
71
79
|
function determineDirectBumps(config, options) {
|
|
@@ -83,14 +91,18 @@ function determineDirectBumps(config, options) {
|
|
|
83
91
|
const knownPrefixes = config.workspaces.flatMap(getAllTagPrefixes);
|
|
84
92
|
for (const workspace of config.workspaces) {
|
|
85
93
|
const name = workspace.dir;
|
|
86
|
-
const
|
|
94
|
+
const stageLabel = workspaceStageLabel(workspace.dir);
|
|
95
|
+
const { tag, commits } = tryStage(
|
|
96
|
+
stageLabel,
|
|
97
|
+
() => getCommitsSinceTarget(getAllTagPrefixes(workspace), workspace.paths)
|
|
98
|
+
);
|
|
87
99
|
const since = tag === void 0 ? "(no previous release found)" : `since ${tag}`;
|
|
88
100
|
if (tag === void 0) {
|
|
89
101
|
maybeEmitBaselineHint(workspace, knownPrefixes, hintState);
|
|
90
102
|
}
|
|
91
103
|
const primaryPackageFile = workspace.packageFiles[0];
|
|
92
104
|
if (primaryPackageFile !== void 0) {
|
|
93
|
-
const currentVersion = readCurrentVersion(primaryPackageFile);
|
|
105
|
+
const currentVersion = tryStage(stageLabel, () => readCurrentVersion(primaryPackageFile));
|
|
94
106
|
if (currentVersion !== void 0) {
|
|
95
107
|
currentVersions.set(workspace.dir, currentVersion);
|
|
96
108
|
}
|
|
@@ -113,51 +125,46 @@ function determineDirectBumps(config, options) {
|
|
|
113
125
|
releaseType: void 0,
|
|
114
126
|
parsedCommitCount: void 0,
|
|
115
127
|
unparseableCommits: void 0,
|
|
128
|
+
bumpOverride: void 0,
|
|
116
129
|
setVersion
|
|
117
130
|
});
|
|
118
131
|
continue;
|
|
119
132
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
parsedCommitCount = determination.parsedCommitCount;
|
|
137
|
-
unparseableCommits = determination.unparseableCommits;
|
|
138
|
-
releaseType = determination.releaseType;
|
|
139
|
-
} else {
|
|
140
|
-
releaseType = bumpOverride;
|
|
141
|
-
}
|
|
142
|
-
if (releaseType === void 0) {
|
|
133
|
+
const decision = tryStage(
|
|
134
|
+
stageLabel,
|
|
135
|
+
() => decideRelease({
|
|
136
|
+
commits,
|
|
137
|
+
force,
|
|
138
|
+
bumpOverride,
|
|
139
|
+
workTypes,
|
|
140
|
+
versionPatterns,
|
|
141
|
+
scopeAliases: config.scopeAliases,
|
|
142
|
+
skipReasons: {
|
|
143
|
+
noCommits: `No commits for ${name} ${since}. Pass --force to release at patch. Skipping.`,
|
|
144
|
+
noBumpWorthy: `No bump-worthy commits for ${name} ${since}. Pass --force to release at patch (or --force --bump=X for a different level). Skipping.`
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
);
|
|
148
|
+
if (decision.outcome === "skip") {
|
|
143
149
|
skippedResults.push({
|
|
144
150
|
workspace,
|
|
145
151
|
tag,
|
|
146
152
|
commitCount: commits.length,
|
|
147
|
-
parsedCommitCount,
|
|
148
|
-
unparseableCommits,
|
|
149
|
-
skipReason:
|
|
153
|
+
parsedCommitCount: decision.parsedCommitCount,
|
|
154
|
+
unparseableCommits: decision.unparseableCommits,
|
|
155
|
+
skipReason: decision.skipReason
|
|
150
156
|
});
|
|
151
157
|
continue;
|
|
152
158
|
}
|
|
153
|
-
directBumps.set(workspace.dir, { releaseType });
|
|
159
|
+
directBumps.set(workspace.dir, { releaseType: decision.releaseType });
|
|
154
160
|
directResults.set(workspace.dir, {
|
|
155
161
|
workspace,
|
|
156
162
|
tag,
|
|
157
163
|
commits,
|
|
158
|
-
releaseType,
|
|
159
|
-
parsedCommitCount,
|
|
160
|
-
unparseableCommits
|
|
164
|
+
releaseType: decision.releaseType,
|
|
165
|
+
parsedCommitCount: decision.parsedCommitCount,
|
|
166
|
+
unparseableCommits: decision.unparseableCommits,
|
|
167
|
+
bumpOverride
|
|
161
168
|
});
|
|
162
169
|
}
|
|
163
170
|
return { directBumps, directResults, skippedResults, currentVersions };
|
|
@@ -168,17 +175,22 @@ function collectSkippedWorkspaces(skippedResults, fullReleaseSet) {
|
|
|
168
175
|
if (fullReleaseSet.has(skipped.workspace.dir)) {
|
|
169
176
|
continue;
|
|
170
177
|
}
|
|
171
|
-
|
|
178
|
+
const result = {
|
|
172
179
|
name: skipped.workspace.dir,
|
|
173
180
|
status: "skipped",
|
|
174
|
-
previousTag: skipped.tag,
|
|
175
181
|
commitCount: skipped.commitCount,
|
|
176
|
-
parsedCommitCount: skipped.parsedCommitCount,
|
|
177
|
-
unparseableCommits: skipped.unparseableCommits,
|
|
178
|
-
bumpedFiles: [],
|
|
179
|
-
changelogFiles: [],
|
|
180
182
|
skipReason: skipped.skipReason
|
|
181
|
-
}
|
|
183
|
+
};
|
|
184
|
+
if (skipped.tag !== void 0) {
|
|
185
|
+
result.previousTag = skipped.tag;
|
|
186
|
+
}
|
|
187
|
+
if (skipped.parsedCommitCount !== void 0) {
|
|
188
|
+
result.parsedCommitCount = skipped.parsedCommitCount;
|
|
189
|
+
}
|
|
190
|
+
if (skipped.unparseableCommits !== void 0) {
|
|
191
|
+
result.unparseableCommits = skipped.unparseableCommits;
|
|
192
|
+
}
|
|
193
|
+
workspaces.push(result);
|
|
182
194
|
}
|
|
183
195
|
return workspaces;
|
|
184
196
|
}
|
|
@@ -195,20 +207,23 @@ function executeReleaseSet(sortedDirs, fullReleaseSet, config, directResults, pr
|
|
|
195
207
|
if (workspace === void 0) {
|
|
196
208
|
continue;
|
|
197
209
|
}
|
|
198
|
-
|
|
199
|
-
dir,
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
210
|
+
tryStage(
|
|
211
|
+
workspaceStageLabel(dir),
|
|
212
|
+
() => executeWorkspaceRelease({
|
|
213
|
+
dir,
|
|
214
|
+
workspace,
|
|
215
|
+
releaseEntry,
|
|
216
|
+
directResult: directResults.get(dir),
|
|
217
|
+
previousTags,
|
|
218
|
+
config,
|
|
219
|
+
dryRun,
|
|
220
|
+
today,
|
|
221
|
+
tags,
|
|
222
|
+
modifiedFiles,
|
|
223
|
+
workspaces,
|
|
224
|
+
previewOptions
|
|
225
|
+
})
|
|
226
|
+
);
|
|
212
227
|
}
|
|
213
228
|
return { tags, modifiedFiles };
|
|
214
229
|
}
|
|
@@ -245,25 +260,42 @@ function executeWorkspaceRelease(args) {
|
|
|
245
260
|
modifiedFiles,
|
|
246
261
|
previewOptions
|
|
247
262
|
});
|
|
248
|
-
|
|
263
|
+
const released = {
|
|
249
264
|
name: dir,
|
|
250
265
|
status: "released",
|
|
251
|
-
previousTag: directResult?.tag ?? previousTags.get(dir),
|
|
252
266
|
commitCount: directResult?.commits.length ?? 0,
|
|
253
|
-
parsedCommitCount: directResult?.parsedCommitCount,
|
|
254
|
-
// For --set-version workspaces releaseType is left undefined so reporting can branch
|
|
255
|
-
// on the override case without conflating it with a bump type.
|
|
256
|
-
releaseType: setVersionTarget === void 0 ? releaseEntry.releaseType : void 0,
|
|
257
267
|
currentVersion: bump.currentVersion,
|
|
258
268
|
newVersion: bump.newVersion,
|
|
259
269
|
tag: newTag,
|
|
260
270
|
bumpedFiles: bump.files,
|
|
261
|
-
changelogFiles
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
}
|
|
271
|
+
changelogFiles
|
|
272
|
+
};
|
|
273
|
+
const previousTag = directResult?.tag ?? previousTags.get(dir);
|
|
274
|
+
if (previousTag !== void 0) {
|
|
275
|
+
released.previousTag = previousTag;
|
|
276
|
+
}
|
|
277
|
+
if (directResult?.parsedCommitCount !== void 0) {
|
|
278
|
+
released.parsedCommitCount = directResult.parsedCommitCount;
|
|
279
|
+
}
|
|
280
|
+
if (setVersionTarget === void 0) {
|
|
281
|
+
released.releaseType = releaseEntry.releaseType;
|
|
282
|
+
}
|
|
283
|
+
if (directResult?.commits !== void 0) {
|
|
284
|
+
released.commits = directResult.commits;
|
|
285
|
+
}
|
|
286
|
+
if (directResult?.unparseableCommits !== void 0) {
|
|
287
|
+
released.unparseableCommits = directResult.unparseableCommits;
|
|
288
|
+
}
|
|
289
|
+
if (releaseEntry.propagatedFrom !== void 0) {
|
|
290
|
+
released.propagatedFrom = releaseEntry.propagatedFrom;
|
|
291
|
+
}
|
|
292
|
+
if (directResult?.bumpOverride !== void 0) {
|
|
293
|
+
released.bumpOverride = directResult.bumpOverride;
|
|
294
|
+
}
|
|
295
|
+
if (setVersionTarget !== void 0) {
|
|
296
|
+
released.setVersion = setVersionTarget;
|
|
297
|
+
}
|
|
298
|
+
workspaces.push(released);
|
|
267
299
|
}
|
|
268
300
|
function generateWorkspaceChangelogs(args) {
|
|
269
301
|
const {
|
|
@@ -293,17 +325,14 @@ function generateWorkspaceChangelogs(args) {
|
|
|
293
325
|
);
|
|
294
326
|
}
|
|
295
327
|
if (config.changelogJson.enabled) {
|
|
328
|
+
const syntheticEntry = buildSyntheticChangelogEntry(releaseEntry.propagatedFrom, newVersion, today);
|
|
296
329
|
for (const changelogPath of workspace.changelogPaths) {
|
|
297
|
-
const
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
dryRun
|
|
304
|
-
);
|
|
305
|
-
modifiedFiles.push(...jsonFiles);
|
|
306
|
-
firstChangelogJsonPath ??= jsonFiles[0];
|
|
330
|
+
const jsonPath = resolveChangelogJsonPath(config, changelogPath);
|
|
331
|
+
if (!dryRun) {
|
|
332
|
+
upsertChangelogJson(jsonPath, [syntheticEntry]);
|
|
333
|
+
}
|
|
334
|
+
modifiedFiles.push(jsonPath);
|
|
335
|
+
firstChangelogJsonPath ??= jsonPath;
|
|
307
336
|
}
|
|
308
337
|
}
|
|
309
338
|
maybeWritePreviews(workspace, newTag, firstChangelogJsonPath, previewOptions, dryRun);
|
|
@@ -319,13 +348,17 @@ function generateWorkspaceChangelogs(args) {
|
|
|
319
348
|
);
|
|
320
349
|
}
|
|
321
350
|
if (config.changelogJson.enabled) {
|
|
351
|
+
const entries = buildChangelogEntries(config, newTag, {
|
|
352
|
+
tagPattern,
|
|
353
|
+
includePaths: workspace.paths
|
|
354
|
+
});
|
|
322
355
|
for (const changelogPath of workspace.changelogPaths) {
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
327
|
-
modifiedFiles.push(
|
|
328
|
-
firstChangelogJsonPath ??=
|
|
356
|
+
const jsonPath = resolveChangelogJsonPath(config, changelogPath);
|
|
357
|
+
if (!dryRun) {
|
|
358
|
+
upsertChangelogJson(jsonPath, entries);
|
|
359
|
+
}
|
|
360
|
+
modifiedFiles.push(jsonPath);
|
|
361
|
+
firstChangelogJsonPath ??= jsonPath;
|
|
329
362
|
}
|
|
330
363
|
}
|
|
331
364
|
maybeWritePreviews(workspace, newTag, firstChangelogJsonPath, previewOptions, dryRun);
|
|
@@ -355,15 +388,28 @@ function runFormatCommand(config, tags, modifiedFiles, dryRun) {
|
|
|
355
388
|
try {
|
|
356
389
|
execSync(fullCommand, { stdio: "inherit" });
|
|
357
390
|
} catch (error) {
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
);
|
|
391
|
+
const baseMessage = error instanceof Error ? error.message : String(error);
|
|
392
|
+
throw new Error(`format stage: ${baseMessage} (command: '${fullCommand}')`, { cause: error });
|
|
361
393
|
}
|
|
362
394
|
return { command: fullCommand, executed: true, files: modifiedFiles };
|
|
363
395
|
}
|
|
364
396
|
function findWorkspace(workspaces, dir) {
|
|
365
397
|
return workspaces.find((w) => w.dir === dir);
|
|
366
398
|
}
|
|
399
|
+
function wrapStageError(stageLabel, error) {
|
|
400
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
401
|
+
return new Error(`${stageLabel}: ${message}`, { cause: error });
|
|
402
|
+
}
|
|
403
|
+
function tryStage(stageLabel, fn) {
|
|
404
|
+
try {
|
|
405
|
+
return fn();
|
|
406
|
+
} catch (error) {
|
|
407
|
+
throw wrapStageError(stageLabel, error);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
function workspaceStageLabel(dir) {
|
|
411
|
+
return `workspace '${dir}' release stage`;
|
|
412
|
+
}
|
|
367
413
|
function maybeEmitBaselineHint(workspace, knownPrefixes, state) {
|
|
368
414
|
if (state.emitted) return;
|
|
369
415
|
if ((workspace.legacyIdentities?.length ?? 0) > 0) return;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ReleasePrepareOptions } from './releasePrepare.ts';
|
|
2
|
+
import type { MonorepoReleaseConfig, ProjectPrepareResult } from './types.ts';
|
|
3
|
+
export interface ReleasePrepareProjectArgs {
|
|
4
|
+
config: MonorepoReleaseConfig;
|
|
5
|
+
options: ReleasePrepareOptions;
|
|
6
|
+
modifiedFiles: string[];
|
|
7
|
+
tags: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare function releasePrepareProject(args: ReleasePrepareProjectArgs): ProjectPrepareResult;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { buildChangelogEntries } from "./buildChangelogEntries.js";
|
|
2
|
+
import { bumpAllVersions } from "./bumpAllVersions.js";
|
|
3
|
+
import { resolveChangelogJsonPath, writeChangelogJson } from "./changelogJsonFile.js";
|
|
4
|
+
import { decideRelease } from "./decideRelease.js";
|
|
5
|
+
import { DEFAULT_VERSION_PATTERNS, DEFAULT_WORK_TYPES } from "./defaults.js";
|
|
6
|
+
import { buildTagPattern, generateChangelog } from "./generateChangelogs.js";
|
|
7
|
+
import { getCommitsSinceTarget } from "./getCommitsSinceTarget.js";
|
|
8
|
+
import { deriveSectionOrder } from "./resolveReleaseNotesConfig.js";
|
|
9
|
+
import { writeReleaseNotesPreviews } from "./writeReleaseNotesPreviews.js";
|
|
10
|
+
const ROOT_PACKAGE_FILE = "./package.json";
|
|
11
|
+
const ROOT_CHANGELOG_PATH = ".";
|
|
12
|
+
function releasePrepareProject(args) {
|
|
13
|
+
const { config, options, modifiedFiles, tags } = args;
|
|
14
|
+
const { dryRun, bumpOverride, withReleaseNotes, force } = options;
|
|
15
|
+
const project = config.project;
|
|
16
|
+
if (project === void 0) {
|
|
17
|
+
throw new Error("releasePrepareProject called without a configured project block");
|
|
18
|
+
}
|
|
19
|
+
const workTypes = config.workTypes ?? { ...DEFAULT_WORK_TYPES };
|
|
20
|
+
const versionPatterns = config.versionPatterns ?? { ...DEFAULT_VERSION_PATTERNS };
|
|
21
|
+
const contributingPaths = config.workspaces.flatMap((workspace) => workspace.paths);
|
|
22
|
+
const { tag, commits } = getCommitsSinceTarget([project.tagPrefix], contributingPaths);
|
|
23
|
+
const since = tag === void 0 ? "(no previous release found)" : `since ${tag}`;
|
|
24
|
+
const decision = decideRelease({
|
|
25
|
+
commits,
|
|
26
|
+
force,
|
|
27
|
+
bumpOverride,
|
|
28
|
+
workTypes,
|
|
29
|
+
versionPatterns,
|
|
30
|
+
scopeAliases: config.scopeAliases,
|
|
31
|
+
skipReasons: {
|
|
32
|
+
noCommits: `No commits ${since}. Pass --force to release at patch. Skipping.`,
|
|
33
|
+
noBumpWorthy: `No bump-worthy commits ${since}. Pass --force to release at patch (or --force --bump=X for a different level). Skipping.`
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
if (decision.outcome === "skip") {
|
|
37
|
+
const skipped = {
|
|
38
|
+
status: "skipped",
|
|
39
|
+
commitCount: commits.length,
|
|
40
|
+
parsedCommitCount: decision.parsedCommitCount,
|
|
41
|
+
skipReason: decision.skipReason
|
|
42
|
+
};
|
|
43
|
+
if (tag !== void 0) {
|
|
44
|
+
skipped.previousTag = tag;
|
|
45
|
+
}
|
|
46
|
+
if (decision.unparseableCommits !== void 0) {
|
|
47
|
+
skipped.unparseableCommits = decision.unparseableCommits;
|
|
48
|
+
}
|
|
49
|
+
return skipped;
|
|
50
|
+
}
|
|
51
|
+
const { releaseType, parsedCommitCount, unparseableCommits } = decision;
|
|
52
|
+
const bump = bumpAllVersions([ROOT_PACKAGE_FILE], releaseType, dryRun);
|
|
53
|
+
const newTag = `${project.tagPrefix}${bump.newVersion}`;
|
|
54
|
+
const tagPattern = buildTagPattern([project.tagPrefix]);
|
|
55
|
+
const changelogFiles = generateChangelog(config, ROOT_CHANGELOG_PATH, newTag, dryRun, {
|
|
56
|
+
tagPattern,
|
|
57
|
+
includePaths: contributingPaths
|
|
58
|
+
});
|
|
59
|
+
const changelogJsonFiles = [];
|
|
60
|
+
if (config.changelogJson.enabled) {
|
|
61
|
+
const changelogJsonPath = resolveChangelogJsonPath(config, ROOT_CHANGELOG_PATH);
|
|
62
|
+
const entries = buildChangelogEntries(config, newTag, {
|
|
63
|
+
tagPattern,
|
|
64
|
+
includePaths: contributingPaths
|
|
65
|
+
});
|
|
66
|
+
if (!dryRun) {
|
|
67
|
+
writeChangelogJson(changelogJsonPath, entries);
|
|
68
|
+
}
|
|
69
|
+
changelogJsonFiles.push(changelogJsonPath);
|
|
70
|
+
}
|
|
71
|
+
const firstChangelogJsonPath = changelogJsonFiles[0];
|
|
72
|
+
if (withReleaseNotes === true && config.changelogJson.enabled && firstChangelogJsonPath !== void 0) {
|
|
73
|
+
const sectionOrder = deriveSectionOrder(workTypes);
|
|
74
|
+
writeReleaseNotesPreviews({
|
|
75
|
+
workspacePath: ROOT_CHANGELOG_PATH,
|
|
76
|
+
tag: newTag,
|
|
77
|
+
changelogJsonPath: firstChangelogJsonPath,
|
|
78
|
+
sectionOrder,
|
|
79
|
+
dryRun
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
tags.push(newTag);
|
|
83
|
+
modifiedFiles.push(ROOT_PACKAGE_FILE, ...changelogFiles, ...changelogJsonFiles);
|
|
84
|
+
const result = {
|
|
85
|
+
status: "released",
|
|
86
|
+
commitCount: commits.length,
|
|
87
|
+
parsedCommitCount,
|
|
88
|
+
releaseType,
|
|
89
|
+
currentVersion: bump.currentVersion,
|
|
90
|
+
newVersion: bump.newVersion,
|
|
91
|
+
tag: newTag,
|
|
92
|
+
bumpedFiles: bump.files,
|
|
93
|
+
changelogFiles,
|
|
94
|
+
commits
|
|
95
|
+
};
|
|
96
|
+
if (tag !== void 0) {
|
|
97
|
+
result.previousTag = tag;
|
|
98
|
+
}
|
|
99
|
+
if (unparseableCommits !== void 0) {
|
|
100
|
+
result.unparseableCommits = unparseableCommits;
|
|
101
|
+
}
|
|
102
|
+
if (bumpOverride !== void 0) {
|
|
103
|
+
result.bumpOverride = bumpOverride;
|
|
104
|
+
}
|
|
105
|
+
return result;
|
|
106
|
+
}
|
|
107
|
+
export {
|
|
108
|
+
releasePrepareProject
|
|
109
|
+
};
|