relizy 0.2.3 → 0.2.5-beta.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/README.md +7 -0
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +191 -101
- package/dist/index.d.ts +191 -101
- package/dist/index.mjs +1 -1
- package/dist/shared/{relizy.Esbxb_ll.mjs → relizy.D41jJZ2S.mjs} +1358 -1322
- package/package.json +1 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { logger, execPromise } from '@maz-ui/node';
|
|
2
2
|
import { execSync } from 'node:child_process';
|
|
3
3
|
import { existsSync, readFileSync, writeFileSync, statSync } from 'node:fs';
|
|
4
|
-
import path, { join } from 'node:path';
|
|
4
|
+
import path, { join, relative } from 'node:path';
|
|
5
5
|
import process$1 from 'node:process';
|
|
6
6
|
import { upperFirst, formatJson } from '@maz-ui/utils';
|
|
7
7
|
import { setupDotenv, loadConfig } from 'c12';
|
|
8
|
-
import { formatCompareChanges, formatReference, resolveRepoConfig, getRepoConfig, createGithubRelease, getGitDiff, parseCommits
|
|
8
|
+
import { formatCompareChanges, formatReference, resolveRepoConfig, getRepoConfig, createGithubRelease, getGitDiff, parseCommits } from 'changelogen';
|
|
9
9
|
import { defu } from 'defu';
|
|
10
10
|
import fastGlob from 'fast-glob';
|
|
11
11
|
import { confirm, input } from '@inquirer/prompts';
|
|
@@ -13,154 +13,6 @@ import * as semver from 'semver';
|
|
|
13
13
|
import { convert } from 'convert-gitmoji';
|
|
14
14
|
import { fetch as fetch$1 } from 'node-fetch-native';
|
|
15
15
|
|
|
16
|
-
async function generateMarkDown({
|
|
17
|
-
commits,
|
|
18
|
-
config,
|
|
19
|
-
from,
|
|
20
|
-
to
|
|
21
|
-
}) {
|
|
22
|
-
const typeGroups = groupBy(commits, "type");
|
|
23
|
-
const markdown = [];
|
|
24
|
-
const breakingChanges = [];
|
|
25
|
-
const updatedConfig = {
|
|
26
|
-
...config,
|
|
27
|
-
from,
|
|
28
|
-
to
|
|
29
|
-
};
|
|
30
|
-
const versionTitle = updatedConfig.to;
|
|
31
|
-
markdown.push("", `## ${versionTitle || `${updatedConfig.from || ""}...${updatedConfig.to}`}`, "");
|
|
32
|
-
if (updatedConfig.repo && updatedConfig.from && versionTitle) {
|
|
33
|
-
const formattedCompareLink = formatCompareChanges(versionTitle, updatedConfig);
|
|
34
|
-
markdown.push(formattedCompareLink);
|
|
35
|
-
}
|
|
36
|
-
for (const type in updatedConfig.types) {
|
|
37
|
-
const group = typeGroups[type];
|
|
38
|
-
if (!group || group.length === 0) {
|
|
39
|
-
continue;
|
|
40
|
-
}
|
|
41
|
-
if (typeof updatedConfig.types[type] === "boolean") {
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
markdown.push("", `### ${updatedConfig.types[type]?.title}`, "");
|
|
45
|
-
for (const commit of group.reverse()) {
|
|
46
|
-
const line = formatCommit(commit, updatedConfig);
|
|
47
|
-
markdown.push(line);
|
|
48
|
-
if (commit.isBreaking) {
|
|
49
|
-
breakingChanges.push(line);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
if (breakingChanges.length > 0) {
|
|
54
|
-
markdown.push("", "#### \u26A0\uFE0F Breaking Changes", "", ...breakingChanges);
|
|
55
|
-
}
|
|
56
|
-
const _authors = /* @__PURE__ */ new Map();
|
|
57
|
-
for (const commit of commits) {
|
|
58
|
-
if (!commit.author) {
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
const name = formatName(commit.author.name);
|
|
62
|
-
if (!name || name.includes("[bot]")) {
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
if (updatedConfig.excludeAuthors && updatedConfig.excludeAuthors.some(
|
|
66
|
-
(v) => name.includes(v) || commit.author.email?.includes(v)
|
|
67
|
-
)) {
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
if (_authors.has(name)) {
|
|
71
|
-
const entry = _authors.get(name);
|
|
72
|
-
entry?.email.add(commit.author.email);
|
|
73
|
-
} else {
|
|
74
|
-
_authors.set(name, { email: /* @__PURE__ */ new Set([commit.author.email]), name });
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
await Promise.all(
|
|
78
|
-
[..._authors.keys()].map(async (authorName) => {
|
|
79
|
-
const meta = _authors.get(authorName);
|
|
80
|
-
if (!meta) {
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
for (const data of [...meta.email, meta.name]) {
|
|
84
|
-
const { user } = await fetch$1(`https://ungh.cc/users/find/${data}`).then((r) => r.json()).catch(() => ({ user: null }));
|
|
85
|
-
if (user) {
|
|
86
|
-
meta.github = user.username;
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
})
|
|
91
|
-
);
|
|
92
|
-
const authors = [..._authors.entries()].map((e) => ({
|
|
93
|
-
name: e[0],
|
|
94
|
-
...e[1]
|
|
95
|
-
}));
|
|
96
|
-
if (authors.length > 0 && !updatedConfig.noAuthors) {
|
|
97
|
-
markdown.push(
|
|
98
|
-
"",
|
|
99
|
-
"### \u2764\uFE0F Contributors",
|
|
100
|
-
"",
|
|
101
|
-
...authors.map((i) => {
|
|
102
|
-
const _email = [...i.email].find(
|
|
103
|
-
(e) => !e.includes("noreply.github.com")
|
|
104
|
-
);
|
|
105
|
-
const email = updatedConfig.hideAuthorEmail !== true && _email ? ` <${_email}>` : "";
|
|
106
|
-
const github = i.github ? ` ([@${i.github}](https://github.com/${i.github}))` : "";
|
|
107
|
-
return `- ${i.name}${github || email || ""}`;
|
|
108
|
-
})
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
const result = convert(markdown.join("\n").trim(), true);
|
|
112
|
-
return result;
|
|
113
|
-
}
|
|
114
|
-
function getCommitBody(commit) {
|
|
115
|
-
if (!commit.body) {
|
|
116
|
-
return "";
|
|
117
|
-
}
|
|
118
|
-
const lines = commit.body.split("\n");
|
|
119
|
-
const contentLines = lines.filter((line) => {
|
|
120
|
-
const trimmedLine = line.trim();
|
|
121
|
-
if (!trimmedLine) {
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
const isFileLine = /^[AMDRC]\s+/.test(trimmedLine);
|
|
125
|
-
const R100 = /R100\s+/.test(trimmedLine);
|
|
126
|
-
return !isFileLine && !R100;
|
|
127
|
-
});
|
|
128
|
-
if (contentLines.length === 0) {
|
|
129
|
-
return "";
|
|
130
|
-
}
|
|
131
|
-
const indentedBody = contentLines.map((line) => ` ${line}`).join("\n");
|
|
132
|
-
return `
|
|
133
|
-
|
|
134
|
-
${indentedBody}
|
|
135
|
-
`;
|
|
136
|
-
}
|
|
137
|
-
function formatCommit(commit, config) {
|
|
138
|
-
const body = config.changelog.includeCommitBody ? getCommitBody(commit) : "";
|
|
139
|
-
return `- ${commit.scope ? `**${commit.scope.trim()}:** ` : ""}${commit.isBreaking ? "\u26A0\uFE0F " : ""}${upperFirst(commit.description)}${formatReferences(commit.references, config)}${body}`;
|
|
140
|
-
}
|
|
141
|
-
function formatReferences(references, config) {
|
|
142
|
-
const pr = references.filter((ref) => ref.type === "pull-request");
|
|
143
|
-
const issue = references.filter((ref) => ref.type === "issue");
|
|
144
|
-
if (pr.length > 0 || issue.length > 0) {
|
|
145
|
-
return ` (${[...pr, ...issue].map((ref) => formatReference(ref, config.repo)).join(", ")})`;
|
|
146
|
-
}
|
|
147
|
-
if (references.length > 0) {
|
|
148
|
-
return ` (${formatReference(references[0], config.repo)})`;
|
|
149
|
-
}
|
|
150
|
-
return "";
|
|
151
|
-
}
|
|
152
|
-
function formatName(name = "") {
|
|
153
|
-
return name.split(" ").map((p) => upperFirst(p.trim())).join(" ");
|
|
154
|
-
}
|
|
155
|
-
function groupBy(items, key) {
|
|
156
|
-
const groups = {};
|
|
157
|
-
for (const item of items) {
|
|
158
|
-
groups[item[key]] = groups[item[key]] || [];
|
|
159
|
-
groups[item[key]]?.push(item);
|
|
160
|
-
}
|
|
161
|
-
return groups;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
16
|
async function executeHook(hook, config, dryRun, params) {
|
|
165
17
|
const hookInput = config.hooks?.[hook];
|
|
166
18
|
if (!hookInput) {
|
|
@@ -291,23 +143,407 @@ async function executeBuildCmd({
|
|
|
291
143
|
logger.debug("No build command specified");
|
|
292
144
|
}
|
|
293
145
|
}
|
|
146
|
+
function isBumpedPackage(pkg) {
|
|
147
|
+
return "oldVersion" in pkg && !!pkg.oldVersion;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function getGitStatus(cwd) {
|
|
151
|
+
return execSync("git status --porcelain", {
|
|
152
|
+
cwd,
|
|
153
|
+
encoding: "utf8"
|
|
154
|
+
}).trim();
|
|
155
|
+
}
|
|
156
|
+
function checkGitStatusIfDirty() {
|
|
157
|
+
logger.debug("Checking git status");
|
|
158
|
+
const dirty = getGitStatus();
|
|
159
|
+
if (dirty) {
|
|
160
|
+
logger.debug("git status:", `
|
|
161
|
+
${dirty.trim().split("\n").map((line) => line.trim()).join("\n")}`);
|
|
162
|
+
const error = `Git status is dirty!
|
|
163
|
+
|
|
164
|
+
Please commit or stash your changes before bumping or use --no-clean flag.
|
|
165
|
+
|
|
166
|
+
Unstaged files:
|
|
167
|
+
|
|
168
|
+
${dirty.trim()}`;
|
|
169
|
+
throw new Error(error);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async function fetchGitTags(cwd) {
|
|
173
|
+
logger.debug("Fetching git tags from remote");
|
|
174
|
+
try {
|
|
175
|
+
await execPromise("git fetch --tags", { cwd, noStderr: true, noStdout: true, noSuccess: true });
|
|
176
|
+
logger.debug("Git tags fetched successfully");
|
|
177
|
+
} catch (error) {
|
|
178
|
+
logger.fail("Failed to fetch some git tags from remote (tags might already exist locally)", error);
|
|
179
|
+
logger.info("Continuing with local tags");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function detectGitProvider(cwd = process.cwd()) {
|
|
183
|
+
try {
|
|
184
|
+
const remoteUrl = execSync("git remote get-url origin", {
|
|
185
|
+
cwd,
|
|
186
|
+
encoding: "utf8"
|
|
187
|
+
}).trim();
|
|
188
|
+
if (remoteUrl.includes("github.com")) {
|
|
189
|
+
return "github";
|
|
190
|
+
}
|
|
191
|
+
if (remoteUrl.includes("gitlab.com") || remoteUrl.includes("gitlab")) {
|
|
192
|
+
return "gitlab";
|
|
193
|
+
}
|
|
194
|
+
return null;
|
|
195
|
+
} catch {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function parseGitRemoteUrl(remoteUrl) {
|
|
200
|
+
const sshRegex = /git@[\w.-]+:([\w.-]+)\/([\w.-]+?)(?:\.git)?$/;
|
|
201
|
+
const httpsRegex = /https?:\/\/[\w.-]+\/([\w.-]+)\/([\w.-]+?)(?:\.git)?$/;
|
|
202
|
+
const sshMatch = remoteUrl.match(sshRegex);
|
|
203
|
+
if (sshMatch) {
|
|
204
|
+
return {
|
|
205
|
+
owner: sshMatch[1],
|
|
206
|
+
repo: sshMatch[2]
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
const httpsMatch = remoteUrl.match(httpsRegex);
|
|
210
|
+
if (httpsMatch) {
|
|
211
|
+
return {
|
|
212
|
+
owner: httpsMatch[1],
|
|
213
|
+
repo: httpsMatch[2]
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
async function createCommitAndTags({
|
|
219
|
+
config,
|
|
220
|
+
noVerify,
|
|
221
|
+
bumpedPackages,
|
|
222
|
+
newVersion,
|
|
223
|
+
dryRun,
|
|
224
|
+
logLevel
|
|
225
|
+
}) {
|
|
226
|
+
const internalConfig = config || await loadRelizyConfig();
|
|
227
|
+
try {
|
|
228
|
+
await executeHook("before:commit-and-tag", internalConfig, dryRun ?? false);
|
|
229
|
+
const filePatternsToAdd = [
|
|
230
|
+
"package.json",
|
|
231
|
+
"lerna.json",
|
|
232
|
+
"CHANGELOG.md",
|
|
233
|
+
"**/CHANGELOG.md",
|
|
234
|
+
"**/package.json"
|
|
235
|
+
];
|
|
236
|
+
logger.start("Start commit and tag");
|
|
237
|
+
logger.debug("Adding files to git staging area...");
|
|
238
|
+
for (const pattern of filePatternsToAdd) {
|
|
239
|
+
if (pattern === "lerna.json" && !hasLernaJson(internalConfig.cwd)) {
|
|
240
|
+
logger.verbose(`Skipping lerna.json as it doesn't exist`);
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if ((pattern === "lerna.json" || pattern === "CHANGELOG.md") && !existsSync(join(internalConfig.cwd, pattern))) {
|
|
244
|
+
logger.verbose(`Skipping ${pattern} as it doesn't exist`);
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (dryRun) {
|
|
248
|
+
logger.info(`[dry-run] git add ${pattern}`);
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
try {
|
|
252
|
+
logger.debug(`git add ${pattern}`);
|
|
253
|
+
execSync(`git add ${pattern}`);
|
|
254
|
+
} catch {
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
const rootPackage = readPackageJson(internalConfig.cwd);
|
|
258
|
+
newVersion = newVersion || rootPackage.version;
|
|
259
|
+
const versionForMessage = internalConfig.monorepo?.versionMode === "independent" ? bumpedPackages?.map((pkg) => getIndependentTag(pkg)).join(", ") || "unknown" : newVersion || "unknown";
|
|
260
|
+
const commitMessage = internalConfig.templates.commitMessage?.replaceAll("{{newVersion}}", versionForMessage) || `chore(release): bump version to ${versionForMessage}`;
|
|
261
|
+
const noVerifyFlag = noVerify ? "--no-verify " : "";
|
|
262
|
+
logger.debug(`No verify: ${noVerify}`);
|
|
263
|
+
if (dryRun) {
|
|
264
|
+
logger.info(`[dry-run] git commit ${noVerifyFlag}-m "${commitMessage}"`);
|
|
265
|
+
} else {
|
|
266
|
+
logger.debug(`Executing: git commit ${noVerifyFlag}-m "${commitMessage}"`);
|
|
267
|
+
await execPromise(`git commit ${noVerifyFlag}-m "${commitMessage}"`, {
|
|
268
|
+
logLevel,
|
|
269
|
+
noStderr: true,
|
|
270
|
+
noStdout: true,
|
|
271
|
+
cwd: internalConfig.cwd
|
|
272
|
+
});
|
|
273
|
+
logger.success(`Committed: ${commitMessage}${noVerify ? " (--no-verify)" : ""}`);
|
|
274
|
+
}
|
|
275
|
+
const signTags = internalConfig.signTags ? "-s" : "";
|
|
276
|
+
logger.debug(`Sign tags: ${internalConfig.signTags}`);
|
|
277
|
+
const createdTags = [];
|
|
278
|
+
if (internalConfig.monorepo?.versionMode === "independent" && bumpedPackages && bumpedPackages.length > 0) {
|
|
279
|
+
logger.debug(`Creating ${bumpedPackages.length} independent package tags`);
|
|
280
|
+
for (const pkg of bumpedPackages) {
|
|
281
|
+
if (!pkg.newVersion) {
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
const tagName = getIndependentTag({ version: pkg.newVersion, name: pkg.name });
|
|
285
|
+
const tagMessage = internalConfig.templates?.tagMessage?.replaceAll("{{newVersion}}", pkg.newVersion) || tagName;
|
|
286
|
+
if (dryRun) {
|
|
287
|
+
logger.info(`[dry-run] git tag ${signTags} -a ${tagName} -m "${tagMessage}"`);
|
|
288
|
+
} else {
|
|
289
|
+
const cmd = `git tag ${signTags} -a ${tagName} -m "${tagMessage}"`;
|
|
290
|
+
logger.debug(`Executing: ${cmd}`);
|
|
291
|
+
try {
|
|
292
|
+
await execPromise(cmd, {
|
|
293
|
+
logLevel,
|
|
294
|
+
noStderr: true,
|
|
295
|
+
noStdout: true,
|
|
296
|
+
cwd: internalConfig.cwd
|
|
297
|
+
});
|
|
298
|
+
logger.debug(`Tag created: ${tagName}`);
|
|
299
|
+
} catch (error) {
|
|
300
|
+
logger.error(`Failed to create tag ${tagName}:`, error);
|
|
301
|
+
throw error;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
createdTags.push(tagName);
|
|
305
|
+
}
|
|
306
|
+
logger.success(`Created ${createdTags.length} tags for independent packages, ${createdTags.join(", ")}`);
|
|
307
|
+
} else {
|
|
308
|
+
const tagName = internalConfig.templates.tagBody?.replaceAll("{{newVersion}}", newVersion);
|
|
309
|
+
const tagMessage = internalConfig.templates?.tagMessage?.replaceAll("{{newVersion}}", newVersion) || tagName;
|
|
310
|
+
if (dryRun) {
|
|
311
|
+
logger.info(`[dry-run] git tag ${signTags} -a ${tagName} -m "${tagMessage}"`);
|
|
312
|
+
} else {
|
|
313
|
+
const cmd = `git tag ${signTags} -a ${tagName} -m "${tagMessage}"`;
|
|
314
|
+
logger.debug(`Executing: ${cmd}`);
|
|
315
|
+
try {
|
|
316
|
+
await execPromise(cmd, {
|
|
317
|
+
logLevel,
|
|
318
|
+
noStderr: true,
|
|
319
|
+
noStdout: true,
|
|
320
|
+
cwd: internalConfig.cwd
|
|
321
|
+
});
|
|
322
|
+
logger.debug(`Tag created: ${tagName}`);
|
|
323
|
+
} catch (error) {
|
|
324
|
+
logger.error(`Failed to create tag ${tagName}:`, error);
|
|
325
|
+
throw error;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
createdTags.push(tagName);
|
|
329
|
+
}
|
|
330
|
+
logger.debug("Created Tags:", createdTags.join(", "));
|
|
331
|
+
logger.success("Commit and tag completed!");
|
|
332
|
+
await executeHook("success:commit-and-tag", internalConfig, dryRun ?? false);
|
|
333
|
+
return createdTags;
|
|
334
|
+
} catch (error) {
|
|
335
|
+
logger.error("Error committing and tagging:", error);
|
|
336
|
+
await executeHook("error:commit-and-tag", internalConfig, dryRun ?? false);
|
|
337
|
+
throw error;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
async function pushCommitAndTags({ dryRun, logLevel, cwd }) {
|
|
341
|
+
logger.start("Start push changes and tags");
|
|
342
|
+
if (dryRun) {
|
|
343
|
+
logger.info("[dry-run] git push --follow-tags");
|
|
344
|
+
} else {
|
|
345
|
+
logger.debug("Executing: git push --follow-tags");
|
|
346
|
+
await execPromise("git push --follow-tags", { noStderr: true, noStdout: true, logLevel, cwd });
|
|
347
|
+
}
|
|
348
|
+
logger.success("Pushing changes and tags completed!");
|
|
349
|
+
}
|
|
350
|
+
function getFirstCommit(cwd) {
|
|
351
|
+
const result = execSync(
|
|
352
|
+
"git rev-list --max-parents=0 HEAD",
|
|
353
|
+
{
|
|
354
|
+
cwd,
|
|
355
|
+
encoding: "utf8"
|
|
356
|
+
}
|
|
357
|
+
);
|
|
358
|
+
return result.trim();
|
|
359
|
+
}
|
|
360
|
+
function getCurrentGitBranch(cwd) {
|
|
361
|
+
const result = execSync("git rev-parse --abbrev-ref HEAD", {
|
|
362
|
+
cwd,
|
|
363
|
+
encoding: "utf8"
|
|
364
|
+
});
|
|
365
|
+
return result.trim();
|
|
366
|
+
}
|
|
367
|
+
function getCurrentGitRef(cwd) {
|
|
368
|
+
const branch = getCurrentGitBranch(cwd);
|
|
369
|
+
return branch || "HEAD";
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
async function generateMarkDown({
|
|
373
|
+
commits,
|
|
374
|
+
config,
|
|
375
|
+
from,
|
|
376
|
+
to,
|
|
377
|
+
isFirstCommit
|
|
378
|
+
}) {
|
|
379
|
+
const typeGroups = groupBy(commits, "type");
|
|
380
|
+
const markdown = [];
|
|
381
|
+
const breakingChanges = [];
|
|
382
|
+
const updatedConfig = {
|
|
383
|
+
...config,
|
|
384
|
+
from,
|
|
385
|
+
to
|
|
386
|
+
};
|
|
387
|
+
const versionTitle = updatedConfig.to;
|
|
388
|
+
const changelogTitle = `${updatedConfig.from}...${updatedConfig.to}`;
|
|
389
|
+
markdown.push("", `## ${changelogTitle}`, "");
|
|
390
|
+
if (updatedConfig.repo && updatedConfig.from && versionTitle) {
|
|
391
|
+
const formattedCompareLink = formatCompareChanges(versionTitle, {
|
|
392
|
+
...updatedConfig,
|
|
393
|
+
from: isFirstCommit ? getFirstCommit(updatedConfig.cwd) : updatedConfig.from
|
|
394
|
+
});
|
|
395
|
+
markdown.push(formattedCompareLink);
|
|
396
|
+
}
|
|
397
|
+
for (const type in updatedConfig.types) {
|
|
398
|
+
const group = typeGroups[type];
|
|
399
|
+
if (!group || group.length === 0) {
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
if (typeof updatedConfig.types[type] === "boolean") {
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
markdown.push("", `### ${updatedConfig.types[type]?.title}`, "");
|
|
406
|
+
for (const commit of group.reverse()) {
|
|
407
|
+
const line = formatCommit(commit, updatedConfig);
|
|
408
|
+
markdown.push(line);
|
|
409
|
+
if (commit.isBreaking) {
|
|
410
|
+
breakingChanges.push(line);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
if (breakingChanges.length > 0) {
|
|
415
|
+
markdown.push("", "#### \u26A0\uFE0F Breaking Changes", "", ...breakingChanges);
|
|
416
|
+
}
|
|
417
|
+
const _authors = /* @__PURE__ */ new Map();
|
|
418
|
+
for (const commit of commits) {
|
|
419
|
+
if (!commit.author) {
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
const name = formatName(commit.author.name);
|
|
423
|
+
if (!name || name.includes("[bot]")) {
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
if (updatedConfig.excludeAuthors && updatedConfig.excludeAuthors.some(
|
|
427
|
+
(v) => name.includes(v) || commit.author.email?.includes(v)
|
|
428
|
+
)) {
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
if (_authors.has(name)) {
|
|
432
|
+
const entry = _authors.get(name);
|
|
433
|
+
entry?.email.add(commit.author.email);
|
|
434
|
+
} else {
|
|
435
|
+
_authors.set(name, { email: /* @__PURE__ */ new Set([commit.author.email]), name });
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
await Promise.all(
|
|
439
|
+
[..._authors.keys()].map(async (authorName) => {
|
|
440
|
+
const meta = _authors.get(authorName);
|
|
441
|
+
if (!meta) {
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
for (const data of [...meta.email, meta.name]) {
|
|
445
|
+
const { user } = await fetch$1(`https://ungh.cc/users/find/${data}`).then((r) => r.json()).catch(() => ({ user: null }));
|
|
446
|
+
if (user) {
|
|
447
|
+
meta.github = user.username;
|
|
448
|
+
break;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
})
|
|
452
|
+
);
|
|
453
|
+
const authors = [..._authors.entries()].map((e) => ({
|
|
454
|
+
name: e[0],
|
|
455
|
+
...e[1]
|
|
456
|
+
}));
|
|
457
|
+
if (authors.length > 0 && !updatedConfig.noAuthors) {
|
|
458
|
+
markdown.push(
|
|
459
|
+
"",
|
|
460
|
+
"### \u2764\uFE0F Contributors",
|
|
461
|
+
"",
|
|
462
|
+
...authors.map((i) => {
|
|
463
|
+
const _email = [...i.email].find(
|
|
464
|
+
(e) => !e.includes("noreply.github.com")
|
|
465
|
+
);
|
|
466
|
+
const email = updatedConfig.hideAuthorEmail !== true && _email ? ` <${_email}>` : "";
|
|
467
|
+
const github = i.github ? ` ([@${i.github}](https://github.com/${i.github}))` : "";
|
|
468
|
+
return `- ${i.name}${github || email || ""}`;
|
|
469
|
+
})
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
const result = convert(markdown.join("\n").trim(), true);
|
|
473
|
+
return result;
|
|
474
|
+
}
|
|
475
|
+
function getCommitBody(commit) {
|
|
476
|
+
if (!commit.body) {
|
|
477
|
+
return "";
|
|
478
|
+
}
|
|
479
|
+
const lines = commit.body.split("\n");
|
|
480
|
+
const contentLines = lines.filter((line) => {
|
|
481
|
+
const trimmedLine = line.trim();
|
|
482
|
+
if (!trimmedLine) {
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
const isFileLine = /^[AMDRC]\s+/.test(trimmedLine);
|
|
486
|
+
const R100 = /R100\s+/.test(trimmedLine);
|
|
487
|
+
return !isFileLine && !R100;
|
|
488
|
+
});
|
|
489
|
+
if (contentLines.length === 0) {
|
|
490
|
+
return "";
|
|
491
|
+
}
|
|
492
|
+
const indentedBody = contentLines.map((line) => ` ${line}`).join("\n");
|
|
493
|
+
return `
|
|
494
|
+
|
|
495
|
+
${indentedBody}
|
|
496
|
+
`;
|
|
497
|
+
}
|
|
498
|
+
function formatCommit(commit, config) {
|
|
499
|
+
const body = config.changelog.includeCommitBody ? getCommitBody(commit) : "";
|
|
500
|
+
return `- ${commit.scope ? `**${commit.scope.trim()}:** ` : ""}${commit.isBreaking ? "\u26A0\uFE0F " : ""}${upperFirst(commit.description)}${formatReferences(commit.references, config)}${body}`;
|
|
501
|
+
}
|
|
502
|
+
function formatReferences(references, config) {
|
|
503
|
+
const pr = references.filter((ref) => ref.type === "pull-request");
|
|
504
|
+
const issue = references.filter((ref) => ref.type === "issue");
|
|
505
|
+
if (pr.length > 0 || issue.length > 0) {
|
|
506
|
+
return ` (${[...pr, ...issue].map((ref) => formatReference(ref, config.repo)).join(", ")})`;
|
|
507
|
+
}
|
|
508
|
+
if (references.length > 0) {
|
|
509
|
+
return ` (${formatReference(references[0], config.repo)})`;
|
|
510
|
+
}
|
|
511
|
+
return "";
|
|
512
|
+
}
|
|
513
|
+
function formatName(name = "") {
|
|
514
|
+
return name.split(" ").map((p) => upperFirst(p.trim())).join(" ");
|
|
515
|
+
}
|
|
516
|
+
function groupBy(items, key) {
|
|
517
|
+
const groups = {};
|
|
518
|
+
for (const item of items) {
|
|
519
|
+
groups[item[key]] = groups[item[key]] || [];
|
|
520
|
+
groups[item[key]]?.push(item);
|
|
521
|
+
}
|
|
522
|
+
return groups;
|
|
523
|
+
}
|
|
294
524
|
|
|
295
525
|
function fromTagIsFirstCommit(fromTag, cwd) {
|
|
296
526
|
return fromTag === getFirstCommit(cwd);
|
|
297
527
|
}
|
|
298
528
|
async function generateChangelog({
|
|
299
529
|
pkg,
|
|
300
|
-
commits,
|
|
301
530
|
config,
|
|
302
|
-
|
|
303
|
-
|
|
531
|
+
dryRun,
|
|
532
|
+
newVersion
|
|
304
533
|
}) {
|
|
305
|
-
let fromTag = config.from ||
|
|
534
|
+
let fromTag = config.from || pkg.fromTag || getFirstCommit(config.cwd);
|
|
306
535
|
const isFirstCommit = fromTagIsFirstCommit(fromTag, config.cwd);
|
|
307
536
|
if (isFirstCommit) {
|
|
308
|
-
fromTag = config.monorepo?.versionMode === "independent" ?
|
|
537
|
+
fromTag = config.monorepo?.versionMode === "independent" ? getIndependentTag({ version: "0.0.0", name: pkg.name }) : config.templates.tagBody.replace("{{newVersion}}", "0.0.0");
|
|
538
|
+
}
|
|
539
|
+
newVersion = newVersion || pkg.newVersion;
|
|
540
|
+
let toTag = config.to;
|
|
541
|
+
if (!toTag && newVersion) {
|
|
542
|
+
toTag = config.monorepo?.versionMode === "independent" ? getIndependentTag({ version: newVersion, name: pkg.name }) : config.templates.tagBody.replace("{{newVersion}}", newVersion);
|
|
543
|
+
}
|
|
544
|
+
if (!toTag) {
|
|
545
|
+
throw new Error(`No tag found for ${pkg.name}`);
|
|
309
546
|
}
|
|
310
|
-
const toTag = config.to || (config.monorepo?.versionMode === "independent" ? `${pkg.name}@${pkg.version}` : config.templates.tagBody.replace("{{newVersion}}", pkg.version));
|
|
311
547
|
logger.debug(`Generating changelog for ${pkg.name} - from ${fromTag} to ${toTag}`);
|
|
312
548
|
try {
|
|
313
549
|
config = {
|
|
@@ -316,25 +552,26 @@ async function generateChangelog({
|
|
|
316
552
|
to: toTag
|
|
317
553
|
};
|
|
318
554
|
const generatedChangelog = await generateMarkDown({
|
|
319
|
-
commits,
|
|
555
|
+
commits: pkg.commits,
|
|
320
556
|
config,
|
|
321
557
|
from: fromTag,
|
|
558
|
+
isFirstCommit,
|
|
322
559
|
to: toTag
|
|
323
560
|
});
|
|
324
561
|
let changelog = generatedChangelog;
|
|
325
|
-
if (commits.length === 0) {
|
|
562
|
+
if (pkg.commits.length === 0) {
|
|
326
563
|
changelog = `${changelog}
|
|
327
564
|
|
|
328
565
|
${config.templates.emptyChangelogContent}`;
|
|
329
566
|
}
|
|
330
567
|
const changelogResult = await executeHook("generate:changelog", config, dryRun, {
|
|
331
|
-
commits,
|
|
568
|
+
commits: pkg.commits,
|
|
332
569
|
changelog
|
|
333
570
|
});
|
|
334
571
|
changelog = changelogResult || changelog;
|
|
335
572
|
logger.verbose(`Output changelog for ${pkg.name}:
|
|
336
573
|
${changelog}`);
|
|
337
|
-
logger.debug(`Changelog generated for ${pkg.name} (${commits.length} commits)`);
|
|
574
|
+
logger.debug(`Changelog generated for ${pkg.name} (${pkg.commits.length} commits)`);
|
|
338
575
|
logger.verbose(`Final changelog for ${pkg.name}:
|
|
339
576
|
|
|
340
577
|
${changelog}
|
|
@@ -349,6 +586,7 @@ ${changelog}
|
|
|
349
586
|
}
|
|
350
587
|
}
|
|
351
588
|
function writeChangelogToFile({
|
|
589
|
+
cwd,
|
|
352
590
|
pkg,
|
|
353
591
|
changelog,
|
|
354
592
|
dryRun = false
|
|
@@ -372,11 +610,12 @@ ${changelog}
|
|
|
372
610
|
${existingChangelog}`;
|
|
373
611
|
}
|
|
374
612
|
if (dryRun) {
|
|
375
|
-
|
|
613
|
+
const relativeChangelogPath = relative(cwd, changelogPath);
|
|
614
|
+
logger.info(`[dry-run] ${pkg.name} - Write changelog to ${relativeChangelogPath}`);
|
|
376
615
|
} else {
|
|
377
616
|
logger.debug(`Writing changelog to ${changelogPath}`);
|
|
378
617
|
writeFileSync(changelogPath, updatedChangelog, "utf8");
|
|
379
|
-
logger.info(`Changelog updated for ${pkg.name}`);
|
|
618
|
+
logger.info(`Changelog updated for ${pkg.name} (${"newVersion" in pkg && pkg.newVersion || pkg.version})`);
|
|
380
619
|
}
|
|
381
620
|
}
|
|
382
621
|
|
|
@@ -399,7 +638,7 @@ function getDefaultConfig() {
|
|
|
399
638
|
},
|
|
400
639
|
templates: {
|
|
401
640
|
commitMessage: "chore(release): bump version to {{newVersion}}",
|
|
402
|
-
tagMessage: "Bump version to
|
|
641
|
+
tagMessage: "Bump version to {{newVersion}}",
|
|
403
642
|
tagBody: "v{{newVersion}}",
|
|
404
643
|
emptyChangelogContent: "No relevant changes for this release"
|
|
405
644
|
},
|
|
@@ -490,7 +729,11 @@ function defineConfig(config) {
|
|
|
490
729
|
return config;
|
|
491
730
|
}
|
|
492
731
|
|
|
493
|
-
function getPackageDependencies(
|
|
732
|
+
function getPackageDependencies({
|
|
733
|
+
packagePath,
|
|
734
|
+
allPackageNames,
|
|
735
|
+
dependencyTypes
|
|
736
|
+
}) {
|
|
494
737
|
const packageJsonPath = join(packagePath, "package.json");
|
|
495
738
|
if (!existsSync(packageJsonPath)) {
|
|
496
739
|
return [];
|
|
@@ -509,32 +752,26 @@ function getPackageDependencies(packagePath, allPackageNames, dependencyTypes) {
|
|
|
509
752
|
}
|
|
510
753
|
return deps;
|
|
511
754
|
}
|
|
512
|
-
function
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
dependencies: getPackageDependencies(pkg.path, allPackageNames, dependencyTypes)
|
|
517
|
-
}));
|
|
518
|
-
}
|
|
519
|
-
function getDependentsOf(packageName, allPackages) {
|
|
755
|
+
function getDependentsOf({
|
|
756
|
+
allPackages,
|
|
757
|
+
packageName
|
|
758
|
+
}) {
|
|
520
759
|
return allPackages.filter(
|
|
521
760
|
(pkg) => pkg.dependencies.includes(packageName)
|
|
522
761
|
);
|
|
523
762
|
}
|
|
524
763
|
function expandPackagesToBumpWithDependents({
|
|
525
|
-
packagesWithCommits,
|
|
526
764
|
allPackages,
|
|
527
|
-
|
|
765
|
+
packagesWithCommits
|
|
528
766
|
}) {
|
|
529
|
-
const packagesWithDeps = getPackagesWithDependencies(allPackages, dependencyTypes);
|
|
530
767
|
const result = /* @__PURE__ */ new Map();
|
|
531
768
|
logger.debug(`Expanding packages to bump: ${packagesWithCommits.length} packages with commits, ${allPackages.length} total packages`);
|
|
532
769
|
for (const pkg of packagesWithCommits) {
|
|
533
|
-
|
|
770
|
+
const packageToBump = {
|
|
534
771
|
...pkg,
|
|
535
|
-
reason: "commits"
|
|
536
|
-
|
|
537
|
-
|
|
772
|
+
reason: "commits"
|
|
773
|
+
};
|
|
774
|
+
result.set(pkg.name, packageToBump);
|
|
538
775
|
}
|
|
539
776
|
const toProcess = [...packagesWithCommits.map((p) => p.name)];
|
|
540
777
|
const processed = /* @__PURE__ */ new Set();
|
|
@@ -544,19 +781,22 @@ function expandPackagesToBumpWithDependents({
|
|
|
544
781
|
continue;
|
|
545
782
|
}
|
|
546
783
|
processed.add(currentPkgName);
|
|
547
|
-
const dependents = getDependentsOf(
|
|
784
|
+
const dependents = getDependentsOf({
|
|
785
|
+
packageName: currentPkgName,
|
|
786
|
+
allPackages
|
|
787
|
+
});
|
|
548
788
|
for (const dependent of dependents) {
|
|
549
789
|
if (!result.has(dependent.name)) {
|
|
550
790
|
const currentChain = result.get(currentPkgName)?.dependencyChain || [];
|
|
551
791
|
const chain = [...currentChain, currentPkgName];
|
|
552
|
-
const
|
|
553
|
-
if (
|
|
554
|
-
|
|
555
|
-
...
|
|
792
|
+
const packageBase = allPackages.find((p) => p.name === dependent.name);
|
|
793
|
+
if (packageBase) {
|
|
794
|
+
const packageToBump = {
|
|
795
|
+
...packageBase,
|
|
556
796
|
reason: "dependency",
|
|
557
|
-
dependencyChain: chain
|
|
558
|
-
|
|
559
|
-
|
|
797
|
+
dependencyChain: chain
|
|
798
|
+
};
|
|
799
|
+
result.set(dependent.name, packageToBump);
|
|
560
800
|
toProcess.push(dependent.name);
|
|
561
801
|
logger.debug(`${dependent.name} will be bumped (depends on ${chain.join(" \u2192 ")})`);
|
|
562
802
|
}
|
|
@@ -577,7 +817,7 @@ function topologicalSort(packages) {
|
|
|
577
817
|
if (visited.has(pkgName))
|
|
578
818
|
return;
|
|
579
819
|
if (visiting.has(pkgName)) {
|
|
580
|
-
logger.
|
|
820
|
+
logger.fail(`Circular dependency detected involving ${pkgName}`);
|
|
581
821
|
return;
|
|
582
822
|
}
|
|
583
823
|
visiting.add(pkgName);
|
|
@@ -597,229 +837,12 @@ function topologicalSort(packages) {
|
|
|
597
837
|
return sorted;
|
|
598
838
|
}
|
|
599
839
|
|
|
600
|
-
function getGitStatus(cwd) {
|
|
601
|
-
return execSync("git status --porcelain", {
|
|
602
|
-
cwd,
|
|
603
|
-
encoding: "utf8"
|
|
604
|
-
}).trim();
|
|
605
|
-
}
|
|
606
|
-
function checkGitStatusIfDirty() {
|
|
607
|
-
logger.debug("Checking git status");
|
|
608
|
-
const dirty = getGitStatus();
|
|
609
|
-
if (dirty) {
|
|
610
|
-
logger.debug("git status:", `
|
|
611
|
-
${dirty.trim().split("\n").map((line) => line.trim()).join("\n")}`);
|
|
612
|
-
const error = `Git status is dirty!
|
|
613
|
-
|
|
614
|
-
Please commit or stash your changes before bumping or use --no-clean flag.
|
|
615
|
-
|
|
616
|
-
Unstaged files:
|
|
617
|
-
|
|
618
|
-
${dirty.trim()}`;
|
|
619
|
-
throw new Error(error);
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
async function fetchGitTags(cwd) {
|
|
623
|
-
logger.debug("Fetching git tags from remote");
|
|
624
|
-
try {
|
|
625
|
-
await execPromise("git fetch --tags", { cwd, noStderr: true, noStdout: true, noSuccess: true });
|
|
626
|
-
logger.debug("Git tags fetched successfully");
|
|
627
|
-
} catch (error) {
|
|
628
|
-
logger.warn("Failed to fetch some git tags from remote (tags might already exist locally)", error);
|
|
629
|
-
logger.info("Continuing with local tags");
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
function detectGitProvider(cwd = process.cwd()) {
|
|
633
|
-
try {
|
|
634
|
-
const remoteUrl = execSync("git remote get-url origin", {
|
|
635
|
-
cwd,
|
|
636
|
-
encoding: "utf8"
|
|
637
|
-
}).trim();
|
|
638
|
-
if (remoteUrl.includes("github.com")) {
|
|
639
|
-
return "github";
|
|
640
|
-
}
|
|
641
|
-
if (remoteUrl.includes("gitlab.com") || remoteUrl.includes("gitlab")) {
|
|
642
|
-
return "gitlab";
|
|
643
|
-
}
|
|
644
|
-
return null;
|
|
645
|
-
} catch {
|
|
646
|
-
return null;
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
function parseGitRemoteUrl(remoteUrl) {
|
|
650
|
-
const sshRegex = /git@[\w.-]+:([\w.-]+)\/([\w.-]+?)(?:\.git)?$/;
|
|
651
|
-
const httpsRegex = /https?:\/\/[\w.-]+\/([\w.-]+)\/([\w.-]+?)(?:\.git)?$/;
|
|
652
|
-
const sshMatch = remoteUrl.match(sshRegex);
|
|
653
|
-
if (sshMatch) {
|
|
654
|
-
return {
|
|
655
|
-
owner: sshMatch[1],
|
|
656
|
-
repo: sshMatch[2]
|
|
657
|
-
};
|
|
658
|
-
}
|
|
659
|
-
const httpsMatch = remoteUrl.match(httpsRegex);
|
|
660
|
-
if (httpsMatch) {
|
|
661
|
-
return {
|
|
662
|
-
owner: httpsMatch[1],
|
|
663
|
-
repo: httpsMatch[2]
|
|
664
|
-
};
|
|
665
|
-
}
|
|
666
|
-
return null;
|
|
667
|
-
}
|
|
668
|
-
async function createCommitAndTags({
|
|
669
|
-
config,
|
|
670
|
-
noVerify,
|
|
671
|
-
bumpedPackages,
|
|
672
|
-
newVersion,
|
|
673
|
-
dryRun,
|
|
674
|
-
logLevel
|
|
675
|
-
} = {}) {
|
|
676
|
-
const internalConfig = config || await loadRelizyConfig();
|
|
677
|
-
try {
|
|
678
|
-
await executeHook("before:commit-and-tag", internalConfig, dryRun ?? false);
|
|
679
|
-
const filePatternsToAdd = [
|
|
680
|
-
"package.json",
|
|
681
|
-
"lerna.json",
|
|
682
|
-
"CHANGELOG.md",
|
|
683
|
-
"**/CHANGELOG.md",
|
|
684
|
-
"**/package.json"
|
|
685
|
-
];
|
|
686
|
-
logger.start("Start commit and tag");
|
|
687
|
-
logger.debug("Adding files to git staging area...");
|
|
688
|
-
for (const pattern of filePatternsToAdd) {
|
|
689
|
-
if (pattern === "lerna.json" && !hasLernaJson(internalConfig.cwd)) {
|
|
690
|
-
logger.verbose(`Skipping lerna.json as it doesn't exist`);
|
|
691
|
-
continue;
|
|
692
|
-
}
|
|
693
|
-
if ((pattern === "lerna.json" || pattern === "CHANGELOG.md") && !existsSync(join(internalConfig.cwd, pattern))) {
|
|
694
|
-
logger.verbose(`Skipping ${pattern} as it doesn't exist`);
|
|
695
|
-
continue;
|
|
696
|
-
}
|
|
697
|
-
if (dryRun) {
|
|
698
|
-
logger.info(`[dry-run] git add ${pattern}`);
|
|
699
|
-
continue;
|
|
700
|
-
}
|
|
701
|
-
try {
|
|
702
|
-
logger.debug(`git add ${pattern}`);
|
|
703
|
-
execSync(`git add ${pattern}`);
|
|
704
|
-
} catch {
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
const rootPackage = getRootPackage(internalConfig.cwd);
|
|
708
|
-
newVersion = newVersion || rootPackage.version;
|
|
709
|
-
const versionForMessage = internalConfig.monorepo?.versionMode === "independent" ? bumpedPackages?.map((pkg) => `${pkg.name}@${pkg.version}`).join(", ") || "unknown" : newVersion || "unknown";
|
|
710
|
-
const commitMessage = internalConfig.templates.commitMessage?.replaceAll("{{newVersion}}", versionForMessage) || `chore(release): bump version to ${versionForMessage}`;
|
|
711
|
-
const noVerifyFlag = noVerify ? "--no-verify " : "";
|
|
712
|
-
logger.debug(`No verify: ${noVerify}`);
|
|
713
|
-
if (dryRun) {
|
|
714
|
-
logger.info(`[dry-run] git commit ${noVerifyFlag}-m "${commitMessage}"`);
|
|
715
|
-
} else {
|
|
716
|
-
logger.debug(`Executing: git commit ${noVerifyFlag}-m "${commitMessage}"`);
|
|
717
|
-
await execPromise(`git commit ${noVerifyFlag}-m "${commitMessage}"`, {
|
|
718
|
-
logLevel,
|
|
719
|
-
noStderr: true,
|
|
720
|
-
noStdout: true,
|
|
721
|
-
cwd: internalConfig.cwd
|
|
722
|
-
});
|
|
723
|
-
logger.success(`Committed: ${commitMessage}${noVerify ? " (--no-verify)" : ""}`);
|
|
724
|
-
}
|
|
725
|
-
const signTags = internalConfig.signTags ? "-s" : "";
|
|
726
|
-
logger.debug(`Sign tags: ${internalConfig.signTags}`);
|
|
727
|
-
const createdTags = [];
|
|
728
|
-
if (internalConfig.monorepo?.versionMode === "independent" && bumpedPackages && bumpedPackages.length > 0) {
|
|
729
|
-
logger.debug(`Creating ${bumpedPackages.length} independent package tags`);
|
|
730
|
-
for (const pkg of bumpedPackages) {
|
|
731
|
-
const tagName = `${pkg.name}@${pkg.version}`;
|
|
732
|
-
const tagMessage = internalConfig.templates?.tagMessage?.replaceAll("{{newVersion}}", pkg.version || "") || tagName;
|
|
733
|
-
if (dryRun) {
|
|
734
|
-
logger.info(`[dry-run] git tag ${signTags} -a ${tagName} -m "${tagMessage}"`);
|
|
735
|
-
} else {
|
|
736
|
-
const cmd = `git tag ${signTags} -a ${tagName} -m "${tagMessage}"`;
|
|
737
|
-
logger.debug(`Executing: ${cmd}`);
|
|
738
|
-
try {
|
|
739
|
-
await execPromise(cmd, {
|
|
740
|
-
logLevel,
|
|
741
|
-
noStderr: true,
|
|
742
|
-
noStdout: true,
|
|
743
|
-
cwd: internalConfig.cwd
|
|
744
|
-
});
|
|
745
|
-
logger.debug(`Tag created: ${tagName}`);
|
|
746
|
-
} catch (error) {
|
|
747
|
-
logger.error(`Failed to create tag ${tagName}:`, error);
|
|
748
|
-
throw error;
|
|
749
|
-
}
|
|
750
|
-
}
|
|
751
|
-
createdTags.push(tagName);
|
|
752
|
-
}
|
|
753
|
-
logger.success(`Created ${createdTags.length} tags for independent packages, ${createdTags.join(", ")}`);
|
|
754
|
-
} else {
|
|
755
|
-
const tagName = internalConfig.templates.tagBody?.replaceAll("{{newVersion}}", newVersion);
|
|
756
|
-
const tagMessage = internalConfig.templates?.tagMessage?.replaceAll("{{newVersion}}", newVersion) || tagName;
|
|
757
|
-
if (dryRun) {
|
|
758
|
-
logger.info(`[dry-run] git tag ${signTags} -a ${tagName} -m "${tagMessage}"`);
|
|
759
|
-
} else {
|
|
760
|
-
const cmd = `git tag ${signTags} -a ${tagName} -m "${tagMessage}"`;
|
|
761
|
-
logger.debug(`Executing: ${cmd}`);
|
|
762
|
-
try {
|
|
763
|
-
await execPromise(cmd, {
|
|
764
|
-
logLevel,
|
|
765
|
-
noStderr: true,
|
|
766
|
-
noStdout: true,
|
|
767
|
-
cwd: internalConfig.cwd
|
|
768
|
-
});
|
|
769
|
-
logger.debug(`Tag created: ${tagName}`);
|
|
770
|
-
} catch (error) {
|
|
771
|
-
logger.error(`Failed to create tag ${tagName}:`, error);
|
|
772
|
-
throw error;
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
createdTags.push(tagName);
|
|
776
|
-
}
|
|
777
|
-
logger.debug("Created Tags:", createdTags.join(", "));
|
|
778
|
-
logger.success("Commit and tag completed!");
|
|
779
|
-
await executeHook("success:commit-and-tag", internalConfig, dryRun ?? false);
|
|
780
|
-
return createdTags;
|
|
781
|
-
} catch (error) {
|
|
782
|
-
logger.error("Error committing and tagging:", error);
|
|
783
|
-
await executeHook("error:commit-and-tag", internalConfig, dryRun ?? false);
|
|
784
|
-
throw error;
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
async function pushCommitAndTags({ dryRun, logLevel, cwd }) {
|
|
788
|
-
logger.start("Start push changes and tags");
|
|
789
|
-
if (dryRun) {
|
|
790
|
-
logger.info("[dry-run] git push --follow-tags");
|
|
791
|
-
} else {
|
|
792
|
-
logger.debug("Executing: git push --follow-tags");
|
|
793
|
-
await execPromise("git push --follow-tags", { noStderr: true, noStdout: true, logLevel, cwd });
|
|
794
|
-
}
|
|
795
|
-
logger.success("Pushing changes and tags completed!");
|
|
796
|
-
}
|
|
797
|
-
function getFirstCommit(cwd) {
|
|
798
|
-
const result = execSync(
|
|
799
|
-
"git rev-list --max-parents=0 HEAD",
|
|
800
|
-
{
|
|
801
|
-
cwd,
|
|
802
|
-
encoding: "utf8"
|
|
803
|
-
}
|
|
804
|
-
);
|
|
805
|
-
return result.trim();
|
|
806
|
-
}
|
|
807
|
-
function getCurrentGitBranch(cwd) {
|
|
808
|
-
const result = execSync("git rev-parse --abbrev-ref HEAD", {
|
|
809
|
-
cwd,
|
|
810
|
-
encoding: "utf8"
|
|
811
|
-
});
|
|
812
|
-
return result.trim();
|
|
813
|
-
}
|
|
814
|
-
function getCurrentGitRef(cwd) {
|
|
815
|
-
const branch = getCurrentGitBranch(cwd);
|
|
816
|
-
return branch || "HEAD";
|
|
817
|
-
}
|
|
818
|
-
|
|
819
840
|
async function githubIndependentMode({
|
|
820
841
|
config,
|
|
821
842
|
dryRun,
|
|
822
|
-
|
|
843
|
+
bumpResult,
|
|
844
|
+
force,
|
|
845
|
+
suffix
|
|
823
846
|
}) {
|
|
824
847
|
const repoConfig = config.repo;
|
|
825
848
|
if (!repoConfig) {
|
|
@@ -829,42 +852,36 @@ async function githubIndependentMode({
|
|
|
829
852
|
if (!config.tokens.github && !config.repo?.token) {
|
|
830
853
|
throw new Error("No GitHub token specified. Set GITHUB_TOKEN or GH_TOKEN environment variable.");
|
|
831
854
|
}
|
|
832
|
-
const packages = bumpedPackages || getPackages({
|
|
833
|
-
|
|
855
|
+
const packages = bumpResult?.bumped && bumpResult?.bumpedPackages || await getPackages({
|
|
856
|
+
suffix,
|
|
834
857
|
patterns: config.monorepo?.packages,
|
|
835
|
-
|
|
858
|
+
config,
|
|
859
|
+
force
|
|
836
860
|
});
|
|
837
861
|
logger.info(`Creating ${packages.length} GitHub release(s)`);
|
|
838
862
|
const postedReleases = [];
|
|
839
863
|
for (const pkg of packages) {
|
|
840
|
-
const
|
|
841
|
-
const from = pkg.fromTag;
|
|
864
|
+
const newVersion = isBumpedPackage(pkg) && pkg.newVersion || pkg.version;
|
|
865
|
+
const from = config.from || pkg.fromTag;
|
|
866
|
+
const to = config.to || getIndependentTag({ version: newVersion, name: pkg.name });
|
|
842
867
|
if (!from) {
|
|
843
|
-
logger.warn(`No
|
|
868
|
+
logger.warn(`No from tag found for ${pkg.name}, skipping release`);
|
|
844
869
|
continue;
|
|
845
870
|
}
|
|
846
871
|
const toTag = dryRun ? "HEAD" : to;
|
|
847
872
|
logger.debug(`Processing ${pkg.name}: ${from} \u2192 ${toTag}`);
|
|
848
|
-
const commits = await getPackageCommits({
|
|
849
|
-
pkg,
|
|
850
|
-
to: toTag,
|
|
851
|
-
from,
|
|
852
|
-
config,
|
|
853
|
-
changelog: true
|
|
854
|
-
});
|
|
855
873
|
const changelog = await generateChangelog({
|
|
856
874
|
pkg,
|
|
857
|
-
commits,
|
|
858
875
|
config,
|
|
859
|
-
|
|
860
|
-
|
|
876
|
+
dryRun,
|
|
877
|
+
newVersion
|
|
861
878
|
});
|
|
862
879
|
const releaseBody = changelog.split("\n").slice(2).join("\n");
|
|
863
880
|
const release = {
|
|
864
881
|
tag_name: to,
|
|
865
882
|
name: to,
|
|
866
883
|
body: releaseBody,
|
|
867
|
-
prerelease: isPrerelease(
|
|
884
|
+
prerelease: isPrerelease(newVersion)
|
|
868
885
|
};
|
|
869
886
|
logger.debug(`Creating release for ${to}${release.prerelease ? " (prerelease)" : ""}`);
|
|
870
887
|
if (dryRun) {
|
|
@@ -872,7 +889,7 @@ async function githubIndependentMode({
|
|
|
872
889
|
postedReleases.push({
|
|
873
890
|
name: pkg.name,
|
|
874
891
|
tag: release.tag_name,
|
|
875
|
-
version:
|
|
892
|
+
version: newVersion,
|
|
876
893
|
prerelease: release.prerelease
|
|
877
894
|
});
|
|
878
895
|
} else {
|
|
@@ -886,7 +903,7 @@ async function githubIndependentMode({
|
|
|
886
903
|
postedReleases.push({
|
|
887
904
|
name: pkg.name,
|
|
888
905
|
tag: release.tag_name,
|
|
889
|
-
version:
|
|
906
|
+
version: newVersion,
|
|
890
907
|
prerelease: release.prerelease
|
|
891
908
|
});
|
|
892
909
|
}
|
|
@@ -912,21 +929,12 @@ async function githubUnified({
|
|
|
912
929
|
if (!config.tokens.github && !config.repo?.token) {
|
|
913
930
|
throw new Error("No GitHub token specified. Set GITHUB_TOKEN or GH_TOKEN environment variable.");
|
|
914
931
|
}
|
|
915
|
-
const to = config.templates.tagBody.replace("{{newVersion}}", bumpResult?.newVersion || rootPackage.version);
|
|
916
|
-
const toTag = dryRun ? getCurrentGitRef(config.cwd) : to;
|
|
917
|
-
const commits = await getPackageCommits({
|
|
918
|
-
pkg: rootPackage,
|
|
919
|
-
config,
|
|
920
|
-
from: bumpResult?.fromTag || getFirstCommit(config.cwd),
|
|
921
|
-
to: toTag,
|
|
922
|
-
changelog: true
|
|
923
|
-
});
|
|
932
|
+
const to = config.to || config.templates.tagBody.replace("{{newVersion}}", bumpResult?.bumped && bumpResult.newVersion || rootPackage.version);
|
|
924
933
|
const changelog = await generateChangelog({
|
|
925
934
|
pkg: rootPackage,
|
|
926
|
-
commits,
|
|
927
935
|
config,
|
|
928
|
-
|
|
929
|
-
|
|
936
|
+
dryRun,
|
|
937
|
+
newVersion: bumpResult?.newVersion || rootPackage.version
|
|
930
938
|
});
|
|
931
939
|
const releaseBody = changelog.split("\n").slice(2).join("\n");
|
|
932
940
|
const release = {
|
|
@@ -947,7 +955,7 @@ async function githubUnified({
|
|
|
947
955
|
logger.debug("Publishing release to GitHub...");
|
|
948
956
|
await createGithubRelease({
|
|
949
957
|
...config,
|
|
950
|
-
from: bumpResult?.fromTag || "v0.0.0",
|
|
958
|
+
from: bumpResult?.bumped && bumpResult.fromTag || "v0.0.0",
|
|
951
959
|
to,
|
|
952
960
|
repo: repoConfig
|
|
953
961
|
}, release);
|
|
@@ -960,7 +968,7 @@ async function githubUnified({
|
|
|
960
968
|
prerelease: release.prerelease
|
|
961
969
|
}];
|
|
962
970
|
}
|
|
963
|
-
async function github(options
|
|
971
|
+
async function github(options) {
|
|
964
972
|
try {
|
|
965
973
|
const dryRun = options.dryRun ?? false;
|
|
966
974
|
logger.debug(`Dry run: ${dryRun}`);
|
|
@@ -976,18 +984,30 @@ async function github(options = {}) {
|
|
|
976
984
|
}
|
|
977
985
|
}
|
|
978
986
|
});
|
|
979
|
-
if (!options.bumpResult?.bumped) {
|
|
980
|
-
logger.warn("No bump result found, skipping release");
|
|
981
|
-
return [];
|
|
982
|
-
}
|
|
983
987
|
if (config.monorepo?.versionMode === "independent") {
|
|
984
|
-
return await githubIndependentMode({
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
988
|
+
return await githubIndependentMode({
|
|
989
|
+
config,
|
|
990
|
+
dryRun,
|
|
991
|
+
bumpResult: options.bumpResult,
|
|
992
|
+
force: options.force ?? false,
|
|
993
|
+
suffix: options.suffix
|
|
994
|
+
});
|
|
990
995
|
}
|
|
996
|
+
const rootPackageBase = readPackageJson(config.cwd);
|
|
997
|
+
const { from, to } = await resolveTags({
|
|
998
|
+
config,
|
|
999
|
+
step: "provider-release",
|
|
1000
|
+
newVersion: options.bumpResult?.newVersion || rootPackageBase.version,
|
|
1001
|
+
pkg: rootPackageBase
|
|
1002
|
+
});
|
|
1003
|
+
const rootPackage = options.bumpResult?.rootPackage || await getRootPackage({
|
|
1004
|
+
config,
|
|
1005
|
+
force: options.force ?? false,
|
|
1006
|
+
suffix: options.suffix,
|
|
1007
|
+
changelog: true,
|
|
1008
|
+
from,
|
|
1009
|
+
to
|
|
1010
|
+
});
|
|
991
1011
|
return await githubUnified({
|
|
992
1012
|
config,
|
|
993
1013
|
dryRun,
|
|
@@ -1064,13 +1084,16 @@ async function createGitlabRelease({
|
|
|
1064
1084
|
async function gitlabIndependentMode({
|
|
1065
1085
|
config,
|
|
1066
1086
|
dryRun,
|
|
1067
|
-
|
|
1087
|
+
bumpResult,
|
|
1088
|
+
suffix,
|
|
1089
|
+
force
|
|
1068
1090
|
}) {
|
|
1069
1091
|
logger.debug(`GitLab token: ${config.tokens.gitlab || config.repo?.token ? "\u2713 provided" : "\u2717 missing"}`);
|
|
1070
|
-
const packages = bumpedPackages || getPackages({
|
|
1071
|
-
cwd: config.cwd,
|
|
1092
|
+
const packages = bumpResult?.bumped && bumpResult?.bumpedPackages || await getPackages({
|
|
1072
1093
|
patterns: config.monorepo?.packages,
|
|
1073
|
-
|
|
1094
|
+
config,
|
|
1095
|
+
suffix,
|
|
1096
|
+
force
|
|
1074
1097
|
});
|
|
1075
1098
|
logger.info(`Creating ${packages.length} GitLab release(s) for independent packages`);
|
|
1076
1099
|
logger.debug("Getting current branch...");
|
|
@@ -1082,26 +1105,19 @@ async function gitlabIndependentMode({
|
|
|
1082
1105
|
});
|
|
1083
1106
|
const postedReleases = [];
|
|
1084
1107
|
for (const pkg of packages) {
|
|
1085
|
-
const
|
|
1086
|
-
const from = pkg.fromTag;
|
|
1108
|
+
const newVersion = isBumpedPackage(pkg) && pkg.newVersion || pkg.version;
|
|
1109
|
+
const from = config.from || pkg.fromTag;
|
|
1110
|
+
const to = getIndependentTag({ version: newVersion, name: pkg.name });
|
|
1087
1111
|
if (!from) {
|
|
1088
|
-
logger.warn(`No
|
|
1112
|
+
logger.warn(`No from tag found for ${pkg.name}, skipping release`);
|
|
1089
1113
|
continue;
|
|
1090
1114
|
}
|
|
1091
1115
|
logger.debug(`Processing ${pkg.name}: ${from} \u2192 ${to}`);
|
|
1092
|
-
const commits = await getPackageCommits({
|
|
1093
|
-
pkg,
|
|
1094
|
-
config,
|
|
1095
|
-
from,
|
|
1096
|
-
to,
|
|
1097
|
-
changelog: true
|
|
1098
|
-
});
|
|
1099
1116
|
const changelog = await generateChangelog({
|
|
1100
1117
|
pkg,
|
|
1101
|
-
commits,
|
|
1102
1118
|
config,
|
|
1103
|
-
|
|
1104
|
-
|
|
1119
|
+
dryRun,
|
|
1120
|
+
newVersion
|
|
1105
1121
|
});
|
|
1106
1122
|
if (!changelog) {
|
|
1107
1123
|
logger.warn(`No changelog found for ${pkg.name}`);
|
|
@@ -1114,335 +1130,186 @@ async function gitlabIndependentMode({
|
|
|
1114
1130
|
description: releaseBody,
|
|
1115
1131
|
ref: currentBranch.trim()
|
|
1116
1132
|
};
|
|
1117
|
-
logger.debug(`Creating release for ${to} (ref: ${release.ref})`);
|
|
1118
|
-
if (dryRun) {
|
|
1119
|
-
logger.info(`[dry-run] Publish GitLab release for ${to}`);
|
|
1120
|
-
} else {
|
|
1121
|
-
logger.debug(`Publishing release ${to} to GitLab...`);
|
|
1122
|
-
await createGitlabRelease({
|
|
1123
|
-
config,
|
|
1124
|
-
release,
|
|
1125
|
-
dryRun
|
|
1126
|
-
});
|
|
1127
|
-
postedReleases.push({
|
|
1128
|
-
name: pkg.name,
|
|
1129
|
-
tag: release.tag_name,
|
|
1130
|
-
version:
|
|
1131
|
-
prerelease: isPrerelease(
|
|
1132
|
-
});
|
|
1133
|
-
}
|
|
1134
|
-
}
|
|
1135
|
-
if (postedReleases.length === 0) {
|
|
1136
|
-
logger.warn("No releases created");
|
|
1137
|
-
} else {
|
|
1138
|
-
logger.success(`Releases ${postedReleases.map((r) => r.tag).join(", ")} published to GitLab!`);
|
|
1139
|
-
}
|
|
1140
|
-
return postedReleases;
|
|
1141
|
-
}
|
|
1142
|
-
async function gitlabUnified({
|
|
1143
|
-
config,
|
|
1144
|
-
dryRun,
|
|
1145
|
-
rootPackage,
|
|
1146
|
-
fromTag,
|
|
1147
|
-
oldVersion
|
|
1148
|
-
}) {
|
|
1149
|
-
logger.debug(`GitLab token: ${config.tokens.gitlab || config.repo?.token ? "\u2713 provided" : "\u2717 missing"}`);
|
|
1150
|
-
const to = config.templates.tagBody.replace("{{newVersion}}", rootPackage.version);
|
|
1151
|
-
const commits = await getPackageCommits({
|
|
1152
|
-
pkg: rootPackage,
|
|
1153
|
-
config,
|
|
1154
|
-
from: fromTag || getFirstCommit(config.cwd),
|
|
1155
|
-
to,
|
|
1156
|
-
changelog: true
|
|
1157
|
-
});
|
|
1158
|
-
logger.debug(`Found ${commits.length} commit(s)`);
|
|
1159
|
-
const changelog = await generateChangelog({
|
|
1160
|
-
pkg: rootPackage,
|
|
1161
|
-
commits,
|
|
1162
|
-
config,
|
|
1163
|
-
from: fromTag || oldVersion || "v0.0.0",
|
|
1164
|
-
dryRun
|
|
1165
|
-
});
|
|
1166
|
-
const releaseBody = changelog.split("\n").slice(2).join("\n");
|
|
1167
|
-
logger.debug("Getting current branch...");
|
|
1168
|
-
const { stdout: currentBranch } = await execPromise("git rev-parse --abbrev-ref HEAD", {
|
|
1169
|
-
noSuccess: true,
|
|
1170
|
-
noStdout: true,
|
|
1171
|
-
logLevel: config.logLevel,
|
|
1172
|
-
cwd: config.cwd
|
|
1173
|
-
});
|
|
1174
|
-
const release = {
|
|
1175
|
-
tag_name: to,
|
|
1176
|
-
name: to,
|
|
1177
|
-
description: releaseBody,
|
|
1178
|
-
ref: currentBranch.trim()
|
|
1179
|
-
};
|
|
1180
|
-
logger.info(`Creating release for ${to} (ref: ${release.ref})`);
|
|
1181
|
-
logger.debug("Release details:", formatJson({
|
|
1182
|
-
tag_name: release.tag_name,
|
|
1183
|
-
name: release.name,
|
|
1184
|
-
ref: release.ref
|
|
1185
|
-
}));
|
|
1186
|
-
if (dryRun) {
|
|
1187
|
-
logger.info("[dry-run] Publish GitLab release for", release.tag_name);
|
|
1188
|
-
} else {
|
|
1189
|
-
logger.debug("Publishing release to GitLab...");
|
|
1190
|
-
await createGitlabRelease({
|
|
1191
|
-
config,
|
|
1192
|
-
release,
|
|
1193
|
-
dryRun
|
|
1194
|
-
});
|
|
1195
|
-
}
|
|
1196
|
-
logger.success(`Release ${to} published to GitLab!`);
|
|
1197
|
-
return [{
|
|
1198
|
-
name: to,
|
|
1199
|
-
tag: to,
|
|
1200
|
-
version: to,
|
|
1201
|
-
prerelease: isPrerelease(rootPackage.version)
|
|
1202
|
-
}];
|
|
1203
|
-
}
|
|
1204
|
-
async function gitlab(options = {}) {
|
|
1205
|
-
try {
|
|
1206
|
-
const dryRun = options.dryRun ?? false;
|
|
1207
|
-
logger.debug(`Dry run: ${dryRun}`);
|
|
1208
|
-
const config = await loadRelizyConfig({
|
|
1209
|
-
configName: options.configName,
|
|
1210
|
-
baseConfig: options.config,
|
|
1211
|
-
overrides: {
|
|
1212
|
-
from: options.from,
|
|
1213
|
-
to: options.to,
|
|
1214
|
-
logLevel: options.logLevel,
|
|
1215
|
-
tokens: {
|
|
1216
|
-
gitlab: options.token
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
});
|
|
1220
|
-
if (!options.bumpResult?.bumped) {
|
|
1221
|
-
logger.warn("No bump result found, skipping release");
|
|
1222
|
-
return [];
|
|
1223
|
-
}
|
|
1224
|
-
if (config.monorepo?.versionMode === "independent") {
|
|
1225
|
-
return await gitlabIndependentMode({
|
|
1226
|
-
config,
|
|
1227
|
-
dryRun,
|
|
1228
|
-
bumpedPackages: options.bumpResult.bumpedPackages
|
|
1229
|
-
});
|
|
1230
|
-
}
|
|
1231
|
-
const rootPackage = getRootPackage(process.cwd());
|
|
1232
|
-
logger.debug(`Root package: ${rootPackage.name}@${rootPackage.version}`);
|
|
1233
|
-
return await gitlabUnified({
|
|
1234
|
-
config,
|
|
1235
|
-
dryRun,
|
|
1236
|
-
rootPackage,
|
|
1237
|
-
fromTag: options.bumpResult.fromTag,
|
|
1238
|
-
oldVersion: options.bumpResult.oldVersion
|
|
1239
|
-
});
|
|
1240
|
-
} catch (error) {
|
|
1241
|
-
logger.error("Error publishing GitLab release:", error);
|
|
1242
|
-
throw error;
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
|
|
1246
|
-
function getPackageInfo(packagePath, ignorePackageNames) {
|
|
1247
|
-
const packageJsonPath = join(packagePath, "package.json");
|
|
1248
|
-
if (!existsSync(packageJsonPath))
|
|
1249
|
-
return null;
|
|
1250
|
-
if (!statSync(packagePath).isDirectory())
|
|
1251
|
-
return null;
|
|
1252
|
-
try {
|
|
1253
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
1254
|
-
if (packageJson.private) {
|
|
1255
|
-
logger.debug(`${packageJson.name} is private and will be ignored`);
|
|
1256
|
-
return null;
|
|
1257
|
-
}
|
|
1258
|
-
if (ignorePackageNames?.includes(packageJson.name)) {
|
|
1259
|
-
logger.debug(`${packageJson.name} ignored by config monorepo.ignorePackageNames`);
|
|
1260
|
-
return null;
|
|
1261
|
-
}
|
|
1262
|
-
if (!packageJson.version) {
|
|
1263
|
-
logger.warn(`${packageJson.name} has no version and will be ignored`);
|
|
1264
|
-
return null;
|
|
1265
|
-
}
|
|
1266
|
-
return {
|
|
1267
|
-
name: packageJson.name,
|
|
1268
|
-
currentVersion: packageJson.version,
|
|
1269
|
-
path: packagePath,
|
|
1270
|
-
version: packageJson.version
|
|
1271
|
-
};
|
|
1272
|
-
} catch (error) {
|
|
1273
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1274
|
-
logger.warn(`Unable to read ${packageJsonPath}:`, errorMessage);
|
|
1275
|
-
return null;
|
|
1276
|
-
}
|
|
1277
|
-
}
|
|
1278
|
-
function getPackages({
|
|
1279
|
-
cwd,
|
|
1280
|
-
patterns,
|
|
1281
|
-
ignorePackageNames
|
|
1282
|
-
}) {
|
|
1283
|
-
const packages = [];
|
|
1284
|
-
const foundPaths = /* @__PURE__ */ new Set();
|
|
1285
|
-
if (!patterns)
|
|
1286
|
-
patterns = ["."];
|
|
1287
|
-
logger.debug(`Getting packages from patterns: ${patterns.join(", ")}`);
|
|
1288
|
-
for (const pattern of patterns) {
|
|
1289
|
-
try {
|
|
1290
|
-
const matches = fastGlob.sync(pattern, {
|
|
1291
|
-
cwd,
|
|
1292
|
-
onlyDirectories: true,
|
|
1293
|
-
absolute: true,
|
|
1294
|
-
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"]
|
|
1295
|
-
});
|
|
1296
|
-
for (const matchPath of matches) {
|
|
1297
|
-
if (foundPaths.has(matchPath))
|
|
1298
|
-
continue;
|
|
1299
|
-
const packageInfo = getPackageInfo(matchPath, ignorePackageNames);
|
|
1300
|
-
if (packageInfo) {
|
|
1301
|
-
foundPaths.add(matchPath);
|
|
1302
|
-
packages.push(packageInfo);
|
|
1303
|
-
}
|
|
1304
|
-
}
|
|
1305
|
-
} catch (error) {
|
|
1306
|
-
logger.error(`Unable to match pattern "${pattern}":`, error);
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
return packages;
|
|
1310
|
-
}
|
|
1311
|
-
function isAllowedCommit({
|
|
1312
|
-
commit,
|
|
1313
|
-
type,
|
|
1314
|
-
changelog
|
|
1315
|
-
}) {
|
|
1316
|
-
if (commit.type === "chore" && ["deps", "release"].includes(commit.scope) && !commit.isBreaking) {
|
|
1317
|
-
return false;
|
|
1318
|
-
}
|
|
1319
|
-
if (typeof type === "object") {
|
|
1320
|
-
return !!type.semver || changelog && !!type.title;
|
|
1321
|
-
}
|
|
1322
|
-
if (typeof type === "boolean") {
|
|
1323
|
-
return type;
|
|
1324
|
-
}
|
|
1325
|
-
return false;
|
|
1326
|
-
}
|
|
1327
|
-
async function getPackageCommits({
|
|
1328
|
-
pkg,
|
|
1329
|
-
from,
|
|
1330
|
-
to,
|
|
1331
|
-
config,
|
|
1332
|
-
changelog
|
|
1333
|
-
}) {
|
|
1334
|
-
logger.debug(`Analyzing commits for ${pkg.name} since ${from} to ${to}`);
|
|
1335
|
-
const changelogConfig = {
|
|
1336
|
-
...config,
|
|
1337
|
-
from,
|
|
1338
|
-
to
|
|
1339
|
-
};
|
|
1340
|
-
const rawCommits = await getGitDiff(from, to, changelogConfig.cwd);
|
|
1341
|
-
const allCommits = parseCommits(rawCommits, changelogConfig);
|
|
1342
|
-
const hasBreakingChanges = allCommits.some((commit) => commit.isBreaking);
|
|
1343
|
-
logger.debug(`Has breaking changes: ${hasBreakingChanges}`);
|
|
1344
|
-
const rootPackage = getRootPackage(changelogConfig.cwd);
|
|
1345
|
-
const commits = allCommits.filter((commit) => {
|
|
1346
|
-
const type = changelogConfig?.types[commit.type];
|
|
1347
|
-
if (!isAllowedCommit({ commit, type, changelog })) {
|
|
1348
|
-
return false;
|
|
1349
|
-
}
|
|
1350
|
-
if (pkg.path === changelogConfig.cwd || pkg.name === rootPackage.name) {
|
|
1351
|
-
return true;
|
|
1352
|
-
}
|
|
1353
|
-
const packageRelativePath = pkg.path.replace(`${changelogConfig.cwd}/`, "");
|
|
1354
|
-
const scopeMatches = commit.scope === pkg.name;
|
|
1355
|
-
const bodyContainsPath = commit.body.includes(packageRelativePath);
|
|
1356
|
-
return scopeMatches || bodyContainsPath;
|
|
1357
|
-
});
|
|
1358
|
-
logger.debug(`Found ${commits.length} commit(s) for ${pkg.name} from ${from} to ${to}`);
|
|
1359
|
-
if (commits.length > 0) {
|
|
1360
|
-
logger.debug(`${pkg.name}: ${commits.length} commit(s) found`);
|
|
1361
|
-
} else {
|
|
1362
|
-
logger.debug(`${pkg.name}: No commits found`);
|
|
1363
|
-
}
|
|
1364
|
-
return commits;
|
|
1365
|
-
}
|
|
1366
|
-
function getRootPackage(rootDir) {
|
|
1367
|
-
const packageJsonPath = join(rootDir, "package.json");
|
|
1368
|
-
if (!existsSync(packageJsonPath)) {
|
|
1369
|
-
throw new Error(`package.json not found at ${packageJsonPath}`);
|
|
1370
|
-
}
|
|
1371
|
-
try {
|
|
1372
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
1373
|
-
return {
|
|
1374
|
-
name: packageJson.name,
|
|
1375
|
-
currentVersion: packageJson.version || "0.0.0",
|
|
1376
|
-
path: rootDir,
|
|
1377
|
-
version: packageJson.version || "0.0.0"
|
|
1378
|
-
};
|
|
1379
|
-
} catch (error) {
|
|
1380
|
-
throw new Error(`Unable to read ${packageJsonPath}: ${error}`);
|
|
1133
|
+
logger.debug(`Creating release for ${to} (ref: ${release.ref})`);
|
|
1134
|
+
if (dryRun) {
|
|
1135
|
+
logger.info(`[dry-run] Publish GitLab release for ${to}`);
|
|
1136
|
+
} else {
|
|
1137
|
+
logger.debug(`Publishing release ${to} to GitLab...`);
|
|
1138
|
+
await createGitlabRelease({
|
|
1139
|
+
config,
|
|
1140
|
+
release,
|
|
1141
|
+
dryRun
|
|
1142
|
+
});
|
|
1143
|
+
postedReleases.push({
|
|
1144
|
+
name: pkg.name,
|
|
1145
|
+
tag: release.tag_name,
|
|
1146
|
+
version: newVersion,
|
|
1147
|
+
prerelease: isPrerelease(newVersion)
|
|
1148
|
+
});
|
|
1149
|
+
}
|
|
1381
1150
|
}
|
|
1151
|
+
if (postedReleases.length === 0) {
|
|
1152
|
+
logger.warn("No releases created");
|
|
1153
|
+
} else {
|
|
1154
|
+
logger.success(`Releases ${postedReleases.map((r) => r.tag).join(", ")} published to GitLab!`);
|
|
1155
|
+
}
|
|
1156
|
+
return postedReleases;
|
|
1382
1157
|
}
|
|
1383
|
-
function
|
|
1384
|
-
const lernaJsonPath = join(rootDir, "lerna.json");
|
|
1385
|
-
return existsSync(lernaJsonPath);
|
|
1386
|
-
}
|
|
1387
|
-
async function getPackageToBump({
|
|
1388
|
-
packages,
|
|
1158
|
+
async function gitlabUnified({
|
|
1389
1159
|
config,
|
|
1390
|
-
|
|
1391
|
-
|
|
1160
|
+
dryRun,
|
|
1161
|
+
rootPackage,
|
|
1162
|
+
bumpResult
|
|
1392
1163
|
}) {
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1164
|
+
logger.debug(`GitLab token: ${config.tokens.gitlab || config.repo?.token ? "\u2713 provided" : "\u2717 missing"}`);
|
|
1165
|
+
const to = config.templates.tagBody.replace("{{newVersion}}", rootPackage.newVersion || rootPackage.version);
|
|
1166
|
+
const changelog = await generateChangelog({
|
|
1167
|
+
pkg: rootPackage,
|
|
1168
|
+
config,
|
|
1169
|
+
dryRun,
|
|
1170
|
+
newVersion: bumpResult?.newVersion || rootPackage.version
|
|
1171
|
+
});
|
|
1172
|
+
const releaseBody = changelog.split("\n").slice(2).join("\n");
|
|
1173
|
+
logger.debug("Getting current branch...");
|
|
1174
|
+
const { stdout: currentBranch } = await execPromise("git rev-parse --abbrev-ref HEAD", {
|
|
1175
|
+
noSuccess: true,
|
|
1176
|
+
noStdout: true,
|
|
1177
|
+
logLevel: config.logLevel,
|
|
1178
|
+
cwd: config.cwd
|
|
1179
|
+
});
|
|
1180
|
+
const release = {
|
|
1181
|
+
tag_name: to,
|
|
1182
|
+
name: to,
|
|
1183
|
+
description: releaseBody,
|
|
1184
|
+
ref: currentBranch.trim()
|
|
1185
|
+
};
|
|
1186
|
+
logger.info(`Creating release for ${to} (ref: ${release.ref})`);
|
|
1187
|
+
logger.debug("Release details:", formatJson({
|
|
1188
|
+
tag_name: release.tag_name,
|
|
1189
|
+
name: release.name,
|
|
1190
|
+
ref: release.ref
|
|
1191
|
+
}));
|
|
1192
|
+
if (dryRun) {
|
|
1193
|
+
logger.info("[dry-run] Publish GitLab release for", release.tag_name);
|
|
1194
|
+
} else {
|
|
1195
|
+
logger.debug("Publishing release to GitLab...");
|
|
1196
|
+
await createGitlabRelease({
|
|
1399
1197
|
config,
|
|
1400
|
-
|
|
1198
|
+
release,
|
|
1199
|
+
dryRun
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
logger.success(`Release ${to} published to GitLab!`);
|
|
1203
|
+
return [{
|
|
1204
|
+
name: to,
|
|
1205
|
+
tag: to,
|
|
1206
|
+
version: to,
|
|
1207
|
+
prerelease: isPrerelease(rootPackage.version)
|
|
1208
|
+
}];
|
|
1209
|
+
}
|
|
1210
|
+
async function gitlab(options = {}) {
|
|
1211
|
+
try {
|
|
1212
|
+
const dryRun = options.dryRun ?? false;
|
|
1213
|
+
logger.debug(`Dry run: ${dryRun}`);
|
|
1214
|
+
const config = await loadRelizyConfig({
|
|
1215
|
+
configName: options.configName,
|
|
1216
|
+
baseConfig: options.config,
|
|
1217
|
+
overrides: {
|
|
1218
|
+
from: options.from,
|
|
1219
|
+
to: options.to,
|
|
1220
|
+
logLevel: options.logLevel,
|
|
1221
|
+
tokens: {
|
|
1222
|
+
gitlab: options.token
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1401
1225
|
});
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1226
|
+
if (config.monorepo?.versionMode === "independent") {
|
|
1227
|
+
return await gitlabIndependentMode({
|
|
1228
|
+
config,
|
|
1229
|
+
dryRun,
|
|
1230
|
+
bumpResult: options.bumpResult,
|
|
1231
|
+
suffix: options.suffix,
|
|
1232
|
+
force: options.force ?? false
|
|
1233
|
+
});
|
|
1405
1234
|
}
|
|
1235
|
+
const rootPackageBase = readPackageJson(config.cwd);
|
|
1236
|
+
const { from, to } = await resolveTags({
|
|
1237
|
+
config,
|
|
1238
|
+
step: "provider-release",
|
|
1239
|
+
newVersion: options.bumpResult?.newVersion || rootPackageBase.version,
|
|
1240
|
+
pkg: rootPackageBase
|
|
1241
|
+
});
|
|
1242
|
+
const rootPackage = options.bumpResult?.rootPackage || await getRootPackage({
|
|
1243
|
+
config,
|
|
1244
|
+
force: options.force ?? false,
|
|
1245
|
+
suffix: options.suffix,
|
|
1246
|
+
changelog: true,
|
|
1247
|
+
from,
|
|
1248
|
+
to
|
|
1249
|
+
});
|
|
1250
|
+
logger.debug(`Root package: ${getIndependentTag(rootPackage)}`);
|
|
1251
|
+
return await gitlabUnified({
|
|
1252
|
+
config,
|
|
1253
|
+
dryRun,
|
|
1254
|
+
rootPackage,
|
|
1255
|
+
bumpResult: options.bumpResult
|
|
1256
|
+
});
|
|
1257
|
+
} catch (error) {
|
|
1258
|
+
logger.error("Error publishing GitLab release:", error);
|
|
1259
|
+
throw error;
|
|
1406
1260
|
}
|
|
1407
|
-
const allPackagesToBump = expandPackagesToBumpWithDependents({
|
|
1408
|
-
allPackages: packages,
|
|
1409
|
-
packagesWithCommits,
|
|
1410
|
-
dependencyTypes: config.bump?.dependencyTypes
|
|
1411
|
-
});
|
|
1412
|
-
return allPackagesToBump;
|
|
1413
1261
|
}
|
|
1414
1262
|
|
|
1415
|
-
function
|
|
1416
|
-
|
|
1263
|
+
function determineSemverChange(commits, types) {
|
|
1264
|
+
let [hasMajor, hasMinor, hasPatch] = [false, false, false];
|
|
1265
|
+
for (const commit of commits) {
|
|
1266
|
+
const commitType = types[commit.type];
|
|
1267
|
+
if (!commitType) {
|
|
1268
|
+
continue;
|
|
1269
|
+
}
|
|
1270
|
+
const semverType = commitType.semver;
|
|
1271
|
+
if (semverType === "major" || commit.isBreaking) {
|
|
1272
|
+
hasMajor = true;
|
|
1273
|
+
} else if (semverType === "minor") {
|
|
1274
|
+
hasMinor = true;
|
|
1275
|
+
} else if (semverType === "patch") {
|
|
1276
|
+
hasPatch = true;
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
return hasMajor ? "major" : hasMinor ? "minor" : hasPatch ? "patch" : void 0;
|
|
1280
|
+
}
|
|
1281
|
+
function detectReleaseTypeFromCommits(commits, types) {
|
|
1282
|
+
return determineSemverChange(commits, types);
|
|
1417
1283
|
}
|
|
1418
1284
|
function validatePrereleaseDowngrade(currentVersion, targetPreid, configuredType) {
|
|
1419
1285
|
if (configuredType !== "prerelease" || !targetPreid || !isPrerelease(currentVersion)) {
|
|
1420
1286
|
return;
|
|
1421
1287
|
}
|
|
1422
1288
|
const testVersion = semver.inc(currentVersion, "prerelease", targetPreid);
|
|
1423
|
-
|
|
1289
|
+
const isNotUpgrade = testVersion && !semver.gt(testVersion, currentVersion);
|
|
1290
|
+
if (isNotUpgrade) {
|
|
1424
1291
|
throw new Error(`Unable to graduate from ${currentVersion} to ${testVersion}, it's not a valid prerelease`);
|
|
1425
1292
|
}
|
|
1426
1293
|
}
|
|
1427
|
-
function handleStableVersionWithReleaseType(commits,
|
|
1294
|
+
function handleStableVersionWithReleaseType(commits, types, force) {
|
|
1428
1295
|
if (!commits?.length && !force) {
|
|
1429
1296
|
logger.debug('No commits found for stable version with "release" type, skipping bump');
|
|
1430
|
-
return
|
|
1297
|
+
return void 0;
|
|
1431
1298
|
}
|
|
1432
|
-
const detectedType = commits?.length ? detectReleaseTypeFromCommits(commits,
|
|
1299
|
+
const detectedType = commits?.length ? detectReleaseTypeFromCommits(commits, types) : void 0;
|
|
1433
1300
|
if (!detectedType && !force) {
|
|
1434
1301
|
logger.debug("No significant commits found, skipping bump");
|
|
1435
|
-
return
|
|
1302
|
+
return void 0;
|
|
1436
1303
|
}
|
|
1437
1304
|
logger.debug(`Auto-detected release type from commits: ${detectedType}`);
|
|
1438
1305
|
return detectedType;
|
|
1439
1306
|
}
|
|
1440
|
-
function handleStableVersionWithPrereleaseType(commits,
|
|
1307
|
+
function handleStableVersionWithPrereleaseType(commits, types, force) {
|
|
1441
1308
|
if (!commits?.length && !force) {
|
|
1442
1309
|
logger.debug('No commits found for stable version with "prerelease" type, skipping bump');
|
|
1443
|
-
return
|
|
1310
|
+
return void 0;
|
|
1444
1311
|
}
|
|
1445
|
-
const detectedType = commits?.length ? detectReleaseTypeFromCommits(commits,
|
|
1312
|
+
const detectedType = commits?.length ? detectReleaseTypeFromCommits(commits, types) : void 0;
|
|
1446
1313
|
if (!detectedType) {
|
|
1447
1314
|
logger.debug("No significant commits found, using prepatch as default");
|
|
1448
1315
|
return "prepatch";
|
|
@@ -1455,83 +1322,73 @@ function handlePrereleaseVersionToStable(currentVersion) {
|
|
|
1455
1322
|
logger.debug(`Graduating from prerelease ${currentVersion} to stable release`);
|
|
1456
1323
|
return "release";
|
|
1457
1324
|
}
|
|
1458
|
-
function handlePrereleaseVersionWithPrereleaseType(currentVersion,
|
|
1325
|
+
function handlePrereleaseVersionWithPrereleaseType({ currentVersion, preid, commits, force }) {
|
|
1459
1326
|
const currentPreid = getPreid(currentVersion);
|
|
1460
|
-
const hasChangedPreid =
|
|
1327
|
+
const hasChangedPreid = preid && currentPreid && currentPreid !== preid;
|
|
1461
1328
|
if (hasChangedPreid) {
|
|
1462
|
-
const testVersion = semver.inc(currentVersion, "prerelease",
|
|
1329
|
+
const testVersion = semver.inc(currentVersion, "prerelease", preid);
|
|
1463
1330
|
if (!testVersion) {
|
|
1464
|
-
throw new Error(`Unable to change preid from ${currentPreid} to ${
|
|
1331
|
+
throw new Error(`Unable to change preid from ${currentPreid} to ${preid} for version ${currentVersion}`);
|
|
1465
1332
|
}
|
|
1466
1333
|
const isUpgrade = semver.gt(testVersion, currentVersion);
|
|
1467
1334
|
if (!isUpgrade) {
|
|
1468
|
-
throw new Error(`Unable to change preid from ${currentVersion} to ${testVersion}, it's not a valid upgrade (cannot downgrade from ${currentPreid} to ${
|
|
1335
|
+
throw new Error(`Unable to change preid from ${currentVersion} to ${testVersion}, it's not a valid upgrade (cannot downgrade from ${currentPreid} to ${preid})`);
|
|
1469
1336
|
}
|
|
1470
1337
|
return "prerelease";
|
|
1471
1338
|
}
|
|
1472
1339
|
if (!commits?.length && !force) {
|
|
1473
1340
|
logger.debug("No commits found for prerelease version, skipping bump");
|
|
1474
|
-
return
|
|
1341
|
+
return void 0;
|
|
1475
1342
|
}
|
|
1476
1343
|
logger.debug(`Incrementing prerelease version: ${currentVersion}`);
|
|
1477
1344
|
return "prerelease";
|
|
1478
1345
|
}
|
|
1479
|
-
function handleExplicitReleaseType(
|
|
1346
|
+
function handleExplicitReleaseType({
|
|
1347
|
+
releaseType,
|
|
1348
|
+
currentVersion
|
|
1349
|
+
}) {
|
|
1480
1350
|
const isCurrentPrerelease = isPrerelease(currentVersion);
|
|
1481
|
-
const isGraduatingToStable = isCurrentPrerelease && isStableReleaseType(
|
|
1351
|
+
const isGraduatingToStable = isCurrentPrerelease && isStableReleaseType(releaseType);
|
|
1482
1352
|
if (isGraduatingToStable) {
|
|
1483
|
-
logger.debug(`Graduating from prerelease ${currentVersion} to stable with type: ${
|
|
1353
|
+
logger.debug(`Graduating from prerelease ${currentVersion} to stable with type: ${releaseType}`);
|
|
1484
1354
|
} else {
|
|
1485
|
-
logger.debug(`Using explicit release type: ${
|
|
1355
|
+
logger.debug(`Using explicit release type: ${releaseType}`);
|
|
1486
1356
|
}
|
|
1487
|
-
return
|
|
1357
|
+
return releaseType;
|
|
1488
1358
|
}
|
|
1489
1359
|
function determineReleaseType({
|
|
1490
1360
|
currentVersion,
|
|
1491
|
-
from,
|
|
1492
|
-
to,
|
|
1493
1361
|
commits,
|
|
1494
|
-
|
|
1362
|
+
releaseType,
|
|
1363
|
+
preid,
|
|
1364
|
+
types,
|
|
1495
1365
|
force
|
|
1496
1366
|
}) {
|
|
1497
|
-
|
|
1498
|
-
...config,
|
|
1499
|
-
from,
|
|
1500
|
-
to
|
|
1501
|
-
};
|
|
1502
|
-
const configuredType = configWithRange.bump.type;
|
|
1503
|
-
const targetPreid = configWithRange.bump.preid;
|
|
1504
|
-
if (configuredType === "release" && targetPreid) {
|
|
1367
|
+
if (releaseType === "release" && preid) {
|
|
1505
1368
|
throw new Error('You cannot use a "release" type with a "preid", to use a preid you must use a "prerelease" type');
|
|
1506
1369
|
}
|
|
1507
|
-
validatePrereleaseDowngrade(currentVersion,
|
|
1370
|
+
validatePrereleaseDowngrade(currentVersion, preid, releaseType);
|
|
1508
1371
|
if (force) {
|
|
1509
|
-
logger.debug(`Force flag enabled, using configured type: ${
|
|
1510
|
-
return
|
|
1372
|
+
logger.debug(`Force flag enabled, using configured type: ${releaseType}`);
|
|
1373
|
+
return releaseType;
|
|
1511
1374
|
}
|
|
1512
1375
|
const isCurrentPrerelease = isPrerelease(currentVersion);
|
|
1513
1376
|
if (!isCurrentPrerelease) {
|
|
1514
|
-
if (
|
|
1515
|
-
return handleStableVersionWithReleaseType(commits,
|
|
1377
|
+
if (releaseType === "release") {
|
|
1378
|
+
return handleStableVersionWithReleaseType(commits, types, force);
|
|
1516
1379
|
}
|
|
1517
|
-
if (
|
|
1518
|
-
return handleStableVersionWithPrereleaseType(commits,
|
|
1380
|
+
if (releaseType === "prerelease") {
|
|
1381
|
+
return handleStableVersionWithPrereleaseType(commits, types, force);
|
|
1519
1382
|
}
|
|
1520
|
-
return handleExplicitReleaseType(
|
|
1383
|
+
return handleExplicitReleaseType({ releaseType, currentVersion });
|
|
1521
1384
|
}
|
|
1522
|
-
if (
|
|
1385
|
+
if (releaseType === "release") {
|
|
1523
1386
|
return handlePrereleaseVersionToStable(currentVersion);
|
|
1524
1387
|
}
|
|
1525
|
-
if (
|
|
1526
|
-
return handlePrereleaseVersionWithPrereleaseType(
|
|
1527
|
-
currentVersion,
|
|
1528
|
-
targetPreid,
|
|
1529
|
-
commits,
|
|
1530
|
-
configWithRange,
|
|
1531
|
-
force
|
|
1532
|
-
);
|
|
1388
|
+
if (releaseType === "prerelease") {
|
|
1389
|
+
return handlePrereleaseVersionWithPrereleaseType({ currentVersion, preid, commits, force });
|
|
1533
1390
|
}
|
|
1534
|
-
return handleExplicitReleaseType(
|
|
1391
|
+
return handleExplicitReleaseType({ releaseType, currentVersion });
|
|
1535
1392
|
}
|
|
1536
1393
|
function writeVersion(pkgPath, version, dryRun = false) {
|
|
1537
1394
|
const packageJsonPath = join(pkgPath, "package.json");
|
|
@@ -1552,33 +1409,32 @@ function writeVersion(pkgPath, version, dryRun = false) {
|
|
|
1552
1409
|
throw new Error(`Unable to write version to ${packageJsonPath}: ${error}`);
|
|
1553
1410
|
}
|
|
1554
1411
|
}
|
|
1555
|
-
function
|
|
1412
|
+
function getPackageNewVersion({
|
|
1556
1413
|
currentVersion,
|
|
1557
1414
|
releaseType,
|
|
1558
1415
|
preid,
|
|
1559
1416
|
suffix
|
|
1560
1417
|
}) {
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
throw new Error(`Unable to bump version "${currentVersion}" with release type "${releaseType}"
|
|
1418
|
+
let newVersion = semver.inc(currentVersion, releaseType, preid);
|
|
1419
|
+
if (!newVersion) {
|
|
1420
|
+
throw new Error(`Unable to bump version "${currentVersion}" with release type "${releaseType}"
|
|
1565
1421
|
|
|
1566
1422
|
You should use an explicit release type (use flag: --major, --minor, --patch, --premajor, --preminor, --prepatch, --prerelease)`);
|
|
1567
|
-
}
|
|
1568
|
-
if (isPrereleaseReleaseType(releaseType) && suffix) {
|
|
1569
|
-
newVersion = newVersion.replace(/\.(\d+)$/, `.${suffix}`);
|
|
1570
|
-
}
|
|
1571
|
-
const isValidVersion = semver.gt(newVersion, currentVersion);
|
|
1572
|
-
if (!isValidVersion) {
|
|
1573
|
-
throw new Error(`Unable to bump version "${currentVersion}" to "${newVersion}", new version is not greater than current version`);
|
|
1574
|
-
}
|
|
1575
|
-
if (isGraduating(currentVersion, releaseType)) {
|
|
1576
|
-
logger.info(`Graduating from prerelease ${currentVersion} to stable ${newVersion}`);
|
|
1577
|
-
}
|
|
1578
|
-
return newVersion;
|
|
1579
|
-
} catch (error) {
|
|
1580
|
-
throw new Error(`Unable to bump version: ${error}`);
|
|
1581
1423
|
}
|
|
1424
|
+
if (isPrereleaseReleaseType(releaseType) && suffix) {
|
|
1425
|
+
newVersion = newVersion.replace(/\.(\d+)$/, `.${suffix}`);
|
|
1426
|
+
}
|
|
1427
|
+
const isValidVersion = semver.gt(newVersion, currentVersion);
|
|
1428
|
+
if (!isValidVersion) {
|
|
1429
|
+
throw new Error(`Unable to bump version "${currentVersion}" to "${newVersion}", new version is not greater than current version`);
|
|
1430
|
+
}
|
|
1431
|
+
if (isGraduating(currentVersion, releaseType)) {
|
|
1432
|
+
logger.info(`Graduating from prerelease ${currentVersion} to stable ${newVersion}`);
|
|
1433
|
+
}
|
|
1434
|
+
if (isChangedPreid(currentVersion, preid)) {
|
|
1435
|
+
logger.info(`Graduating from ${getPreid(currentVersion)} to ${preid}`);
|
|
1436
|
+
}
|
|
1437
|
+
return newVersion;
|
|
1582
1438
|
}
|
|
1583
1439
|
function updateLernaVersion({
|
|
1584
1440
|
rootDir,
|
|
@@ -1612,7 +1468,7 @@ function updateLernaVersion({
|
|
|
1612
1468
|
`, "utf8");
|
|
1613
1469
|
logger.success(`Updated lerna.json: ${oldVersion} \u2192 ${version}`);
|
|
1614
1470
|
} catch (error) {
|
|
1615
|
-
logger.
|
|
1471
|
+
logger.fail(`Unable to update lerna.json: ${error}`);
|
|
1616
1472
|
}
|
|
1617
1473
|
}
|
|
1618
1474
|
function extractVersionFromPackageTag(tag) {
|
|
@@ -1658,13 +1514,16 @@ function isChangedPreid(currentVersion, targetPreid) {
|
|
|
1658
1514
|
}
|
|
1659
1515
|
return currentPreid !== targetPreid;
|
|
1660
1516
|
}
|
|
1661
|
-
function
|
|
1517
|
+
function getBumpedPackageIndependently({
|
|
1662
1518
|
pkg,
|
|
1663
1519
|
dryRun
|
|
1664
1520
|
}) {
|
|
1665
1521
|
logger.debug(`Analyzing ${pkg.name}`);
|
|
1666
1522
|
const currentVersion = pkg.version || "0.0.0";
|
|
1667
|
-
const newVersion = pkg.
|
|
1523
|
+
const newVersion = pkg.newVersion;
|
|
1524
|
+
if (!newVersion) {
|
|
1525
|
+
return { bumped: false };
|
|
1526
|
+
}
|
|
1668
1527
|
logger.debug(`Bumping ${pkg.name} from ${currentVersion} to ${newVersion}`);
|
|
1669
1528
|
writeVersion(pkg.path, newVersion, dryRun);
|
|
1670
1529
|
return { bumped: true, newVersion, oldVersion: currentVersion };
|
|
@@ -1690,9 +1549,9 @@ function displayUnifiedModePackages({
|
|
|
1690
1549
|
newVersion,
|
|
1691
1550
|
force
|
|
1692
1551
|
}) {
|
|
1693
|
-
logger.log(`${packages.length} package(s)
|
|
1552
|
+
logger.log(`${packages.length} package(s):`);
|
|
1694
1553
|
packages.forEach((pkg) => {
|
|
1695
|
-
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion}`);
|
|
1554
|
+
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion} ${force ? "(force)" : ""}`);
|
|
1696
1555
|
});
|
|
1697
1556
|
logger.log("");
|
|
1698
1557
|
}
|
|
@@ -1702,14 +1561,15 @@ function displaySelectiveModePackages({
|
|
|
1702
1561
|
force
|
|
1703
1562
|
}) {
|
|
1704
1563
|
if (force) {
|
|
1705
|
-
logger.log(`${packages.length} package(s)
|
|
1564
|
+
logger.log(`${packages.length} package(s):`);
|
|
1706
1565
|
packages.forEach((pkg) => {
|
|
1707
|
-
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion}`);
|
|
1566
|
+
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion} (force)`);
|
|
1708
1567
|
});
|
|
1709
1568
|
logger.log("");
|
|
1710
1569
|
} else {
|
|
1711
1570
|
const packagesWithCommits = packages.filter((p) => "reason" in p && p.reason === "commits");
|
|
1712
1571
|
const packagesAsDependents = packages.filter((p) => "reason" in p && p.reason === "dependency");
|
|
1572
|
+
const packagesAsGraduation = packages.filter((p) => "reason" in p && p.reason === "graduation");
|
|
1713
1573
|
if (packagesWithCommits.length > 0) {
|
|
1714
1574
|
logger.log(`${packagesWithCommits.length} package(s) with commits:`);
|
|
1715
1575
|
packagesWithCommits.forEach((pkg) => {
|
|
@@ -1724,33 +1584,47 @@ function displaySelectiveModePackages({
|
|
|
1724
1584
|
});
|
|
1725
1585
|
logger.log("");
|
|
1726
1586
|
}
|
|
1587
|
+
if (packagesAsGraduation.length > 0) {
|
|
1588
|
+
logger.log(`${packagesAsGraduation.length} graduation package(s):`);
|
|
1589
|
+
packagesAsGraduation.forEach((pkg) => {
|
|
1590
|
+
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion}`);
|
|
1591
|
+
});
|
|
1592
|
+
logger.log("");
|
|
1593
|
+
}
|
|
1727
1594
|
}
|
|
1728
1595
|
}
|
|
1729
1596
|
function displayIndependentModePackages({
|
|
1730
1597
|
packages,
|
|
1731
|
-
force
|
|
1732
|
-
dryRun
|
|
1598
|
+
force
|
|
1733
1599
|
}) {
|
|
1734
1600
|
if (force) {
|
|
1735
|
-
logger.log(`${
|
|
1601
|
+
logger.log(`${packages.length} package(s):`);
|
|
1736
1602
|
packages.forEach((pkg) => {
|
|
1737
|
-
logger.log(` \u2022 ${pkg.name}: ${pkg.
|
|
1603
|
+
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion} (force)`);
|
|
1738
1604
|
});
|
|
1739
1605
|
logger.log("");
|
|
1740
1606
|
} else {
|
|
1741
1607
|
const packagesWithCommits = packages.filter((p) => "reason" in p && p.reason === "commits");
|
|
1742
1608
|
const packagesAsDependents = packages.filter((p) => "reason" in p && p.reason === "dependency");
|
|
1609
|
+
const packagesAsGraduation = packages.filter((p) => "reason" in p && p.reason === "graduation");
|
|
1743
1610
|
if (packagesWithCommits.length > 0) {
|
|
1744
|
-
logger.log(`${
|
|
1611
|
+
logger.log(`${packagesWithCommits.length} package(s) with commits:`);
|
|
1745
1612
|
packagesWithCommits.forEach((pkg) => {
|
|
1746
|
-
logger.log(` \u2022 ${pkg.name}: ${pkg.
|
|
1613
|
+
pkg.newVersion && logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion}`);
|
|
1747
1614
|
});
|
|
1748
1615
|
logger.log("");
|
|
1749
1616
|
}
|
|
1750
1617
|
if (packagesAsDependents.length > 0) {
|
|
1751
|
-
logger.log(`${
|
|
1618
|
+
logger.log(`${packagesAsDependents.length} dependent package(s):`);
|
|
1752
1619
|
packagesAsDependents.forEach((pkg) => {
|
|
1753
|
-
logger.log(` \u2022 ${pkg.name}: ${pkg.
|
|
1620
|
+
pkg.newVersion && logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion}`);
|
|
1621
|
+
});
|
|
1622
|
+
logger.log("");
|
|
1623
|
+
}
|
|
1624
|
+
if (packagesAsGraduation.length > 0) {
|
|
1625
|
+
logger.log(`${packagesAsGraduation.length} graduation package(s):`);
|
|
1626
|
+
packagesAsGraduation.forEach((pkg) => {
|
|
1627
|
+
pkg.newVersion && logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion}`);
|
|
1754
1628
|
});
|
|
1755
1629
|
logger.log("");
|
|
1756
1630
|
}
|
|
@@ -1765,6 +1639,10 @@ async function confirmBump({
|
|
|
1765
1639
|
newVersion,
|
|
1766
1640
|
dryRun
|
|
1767
1641
|
}) {
|
|
1642
|
+
if (packages.length === 0) {
|
|
1643
|
+
logger.debug("No packages to bump");
|
|
1644
|
+
return;
|
|
1645
|
+
}
|
|
1768
1646
|
const lernaJsonExists = hasLernaJson(config.cwd);
|
|
1769
1647
|
logger.log("");
|
|
1770
1648
|
logger.info(`${dryRun ? "[dry-run] " : ""}The following packages will be updated:
|
|
@@ -1776,220 +1654,100 @@ async function confirmBump({
|
|
|
1776
1654
|
lernaJsonExists,
|
|
1777
1655
|
dryRun
|
|
1778
1656
|
});
|
|
1779
|
-
if (versionMode === "unified"
|
|
1657
|
+
if (versionMode === "unified") {
|
|
1658
|
+
if (!newVersion) {
|
|
1659
|
+
logger.error("Cannot confirm bump in unified mode without a new version");
|
|
1660
|
+
process.exit(1);
|
|
1661
|
+
}
|
|
1780
1662
|
displayUnifiedModePackages({ packages, newVersion, force });
|
|
1781
|
-
} else if (versionMode === "selective"
|
|
1663
|
+
} else if (versionMode === "selective") {
|
|
1664
|
+
if (!newVersion) {
|
|
1665
|
+
logger.error("Cannot confirm bump in selective mode without a new version");
|
|
1666
|
+
process.exit(1);
|
|
1667
|
+
}
|
|
1782
1668
|
displaySelectiveModePackages({ packages, newVersion, force });
|
|
1783
1669
|
} else if (versionMode === "independent") {
|
|
1784
|
-
displayIndependentModePackages({ packages, force
|
|
1670
|
+
displayIndependentModePackages({ packages, force });
|
|
1785
1671
|
}
|
|
1786
1672
|
try {
|
|
1787
1673
|
const confirmed = await confirm({
|
|
1788
1674
|
message: `${dryRun ? "[dry-run] " : ""}Do you want to proceed with these version updates?`,
|
|
1789
1675
|
default: true
|
|
1790
1676
|
});
|
|
1791
|
-
if (!confirmed) {
|
|
1792
|
-
logger.
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
}) {
|
|
1806
|
-
const packagesWithCommits = [];
|
|
1807
|
-
logger.debug(`Checking for commits in ${packages.length} package(s)`);
|
|
1808
|
-
for (const pkg of packages) {
|
|
1809
|
-
const { from, to } = await resolveTags({
|
|
1810
|
-
config,
|
|
1811
|
-
versionMode: "independent",
|
|
1812
|
-
step: "bump",
|
|
1813
|
-
currentVersion: pkg.version,
|
|
1814
|
-
newVersion: void 0,
|
|
1815
|
-
pkg,
|
|
1816
|
-
logLevel: config.logLevel
|
|
1817
|
-
});
|
|
1818
|
-
const commits = await getPackageCommits({
|
|
1819
|
-
pkg,
|
|
1820
|
-
from,
|
|
1821
|
-
to,
|
|
1822
|
-
config,
|
|
1823
|
-
changelog: false
|
|
1824
|
-
});
|
|
1825
|
-
if (commits.length <= 0 && !force) {
|
|
1826
|
-
logger.debug(`${pkg.name}: No commits found, skipping`);
|
|
1827
|
-
continue;
|
|
1828
|
-
}
|
|
1829
|
-
packagesWithCommits.push({ ...pkg, commits });
|
|
1830
|
-
logger.debug(`${pkg.name}: ${commits.length} commit(s)`);
|
|
1831
|
-
}
|
|
1832
|
-
return packagesWithCommits;
|
|
1833
|
-
}
|
|
1834
|
-
async function calculatePackageNewVersion({
|
|
1835
|
-
pkg,
|
|
1836
|
-
config,
|
|
1837
|
-
force,
|
|
1838
|
-
suffix
|
|
1839
|
-
}) {
|
|
1840
|
-
const releaseType = config.bump.type;
|
|
1841
|
-
const { from, to } = await resolveTags({
|
|
1842
|
-
config,
|
|
1843
|
-
versionMode: "independent",
|
|
1844
|
-
step: "bump",
|
|
1845
|
-
currentVersion: pkg.version,
|
|
1846
|
-
newVersion: void 0,
|
|
1847
|
-
pkg,
|
|
1848
|
-
logLevel: config.logLevel
|
|
1849
|
-
});
|
|
1850
|
-
const forcedBump = pkg.reason === "dependency";
|
|
1851
|
-
let forcedBumpType;
|
|
1852
|
-
if (forcedBump) {
|
|
1853
|
-
if (isStableReleaseType(releaseType)) {
|
|
1854
|
-
forcedBumpType = "patch";
|
|
1855
|
-
} else {
|
|
1856
|
-
forcedBumpType = isPrerelease(pkg.version) ? "prerelease" : "prepatch";
|
|
1857
|
-
}
|
|
1858
|
-
}
|
|
1859
|
-
const commits = pkg.commits?.length > 0 ? pkg.commits : await getPackageCommits({
|
|
1860
|
-
pkg,
|
|
1861
|
-
from,
|
|
1862
|
-
to,
|
|
1863
|
-
config,
|
|
1864
|
-
changelog: false
|
|
1865
|
-
});
|
|
1866
|
-
let calculatedReleaseType = null;
|
|
1867
|
-
if (forcedBumpType) {
|
|
1868
|
-
calculatedReleaseType = forcedBumpType;
|
|
1869
|
-
} else if (commits.length === 0 && !force) {
|
|
1870
|
-
return null;
|
|
1871
|
-
} else {
|
|
1872
|
-
calculatedReleaseType = determineReleaseType({ from, to, commits, config, force, currentVersion: pkg.version });
|
|
1873
|
-
if (!calculatedReleaseType) {
|
|
1874
|
-
return null;
|
|
1875
|
-
}
|
|
1876
|
-
}
|
|
1877
|
-
const currentVersion = pkg.version || "0.0.0";
|
|
1878
|
-
const newVersion = bumpPackageVersion({
|
|
1879
|
-
currentVersion,
|
|
1880
|
-
releaseType: calculatedReleaseType,
|
|
1881
|
-
preid: config.bump.preid,
|
|
1882
|
-
suffix
|
|
1883
|
-
});
|
|
1884
|
-
return {
|
|
1885
|
-
name: pkg.name,
|
|
1886
|
-
path: pkg.path,
|
|
1887
|
-
currentVersion,
|
|
1888
|
-
version: newVersion,
|
|
1889
|
-
fromTag: from,
|
|
1890
|
-
reason: pkg.reason,
|
|
1891
|
-
commits,
|
|
1892
|
-
dependencyChain: pkg.dependencyChain
|
|
1893
|
-
};
|
|
1894
|
-
}
|
|
1895
|
-
async function calculateNewVersionsForPackages({
|
|
1896
|
-
allPackagesToBump,
|
|
1897
|
-
config,
|
|
1898
|
-
force,
|
|
1899
|
-
suffix
|
|
1900
|
-
}) {
|
|
1901
|
-
const packagesWithNewVersions = [];
|
|
1902
|
-
for (const pkgToBump of allPackagesToBump) {
|
|
1903
|
-
const packageWithNewVersion = await calculatePackageNewVersion({
|
|
1904
|
-
pkg: pkgToBump,
|
|
1905
|
-
config,
|
|
1906
|
-
force,
|
|
1907
|
-
suffix
|
|
1908
|
-
});
|
|
1909
|
-
if (packageWithNewVersion) {
|
|
1910
|
-
packagesWithNewVersions.push(packageWithNewVersion);
|
|
1911
|
-
}
|
|
1912
|
-
}
|
|
1913
|
-
return packagesWithNewVersions;
|
|
1914
|
-
}
|
|
1915
|
-
async function findPackagesWithCommitsAndCalculateVersions({
|
|
1916
|
-
packages,
|
|
1917
|
-
config,
|
|
1918
|
-
force,
|
|
1919
|
-
suffix
|
|
1920
|
-
}) {
|
|
1921
|
-
const packagesWithCommits = await findPackagesWithCommits({
|
|
1922
|
-
packages,
|
|
1923
|
-
config,
|
|
1924
|
-
force
|
|
1925
|
-
});
|
|
1926
|
-
if (packagesWithCommits.length === 0) {
|
|
1927
|
-
return [];
|
|
1677
|
+
if (!confirmed) {
|
|
1678
|
+
logger.log("");
|
|
1679
|
+
logger.fail("Bump refused");
|
|
1680
|
+
process.exit(0);
|
|
1681
|
+
}
|
|
1682
|
+
} catch (error) {
|
|
1683
|
+
const userHasExited = error instanceof Error && error.name === "ExitPromptError";
|
|
1684
|
+
if (userHasExited) {
|
|
1685
|
+
logger.log("");
|
|
1686
|
+
logger.fail("Bump cancelled");
|
|
1687
|
+
process.exit(0);
|
|
1688
|
+
}
|
|
1689
|
+
logger.fail("Error while confirming bump");
|
|
1690
|
+
process.exit(1);
|
|
1928
1691
|
}
|
|
1929
|
-
|
|
1930
|
-
allPackages: packages,
|
|
1931
|
-
packagesWithCommits,
|
|
1932
|
-
dependencyTypes: config.bump.dependencyTypes
|
|
1933
|
-
});
|
|
1934
|
-
logger.debug(`Total packages to bump (including dependents): ${allPackagesToBump.length}`);
|
|
1935
|
-
const packagesWithNewVersions = await calculateNewVersionsForPackages({
|
|
1936
|
-
allPackagesToBump,
|
|
1937
|
-
config,
|
|
1938
|
-
force,
|
|
1939
|
-
suffix
|
|
1940
|
-
});
|
|
1941
|
-
logger.debug(`Found ${packagesWithNewVersions.length} package(s) to bump`);
|
|
1942
|
-
return packagesWithNewVersions;
|
|
1692
|
+
logger.log("");
|
|
1943
1693
|
}
|
|
1944
|
-
function
|
|
1694
|
+
function getBumpedIndependentPackages({
|
|
1945
1695
|
packages,
|
|
1946
1696
|
dryRun
|
|
1947
1697
|
}) {
|
|
1948
1698
|
const bumpedPackages = [];
|
|
1949
1699
|
for (const pkgToBump of packages) {
|
|
1950
|
-
logger.debug(`Bumping ${pkgToBump.name} from ${pkgToBump.
|
|
1951
|
-
const result =
|
|
1700
|
+
logger.debug(`Bumping ${pkgToBump.name} from ${pkgToBump.version} to ${pkgToBump.newVersion} (reason: ${pkgToBump.reason})`);
|
|
1701
|
+
const result = getBumpedPackageIndependently({
|
|
1952
1702
|
pkg: pkgToBump,
|
|
1953
1703
|
dryRun
|
|
1954
1704
|
});
|
|
1955
1705
|
if (result.bumped) {
|
|
1956
1706
|
bumpedPackages.push({
|
|
1957
1707
|
...pkgToBump,
|
|
1958
|
-
version: result.
|
|
1708
|
+
version: result.oldVersion
|
|
1959
1709
|
});
|
|
1960
1710
|
}
|
|
1961
1711
|
}
|
|
1962
1712
|
return bumpedPackages;
|
|
1963
1713
|
}
|
|
1964
1714
|
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1715
|
+
function getIndependentTag({ version, name }) {
|
|
1716
|
+
return `${name}@${version}`;
|
|
1717
|
+
}
|
|
1718
|
+
async function getLastStableTag({ logLevel, cwd }) {
|
|
1719
|
+
const { stdout } = await execPromise(
|
|
1720
|
+
`git tag --sort=-creatordate | grep -E '^[^0-9]*[0-9]+\\.[0-9]+\\.[0-9]+$' | head -n 1`,
|
|
1721
|
+
{
|
|
1722
|
+
logLevel,
|
|
1723
|
+
noStderr: true,
|
|
1724
|
+
noStdout: true,
|
|
1725
|
+
noSuccess: true,
|
|
1726
|
+
cwd
|
|
1727
|
+
}
|
|
1728
|
+
);
|
|
1729
|
+
const lastTag = stdout.trim();
|
|
1730
|
+
logger.debug("Last stable tag:", lastTag || "No stable tags found");
|
|
1731
|
+
return lastTag;
|
|
1732
|
+
}
|
|
1733
|
+
async function getLastTag({ logLevel, cwd }) {
|
|
1982
1734
|
const { stdout } = await execPromise(`git tag --sort=-creatordate | head -n 1`, {
|
|
1983
|
-
logLevel
|
|
1735
|
+
logLevel,
|
|
1984
1736
|
noStderr: true,
|
|
1985
1737
|
noStdout: true,
|
|
1986
1738
|
noSuccess: true,
|
|
1987
|
-
cwd
|
|
1739
|
+
cwd
|
|
1988
1740
|
});
|
|
1989
|
-
lastTag = stdout.trim();
|
|
1741
|
+
const lastTag = stdout.trim();
|
|
1990
1742
|
logger.debug("Last tag:", lastTag || "No tags found");
|
|
1991
1743
|
return lastTag;
|
|
1992
1744
|
}
|
|
1745
|
+
function getLastRepoTag(options) {
|
|
1746
|
+
if (options?.onlyStable) {
|
|
1747
|
+
return getLastStableTag({ logLevel: options?.logLevel, cwd: options?.cwd });
|
|
1748
|
+
}
|
|
1749
|
+
return getLastTag({ logLevel: options?.logLevel, cwd: options?.cwd });
|
|
1750
|
+
}
|
|
1993
1751
|
async function getLastPackageTag({
|
|
1994
1752
|
packageName,
|
|
1995
1753
|
onlyStable,
|
|
@@ -2020,88 +1778,111 @@ async function getLastPackageTag({
|
|
|
2020
1778
|
return null;
|
|
2021
1779
|
}
|
|
2022
1780
|
}
|
|
2023
|
-
async function
|
|
1781
|
+
async function resolveFromTagIndependent({
|
|
2024
1782
|
cwd,
|
|
2025
|
-
|
|
1783
|
+
packageName,
|
|
2026
1784
|
graduating,
|
|
2027
|
-
newVersion,
|
|
2028
|
-
step,
|
|
2029
1785
|
logLevel
|
|
2030
1786
|
}) {
|
|
2031
|
-
let to;
|
|
2032
|
-
if (step === "bump") {
|
|
2033
|
-
to = getCurrentGitRef(cwd);
|
|
2034
|
-
} else {
|
|
2035
|
-
to = newVersion ? `${pkg.name}@${newVersion}` : getCurrentGitRef(cwd);
|
|
2036
|
-
}
|
|
2037
1787
|
const lastPackageTag = await getLastPackageTag({
|
|
2038
|
-
packageName
|
|
1788
|
+
packageName,
|
|
2039
1789
|
onlyStable: graduating,
|
|
2040
1790
|
logLevel
|
|
2041
1791
|
});
|
|
2042
1792
|
if (!lastPackageTag) {
|
|
2043
|
-
|
|
2044
|
-
return { from, to };
|
|
1793
|
+
return getFirstCommit(cwd);
|
|
2045
1794
|
}
|
|
2046
|
-
return
|
|
1795
|
+
return lastPackageTag;
|
|
2047
1796
|
}
|
|
2048
|
-
async function
|
|
1797
|
+
async function resolveFromTagUnified({
|
|
2049
1798
|
config,
|
|
2050
|
-
newVersion,
|
|
2051
1799
|
graduating,
|
|
2052
|
-
step,
|
|
2053
1800
|
logLevel
|
|
2054
1801
|
}) {
|
|
2055
|
-
let to;
|
|
2056
|
-
if (step === "bump") {
|
|
2057
|
-
to = getCurrentGitRef(config.cwd);
|
|
2058
|
-
} else {
|
|
2059
|
-
to = newVersion ? config.templates.tagBody.replace("{{newVersion}}", newVersion) : getCurrentGitRef(config.cwd);
|
|
2060
|
-
}
|
|
2061
1802
|
const from = await getLastRepoTag({ onlyStable: graduating, logLevel }) || getFirstCommit(config.cwd);
|
|
2062
|
-
return
|
|
1803
|
+
return from;
|
|
2063
1804
|
}
|
|
2064
|
-
async function
|
|
1805
|
+
async function resolveFromTag({
|
|
2065
1806
|
config,
|
|
2066
1807
|
versionMode,
|
|
2067
1808
|
step,
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
newVersion,
|
|
1809
|
+
packageName,
|
|
1810
|
+
graduating,
|
|
2071
1811
|
logLevel
|
|
2072
1812
|
}) {
|
|
2073
|
-
|
|
2074
|
-
const graduating = currentVersion && isGraduating(currentVersion, config.bump.type) || false;
|
|
2075
|
-
const newTags = newVersion && config.templates.tagBody.replace("{{newVersion}}", newVersion) || null;
|
|
2076
|
-
if (config.from) {
|
|
2077
|
-
const tags2 = {
|
|
2078
|
-
from: config.from,
|
|
2079
|
-
to: config.to || newTags || getCurrentGitRef(config.cwd)
|
|
2080
|
-
};
|
|
2081
|
-
logger.debug(`[${versionMode}](${step}) Using specified tags: ${tags2.from} \u2192 ${tags2.to}`);
|
|
2082
|
-
return tags2;
|
|
2083
|
-
}
|
|
1813
|
+
let from;
|
|
2084
1814
|
if (versionMode === "independent") {
|
|
2085
|
-
|
|
1815
|
+
if (!packageName) {
|
|
1816
|
+
throw new Error("Package name is required for independent version mode");
|
|
1817
|
+
}
|
|
1818
|
+
from = await resolveFromTagIndependent({
|
|
2086
1819
|
cwd: config.cwd,
|
|
2087
|
-
|
|
1820
|
+
packageName,
|
|
1821
|
+
graduating,
|
|
1822
|
+
logLevel
|
|
1823
|
+
});
|
|
1824
|
+
} else {
|
|
1825
|
+
from = await resolveFromTagUnified({
|
|
1826
|
+
config,
|
|
2088
1827
|
graduating,
|
|
2089
|
-
newVersion,
|
|
2090
|
-
step,
|
|
2091
1828
|
logLevel
|
|
2092
1829
|
});
|
|
2093
|
-
logger.debug(`[${versionMode}](${step}) Using tags: ${tags2.from} \u2192 ${tags2.to}`);
|
|
2094
|
-
return tags2;
|
|
2095
1830
|
}
|
|
2096
|
-
|
|
1831
|
+
logger.debug(`[${versionMode}](${step}) Using from tag: ${from}`);
|
|
1832
|
+
return config.from || from;
|
|
1833
|
+
}
|
|
1834
|
+
function resolveToTag({
|
|
1835
|
+
config,
|
|
1836
|
+
versionMode,
|
|
1837
|
+
newVersion,
|
|
1838
|
+
step,
|
|
1839
|
+
packageName
|
|
1840
|
+
}) {
|
|
1841
|
+
const isUntaggedStep = step === "bump" || step === "changelog";
|
|
1842
|
+
let to;
|
|
1843
|
+
if (isUntaggedStep) {
|
|
1844
|
+
to = getCurrentGitRef(config.cwd);
|
|
1845
|
+
} else if (versionMode === "independent") {
|
|
1846
|
+
if (!packageName) {
|
|
1847
|
+
throw new Error("Package name is required for independent version mode");
|
|
1848
|
+
}
|
|
1849
|
+
if (!newVersion) {
|
|
1850
|
+
throw new Error("New version is required for independent version mode");
|
|
1851
|
+
}
|
|
1852
|
+
to = getIndependentTag({ version: newVersion, name: packageName });
|
|
1853
|
+
} else {
|
|
1854
|
+
to = newVersion ? config.templates.tagBody.replace("{{newVersion}}", newVersion) : getCurrentGitRef(config.cwd);
|
|
1855
|
+
}
|
|
1856
|
+
logger.debug(`[${versionMode}](${step}) Using to tag: ${to}`);
|
|
1857
|
+
return config.to || to;
|
|
1858
|
+
}
|
|
1859
|
+
async function resolveTags({
|
|
1860
|
+
config,
|
|
1861
|
+
step,
|
|
1862
|
+
pkg,
|
|
1863
|
+
newVersion
|
|
1864
|
+
}) {
|
|
1865
|
+
const versionMode = config.monorepo?.versionMode || "standalone";
|
|
1866
|
+
const logLevel = config.logLevel;
|
|
1867
|
+
logger.debug(`[${versionMode}](${step}) Resolving tags`);
|
|
1868
|
+
const releaseType = config.bump.type;
|
|
1869
|
+
const from = await resolveFromTag({
|
|
2097
1870
|
config,
|
|
2098
|
-
|
|
2099
|
-
graduating,
|
|
1871
|
+
versionMode,
|
|
2100
1872
|
step,
|
|
1873
|
+
packageName: pkg.name,
|
|
1874
|
+
graduating: isGraduating(pkg.version, releaseType),
|
|
2101
1875
|
logLevel
|
|
2102
1876
|
});
|
|
2103
|
-
|
|
2104
|
-
|
|
1877
|
+
const to = resolveToTag({
|
|
1878
|
+
config,
|
|
1879
|
+
versionMode,
|
|
1880
|
+
newVersion,
|
|
1881
|
+
step,
|
|
1882
|
+
packageName: pkg.name
|
|
1883
|
+
});
|
|
1884
|
+
logger.debug(`[${versionMode}](${step}) Using tags: ${from} \u2192 ${to}`);
|
|
1885
|
+
return { from, to };
|
|
2105
1886
|
}
|
|
2106
1887
|
|
|
2107
1888
|
let sessionOtp;
|
|
@@ -2120,7 +1901,8 @@ function detectPackageManager(cwd = process.cwd()) {
|
|
|
2120
1901
|
}
|
|
2121
1902
|
}
|
|
2122
1903
|
} catch (e) {
|
|
2123
|
-
|
|
1904
|
+
const errorString = e instanceof Error ? e.message : String(e);
|
|
1905
|
+
logger.debug(`Failed to parse package.json: ${errorString}`);
|
|
2124
1906
|
}
|
|
2125
1907
|
}
|
|
2126
1908
|
const lockFiles = {
|
|
@@ -2146,7 +1928,7 @@ function detectPackageManager(cwd = process.cwd()) {
|
|
|
2146
1928
|
logger.debug("No package manager detected, defaulting to npm");
|
|
2147
1929
|
return "npm";
|
|
2148
1930
|
} catch (error) {
|
|
2149
|
-
logger.
|
|
1931
|
+
logger.fail(`Error detecting package manager: ${error}, defaulting to npm`);
|
|
2150
1932
|
return "npm";
|
|
2151
1933
|
}
|
|
2152
1934
|
}
|
|
@@ -2180,23 +1962,13 @@ async function getPackagesToPublishInIndependentMode(sortedPackages, config) {
|
|
|
2180
1962
|
for (const pkg of sortedPackages) {
|
|
2181
1963
|
const { from, to } = await resolveTags({
|
|
2182
1964
|
config,
|
|
2183
|
-
versionMode: "independent",
|
|
2184
1965
|
step: "publish",
|
|
2185
1966
|
pkg,
|
|
2186
|
-
newVersion: pkg.version
|
|
2187
|
-
currentVersion: void 0,
|
|
2188
|
-
logLevel: config.logLevel
|
|
2189
|
-
});
|
|
2190
|
-
const commits = await getPackageCommits({
|
|
2191
|
-
pkg,
|
|
2192
|
-
from,
|
|
2193
|
-
to,
|
|
2194
|
-
config,
|
|
2195
|
-
changelog: false
|
|
1967
|
+
newVersion: pkg.version
|
|
2196
1968
|
});
|
|
2197
|
-
if (commits.length > 0) {
|
|
1969
|
+
if (pkg.commits.length > 0) {
|
|
2198
1970
|
packagesToPublish.push(pkg);
|
|
2199
|
-
logger.debug(`${pkg.name}: ${commits.length} commit(s) since ${from} \u2192 ${to}`);
|
|
1971
|
+
logger.debug(`${pkg.name}: ${pkg.commits.length} commit(s) since ${from} \u2192 ${to}`);
|
|
2200
1972
|
}
|
|
2201
1973
|
}
|
|
2202
1974
|
return packagesToPublish;
|
|
@@ -2301,7 +2073,7 @@ async function publishPackage({
|
|
|
2301
2073
|
dryRun
|
|
2302
2074
|
}) {
|
|
2303
2075
|
const tag = determinePublishTag(pkg.version, config.publish.tag);
|
|
2304
|
-
const packageNameAndVersion =
|
|
2076
|
+
const packageNameAndVersion = getIndependentTag(pkg);
|
|
2305
2077
|
const baseCommand = packageManager === "yarn" && isYarnBerry() ? "yarn npm" : packageManager;
|
|
2306
2078
|
logger.debug(`Building publish command for ${pkg.name}`);
|
|
2307
2079
|
let dynamicOtp;
|
|
@@ -2342,198 +2114,412 @@ async function publishPackage({
|
|
|
2342
2114
|
}
|
|
2343
2115
|
}
|
|
2344
2116
|
|
|
2117
|
+
function readPackageJson(packagePath) {
|
|
2118
|
+
const packageJsonPath = join(packagePath, "package.json");
|
|
2119
|
+
if (!existsSync(packageJsonPath))
|
|
2120
|
+
throw new Error(`package.json not found at ${packageJsonPath}`);
|
|
2121
|
+
if (!statSync(packagePath).isDirectory())
|
|
2122
|
+
throw new Error(`Not a directory: ${packagePath}`);
|
|
2123
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
2124
|
+
if (!packageJson.name || !packageJson.version) {
|
|
2125
|
+
throw new Error(`Invalid package.json at ${packagePath}`);
|
|
2126
|
+
}
|
|
2127
|
+
return {
|
|
2128
|
+
name: packageJson.name,
|
|
2129
|
+
version: packageJson.version,
|
|
2130
|
+
private: packageJson.private || false,
|
|
2131
|
+
path: packagePath
|
|
2132
|
+
};
|
|
2133
|
+
}
|
|
2134
|
+
async function getRootPackage({
|
|
2135
|
+
config,
|
|
2136
|
+
force,
|
|
2137
|
+
from,
|
|
2138
|
+
to,
|
|
2139
|
+
suffix,
|
|
2140
|
+
changelog
|
|
2141
|
+
}) {
|
|
2142
|
+
try {
|
|
2143
|
+
const packageJson = readPackageJson(config.cwd);
|
|
2144
|
+
const commits = await getPackageCommits({
|
|
2145
|
+
pkg: packageJson,
|
|
2146
|
+
from,
|
|
2147
|
+
to,
|
|
2148
|
+
config,
|
|
2149
|
+
changelog
|
|
2150
|
+
});
|
|
2151
|
+
const releaseType = determineReleaseType({
|
|
2152
|
+
currentVersion: packageJson.version,
|
|
2153
|
+
commits,
|
|
2154
|
+
releaseType: config.bump.type,
|
|
2155
|
+
preid: config.bump.preid,
|
|
2156
|
+
types: config.types,
|
|
2157
|
+
force
|
|
2158
|
+
});
|
|
2159
|
+
if (!releaseType) {
|
|
2160
|
+
logger.fail("No commits require a version bump");
|
|
2161
|
+
process.exit(0);
|
|
2162
|
+
}
|
|
2163
|
+
const newVersion = getPackageNewVersion({
|
|
2164
|
+
currentVersion: packageJson.version,
|
|
2165
|
+
releaseType,
|
|
2166
|
+
preid: config.bump.preid,
|
|
2167
|
+
suffix
|
|
2168
|
+
});
|
|
2169
|
+
return {
|
|
2170
|
+
...packageJson,
|
|
2171
|
+
path: config.cwd,
|
|
2172
|
+
fromTag: from,
|
|
2173
|
+
commits,
|
|
2174
|
+
newVersion
|
|
2175
|
+
};
|
|
2176
|
+
} catch (error) {
|
|
2177
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2178
|
+
throw new Error(errorMessage);
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
function readPackages({
|
|
2182
|
+
cwd,
|
|
2183
|
+
patterns,
|
|
2184
|
+
ignorePackageNames
|
|
2185
|
+
}) {
|
|
2186
|
+
const packages = [];
|
|
2187
|
+
const foundPaths = /* @__PURE__ */ new Set();
|
|
2188
|
+
if (!patterns)
|
|
2189
|
+
patterns = ["."];
|
|
2190
|
+
logger.debug(`Getting packages from patterns: ${patterns.join(", ")}`);
|
|
2191
|
+
for (const pattern of patterns) {
|
|
2192
|
+
try {
|
|
2193
|
+
const matches = fastGlob.sync(pattern, {
|
|
2194
|
+
cwd,
|
|
2195
|
+
onlyDirectories: true,
|
|
2196
|
+
absolute: true,
|
|
2197
|
+
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"]
|
|
2198
|
+
});
|
|
2199
|
+
for (const matchPath of matches) {
|
|
2200
|
+
if (foundPaths.has(matchPath))
|
|
2201
|
+
continue;
|
|
2202
|
+
const packageBase = readPackageJson(matchPath);
|
|
2203
|
+
if (!packageBase || packageBase.private || ignorePackageNames?.includes(packageBase.name))
|
|
2204
|
+
continue;
|
|
2205
|
+
foundPaths.add(matchPath);
|
|
2206
|
+
packages.push({
|
|
2207
|
+
...packageBase,
|
|
2208
|
+
path: matchPath
|
|
2209
|
+
});
|
|
2210
|
+
}
|
|
2211
|
+
} catch (error) {
|
|
2212
|
+
logger.error(error);
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
return packages;
|
|
2216
|
+
}
|
|
2217
|
+
function getPackageReleaseType({
|
|
2218
|
+
pkg,
|
|
2219
|
+
config,
|
|
2220
|
+
force
|
|
2221
|
+
}) {
|
|
2222
|
+
const releaseType = config.bump.type;
|
|
2223
|
+
if (force) {
|
|
2224
|
+
return determineReleaseType({
|
|
2225
|
+
currentVersion: pkg.version,
|
|
2226
|
+
commits: pkg.commits,
|
|
2227
|
+
releaseType,
|
|
2228
|
+
preid: config.bump.preid,
|
|
2229
|
+
types: config.types,
|
|
2230
|
+
force
|
|
2231
|
+
});
|
|
2232
|
+
}
|
|
2233
|
+
if (pkg.reason === "dependency") {
|
|
2234
|
+
if (isStableReleaseType(releaseType))
|
|
2235
|
+
return "patch";
|
|
2236
|
+
if (isPrerelease(pkg.version))
|
|
2237
|
+
return "prerelease";
|
|
2238
|
+
return "prepatch";
|
|
2239
|
+
}
|
|
2240
|
+
return determineReleaseType({
|
|
2241
|
+
currentVersion: pkg.version,
|
|
2242
|
+
commits: pkg.commits,
|
|
2243
|
+
releaseType,
|
|
2244
|
+
preid: config.bump.preid,
|
|
2245
|
+
types: config.types,
|
|
2246
|
+
force
|
|
2247
|
+
});
|
|
2248
|
+
}
|
|
2249
|
+
async function getPackages({
|
|
2250
|
+
patterns,
|
|
2251
|
+
config,
|
|
2252
|
+
suffix,
|
|
2253
|
+
force
|
|
2254
|
+
}) {
|
|
2255
|
+
const readedPackages = readPackages({
|
|
2256
|
+
cwd: config.cwd,
|
|
2257
|
+
patterns,
|
|
2258
|
+
ignorePackageNames: config.monorepo?.ignorePackageNames
|
|
2259
|
+
});
|
|
2260
|
+
const packages = /* @__PURE__ */ new Map();
|
|
2261
|
+
const foundPaths = /* @__PURE__ */ new Set();
|
|
2262
|
+
if (!patterns)
|
|
2263
|
+
patterns = ["."];
|
|
2264
|
+
logger.debug(`Getting packages from patterns: ${patterns.join(", ")}`);
|
|
2265
|
+
const patternsSet = new Set(patterns);
|
|
2266
|
+
for (const pattern of patternsSet) {
|
|
2267
|
+
const matches = fastGlob.sync(pattern, {
|
|
2268
|
+
cwd: config.cwd,
|
|
2269
|
+
onlyDirectories: true,
|
|
2270
|
+
absolute: true,
|
|
2271
|
+
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"]
|
|
2272
|
+
});
|
|
2273
|
+
for (const matchPath of matches) {
|
|
2274
|
+
if (foundPaths.has(matchPath))
|
|
2275
|
+
continue;
|
|
2276
|
+
const packageBase = readPackageJson(matchPath);
|
|
2277
|
+
if (packageBase.private) {
|
|
2278
|
+
logger.debug(`${packageBase.name} is private and will be ignored`);
|
|
2279
|
+
continue;
|
|
2280
|
+
}
|
|
2281
|
+
if (config.monorepo?.ignorePackageNames?.includes(packageBase.name)) {
|
|
2282
|
+
logger.debug(`${packageBase.name} ignored by config (monorepo.ignorePackageNames)`);
|
|
2283
|
+
continue;
|
|
2284
|
+
}
|
|
2285
|
+
if (!packageBase.version) {
|
|
2286
|
+
logger.warn(`${packageBase.name} has no version and will be ignored`);
|
|
2287
|
+
continue;
|
|
2288
|
+
}
|
|
2289
|
+
const { from, to } = await resolveTags({
|
|
2290
|
+
config,
|
|
2291
|
+
step: "bump",
|
|
2292
|
+
pkg: packageBase,
|
|
2293
|
+
newVersion: void 0
|
|
2294
|
+
});
|
|
2295
|
+
const commits = await getPackageCommits({
|
|
2296
|
+
pkg: packageBase,
|
|
2297
|
+
from,
|
|
2298
|
+
to,
|
|
2299
|
+
config,
|
|
2300
|
+
changelog: false
|
|
2301
|
+
});
|
|
2302
|
+
foundPaths.add(matchPath);
|
|
2303
|
+
const dependencies = getPackageDependencies({
|
|
2304
|
+
packagePath: matchPath,
|
|
2305
|
+
allPackageNames: new Set(readedPackages.map((p) => p.name)),
|
|
2306
|
+
dependencyTypes: config.bump?.dependencyTypes
|
|
2307
|
+
});
|
|
2308
|
+
packages.set(packageBase.name, {
|
|
2309
|
+
...packageBase,
|
|
2310
|
+
path: matchPath,
|
|
2311
|
+
fromTag: from,
|
|
2312
|
+
dependencies,
|
|
2313
|
+
commits,
|
|
2314
|
+
reason: commits.length > 0 ? "commits" : void 0,
|
|
2315
|
+
dependencyChain: void 0,
|
|
2316
|
+
newVersion: void 0
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
const packagesArray = Array.from(packages.values());
|
|
2321
|
+
const packagesWithCommits = packagesArray.filter((p) => p.commits.length > 0);
|
|
2322
|
+
const expandedPackages = expandPackagesToBumpWithDependents({
|
|
2323
|
+
allPackages: packagesArray,
|
|
2324
|
+
packagesWithCommits
|
|
2325
|
+
});
|
|
2326
|
+
for (const pkg of expandedPackages) {
|
|
2327
|
+
packages.set(pkg.name, pkg);
|
|
2328
|
+
}
|
|
2329
|
+
for (const pkg of Array.from(packages.values())) {
|
|
2330
|
+
const releaseType = getPackageReleaseType({
|
|
2331
|
+
pkg,
|
|
2332
|
+
config,
|
|
2333
|
+
force
|
|
2334
|
+
});
|
|
2335
|
+
const newVersion = releaseType ? getPackageNewVersion({
|
|
2336
|
+
currentVersion: pkg.version,
|
|
2337
|
+
releaseType,
|
|
2338
|
+
preid: config.bump.preid,
|
|
2339
|
+
suffix
|
|
2340
|
+
}) : void 0;
|
|
2341
|
+
const graduating = releaseType && isGraduating(pkg.version, releaseType) || isChangedPreid(pkg.version, config.bump.preid);
|
|
2342
|
+
packages.set(pkg.name, {
|
|
2343
|
+
...pkg,
|
|
2344
|
+
newVersion,
|
|
2345
|
+
reason: pkg.reason || releaseType && graduating && "graduation" || void 0
|
|
2346
|
+
});
|
|
2347
|
+
}
|
|
2348
|
+
const packagesToBump = Array.from(packages.values()).filter((p) => p.reason || force);
|
|
2349
|
+
if (packagesToBump.length === 0) {
|
|
2350
|
+
logger.debug("No packages to bump");
|
|
2351
|
+
return [];
|
|
2352
|
+
}
|
|
2353
|
+
return packagesToBump;
|
|
2354
|
+
}
|
|
2355
|
+
function isAllowedCommit({
|
|
2356
|
+
commit,
|
|
2357
|
+
type,
|
|
2358
|
+
changelog
|
|
2359
|
+
}) {
|
|
2360
|
+
if (commit.type === "chore" && ["deps", "release"].includes(commit.scope) && !commit.isBreaking) {
|
|
2361
|
+
return false;
|
|
2362
|
+
}
|
|
2363
|
+
if (typeof type === "object") {
|
|
2364
|
+
return !!type.semver || changelog && !!type.title;
|
|
2365
|
+
}
|
|
2366
|
+
if (typeof type === "boolean") {
|
|
2367
|
+
return type;
|
|
2368
|
+
}
|
|
2369
|
+
return false;
|
|
2370
|
+
}
|
|
2371
|
+
async function getPackageCommits({
|
|
2372
|
+
pkg,
|
|
2373
|
+
from,
|
|
2374
|
+
to,
|
|
2375
|
+
config,
|
|
2376
|
+
changelog
|
|
2377
|
+
}) {
|
|
2378
|
+
logger.debug(`Analyzing commits for ${pkg.name} since ${from} to ${to}`);
|
|
2379
|
+
const changelogConfig = {
|
|
2380
|
+
...config,
|
|
2381
|
+
from,
|
|
2382
|
+
to
|
|
2383
|
+
};
|
|
2384
|
+
const rawCommits = await getGitDiff(from, to, changelogConfig.cwd);
|
|
2385
|
+
const allCommits = parseCommits(rawCommits, changelogConfig);
|
|
2386
|
+
const hasBreakingChanges = allCommits.some((commit) => commit.isBreaking);
|
|
2387
|
+
logger.debug(`Has breaking changes: ${hasBreakingChanges}`);
|
|
2388
|
+
const rootPackage = readPackageJson(changelogConfig.cwd);
|
|
2389
|
+
const commits = allCommits.filter((commit) => {
|
|
2390
|
+
const type = changelogConfig?.types[commit.type];
|
|
2391
|
+
if (!isAllowedCommit({ commit, type, changelog })) {
|
|
2392
|
+
return false;
|
|
2393
|
+
}
|
|
2394
|
+
if (pkg.path === changelogConfig.cwd || pkg.name === rootPackage.name) {
|
|
2395
|
+
return true;
|
|
2396
|
+
}
|
|
2397
|
+
const packageRelativePath = relative(changelogConfig.cwd, pkg.path);
|
|
2398
|
+
const scopeMatches = commit.scope === pkg.name;
|
|
2399
|
+
const bodyContainsPath = commit.body.includes(packageRelativePath);
|
|
2400
|
+
return scopeMatches || bodyContainsPath;
|
|
2401
|
+
});
|
|
2402
|
+
logger.debug(`Found ${commits.length} commit(s) for ${pkg.name} from ${from} to ${to}`);
|
|
2403
|
+
if (commits.length > 0) {
|
|
2404
|
+
logger.debug(`${pkg.name}: ${commits.length} commit(s) found`);
|
|
2405
|
+
} else {
|
|
2406
|
+
logger.debug(`${pkg.name}: No commits found`);
|
|
2407
|
+
}
|
|
2408
|
+
return commits;
|
|
2409
|
+
}
|
|
2410
|
+
function hasLernaJson(rootDir) {
|
|
2411
|
+
const lernaJsonPath = join(rootDir, "lerna.json");
|
|
2412
|
+
return existsSync(lernaJsonPath);
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2345
2415
|
async function bumpUnifiedMode({
|
|
2346
2416
|
config,
|
|
2347
|
-
packages,
|
|
2348
2417
|
dryRun,
|
|
2349
2418
|
force,
|
|
2350
2419
|
suffix
|
|
2351
2420
|
}) {
|
|
2352
2421
|
logger.debug("Starting bump in unified mode");
|
|
2353
|
-
const
|
|
2354
|
-
const currentVersion = rootPackage.version;
|
|
2422
|
+
const rootPackageBase = readPackageJson(config.cwd);
|
|
2355
2423
|
const { from, to } = await resolveTags({
|
|
2356
2424
|
config,
|
|
2357
|
-
versionMode: "unified",
|
|
2358
2425
|
step: "bump",
|
|
2359
2426
|
newVersion: void 0,
|
|
2360
|
-
pkg:
|
|
2361
|
-
currentVersion,
|
|
2362
|
-
logLevel: config.logLevel
|
|
2427
|
+
pkg: rootPackageBase
|
|
2363
2428
|
});
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2429
|
+
const rootPackage = await getRootPackage({
|
|
2430
|
+
config,
|
|
2431
|
+
force,
|
|
2367
2432
|
from,
|
|
2368
2433
|
to,
|
|
2369
|
-
|
|
2434
|
+
suffix,
|
|
2370
2435
|
changelog: false
|
|
2371
2436
|
});
|
|
2372
|
-
|
|
2373
|
-
const
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2437
|
+
const currentVersion = rootPackage.version;
|
|
2438
|
+
const newVersion = rootPackage.newVersion;
|
|
2439
|
+
if (!newVersion) {
|
|
2440
|
+
throw new Error(`Could not determine a new version for ${rootPackage.name} (root)`);
|
|
2441
|
+
}
|
|
2442
|
+
logger.debug(`Bump from ${from} to ${to}`);
|
|
2443
|
+
logger.debug(`${currentVersion} \u2192 ${newVersion} (${config.monorepo?.versionMode || "standalone"} mode)`);
|
|
2444
|
+
const packages = await getPackages({
|
|
2378
2445
|
config,
|
|
2446
|
+
patterns: config.monorepo?.packages,
|
|
2447
|
+
suffix,
|
|
2379
2448
|
force
|
|
2380
2449
|
});
|
|
2381
|
-
if (!releaseType) {
|
|
2382
|
-
logger.debug("No commits require a version bump");
|
|
2383
|
-
return { bumped: false };
|
|
2384
|
-
}
|
|
2385
|
-
if (config.bump.type && force) {
|
|
2386
|
-
logger.debug(`Using specified release type: ${releaseType}`);
|
|
2387
|
-
} else {
|
|
2388
|
-
logger.debug(`Detected release type from commits: ${releaseType}`);
|
|
2389
|
-
}
|
|
2390
|
-
const newVersion = bumpPackageVersion({
|
|
2391
|
-
currentVersion,
|
|
2392
|
-
releaseType,
|
|
2393
|
-
preid: config.bump.preid,
|
|
2394
|
-
suffix
|
|
2395
|
-
});
|
|
2396
|
-
logger.debug(`${currentVersion} \u2192 ${newVersion} (unified mode)`);
|
|
2397
|
-
const allPackages = [rootPackage, ...packages];
|
|
2398
2450
|
if (!config.bump.yes) {
|
|
2399
2451
|
await confirmBump({
|
|
2400
2452
|
versionMode: "unified",
|
|
2401
|
-
config,
|
|
2402
2453
|
packages,
|
|
2454
|
+
config,
|
|
2403
2455
|
force,
|
|
2404
2456
|
currentVersion,
|
|
2405
2457
|
newVersion,
|
|
2406
2458
|
dryRun
|
|
2407
2459
|
});
|
|
2408
2460
|
} else {
|
|
2409
|
-
logger.info(`${
|
|
2461
|
+
logger.info(`${packages.length === 1 ? packages[0].name : packages.length} package(s) bumped from ${currentVersion} to ${newVersion} (${config.monorepo?.versionMode || "standalone"} mode)`);
|
|
2410
2462
|
}
|
|
2411
|
-
for (const pkg of
|
|
2463
|
+
for (const pkg of [rootPackage, ...packages]) {
|
|
2412
2464
|
writeVersion(pkg.path, newVersion, dryRun);
|
|
2413
2465
|
}
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
});
|
|
2421
|
-
}
|
|
2466
|
+
updateLernaVersion({
|
|
2467
|
+
rootDir: config.cwd,
|
|
2468
|
+
versionMode: config.monorepo?.versionMode,
|
|
2469
|
+
version: newVersion,
|
|
2470
|
+
dryRun
|
|
2471
|
+
});
|
|
2422
2472
|
if (!dryRun) {
|
|
2423
|
-
logger.info(`All ${
|
|
2473
|
+
logger.info(`All ${packages.length} package(s) bumped to ${newVersion}`);
|
|
2424
2474
|
}
|
|
2425
2475
|
return {
|
|
2426
2476
|
bumped: true,
|
|
2427
2477
|
oldVersion: currentVersion,
|
|
2428
2478
|
fromTag: from,
|
|
2429
2479
|
newVersion,
|
|
2480
|
+
rootPackage,
|
|
2430
2481
|
bumpedPackages: packages.map((pkg) => ({
|
|
2431
2482
|
...pkg,
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
fromTag: from
|
|
2483
|
+
oldVersion: pkg.version,
|
|
2484
|
+
newVersion,
|
|
2485
|
+
fromTag: from,
|
|
2486
|
+
reason: "commits"
|
|
2435
2487
|
}))
|
|
2436
2488
|
};
|
|
2437
2489
|
}
|
|
2438
|
-
async function bumpIndependentMode({
|
|
2439
|
-
config,
|
|
2440
|
-
packages,
|
|
2441
|
-
dryRun,
|
|
2442
|
-
force,
|
|
2443
|
-
suffix
|
|
2444
|
-
}) {
|
|
2445
|
-
logger.debug("Starting bump in independent mode");
|
|
2446
|
-
const packagesWithNewVersions = await findPackagesWithCommitsAndCalculateVersions({
|
|
2447
|
-
packages,
|
|
2448
|
-
config,
|
|
2449
|
-
force,
|
|
2450
|
-
suffix
|
|
2451
|
-
});
|
|
2452
|
-
if (packagesWithNewVersions.length === 0) {
|
|
2453
|
-
logger.debug("No packages have commits");
|
|
2454
|
-
return { bumped: false };
|
|
2455
|
-
}
|
|
2456
|
-
if (!config.bump.yes) {
|
|
2457
|
-
await confirmBump({
|
|
2458
|
-
versionMode: "independent",
|
|
2459
|
-
config,
|
|
2460
|
-
packages: packagesWithNewVersions,
|
|
2461
|
-
force,
|
|
2462
|
-
dryRun
|
|
2463
|
-
});
|
|
2464
|
-
} else {
|
|
2465
|
-
const bumpedByCommits2 = packagesWithNewVersions.filter((p) => p.reason === "commits").length;
|
|
2466
|
-
const bumpedByDependency2 = packagesWithNewVersions.length - bumpedByCommits2;
|
|
2467
|
-
logger.info(
|
|
2468
|
-
`${bumpedByCommits2 + bumpedByDependency2} package(s) will be bumped independently (${bumpedByCommits2} from commits, ${bumpedByDependency2} from dependencies)`
|
|
2469
|
-
);
|
|
2470
|
-
}
|
|
2471
|
-
const bumpedPackages = bumpIndependentPackages({
|
|
2472
|
-
packages: packagesWithNewVersions,
|
|
2473
|
-
dryRun
|
|
2474
|
-
});
|
|
2475
|
-
const bumpedByCommits = bumpedPackages.filter(
|
|
2476
|
-
(p) => packagesWithNewVersions.find((pkg) => pkg.name === p.name)?.reason === "commits"
|
|
2477
|
-
).length;
|
|
2478
|
-
const bumpedByDependency = bumpedPackages.length - bumpedByCommits;
|
|
2479
|
-
if (bumpedPackages.length === 0) {
|
|
2480
|
-
logger.debug("No packages were bumped");
|
|
2481
|
-
} else {
|
|
2482
|
-
logger.info(
|
|
2483
|
-
`${dryRun ? "[dry-run] " : ""}${bumpedPackages.length} package(s) bumped independently (${bumpedByCommits} from commits, ${bumpedByDependency} from dependencies)`
|
|
2484
|
-
);
|
|
2485
|
-
}
|
|
2486
|
-
return {
|
|
2487
|
-
bumped: bumpedPackages.length > 0,
|
|
2488
|
-
bumpedPackages
|
|
2489
|
-
};
|
|
2490
|
-
}
|
|
2491
2490
|
async function bumpSelectiveMode({
|
|
2492
2491
|
config,
|
|
2493
|
-
packages,
|
|
2494
2492
|
dryRun,
|
|
2495
2493
|
force,
|
|
2496
2494
|
suffix
|
|
2497
2495
|
}) {
|
|
2498
2496
|
logger.debug("Starting bump in selective mode");
|
|
2499
|
-
const
|
|
2500
|
-
const currentVersion = rootPackage.version;
|
|
2497
|
+
const rootPackageBase = readPackageJson(config.cwd);
|
|
2501
2498
|
const { from, to } = await resolveTags({
|
|
2502
2499
|
config,
|
|
2503
|
-
versionMode: "selective",
|
|
2504
2500
|
step: "bump",
|
|
2505
|
-
|
|
2506
|
-
newVersion: void 0
|
|
2507
|
-
pkg: void 0,
|
|
2508
|
-
logLevel: config.logLevel
|
|
2501
|
+
pkg: rootPackageBase,
|
|
2502
|
+
newVersion: void 0
|
|
2509
2503
|
});
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2504
|
+
const rootPackage = await getRootPackage({
|
|
2505
|
+
config,
|
|
2506
|
+
force,
|
|
2513
2507
|
from,
|
|
2514
2508
|
to,
|
|
2515
|
-
|
|
2509
|
+
suffix,
|
|
2516
2510
|
changelog: false
|
|
2517
2511
|
});
|
|
2518
|
-
const
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
return { bumped: false };
|
|
2522
|
-
}
|
|
2523
|
-
const newVersion = bumpPackageVersion({
|
|
2524
|
-
currentVersion,
|
|
2525
|
-
releaseType,
|
|
2526
|
-
preid: config.bump.preid,
|
|
2527
|
-
suffix
|
|
2528
|
-
});
|
|
2512
|
+
const currentVersion = rootPackage.version;
|
|
2513
|
+
const newVersion = rootPackage.newVersion;
|
|
2514
|
+
logger.debug(`Bump from ${currentVersion} to ${newVersion}`);
|
|
2529
2515
|
logger.debug("Determining packages to bump...");
|
|
2530
|
-
const
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2516
|
+
const packages = await getPackages({
|
|
2517
|
+
config,
|
|
2518
|
+
patterns: config.monorepo?.packages,
|
|
2519
|
+
suffix,
|
|
2520
|
+
force
|
|
2535
2521
|
});
|
|
2536
|
-
if (
|
|
2522
|
+
if (packages.length === 0) {
|
|
2537
2523
|
logger.debug("No packages have commits, skipping bump");
|
|
2538
2524
|
return { bumped: false };
|
|
2539
2525
|
}
|
|
@@ -2541,7 +2527,7 @@ async function bumpSelectiveMode({
|
|
|
2541
2527
|
await confirmBump({
|
|
2542
2528
|
versionMode: "selective",
|
|
2543
2529
|
config,
|
|
2544
|
-
packages
|
|
2530
|
+
packages,
|
|
2545
2531
|
force,
|
|
2546
2532
|
currentVersion,
|
|
2547
2533
|
newVersion,
|
|
@@ -2549,18 +2535,18 @@ async function bumpSelectiveMode({
|
|
|
2549
2535
|
});
|
|
2550
2536
|
} else {
|
|
2551
2537
|
if (force) {
|
|
2552
|
-
logger.info(`${
|
|
2538
|
+
logger.info(`${packages.length} package(s) bumped to ${newVersion} (force)`);
|
|
2553
2539
|
} else {
|
|
2554
|
-
const bumpedByCommits =
|
|
2555
|
-
const bumpedByDependency =
|
|
2540
|
+
const bumpedByCommits = packages.filter((p) => "reason" in p && p.reason === "commits").length;
|
|
2541
|
+
const bumpedByDependency = packages.filter((p) => "reason" in p && p.reason === "dependency").length;
|
|
2542
|
+
const bumpedByGraduation = packages.filter((p) => "reason" in p && p.reason === "graduation").length;
|
|
2556
2543
|
logger.info(
|
|
2557
|
-
`${currentVersion} \u2192 ${newVersion} (selective mode: ${bumpedByCommits} with commits, ${bumpedByDependency} as dependents)`
|
|
2544
|
+
`${currentVersion} \u2192 ${newVersion} (selective mode: ${bumpedByCommits} with commits, ${bumpedByDependency} as dependents, ${bumpedByGraduation} from graduation)`
|
|
2558
2545
|
);
|
|
2559
2546
|
}
|
|
2560
2547
|
}
|
|
2561
|
-
logger.debug(`Writing version to ${
|
|
2562
|
-
|
|
2563
|
-
for (const pkg of packagesToBump) {
|
|
2548
|
+
logger.debug(`Writing version to ${packages.length} package(s)`);
|
|
2549
|
+
for (const pkg of [rootPackage, ...packages]) {
|
|
2564
2550
|
writeVersion(pkg.path, newVersion, dryRun);
|
|
2565
2551
|
}
|
|
2566
2552
|
updateLernaVersion({
|
|
@@ -2571,19 +2557,76 @@ async function bumpSelectiveMode({
|
|
|
2571
2557
|
});
|
|
2572
2558
|
if (!dryRun) {
|
|
2573
2559
|
logger.info(
|
|
2574
|
-
`${
|
|
2560
|
+
`${packages.length} package(s) bumped to ${newVersion}`
|
|
2575
2561
|
);
|
|
2576
2562
|
}
|
|
2577
2563
|
return {
|
|
2578
2564
|
bumped: true,
|
|
2579
2565
|
oldVersion: currentVersion,
|
|
2566
|
+
rootPackage,
|
|
2580
2567
|
fromTag: from,
|
|
2581
2568
|
newVersion,
|
|
2582
|
-
bumpedPackages:
|
|
2569
|
+
bumpedPackages: packages.map((pkg) => ({
|
|
2583
2570
|
...pkg,
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2571
|
+
oldVersion: pkg.version,
|
|
2572
|
+
fromTag: from,
|
|
2573
|
+
newVersion
|
|
2574
|
+
}))
|
|
2575
|
+
};
|
|
2576
|
+
}
|
|
2577
|
+
async function bumpIndependentMode({
|
|
2578
|
+
config,
|
|
2579
|
+
dryRun,
|
|
2580
|
+
suffix,
|
|
2581
|
+
force
|
|
2582
|
+
}) {
|
|
2583
|
+
logger.debug("Starting bump in independent mode");
|
|
2584
|
+
const packagesToBump = await getPackages({
|
|
2585
|
+
config,
|
|
2586
|
+
patterns: config.monorepo?.packages,
|
|
2587
|
+
suffix,
|
|
2588
|
+
force
|
|
2589
|
+
});
|
|
2590
|
+
if (packagesToBump.length === 0) {
|
|
2591
|
+
logger.debug("No packages have commits");
|
|
2592
|
+
return { bumped: false };
|
|
2593
|
+
}
|
|
2594
|
+
if (!config.bump.yes) {
|
|
2595
|
+
await confirmBump({
|
|
2596
|
+
versionMode: "independent",
|
|
2597
|
+
config,
|
|
2598
|
+
packages: packagesToBump,
|
|
2599
|
+
force,
|
|
2600
|
+
dryRun
|
|
2601
|
+
});
|
|
2602
|
+
} else {
|
|
2603
|
+
const bumpedByCommits2 = packagesToBump.filter((p) => p.reason === "commits").length;
|
|
2604
|
+
const bumpedByDependency2 = packagesToBump.filter((p) => p.reason === "dependency").length;
|
|
2605
|
+
const bumpedByGraduation = packagesToBump.filter((p) => p.reason === "graduation").length;
|
|
2606
|
+
logger.info(
|
|
2607
|
+
`${bumpedByCommits2 + bumpedByDependency2 + bumpedByGraduation} package(s) will be bumped independently (${bumpedByCommits2} from commits, ${bumpedByDependency2} from dependencies, ${bumpedByGraduation} from graduation)`
|
|
2608
|
+
);
|
|
2609
|
+
}
|
|
2610
|
+
const bumpedPackages = getBumpedIndependentPackages({
|
|
2611
|
+
packages: packagesToBump,
|
|
2612
|
+
dryRun
|
|
2613
|
+
});
|
|
2614
|
+
const bumpedByCommits = bumpedPackages.filter(
|
|
2615
|
+
(p) => packagesToBump.find((pkg) => pkg.name === p.name)?.reason === "commits"
|
|
2616
|
+
).length;
|
|
2617
|
+
const bumpedByDependency = bumpedPackages.length - bumpedByCommits;
|
|
2618
|
+
if (bumpedPackages.length === 0) {
|
|
2619
|
+
logger.debug("No packages were bumped");
|
|
2620
|
+
} else {
|
|
2621
|
+
logger.info(
|
|
2622
|
+
`${dryRun ? "[dry-run] " : ""}${bumpedPackages.length} package(s) bumped independently (${bumpedByCommits} from commits, ${bumpedByDependency} from dependencies)`
|
|
2623
|
+
);
|
|
2624
|
+
}
|
|
2625
|
+
return {
|
|
2626
|
+
bumped: bumpedPackages.length > 0,
|
|
2627
|
+
bumpedPackages: bumpedPackages.map((pkg) => ({
|
|
2628
|
+
...pkg,
|
|
2629
|
+
oldVersion: pkg.version
|
|
2587
2630
|
}))
|
|
2588
2631
|
};
|
|
2589
2632
|
}
|
|
@@ -2613,7 +2656,7 @@ async function bump(options = {}) {
|
|
|
2613
2656
|
}
|
|
2614
2657
|
await fetchGitTags(config.cwd);
|
|
2615
2658
|
logger.info(`Version mode: ${config.monorepo?.versionMode || "standalone"}`);
|
|
2616
|
-
const packages =
|
|
2659
|
+
const packages = readPackages({
|
|
2617
2660
|
cwd: config.cwd,
|
|
2618
2661
|
patterns: config.monorepo?.packages,
|
|
2619
2662
|
ignorePackageNames: config.monorepo?.ignorePackageNames
|
|
@@ -2622,7 +2665,6 @@ async function bump(options = {}) {
|
|
|
2622
2665
|
let result;
|
|
2623
2666
|
const payload = {
|
|
2624
2667
|
config,
|
|
2625
|
-
packages,
|
|
2626
2668
|
dryRun,
|
|
2627
2669
|
force,
|
|
2628
2670
|
suffix: options.suffix
|
|
@@ -2651,17 +2693,20 @@ async function bump(options = {}) {
|
|
|
2651
2693
|
}
|
|
2652
2694
|
}
|
|
2653
2695
|
|
|
2654
|
-
function getPackagesToGenerateChangelogFor({
|
|
2696
|
+
async function getPackagesToGenerateChangelogFor({
|
|
2655
2697
|
config,
|
|
2656
|
-
|
|
2698
|
+
bumpResult,
|
|
2699
|
+
suffix,
|
|
2700
|
+
force
|
|
2657
2701
|
}) {
|
|
2658
|
-
if (bumpedPackages && bumpedPackages.length > 0) {
|
|
2659
|
-
return bumpedPackages;
|
|
2702
|
+
if (bumpResult?.bumpedPackages && bumpResult.bumpedPackages.length > 0) {
|
|
2703
|
+
return bumpResult.bumpedPackages;
|
|
2660
2704
|
}
|
|
2661
|
-
return getPackages({
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2705
|
+
return await getPackages({
|
|
2706
|
+
config,
|
|
2707
|
+
patterns: config.monorepo?.packages,
|
|
2708
|
+
suffix,
|
|
2709
|
+
force
|
|
2665
2710
|
});
|
|
2666
2711
|
}
|
|
2667
2712
|
async function generateIndependentRootChangelog({
|
|
@@ -2674,39 +2719,16 @@ async function generateIndependentRootChangelog({
|
|
|
2674
2719
|
return;
|
|
2675
2720
|
}
|
|
2676
2721
|
logger.debug("Generating aggregated root changelog for independent mode");
|
|
2677
|
-
const rootPackage = getRootPackage(config.cwd);
|
|
2678
2722
|
const packageChangelogs = [];
|
|
2679
2723
|
for (const pkg of packages) {
|
|
2680
|
-
const { from, to } = await resolveTags({
|
|
2681
|
-
config,
|
|
2682
|
-
versionMode: "independent",
|
|
2683
|
-
step: "changelog",
|
|
2684
|
-
currentVersion: pkg.version,
|
|
2685
|
-
newVersion: void 0,
|
|
2686
|
-
pkg,
|
|
2687
|
-
logLevel: config.logLevel
|
|
2688
|
-
});
|
|
2689
|
-
const lastTag = from;
|
|
2690
|
-
logger.debug(`Generating changelog for ${pkg.name} (${lastTag}...${to})`);
|
|
2691
|
-
const commits = await getPackageCommits({
|
|
2692
|
-
pkg,
|
|
2693
|
-
from: lastTag,
|
|
2694
|
-
to,
|
|
2695
|
-
config,
|
|
2696
|
-
changelog: true
|
|
2697
|
-
});
|
|
2698
2724
|
const changelog2 = await generateChangelog({
|
|
2699
|
-
config,
|
|
2700
2725
|
pkg,
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2726
|
+
config,
|
|
2727
|
+
dryRun,
|
|
2728
|
+
newVersion: isBumpedPackage(pkg) && pkg.newVersion || pkg.version
|
|
2704
2729
|
});
|
|
2705
2730
|
if (changelog2) {
|
|
2706
|
-
|
|
2707
|
-
packageChangelogs.push(`## ${pkg.name}@${pkg.version}
|
|
2708
|
-
|
|
2709
|
-
${cleanedChangelog}`);
|
|
2731
|
+
packageChangelogs.push(changelog2);
|
|
2710
2732
|
}
|
|
2711
2733
|
}
|
|
2712
2734
|
if (packageChangelogs.length === 0) {
|
|
@@ -2718,7 +2740,9 @@ ${cleanedChangelog}`);
|
|
|
2718
2740
|
|
|
2719
2741
|
${packageChangelogs.join("\n\n")}`;
|
|
2720
2742
|
logger.verbose(`Aggregated root changelog: ${aggregatedChangelog}`);
|
|
2743
|
+
const rootPackage = readPackageJson(config.cwd);
|
|
2721
2744
|
writeChangelogToFile({
|
|
2745
|
+
cwd: config.cwd,
|
|
2722
2746
|
pkg: rootPackage,
|
|
2723
2747
|
changelog: aggregatedChangelog,
|
|
2724
2748
|
dryRun
|
|
@@ -2727,41 +2751,43 @@ ${packageChangelogs.join("\n\n")}`;
|
|
|
2727
2751
|
}
|
|
2728
2752
|
async function generateSimpleRootChangelog({
|
|
2729
2753
|
config,
|
|
2730
|
-
dryRun
|
|
2754
|
+
dryRun,
|
|
2755
|
+
force,
|
|
2756
|
+
suffix,
|
|
2757
|
+
bumpResult
|
|
2731
2758
|
}) {
|
|
2732
2759
|
if (!config.changelog?.rootChangelog) {
|
|
2733
2760
|
logger.debug("Skipping root changelog generation");
|
|
2734
2761
|
return;
|
|
2735
2762
|
}
|
|
2736
2763
|
logger.debug("Generating simple root changelog");
|
|
2737
|
-
const
|
|
2764
|
+
const rootPackageRead = readPackageJson(config.cwd);
|
|
2738
2765
|
const { from, to } = await resolveTags({
|
|
2739
2766
|
config,
|
|
2740
|
-
versionMode: config.monorepo?.versionMode || "unified",
|
|
2741
2767
|
step: "changelog",
|
|
2742
|
-
currentVersion: rootPackage.version,
|
|
2743
2768
|
newVersion: void 0,
|
|
2744
|
-
pkg:
|
|
2745
|
-
logLevel: config.logLevel
|
|
2769
|
+
pkg: rootPackageRead
|
|
2746
2770
|
});
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
const rootCommits = await getPackageCommits({
|
|
2750
|
-
pkg: rootPackage,
|
|
2751
|
-
from,
|
|
2752
|
-
to,
|
|
2771
|
+
const fromTag = bumpResult?.fromTag || from;
|
|
2772
|
+
const rootPackage = bumpResult?.rootPackage || await getRootPackage({
|
|
2753
2773
|
config,
|
|
2754
|
-
|
|
2774
|
+
force,
|
|
2775
|
+
suffix,
|
|
2776
|
+
changelog: true,
|
|
2777
|
+
from: fromTag,
|
|
2778
|
+
to
|
|
2755
2779
|
});
|
|
2780
|
+
logger.debug(`Generating ${rootPackage.name} changelog (${fromTag}...${to})`);
|
|
2781
|
+
const newVersion = bumpResult?.newVersion || rootPackage.version;
|
|
2756
2782
|
const rootChangelog = await generateChangelog({
|
|
2757
2783
|
pkg: rootPackage,
|
|
2758
|
-
commits: rootCommits,
|
|
2759
2784
|
config,
|
|
2760
|
-
|
|
2761
|
-
|
|
2785
|
+
dryRun,
|
|
2786
|
+
newVersion
|
|
2762
2787
|
});
|
|
2763
2788
|
if (rootChangelog) {
|
|
2764
2789
|
writeChangelogToFile({
|
|
2790
|
+
cwd: config.cwd,
|
|
2765
2791
|
changelog: rootChangelog,
|
|
2766
2792
|
pkg: rootPackage,
|
|
2767
2793
|
dryRun
|
|
@@ -2791,56 +2817,57 @@ async function changelog(options = {}) {
|
|
|
2791
2817
|
try {
|
|
2792
2818
|
await executeHook("before:changelog", config, dryRun);
|
|
2793
2819
|
logger.start("Start generating changelogs");
|
|
2794
|
-
const packages = getPackagesToGenerateChangelogFor({
|
|
2795
|
-
config,
|
|
2796
|
-
bumpedPackages: options.bumpedPackages
|
|
2797
|
-
});
|
|
2798
2820
|
if (config.changelog?.rootChangelog && config.monorepo) {
|
|
2799
2821
|
if (config.monorepo.versionMode === "independent") {
|
|
2822
|
+
const packages2 = await getPackagesToGenerateChangelogFor({
|
|
2823
|
+
config,
|
|
2824
|
+
bumpResult: options.bumpResult,
|
|
2825
|
+
suffix: options.suffix,
|
|
2826
|
+
force: options.force ?? false
|
|
2827
|
+
});
|
|
2800
2828
|
await generateIndependentRootChangelog({
|
|
2801
|
-
packages,
|
|
2829
|
+
packages: packages2,
|
|
2802
2830
|
config,
|
|
2803
2831
|
dryRun
|
|
2804
2832
|
});
|
|
2805
2833
|
} else {
|
|
2806
2834
|
await generateSimpleRootChangelog({
|
|
2807
2835
|
config,
|
|
2808
|
-
dryRun
|
|
2836
|
+
dryRun,
|
|
2837
|
+
bumpResult: options.bumpResult,
|
|
2838
|
+
suffix: options.suffix,
|
|
2839
|
+
force: options.force ?? false
|
|
2809
2840
|
});
|
|
2810
2841
|
}
|
|
2811
2842
|
} else {
|
|
2812
2843
|
logger.debug("Skipping root changelog generation");
|
|
2813
2844
|
}
|
|
2814
2845
|
logger.debug("Generating package changelogs...");
|
|
2846
|
+
const packages = options.bumpResult?.bumpedPackages ? options.bumpResult.bumpedPackages : await getPackages({
|
|
2847
|
+
config,
|
|
2848
|
+
patterns: config.monorepo?.packages,
|
|
2849
|
+
suffix: options.suffix,
|
|
2850
|
+
force: options.force ?? false
|
|
2851
|
+
});
|
|
2815
2852
|
logger.debug(`Processing ${packages.length} package(s)`);
|
|
2816
2853
|
let generatedCount = 0;
|
|
2817
2854
|
for await (const pkg of packages) {
|
|
2818
2855
|
const { from, to } = await resolveTags({
|
|
2819
2856
|
config,
|
|
2820
|
-
versionMode: config.monorepo?.versionMode || "unified",
|
|
2821
2857
|
step: "changelog",
|
|
2822
|
-
currentVersion: pkg.version,
|
|
2823
|
-
newVersion: void 0,
|
|
2824
2858
|
pkg,
|
|
2825
|
-
|
|
2859
|
+
newVersion: void 0
|
|
2826
2860
|
});
|
|
2827
2861
|
logger.debug(`Processing ${pkg.name} (${from}...${to})`);
|
|
2828
|
-
const commits = await getPackageCommits({
|
|
2829
|
-
pkg,
|
|
2830
|
-
from,
|
|
2831
|
-
to,
|
|
2832
|
-
config,
|
|
2833
|
-
changelog: true
|
|
2834
|
-
});
|
|
2835
2862
|
const changelog2 = await generateChangelog({
|
|
2836
2863
|
pkg,
|
|
2837
|
-
commits,
|
|
2838
2864
|
config,
|
|
2839
|
-
|
|
2840
|
-
|
|
2865
|
+
dryRun,
|
|
2866
|
+
newVersion: options.bumpResult?.bumpedPackages?.find((p) => p.name === pkg.name)?.newVersion
|
|
2841
2867
|
});
|
|
2842
2868
|
if (changelog2) {
|
|
2843
2869
|
writeChangelogToFile({
|
|
2870
|
+
cwd: config.cwd,
|
|
2844
2871
|
pkg,
|
|
2845
2872
|
changelog: changelog2,
|
|
2846
2873
|
dryRun
|
|
@@ -2889,7 +2916,7 @@ async function providerRelease(options = {}) {
|
|
|
2889
2916
|
configName: options.configName,
|
|
2890
2917
|
baseConfig: options.config,
|
|
2891
2918
|
overrides: {
|
|
2892
|
-
from: options.from
|
|
2919
|
+
from: options.from,
|
|
2893
2920
|
to: options.to,
|
|
2894
2921
|
tokens: {
|
|
2895
2922
|
github: options.token,
|
|
@@ -2903,12 +2930,12 @@ async function providerRelease(options = {}) {
|
|
|
2903
2930
|
logger.debug(`Dry run: ${dryRun}`);
|
|
2904
2931
|
logger.info(`Version mode: ${config.monorepo?.versionMode || "standalone"}`);
|
|
2905
2932
|
try {
|
|
2906
|
-
await executeHook("before:provider-release", config, dryRun);
|
|
2907
2933
|
const detectedProvider = options.provider || detectGitProvider();
|
|
2908
2934
|
providerReleaseSafetyCheck({ config, provider: detectedProvider });
|
|
2935
|
+
await executeHook("before:provider-release", config, dryRun);
|
|
2909
2936
|
logger.start("Start provider release");
|
|
2910
2937
|
if (!detectedProvider) {
|
|
2911
|
-
logger.
|
|
2938
|
+
logger.fail("Unable to detect Git provider. Skipping release publication.");
|
|
2912
2939
|
throw new Error("Unable to detect Git provider");
|
|
2913
2940
|
} else {
|
|
2914
2941
|
logger.info(
|
|
@@ -2917,19 +2944,21 @@ async function providerRelease(options = {}) {
|
|
|
2917
2944
|
}
|
|
2918
2945
|
let postedReleases = [];
|
|
2919
2946
|
const payload = {
|
|
2920
|
-
from: config.from,
|
|
2947
|
+
from: config.from || options.bumpResult?.fromTag,
|
|
2921
2948
|
to: config.to,
|
|
2922
2949
|
dryRun,
|
|
2923
2950
|
config,
|
|
2924
2951
|
logLevel: config.logLevel,
|
|
2925
|
-
bumpResult: options.bumpResult
|
|
2952
|
+
bumpResult: options.bumpResult,
|
|
2953
|
+
force: options.force ?? false,
|
|
2954
|
+
suffix: options.suffix
|
|
2926
2955
|
};
|
|
2927
2956
|
if (detectedProvider === "github") {
|
|
2928
2957
|
postedReleases = await github(payload);
|
|
2929
2958
|
} else if (detectedProvider === "gitlab") {
|
|
2930
2959
|
postedReleases = await gitlab(payload);
|
|
2931
2960
|
} else {
|
|
2932
|
-
logger.
|
|
2961
|
+
logger.error(`Unsupported Git provider: ${detectedProvider}`);
|
|
2933
2962
|
}
|
|
2934
2963
|
await executeHook("success:provider-release", config, dryRun);
|
|
2935
2964
|
return {
|
|
@@ -2973,17 +3002,17 @@ async function publish(options = {}) {
|
|
|
2973
3002
|
}
|
|
2974
3003
|
try {
|
|
2975
3004
|
await executeHook("before:publish", config, dryRun);
|
|
3005
|
+
const rootPackage = readPackageJson(config.cwd);
|
|
2976
3006
|
logger.start("Start publishing packages");
|
|
2977
|
-
const packages = options.bumpedPackages || getPackages({
|
|
2978
|
-
|
|
3007
|
+
const packages = options.bumpedPackages || await getPackages({
|
|
3008
|
+
config,
|
|
2979
3009
|
patterns: config.publish.packages ?? config.monorepo?.packages,
|
|
2980
|
-
|
|
3010
|
+
suffix: options.suffix,
|
|
3011
|
+
force: options.force ?? false
|
|
2981
3012
|
});
|
|
2982
|
-
const rootPackage = getRootPackage(config.cwd);
|
|
2983
3013
|
logger.debug(`Found ${packages.length} package(s)`);
|
|
2984
3014
|
logger.debug("Building dependency graph and sorting...");
|
|
2985
|
-
const
|
|
2986
|
-
const sortedPackages = topologicalSort(packagesWithDeps);
|
|
3015
|
+
const sortedPackages = topologicalSort(packages);
|
|
2987
3016
|
let publishedPackages = packages || [];
|
|
2988
3017
|
if (publishedPackages.length === 0 && config.monorepo?.versionMode === "independent") {
|
|
2989
3018
|
logger.debug("Determining packages to publish in independent mode...");
|
|
@@ -3000,7 +3029,7 @@ async function publish(options = {}) {
|
|
|
3000
3029
|
logger.info(`Publishing ${publishedPackages.length} package(s) (unified mode)`);
|
|
3001
3030
|
}
|
|
3002
3031
|
if (publishedPackages.length === 0) {
|
|
3003
|
-
logger.
|
|
3032
|
+
logger.fail("No packages need to be published");
|
|
3004
3033
|
return;
|
|
3005
3034
|
}
|
|
3006
3035
|
await executeBuildCmd({
|
|
@@ -3009,7 +3038,7 @@ async function publish(options = {}) {
|
|
|
3009
3038
|
});
|
|
3010
3039
|
for (const pkg of sortedPackages) {
|
|
3011
3040
|
if (publishedPackages.some((p) => p.name === pkg.name)) {
|
|
3012
|
-
logger.debug(`Publishing ${pkg
|
|
3041
|
+
logger.debug(`Publishing ${getIndependentTag(pkg)}...`);
|
|
3013
3042
|
await publishPackage({
|
|
3014
3043
|
pkg,
|
|
3015
3044
|
config,
|
|
@@ -3104,7 +3133,8 @@ async function release(options = {}) {
|
|
|
3104
3133
|
config,
|
|
3105
3134
|
force,
|
|
3106
3135
|
clean: config.release.clean,
|
|
3107
|
-
configName: options.configName
|
|
3136
|
+
configName: options.configName,
|
|
3137
|
+
suffix: options.suffix
|
|
3108
3138
|
});
|
|
3109
3139
|
if (!bumpResult.bumped) {
|
|
3110
3140
|
logger.debug("No packages bumped");
|
|
@@ -3118,10 +3148,12 @@ async function release(options = {}) {
|
|
|
3118
3148
|
dryRun,
|
|
3119
3149
|
formatCmd: config.changelog.formatCmd,
|
|
3120
3150
|
rootChangelog: config.changelog.rootChangelog,
|
|
3121
|
-
|
|
3151
|
+
bumpResult,
|
|
3122
3152
|
config,
|
|
3123
3153
|
logLevel: config.logLevel,
|
|
3124
|
-
configName: options.configName
|
|
3154
|
+
configName: options.configName,
|
|
3155
|
+
force,
|
|
3156
|
+
suffix: options.suffix
|
|
3125
3157
|
});
|
|
3126
3158
|
} else {
|
|
3127
3159
|
logger.info("Skipping changelog generation (--no-changelog)");
|
|
@@ -3164,7 +3196,9 @@ async function release(options = {}) {
|
|
|
3164
3196
|
bumpedPackages: bumpResult.bumpedPackages,
|
|
3165
3197
|
dryRun,
|
|
3166
3198
|
config,
|
|
3167
|
-
configName: options.configName
|
|
3199
|
+
configName: options.configName,
|
|
3200
|
+
suffix: options.suffix,
|
|
3201
|
+
force
|
|
3168
3202
|
});
|
|
3169
3203
|
} else {
|
|
3170
3204
|
logger.info("Skipping publish (--no-publish)");
|
|
@@ -3184,7 +3218,9 @@ async function release(options = {}) {
|
|
|
3184
3218
|
config,
|
|
3185
3219
|
logLevel: config.logLevel,
|
|
3186
3220
|
bumpResult,
|
|
3187
|
-
configName: options.configName
|
|
3221
|
+
configName: options.configName,
|
|
3222
|
+
force,
|
|
3223
|
+
suffix: options.suffix
|
|
3188
3224
|
});
|
|
3189
3225
|
provider = response.detectedProvider;
|
|
3190
3226
|
postedReleases = response.postedReleases;
|
|
@@ -3195,7 +3231,7 @@ async function release(options = {}) {
|
|
|
3195
3231
|
logger.info("Skipping release (--no-provider-release)");
|
|
3196
3232
|
}
|
|
3197
3233
|
const publishedPackageCount = publishResponse?.publishedPackages.length ?? 0;
|
|
3198
|
-
const versionDisplay = config.monorepo?.versionMode === "independent" ? `${bumpResult.bumpedPackages.length} packages bumped independently` : bumpResult.newVersion ||
|
|
3234
|
+
const versionDisplay = config.monorepo?.versionMode === "independent" ? `${bumpResult.bumpedPackages.length} packages bumped independently` : bumpResult.newVersion || readPackageJson(config.cwd).version;
|
|
3199
3235
|
logger.box(`Release workflow completed!
|
|
3200
3236
|
|
|
3201
3237
|
Version: ${versionDisplay}
|
|
@@ -3212,4 +3248,4 @@ Git provider: ${provider}`);
|
|
|
3212
3248
|
}
|
|
3213
3249
|
}
|
|
3214
3250
|
|
|
3215
|
-
export {
|
|
3251
|
+
export { writeVersion as $, createGitlabRelease as A, gitlab as B, detectPackageManager as C, determinePublishTag as D, getPackagesToPublishInSelectiveMode as E, getPackagesToPublishInIndependentMode as F, publishPackage as G, readPackageJson as H, getRootPackage as I, readPackages as J, getPackages as K, getPackageCommits as L, hasLernaJson as M, getIndependentTag as N, getLastStableTag as O, getLastTag as P, getLastRepoTag as Q, getLastPackageTag as R, resolveTags as S, executeHook as T, isInCI as U, getCIName as V, executeFormatCmd as W, executeBuildCmd as X, isBumpedPackage as Y, determineSemverChange as Z, determineReleaseType as _, providerRelease as a, getPackageNewVersion as a0, updateLernaVersion as a1, extractVersionFromPackageTag as a2, isPrerelease as a3, isStableReleaseType as a4, isPrereleaseReleaseType as a5, isGraduating as a6, getPreid as a7, isChangedPreid as a8, getBumpedPackageIndependently as a9, confirmBump as aa, getBumpedIndependentPackages as ab, bump as b, changelog as c, publish as d, getDefaultConfig as e, defineConfig as f, generateChangelog as g, getPackageDependencies as h, getDependentsOf as i, expandPackagesToBumpWithDependents as j, getGitStatus as k, loadRelizyConfig as l, checkGitStatusIfDirty as m, fetchGitTags as n, detectGitProvider as o, providerReleaseSafetyCheck as p, parseGitRemoteUrl as q, release as r, createCommitAndTags as s, topologicalSort as t, pushCommitAndTags as u, getFirstCommit as v, writeChangelogToFile as w, getCurrentGitBranch as x, getCurrentGitRef as y, github as z };
|