relizy 0.2.4 → 0.2.5-beta.1
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/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.ukhs2-Vt.mjs → relizy.DYn3rUjq.mjs} +1358 -1323
- package/package.json +2 -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,406 @@ 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 = /^[AMDTUXB](?:\d{3})?\s+/.test(trimmedLine) || /^[RCM]\d{3}\s+/.test(trimmedLine);
|
|
486
|
+
return !isFileLine;
|
|
487
|
+
});
|
|
488
|
+
if (contentLines.length === 0) {
|
|
489
|
+
return "";
|
|
490
|
+
}
|
|
491
|
+
const indentedBody = contentLines.map((line) => ` ${line}`).join("\n");
|
|
492
|
+
return `
|
|
493
|
+
|
|
494
|
+
${indentedBody}
|
|
495
|
+
`;
|
|
496
|
+
}
|
|
497
|
+
function formatCommit(commit, config) {
|
|
498
|
+
const body = config.changelog.includeCommitBody ? getCommitBody(commit) : "";
|
|
499
|
+
return `- ${commit.scope ? `**${commit.scope.trim()}:** ` : ""}${commit.isBreaking ? "\u26A0\uFE0F " : ""}${upperFirst(commit.description)}${formatReferences(commit.references, config)}${body}`;
|
|
500
|
+
}
|
|
501
|
+
function formatReferences(references, config) {
|
|
502
|
+
const pr = references.filter((ref) => ref.type === "pull-request");
|
|
503
|
+
const issue = references.filter((ref) => ref.type === "issue");
|
|
504
|
+
if (pr.length > 0 || issue.length > 0) {
|
|
505
|
+
return ` (${[...pr, ...issue].map((ref) => formatReference(ref, config.repo)).join(", ")})`;
|
|
506
|
+
}
|
|
507
|
+
if (references.length > 0) {
|
|
508
|
+
return ` (${formatReference(references[0], config.repo)})`;
|
|
509
|
+
}
|
|
510
|
+
return "";
|
|
511
|
+
}
|
|
512
|
+
function formatName(name = "") {
|
|
513
|
+
return name.split(" ").map((p) => upperFirst(p.trim())).join(" ");
|
|
514
|
+
}
|
|
515
|
+
function groupBy(items, key) {
|
|
516
|
+
const groups = {};
|
|
517
|
+
for (const item of items) {
|
|
518
|
+
groups[item[key]] = groups[item[key]] || [];
|
|
519
|
+
groups[item[key]]?.push(item);
|
|
520
|
+
}
|
|
521
|
+
return groups;
|
|
522
|
+
}
|
|
294
523
|
|
|
295
524
|
function fromTagIsFirstCommit(fromTag, cwd) {
|
|
296
525
|
return fromTag === getFirstCommit(cwd);
|
|
297
526
|
}
|
|
298
527
|
async function generateChangelog({
|
|
299
528
|
pkg,
|
|
300
|
-
commits,
|
|
301
529
|
config,
|
|
302
|
-
|
|
303
|
-
|
|
530
|
+
dryRun,
|
|
531
|
+
newVersion
|
|
304
532
|
}) {
|
|
305
|
-
let fromTag = config.from ||
|
|
533
|
+
let fromTag = config.from || pkg.fromTag || getFirstCommit(config.cwd);
|
|
306
534
|
const isFirstCommit = fromTagIsFirstCommit(fromTag, config.cwd);
|
|
307
535
|
if (isFirstCommit) {
|
|
308
|
-
fromTag = config.monorepo?.versionMode === "independent" ?
|
|
536
|
+
fromTag = config.monorepo?.versionMode === "independent" ? getIndependentTag({ version: "0.0.0", name: pkg.name }) : config.templates.tagBody.replace("{{newVersion}}", "0.0.0");
|
|
537
|
+
}
|
|
538
|
+
newVersion = newVersion || pkg.newVersion;
|
|
539
|
+
let toTag = config.to;
|
|
540
|
+
if (!toTag && newVersion) {
|
|
541
|
+
toTag = config.monorepo?.versionMode === "independent" ? getIndependentTag({ version: newVersion, name: pkg.name }) : config.templates.tagBody.replace("{{newVersion}}", newVersion);
|
|
542
|
+
}
|
|
543
|
+
if (!toTag) {
|
|
544
|
+
throw new Error(`No tag found for ${pkg.name}`);
|
|
309
545
|
}
|
|
310
|
-
const toTag = config.to || (config.monorepo?.versionMode === "independent" ? `${pkg.name}@${pkg.version}` : config.templates.tagBody.replace("{{newVersion}}", pkg.version));
|
|
311
546
|
logger.debug(`Generating changelog for ${pkg.name} - from ${fromTag} to ${toTag}`);
|
|
312
547
|
try {
|
|
313
548
|
config = {
|
|
@@ -316,25 +551,26 @@ async function generateChangelog({
|
|
|
316
551
|
to: toTag
|
|
317
552
|
};
|
|
318
553
|
const generatedChangelog = await generateMarkDown({
|
|
319
|
-
commits,
|
|
554
|
+
commits: pkg.commits,
|
|
320
555
|
config,
|
|
321
556
|
from: fromTag,
|
|
557
|
+
isFirstCommit,
|
|
322
558
|
to: toTag
|
|
323
559
|
});
|
|
324
560
|
let changelog = generatedChangelog;
|
|
325
|
-
if (commits.length === 0) {
|
|
561
|
+
if (pkg.commits.length === 0) {
|
|
326
562
|
changelog = `${changelog}
|
|
327
563
|
|
|
328
564
|
${config.templates.emptyChangelogContent}`;
|
|
329
565
|
}
|
|
330
566
|
const changelogResult = await executeHook("generate:changelog", config, dryRun, {
|
|
331
|
-
commits,
|
|
567
|
+
commits: pkg.commits,
|
|
332
568
|
changelog
|
|
333
569
|
});
|
|
334
570
|
changelog = changelogResult || changelog;
|
|
335
571
|
logger.verbose(`Output changelog for ${pkg.name}:
|
|
336
572
|
${changelog}`);
|
|
337
|
-
logger.debug(`Changelog generated for ${pkg.name} (${commits.length} commits)`);
|
|
573
|
+
logger.debug(`Changelog generated for ${pkg.name} (${pkg.commits.length} commits)`);
|
|
338
574
|
logger.verbose(`Final changelog for ${pkg.name}:
|
|
339
575
|
|
|
340
576
|
${changelog}
|
|
@@ -349,6 +585,7 @@ ${changelog}
|
|
|
349
585
|
}
|
|
350
586
|
}
|
|
351
587
|
function writeChangelogToFile({
|
|
588
|
+
cwd,
|
|
352
589
|
pkg,
|
|
353
590
|
changelog,
|
|
354
591
|
dryRun = false
|
|
@@ -372,11 +609,12 @@ ${changelog}
|
|
|
372
609
|
${existingChangelog}`;
|
|
373
610
|
}
|
|
374
611
|
if (dryRun) {
|
|
375
|
-
|
|
612
|
+
const relativeChangelogPath = relative(cwd, changelogPath);
|
|
613
|
+
logger.info(`[dry-run] ${pkg.name} - Write changelog to ${relativeChangelogPath}`);
|
|
376
614
|
} else {
|
|
377
615
|
logger.debug(`Writing changelog to ${changelogPath}`);
|
|
378
616
|
writeFileSync(changelogPath, updatedChangelog, "utf8");
|
|
379
|
-
logger.info(`Changelog updated for ${pkg.name}`);
|
|
617
|
+
logger.info(`Changelog updated for ${pkg.name} (${"newVersion" in pkg && pkg.newVersion || pkg.version})`);
|
|
380
618
|
}
|
|
381
619
|
}
|
|
382
620
|
|
|
@@ -398,8 +636,8 @@ function getDefaultConfig() {
|
|
|
398
636
|
ci: { title: "\u{1F916} CI" }
|
|
399
637
|
},
|
|
400
638
|
templates: {
|
|
401
|
-
commitMessage: "chore(release): bump version to
|
|
402
|
-
tagMessage: "Bump version to
|
|
639
|
+
commitMessage: "chore(release): bump version to {{newVersion}}",
|
|
640
|
+
tagMessage: "Bump version to {{newVersion}}",
|
|
403
641
|
tagBody: "v{{newVersion}}",
|
|
404
642
|
emptyChangelogContent: "No relevant changes for this release"
|
|
405
643
|
},
|
|
@@ -490,7 +728,11 @@ function defineConfig(config) {
|
|
|
490
728
|
return config;
|
|
491
729
|
}
|
|
492
730
|
|
|
493
|
-
function getPackageDependencies(
|
|
731
|
+
function getPackageDependencies({
|
|
732
|
+
packagePath,
|
|
733
|
+
allPackageNames,
|
|
734
|
+
dependencyTypes
|
|
735
|
+
}) {
|
|
494
736
|
const packageJsonPath = join(packagePath, "package.json");
|
|
495
737
|
if (!existsSync(packageJsonPath)) {
|
|
496
738
|
return [];
|
|
@@ -509,32 +751,26 @@ function getPackageDependencies(packagePath, allPackageNames, dependencyTypes) {
|
|
|
509
751
|
}
|
|
510
752
|
return deps;
|
|
511
753
|
}
|
|
512
|
-
function
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
dependencies: getPackageDependencies(pkg.path, allPackageNames, dependencyTypes)
|
|
517
|
-
}));
|
|
518
|
-
}
|
|
519
|
-
function getDependentsOf(packageName, allPackages) {
|
|
754
|
+
function getDependentsOf({
|
|
755
|
+
allPackages,
|
|
756
|
+
packageName
|
|
757
|
+
}) {
|
|
520
758
|
return allPackages.filter(
|
|
521
759
|
(pkg) => pkg.dependencies.includes(packageName)
|
|
522
760
|
);
|
|
523
761
|
}
|
|
524
762
|
function expandPackagesToBumpWithDependents({
|
|
525
|
-
packagesWithCommits,
|
|
526
763
|
allPackages,
|
|
527
|
-
|
|
764
|
+
packagesWithCommits
|
|
528
765
|
}) {
|
|
529
|
-
const packagesWithDeps = getPackagesWithDependencies(allPackages, dependencyTypes);
|
|
530
766
|
const result = /* @__PURE__ */ new Map();
|
|
531
767
|
logger.debug(`Expanding packages to bump: ${packagesWithCommits.length} packages with commits, ${allPackages.length} total packages`);
|
|
532
768
|
for (const pkg of packagesWithCommits) {
|
|
533
|
-
|
|
769
|
+
const packageToBump = {
|
|
534
770
|
...pkg,
|
|
535
|
-
reason: "commits"
|
|
536
|
-
|
|
537
|
-
|
|
771
|
+
reason: "commits"
|
|
772
|
+
};
|
|
773
|
+
result.set(pkg.name, packageToBump);
|
|
538
774
|
}
|
|
539
775
|
const toProcess = [...packagesWithCommits.map((p) => p.name)];
|
|
540
776
|
const processed = /* @__PURE__ */ new Set();
|
|
@@ -544,19 +780,22 @@ function expandPackagesToBumpWithDependents({
|
|
|
544
780
|
continue;
|
|
545
781
|
}
|
|
546
782
|
processed.add(currentPkgName);
|
|
547
|
-
const dependents = getDependentsOf(
|
|
783
|
+
const dependents = getDependentsOf({
|
|
784
|
+
packageName: currentPkgName,
|
|
785
|
+
allPackages
|
|
786
|
+
});
|
|
548
787
|
for (const dependent of dependents) {
|
|
549
788
|
if (!result.has(dependent.name)) {
|
|
550
789
|
const currentChain = result.get(currentPkgName)?.dependencyChain || [];
|
|
551
790
|
const chain = [...currentChain, currentPkgName];
|
|
552
|
-
const
|
|
553
|
-
if (
|
|
554
|
-
|
|
555
|
-
...
|
|
791
|
+
const packageBase = allPackages.find((p) => p.name === dependent.name);
|
|
792
|
+
if (packageBase) {
|
|
793
|
+
const packageToBump = {
|
|
794
|
+
...packageBase,
|
|
556
795
|
reason: "dependency",
|
|
557
|
-
dependencyChain: chain
|
|
558
|
-
|
|
559
|
-
|
|
796
|
+
dependencyChain: chain
|
|
797
|
+
};
|
|
798
|
+
result.set(dependent.name, packageToBump);
|
|
560
799
|
toProcess.push(dependent.name);
|
|
561
800
|
logger.debug(`${dependent.name} will be bumped (depends on ${chain.join(" \u2192 ")})`);
|
|
562
801
|
}
|
|
@@ -577,7 +816,7 @@ function topologicalSort(packages) {
|
|
|
577
816
|
if (visited.has(pkgName))
|
|
578
817
|
return;
|
|
579
818
|
if (visiting.has(pkgName)) {
|
|
580
|
-
logger.
|
|
819
|
+
logger.fail(`Circular dependency detected involving ${pkgName}`);
|
|
581
820
|
return;
|
|
582
821
|
}
|
|
583
822
|
visiting.add(pkgName);
|
|
@@ -597,229 +836,12 @@ function topologicalSort(packages) {
|
|
|
597
836
|
return sorted;
|
|
598
837
|
}
|
|
599
838
|
|
|
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
839
|
async function githubIndependentMode({
|
|
820
840
|
config,
|
|
821
841
|
dryRun,
|
|
822
|
-
|
|
842
|
+
bumpResult,
|
|
843
|
+
force,
|
|
844
|
+
suffix
|
|
823
845
|
}) {
|
|
824
846
|
const repoConfig = config.repo;
|
|
825
847
|
if (!repoConfig) {
|
|
@@ -829,42 +851,36 @@ async function githubIndependentMode({
|
|
|
829
851
|
if (!config.tokens.github && !config.repo?.token) {
|
|
830
852
|
throw new Error("No GitHub token specified. Set GITHUB_TOKEN or GH_TOKEN environment variable.");
|
|
831
853
|
}
|
|
832
|
-
const packages = bumpedPackages || getPackages({
|
|
833
|
-
|
|
854
|
+
const packages = bumpResult?.bumped && bumpResult?.bumpedPackages || await getPackages({
|
|
855
|
+
suffix,
|
|
834
856
|
patterns: config.monorepo?.packages,
|
|
835
|
-
|
|
857
|
+
config,
|
|
858
|
+
force
|
|
836
859
|
});
|
|
837
860
|
logger.info(`Creating ${packages.length} GitHub release(s)`);
|
|
838
861
|
const postedReleases = [];
|
|
839
862
|
for (const pkg of packages) {
|
|
840
|
-
const
|
|
841
|
-
const from = pkg.fromTag;
|
|
863
|
+
const newVersion = isBumpedPackage(pkg) && pkg.newVersion || pkg.version;
|
|
864
|
+
const from = config.from || pkg.fromTag;
|
|
865
|
+
const to = config.to || getIndependentTag({ version: newVersion, name: pkg.name });
|
|
842
866
|
if (!from) {
|
|
843
|
-
logger.warn(`No
|
|
867
|
+
logger.warn(`No from tag found for ${pkg.name}, skipping release`);
|
|
844
868
|
continue;
|
|
845
869
|
}
|
|
846
870
|
const toTag = dryRun ? "HEAD" : to;
|
|
847
871
|
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
872
|
const changelog = await generateChangelog({
|
|
856
873
|
pkg,
|
|
857
|
-
commits,
|
|
858
874
|
config,
|
|
859
|
-
|
|
860
|
-
|
|
875
|
+
dryRun,
|
|
876
|
+
newVersion
|
|
861
877
|
});
|
|
862
878
|
const releaseBody = changelog.split("\n").slice(2).join("\n");
|
|
863
879
|
const release = {
|
|
864
880
|
tag_name: to,
|
|
865
881
|
name: to,
|
|
866
882
|
body: releaseBody,
|
|
867
|
-
prerelease: isPrerelease(
|
|
883
|
+
prerelease: isPrerelease(newVersion)
|
|
868
884
|
};
|
|
869
885
|
logger.debug(`Creating release for ${to}${release.prerelease ? " (prerelease)" : ""}`);
|
|
870
886
|
if (dryRun) {
|
|
@@ -872,7 +888,7 @@ async function githubIndependentMode({
|
|
|
872
888
|
postedReleases.push({
|
|
873
889
|
name: pkg.name,
|
|
874
890
|
tag: release.tag_name,
|
|
875
|
-
version:
|
|
891
|
+
version: newVersion,
|
|
876
892
|
prerelease: release.prerelease
|
|
877
893
|
});
|
|
878
894
|
} else {
|
|
@@ -886,7 +902,7 @@ async function githubIndependentMode({
|
|
|
886
902
|
postedReleases.push({
|
|
887
903
|
name: pkg.name,
|
|
888
904
|
tag: release.tag_name,
|
|
889
|
-
version:
|
|
905
|
+
version: newVersion,
|
|
890
906
|
prerelease: release.prerelease
|
|
891
907
|
});
|
|
892
908
|
}
|
|
@@ -912,21 +928,12 @@ async function githubUnified({
|
|
|
912
928
|
if (!config.tokens.github && !config.repo?.token) {
|
|
913
929
|
throw new Error("No GitHub token specified. Set GITHUB_TOKEN or GH_TOKEN environment variable.");
|
|
914
930
|
}
|
|
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
|
-
});
|
|
931
|
+
const to = config.to || config.templates.tagBody.replace("{{newVersion}}", bumpResult?.bumped && bumpResult.newVersion || rootPackage.version);
|
|
924
932
|
const changelog = await generateChangelog({
|
|
925
933
|
pkg: rootPackage,
|
|
926
|
-
commits,
|
|
927
934
|
config,
|
|
928
|
-
|
|
929
|
-
|
|
935
|
+
dryRun,
|
|
936
|
+
newVersion: bumpResult?.newVersion || rootPackage.version
|
|
930
937
|
});
|
|
931
938
|
const releaseBody = changelog.split("\n").slice(2).join("\n");
|
|
932
939
|
const release = {
|
|
@@ -947,7 +954,7 @@ async function githubUnified({
|
|
|
947
954
|
logger.debug("Publishing release to GitHub...");
|
|
948
955
|
await createGithubRelease({
|
|
949
956
|
...config,
|
|
950
|
-
from: bumpResult?.fromTag || "v0.0.0",
|
|
957
|
+
from: bumpResult?.bumped && bumpResult.fromTag || "v0.0.0",
|
|
951
958
|
to,
|
|
952
959
|
repo: repoConfig
|
|
953
960
|
}, release);
|
|
@@ -960,7 +967,7 @@ async function githubUnified({
|
|
|
960
967
|
prerelease: release.prerelease
|
|
961
968
|
}];
|
|
962
969
|
}
|
|
963
|
-
async function github(options
|
|
970
|
+
async function github(options) {
|
|
964
971
|
try {
|
|
965
972
|
const dryRun = options.dryRun ?? false;
|
|
966
973
|
logger.debug(`Dry run: ${dryRun}`);
|
|
@@ -976,18 +983,30 @@ async function github(options = {}) {
|
|
|
976
983
|
}
|
|
977
984
|
}
|
|
978
985
|
});
|
|
979
|
-
if (!options.bumpResult?.bumped) {
|
|
980
|
-
logger.warn("No bump result found, skipping release");
|
|
981
|
-
return [];
|
|
982
|
-
}
|
|
983
986
|
if (config.monorepo?.versionMode === "independent") {
|
|
984
|
-
return await githubIndependentMode({
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
987
|
+
return await githubIndependentMode({
|
|
988
|
+
config,
|
|
989
|
+
dryRun,
|
|
990
|
+
bumpResult: options.bumpResult,
|
|
991
|
+
force: options.force ?? false,
|
|
992
|
+
suffix: options.suffix
|
|
993
|
+
});
|
|
990
994
|
}
|
|
995
|
+
const rootPackageBase = readPackageJson(config.cwd);
|
|
996
|
+
const { from, to } = await resolveTags({
|
|
997
|
+
config,
|
|
998
|
+
step: "provider-release",
|
|
999
|
+
newVersion: options.bumpResult?.newVersion || rootPackageBase.version,
|
|
1000
|
+
pkg: rootPackageBase
|
|
1001
|
+
});
|
|
1002
|
+
const rootPackage = options.bumpResult?.rootPackage || await getRootPackage({
|
|
1003
|
+
config,
|
|
1004
|
+
force: options.force ?? false,
|
|
1005
|
+
suffix: options.suffix,
|
|
1006
|
+
changelog: true,
|
|
1007
|
+
from,
|
|
1008
|
+
to
|
|
1009
|
+
});
|
|
991
1010
|
return await githubUnified({
|
|
992
1011
|
config,
|
|
993
1012
|
dryRun,
|
|
@@ -1064,13 +1083,16 @@ async function createGitlabRelease({
|
|
|
1064
1083
|
async function gitlabIndependentMode({
|
|
1065
1084
|
config,
|
|
1066
1085
|
dryRun,
|
|
1067
|
-
|
|
1086
|
+
bumpResult,
|
|
1087
|
+
suffix,
|
|
1088
|
+
force
|
|
1068
1089
|
}) {
|
|
1069
1090
|
logger.debug(`GitLab token: ${config.tokens.gitlab || config.repo?.token ? "\u2713 provided" : "\u2717 missing"}`);
|
|
1070
|
-
const packages = bumpedPackages || getPackages({
|
|
1071
|
-
cwd: config.cwd,
|
|
1091
|
+
const packages = bumpResult?.bumped && bumpResult?.bumpedPackages || await getPackages({
|
|
1072
1092
|
patterns: config.monorepo?.packages,
|
|
1073
|
-
|
|
1093
|
+
config,
|
|
1094
|
+
suffix,
|
|
1095
|
+
force
|
|
1074
1096
|
});
|
|
1075
1097
|
logger.info(`Creating ${packages.length} GitLab release(s) for independent packages`);
|
|
1076
1098
|
logger.debug("Getting current branch...");
|
|
@@ -1082,26 +1104,19 @@ async function gitlabIndependentMode({
|
|
|
1082
1104
|
});
|
|
1083
1105
|
const postedReleases = [];
|
|
1084
1106
|
for (const pkg of packages) {
|
|
1085
|
-
const
|
|
1086
|
-
const from = pkg.fromTag;
|
|
1107
|
+
const newVersion = isBumpedPackage(pkg) && pkg.newVersion || pkg.version;
|
|
1108
|
+
const from = config.from || pkg.fromTag;
|
|
1109
|
+
const to = getIndependentTag({ version: newVersion, name: pkg.name });
|
|
1087
1110
|
if (!from) {
|
|
1088
|
-
logger.warn(`No
|
|
1111
|
+
logger.warn(`No from tag found for ${pkg.name}, skipping release`);
|
|
1089
1112
|
continue;
|
|
1090
1113
|
}
|
|
1091
1114
|
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
1115
|
const changelog = await generateChangelog({
|
|
1100
1116
|
pkg,
|
|
1101
|
-
commits,
|
|
1102
1117
|
config,
|
|
1103
|
-
|
|
1104
|
-
|
|
1118
|
+
dryRun,
|
|
1119
|
+
newVersion
|
|
1105
1120
|
});
|
|
1106
1121
|
if (!changelog) {
|
|
1107
1122
|
logger.warn(`No changelog found for ${pkg.name}`);
|
|
@@ -1114,335 +1129,186 @@ async function gitlabIndependentMode({
|
|
|
1114
1129
|
description: releaseBody,
|
|
1115
1130
|
ref: currentBranch.trim()
|
|
1116
1131
|
};
|
|
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}`);
|
|
1132
|
+
logger.debug(`Creating release for ${to} (ref: ${release.ref})`);
|
|
1133
|
+
if (dryRun) {
|
|
1134
|
+
logger.info(`[dry-run] Publish GitLab release for ${to}`);
|
|
1135
|
+
} else {
|
|
1136
|
+
logger.debug(`Publishing release ${to} to GitLab...`);
|
|
1137
|
+
await createGitlabRelease({
|
|
1138
|
+
config,
|
|
1139
|
+
release,
|
|
1140
|
+
dryRun
|
|
1141
|
+
});
|
|
1142
|
+
postedReleases.push({
|
|
1143
|
+
name: pkg.name,
|
|
1144
|
+
tag: release.tag_name,
|
|
1145
|
+
version: newVersion,
|
|
1146
|
+
prerelease: isPrerelease(newVersion)
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1381
1149
|
}
|
|
1150
|
+
if (postedReleases.length === 0) {
|
|
1151
|
+
logger.warn("No releases created");
|
|
1152
|
+
} else {
|
|
1153
|
+
logger.success(`Releases ${postedReleases.map((r) => r.tag).join(", ")} published to GitLab!`);
|
|
1154
|
+
}
|
|
1155
|
+
return postedReleases;
|
|
1382
1156
|
}
|
|
1383
|
-
function
|
|
1384
|
-
const lernaJsonPath = join(rootDir, "lerna.json");
|
|
1385
|
-
return existsSync(lernaJsonPath);
|
|
1386
|
-
}
|
|
1387
|
-
async function getPackageToBump({
|
|
1388
|
-
packages,
|
|
1157
|
+
async function gitlabUnified({
|
|
1389
1158
|
config,
|
|
1390
|
-
|
|
1391
|
-
|
|
1159
|
+
dryRun,
|
|
1160
|
+
rootPackage,
|
|
1161
|
+
bumpResult
|
|
1392
1162
|
}) {
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1163
|
+
logger.debug(`GitLab token: ${config.tokens.gitlab || config.repo?.token ? "\u2713 provided" : "\u2717 missing"}`);
|
|
1164
|
+
const to = config.templates.tagBody.replace("{{newVersion}}", rootPackage.newVersion || rootPackage.version);
|
|
1165
|
+
const changelog = await generateChangelog({
|
|
1166
|
+
pkg: rootPackage,
|
|
1167
|
+
config,
|
|
1168
|
+
dryRun,
|
|
1169
|
+
newVersion: bumpResult?.newVersion || rootPackage.version
|
|
1170
|
+
});
|
|
1171
|
+
const releaseBody = changelog.split("\n").slice(2).join("\n");
|
|
1172
|
+
logger.debug("Getting current branch...");
|
|
1173
|
+
const { stdout: currentBranch } = await execPromise("git rev-parse --abbrev-ref HEAD", {
|
|
1174
|
+
noSuccess: true,
|
|
1175
|
+
noStdout: true,
|
|
1176
|
+
logLevel: config.logLevel,
|
|
1177
|
+
cwd: config.cwd
|
|
1178
|
+
});
|
|
1179
|
+
const release = {
|
|
1180
|
+
tag_name: to,
|
|
1181
|
+
name: to,
|
|
1182
|
+
description: releaseBody,
|
|
1183
|
+
ref: currentBranch.trim()
|
|
1184
|
+
};
|
|
1185
|
+
logger.info(`Creating release for ${to} (ref: ${release.ref})`);
|
|
1186
|
+
logger.debug("Release details:", formatJson({
|
|
1187
|
+
tag_name: release.tag_name,
|
|
1188
|
+
name: release.name,
|
|
1189
|
+
ref: release.ref
|
|
1190
|
+
}));
|
|
1191
|
+
if (dryRun) {
|
|
1192
|
+
logger.info("[dry-run] Publish GitLab release for", release.tag_name);
|
|
1193
|
+
} else {
|
|
1194
|
+
logger.debug("Publishing release to GitLab...");
|
|
1195
|
+
await createGitlabRelease({
|
|
1399
1196
|
config,
|
|
1400
|
-
|
|
1197
|
+
release,
|
|
1198
|
+
dryRun
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
logger.success(`Release ${to} published to GitLab!`);
|
|
1202
|
+
return [{
|
|
1203
|
+
name: to,
|
|
1204
|
+
tag: to,
|
|
1205
|
+
version: to,
|
|
1206
|
+
prerelease: isPrerelease(rootPackage.version)
|
|
1207
|
+
}];
|
|
1208
|
+
}
|
|
1209
|
+
async function gitlab(options = {}) {
|
|
1210
|
+
try {
|
|
1211
|
+
const dryRun = options.dryRun ?? false;
|
|
1212
|
+
logger.debug(`Dry run: ${dryRun}`);
|
|
1213
|
+
const config = await loadRelizyConfig({
|
|
1214
|
+
configName: options.configName,
|
|
1215
|
+
baseConfig: options.config,
|
|
1216
|
+
overrides: {
|
|
1217
|
+
from: options.from,
|
|
1218
|
+
to: options.to,
|
|
1219
|
+
logLevel: options.logLevel,
|
|
1220
|
+
tokens: {
|
|
1221
|
+
gitlab: options.token
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1401
1224
|
});
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1225
|
+
if (config.monorepo?.versionMode === "independent") {
|
|
1226
|
+
return await gitlabIndependentMode({
|
|
1227
|
+
config,
|
|
1228
|
+
dryRun,
|
|
1229
|
+
bumpResult: options.bumpResult,
|
|
1230
|
+
suffix: options.suffix,
|
|
1231
|
+
force: options.force ?? false
|
|
1232
|
+
});
|
|
1405
1233
|
}
|
|
1234
|
+
const rootPackageBase = readPackageJson(config.cwd);
|
|
1235
|
+
const { from, to } = await resolveTags({
|
|
1236
|
+
config,
|
|
1237
|
+
step: "provider-release",
|
|
1238
|
+
newVersion: options.bumpResult?.newVersion || rootPackageBase.version,
|
|
1239
|
+
pkg: rootPackageBase
|
|
1240
|
+
});
|
|
1241
|
+
const rootPackage = options.bumpResult?.rootPackage || await getRootPackage({
|
|
1242
|
+
config,
|
|
1243
|
+
force: options.force ?? false,
|
|
1244
|
+
suffix: options.suffix,
|
|
1245
|
+
changelog: true,
|
|
1246
|
+
from,
|
|
1247
|
+
to
|
|
1248
|
+
});
|
|
1249
|
+
logger.debug(`Root package: ${getIndependentTag(rootPackage)}`);
|
|
1250
|
+
return await gitlabUnified({
|
|
1251
|
+
config,
|
|
1252
|
+
dryRun,
|
|
1253
|
+
rootPackage,
|
|
1254
|
+
bumpResult: options.bumpResult
|
|
1255
|
+
});
|
|
1256
|
+
} catch (error) {
|
|
1257
|
+
logger.error("Error publishing GitLab release:", error);
|
|
1258
|
+
throw error;
|
|
1406
1259
|
}
|
|
1407
|
-
const allPackagesToBump = expandPackagesToBumpWithDependents({
|
|
1408
|
-
allPackages: packages,
|
|
1409
|
-
packagesWithCommits,
|
|
1410
|
-
dependencyTypes: config.bump?.dependencyTypes
|
|
1411
|
-
});
|
|
1412
|
-
return allPackagesToBump;
|
|
1413
1260
|
}
|
|
1414
1261
|
|
|
1415
|
-
function
|
|
1416
|
-
|
|
1262
|
+
function determineSemverChange(commits, types) {
|
|
1263
|
+
let [hasMajor, hasMinor, hasPatch] = [false, false, false];
|
|
1264
|
+
for (const commit of commits) {
|
|
1265
|
+
const commitType = types[commit.type];
|
|
1266
|
+
if (!commitType) {
|
|
1267
|
+
continue;
|
|
1268
|
+
}
|
|
1269
|
+
const semverType = commitType.semver;
|
|
1270
|
+
if (semverType === "major" || commit.isBreaking) {
|
|
1271
|
+
hasMajor = true;
|
|
1272
|
+
} else if (semverType === "minor") {
|
|
1273
|
+
hasMinor = true;
|
|
1274
|
+
} else if (semverType === "patch") {
|
|
1275
|
+
hasPatch = true;
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
return hasMajor ? "major" : hasMinor ? "minor" : hasPatch ? "patch" : void 0;
|
|
1279
|
+
}
|
|
1280
|
+
function detectReleaseTypeFromCommits(commits, types) {
|
|
1281
|
+
return determineSemverChange(commits, types);
|
|
1417
1282
|
}
|
|
1418
1283
|
function validatePrereleaseDowngrade(currentVersion, targetPreid, configuredType) {
|
|
1419
1284
|
if (configuredType !== "prerelease" || !targetPreid || !isPrerelease(currentVersion)) {
|
|
1420
1285
|
return;
|
|
1421
1286
|
}
|
|
1422
1287
|
const testVersion = semver.inc(currentVersion, "prerelease", targetPreid);
|
|
1423
|
-
|
|
1288
|
+
const isNotUpgrade = testVersion && !semver.gt(testVersion, currentVersion);
|
|
1289
|
+
if (isNotUpgrade) {
|
|
1424
1290
|
throw new Error(`Unable to graduate from ${currentVersion} to ${testVersion}, it's not a valid prerelease`);
|
|
1425
1291
|
}
|
|
1426
1292
|
}
|
|
1427
|
-
function handleStableVersionWithReleaseType(commits,
|
|
1293
|
+
function handleStableVersionWithReleaseType(commits, types, force) {
|
|
1428
1294
|
if (!commits?.length && !force) {
|
|
1429
1295
|
logger.debug('No commits found for stable version with "release" type, skipping bump');
|
|
1430
|
-
return
|
|
1296
|
+
return void 0;
|
|
1431
1297
|
}
|
|
1432
|
-
const detectedType = commits?.length ? detectReleaseTypeFromCommits(commits,
|
|
1298
|
+
const detectedType = commits?.length ? detectReleaseTypeFromCommits(commits, types) : void 0;
|
|
1433
1299
|
if (!detectedType && !force) {
|
|
1434
1300
|
logger.debug("No significant commits found, skipping bump");
|
|
1435
|
-
return
|
|
1301
|
+
return void 0;
|
|
1436
1302
|
}
|
|
1437
1303
|
logger.debug(`Auto-detected release type from commits: ${detectedType}`);
|
|
1438
1304
|
return detectedType;
|
|
1439
1305
|
}
|
|
1440
|
-
function handleStableVersionWithPrereleaseType(commits,
|
|
1306
|
+
function handleStableVersionWithPrereleaseType(commits, types, force) {
|
|
1441
1307
|
if (!commits?.length && !force) {
|
|
1442
1308
|
logger.debug('No commits found for stable version with "prerelease" type, skipping bump');
|
|
1443
|
-
return
|
|
1309
|
+
return void 0;
|
|
1444
1310
|
}
|
|
1445
|
-
const detectedType = commits?.length ? detectReleaseTypeFromCommits(commits,
|
|
1311
|
+
const detectedType = commits?.length ? detectReleaseTypeFromCommits(commits, types) : void 0;
|
|
1446
1312
|
if (!detectedType) {
|
|
1447
1313
|
logger.debug("No significant commits found, using prepatch as default");
|
|
1448
1314
|
return "prepatch";
|
|
@@ -1455,83 +1321,73 @@ function handlePrereleaseVersionToStable(currentVersion) {
|
|
|
1455
1321
|
logger.debug(`Graduating from prerelease ${currentVersion} to stable release`);
|
|
1456
1322
|
return "release";
|
|
1457
1323
|
}
|
|
1458
|
-
function handlePrereleaseVersionWithPrereleaseType(currentVersion,
|
|
1324
|
+
function handlePrereleaseVersionWithPrereleaseType({ currentVersion, preid, commits, force }) {
|
|
1459
1325
|
const currentPreid = getPreid(currentVersion);
|
|
1460
|
-
const hasChangedPreid =
|
|
1326
|
+
const hasChangedPreid = preid && currentPreid && currentPreid !== preid;
|
|
1461
1327
|
if (hasChangedPreid) {
|
|
1462
|
-
const testVersion = semver.inc(currentVersion, "prerelease",
|
|
1328
|
+
const testVersion = semver.inc(currentVersion, "prerelease", preid);
|
|
1463
1329
|
if (!testVersion) {
|
|
1464
|
-
throw new Error(`Unable to change preid from ${currentPreid} to ${
|
|
1330
|
+
throw new Error(`Unable to change preid from ${currentPreid} to ${preid} for version ${currentVersion}`);
|
|
1465
1331
|
}
|
|
1466
1332
|
const isUpgrade = semver.gt(testVersion, currentVersion);
|
|
1467
1333
|
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 ${
|
|
1334
|
+
throw new Error(`Unable to change preid from ${currentVersion} to ${testVersion}, it's not a valid upgrade (cannot downgrade from ${currentPreid} to ${preid})`);
|
|
1469
1335
|
}
|
|
1470
1336
|
return "prerelease";
|
|
1471
1337
|
}
|
|
1472
1338
|
if (!commits?.length && !force) {
|
|
1473
1339
|
logger.debug("No commits found for prerelease version, skipping bump");
|
|
1474
|
-
return
|
|
1340
|
+
return void 0;
|
|
1475
1341
|
}
|
|
1476
1342
|
logger.debug(`Incrementing prerelease version: ${currentVersion}`);
|
|
1477
1343
|
return "prerelease";
|
|
1478
1344
|
}
|
|
1479
|
-
function handleExplicitReleaseType(
|
|
1345
|
+
function handleExplicitReleaseType({
|
|
1346
|
+
releaseType,
|
|
1347
|
+
currentVersion
|
|
1348
|
+
}) {
|
|
1480
1349
|
const isCurrentPrerelease = isPrerelease(currentVersion);
|
|
1481
|
-
const isGraduatingToStable = isCurrentPrerelease && isStableReleaseType(
|
|
1350
|
+
const isGraduatingToStable = isCurrentPrerelease && isStableReleaseType(releaseType);
|
|
1482
1351
|
if (isGraduatingToStable) {
|
|
1483
|
-
logger.debug(`Graduating from prerelease ${currentVersion} to stable with type: ${
|
|
1352
|
+
logger.debug(`Graduating from prerelease ${currentVersion} to stable with type: ${releaseType}`);
|
|
1484
1353
|
} else {
|
|
1485
|
-
logger.debug(`Using explicit release type: ${
|
|
1354
|
+
logger.debug(`Using explicit release type: ${releaseType}`);
|
|
1486
1355
|
}
|
|
1487
|
-
return
|
|
1356
|
+
return releaseType;
|
|
1488
1357
|
}
|
|
1489
1358
|
function determineReleaseType({
|
|
1490
1359
|
currentVersion,
|
|
1491
|
-
from,
|
|
1492
|
-
to,
|
|
1493
1360
|
commits,
|
|
1494
|
-
|
|
1361
|
+
releaseType,
|
|
1362
|
+
preid,
|
|
1363
|
+
types,
|
|
1495
1364
|
force
|
|
1496
1365
|
}) {
|
|
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) {
|
|
1366
|
+
if (releaseType === "release" && preid) {
|
|
1505
1367
|
throw new Error('You cannot use a "release" type with a "preid", to use a preid you must use a "prerelease" type');
|
|
1506
1368
|
}
|
|
1507
|
-
validatePrereleaseDowngrade(currentVersion,
|
|
1369
|
+
validatePrereleaseDowngrade(currentVersion, preid, releaseType);
|
|
1508
1370
|
if (force) {
|
|
1509
|
-
logger.debug(`Force flag enabled, using configured type: ${
|
|
1510
|
-
return
|
|
1371
|
+
logger.debug(`Force flag enabled, using configured type: ${releaseType}`);
|
|
1372
|
+
return releaseType;
|
|
1511
1373
|
}
|
|
1512
1374
|
const isCurrentPrerelease = isPrerelease(currentVersion);
|
|
1513
1375
|
if (!isCurrentPrerelease) {
|
|
1514
|
-
if (
|
|
1515
|
-
return handleStableVersionWithReleaseType(commits,
|
|
1376
|
+
if (releaseType === "release") {
|
|
1377
|
+
return handleStableVersionWithReleaseType(commits, types, force);
|
|
1516
1378
|
}
|
|
1517
|
-
if (
|
|
1518
|
-
return handleStableVersionWithPrereleaseType(commits,
|
|
1379
|
+
if (releaseType === "prerelease") {
|
|
1380
|
+
return handleStableVersionWithPrereleaseType(commits, types, force);
|
|
1519
1381
|
}
|
|
1520
|
-
return handleExplicitReleaseType(
|
|
1382
|
+
return handleExplicitReleaseType({ releaseType, currentVersion });
|
|
1521
1383
|
}
|
|
1522
|
-
if (
|
|
1384
|
+
if (releaseType === "release") {
|
|
1523
1385
|
return handlePrereleaseVersionToStable(currentVersion);
|
|
1524
1386
|
}
|
|
1525
|
-
if (
|
|
1526
|
-
return handlePrereleaseVersionWithPrereleaseType(
|
|
1527
|
-
currentVersion,
|
|
1528
|
-
targetPreid,
|
|
1529
|
-
commits,
|
|
1530
|
-
configWithRange,
|
|
1531
|
-
force
|
|
1532
|
-
);
|
|
1387
|
+
if (releaseType === "prerelease") {
|
|
1388
|
+
return handlePrereleaseVersionWithPrereleaseType({ currentVersion, preid, commits, force });
|
|
1533
1389
|
}
|
|
1534
|
-
return handleExplicitReleaseType(
|
|
1390
|
+
return handleExplicitReleaseType({ releaseType, currentVersion });
|
|
1535
1391
|
}
|
|
1536
1392
|
function writeVersion(pkgPath, version, dryRun = false) {
|
|
1537
1393
|
const packageJsonPath = join(pkgPath, "package.json");
|
|
@@ -1552,33 +1408,32 @@ function writeVersion(pkgPath, version, dryRun = false) {
|
|
|
1552
1408
|
throw new Error(`Unable to write version to ${packageJsonPath}: ${error}`);
|
|
1553
1409
|
}
|
|
1554
1410
|
}
|
|
1555
|
-
function
|
|
1411
|
+
function getPackageNewVersion({
|
|
1556
1412
|
currentVersion,
|
|
1557
1413
|
releaseType,
|
|
1558
1414
|
preid,
|
|
1559
1415
|
suffix
|
|
1560
1416
|
}) {
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
throw new Error(`Unable to bump version "${currentVersion}" with release type "${releaseType}"
|
|
1417
|
+
let newVersion = semver.inc(currentVersion, releaseType, preid);
|
|
1418
|
+
if (!newVersion) {
|
|
1419
|
+
throw new Error(`Unable to bump version "${currentVersion}" with release type "${releaseType}"
|
|
1565
1420
|
|
|
1566
1421
|
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
1422
|
}
|
|
1423
|
+
if (isPrereleaseReleaseType(releaseType) && suffix) {
|
|
1424
|
+
newVersion = newVersion.replace(/\.(\d+)$/, `.${suffix}`);
|
|
1425
|
+
}
|
|
1426
|
+
const isValidVersion = semver.gt(newVersion, currentVersion);
|
|
1427
|
+
if (!isValidVersion) {
|
|
1428
|
+
throw new Error(`Unable to bump version "${currentVersion}" to "${newVersion}", new version is not greater than current version`);
|
|
1429
|
+
}
|
|
1430
|
+
if (isGraduating(currentVersion, releaseType)) {
|
|
1431
|
+
logger.info(`Graduating from prerelease ${currentVersion} to stable ${newVersion}`);
|
|
1432
|
+
}
|
|
1433
|
+
if (isChangedPreid(currentVersion, preid)) {
|
|
1434
|
+
logger.info(`Graduating from ${getPreid(currentVersion)} to ${preid}`);
|
|
1435
|
+
}
|
|
1436
|
+
return newVersion;
|
|
1582
1437
|
}
|
|
1583
1438
|
function updateLernaVersion({
|
|
1584
1439
|
rootDir,
|
|
@@ -1612,7 +1467,7 @@ function updateLernaVersion({
|
|
|
1612
1467
|
`, "utf8");
|
|
1613
1468
|
logger.success(`Updated lerna.json: ${oldVersion} \u2192 ${version}`);
|
|
1614
1469
|
} catch (error) {
|
|
1615
|
-
logger.
|
|
1470
|
+
logger.fail(`Unable to update lerna.json: ${error}`);
|
|
1616
1471
|
}
|
|
1617
1472
|
}
|
|
1618
1473
|
function extractVersionFromPackageTag(tag) {
|
|
@@ -1658,13 +1513,16 @@ function isChangedPreid(currentVersion, targetPreid) {
|
|
|
1658
1513
|
}
|
|
1659
1514
|
return currentPreid !== targetPreid;
|
|
1660
1515
|
}
|
|
1661
|
-
function
|
|
1516
|
+
function getBumpedPackageIndependently({
|
|
1662
1517
|
pkg,
|
|
1663
1518
|
dryRun
|
|
1664
1519
|
}) {
|
|
1665
1520
|
logger.debug(`Analyzing ${pkg.name}`);
|
|
1666
1521
|
const currentVersion = pkg.version || "0.0.0";
|
|
1667
|
-
const newVersion = pkg.
|
|
1522
|
+
const newVersion = pkg.newVersion;
|
|
1523
|
+
if (!newVersion) {
|
|
1524
|
+
return { bumped: false };
|
|
1525
|
+
}
|
|
1668
1526
|
logger.debug(`Bumping ${pkg.name} from ${currentVersion} to ${newVersion}`);
|
|
1669
1527
|
writeVersion(pkg.path, newVersion, dryRun);
|
|
1670
1528
|
return { bumped: true, newVersion, oldVersion: currentVersion };
|
|
@@ -1690,9 +1548,9 @@ function displayUnifiedModePackages({
|
|
|
1690
1548
|
newVersion,
|
|
1691
1549
|
force
|
|
1692
1550
|
}) {
|
|
1693
|
-
logger.log(`${packages.length} package(s)
|
|
1551
|
+
logger.log(`${packages.length} package(s):`);
|
|
1694
1552
|
packages.forEach((pkg) => {
|
|
1695
|
-
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion}`);
|
|
1553
|
+
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion} ${force ? "(force)" : ""}`);
|
|
1696
1554
|
});
|
|
1697
1555
|
logger.log("");
|
|
1698
1556
|
}
|
|
@@ -1702,14 +1560,15 @@ function displaySelectiveModePackages({
|
|
|
1702
1560
|
force
|
|
1703
1561
|
}) {
|
|
1704
1562
|
if (force) {
|
|
1705
|
-
logger.log(`${packages.length} package(s)
|
|
1563
|
+
logger.log(`${packages.length} package(s):`);
|
|
1706
1564
|
packages.forEach((pkg) => {
|
|
1707
|
-
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion}`);
|
|
1565
|
+
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion} (force)`);
|
|
1708
1566
|
});
|
|
1709
1567
|
logger.log("");
|
|
1710
1568
|
} else {
|
|
1711
1569
|
const packagesWithCommits = packages.filter((p) => "reason" in p && p.reason === "commits");
|
|
1712
1570
|
const packagesAsDependents = packages.filter((p) => "reason" in p && p.reason === "dependency");
|
|
1571
|
+
const packagesAsGraduation = packages.filter((p) => "reason" in p && p.reason === "graduation");
|
|
1713
1572
|
if (packagesWithCommits.length > 0) {
|
|
1714
1573
|
logger.log(`${packagesWithCommits.length} package(s) with commits:`);
|
|
1715
1574
|
packagesWithCommits.forEach((pkg) => {
|
|
@@ -1724,33 +1583,47 @@ function displaySelectiveModePackages({
|
|
|
1724
1583
|
});
|
|
1725
1584
|
logger.log("");
|
|
1726
1585
|
}
|
|
1586
|
+
if (packagesAsGraduation.length > 0) {
|
|
1587
|
+
logger.log(`${packagesAsGraduation.length} graduation package(s):`);
|
|
1588
|
+
packagesAsGraduation.forEach((pkg) => {
|
|
1589
|
+
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion}`);
|
|
1590
|
+
});
|
|
1591
|
+
logger.log("");
|
|
1592
|
+
}
|
|
1727
1593
|
}
|
|
1728
1594
|
}
|
|
1729
1595
|
function displayIndependentModePackages({
|
|
1730
1596
|
packages,
|
|
1731
|
-
force
|
|
1732
|
-
dryRun
|
|
1597
|
+
force
|
|
1733
1598
|
}) {
|
|
1734
1599
|
if (force) {
|
|
1735
|
-
logger.log(`${
|
|
1600
|
+
logger.log(`${packages.length} package(s):`);
|
|
1736
1601
|
packages.forEach((pkg) => {
|
|
1737
|
-
logger.log(` \u2022 ${pkg.name}: ${pkg.
|
|
1602
|
+
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion} (force)`);
|
|
1738
1603
|
});
|
|
1739
1604
|
logger.log("");
|
|
1740
1605
|
} else {
|
|
1741
1606
|
const packagesWithCommits = packages.filter((p) => "reason" in p && p.reason === "commits");
|
|
1742
1607
|
const packagesAsDependents = packages.filter((p) => "reason" in p && p.reason === "dependency");
|
|
1608
|
+
const packagesAsGraduation = packages.filter((p) => "reason" in p && p.reason === "graduation");
|
|
1743
1609
|
if (packagesWithCommits.length > 0) {
|
|
1744
|
-
logger.log(`${
|
|
1610
|
+
logger.log(`${packagesWithCommits.length} package(s) with commits:`);
|
|
1745
1611
|
packagesWithCommits.forEach((pkg) => {
|
|
1746
|
-
logger.log(` \u2022 ${pkg.name}: ${pkg.
|
|
1612
|
+
pkg.newVersion && logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion}`);
|
|
1747
1613
|
});
|
|
1748
1614
|
logger.log("");
|
|
1749
1615
|
}
|
|
1750
1616
|
if (packagesAsDependents.length > 0) {
|
|
1751
|
-
logger.log(`${
|
|
1617
|
+
logger.log(`${packagesAsDependents.length} dependent package(s):`);
|
|
1752
1618
|
packagesAsDependents.forEach((pkg) => {
|
|
1753
|
-
logger.log(` \u2022 ${pkg.name}: ${pkg.
|
|
1619
|
+
pkg.newVersion && logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion}`);
|
|
1620
|
+
});
|
|
1621
|
+
logger.log("");
|
|
1622
|
+
}
|
|
1623
|
+
if (packagesAsGraduation.length > 0) {
|
|
1624
|
+
logger.log(`${packagesAsGraduation.length} graduation package(s):`);
|
|
1625
|
+
packagesAsGraduation.forEach((pkg) => {
|
|
1626
|
+
pkg.newVersion && logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion}`);
|
|
1754
1627
|
});
|
|
1755
1628
|
logger.log("");
|
|
1756
1629
|
}
|
|
@@ -1765,6 +1638,10 @@ async function confirmBump({
|
|
|
1765
1638
|
newVersion,
|
|
1766
1639
|
dryRun
|
|
1767
1640
|
}) {
|
|
1641
|
+
if (packages.length === 0) {
|
|
1642
|
+
logger.debug("No packages to bump");
|
|
1643
|
+
return;
|
|
1644
|
+
}
|
|
1768
1645
|
const lernaJsonExists = hasLernaJson(config.cwd);
|
|
1769
1646
|
logger.log("");
|
|
1770
1647
|
logger.info(`${dryRun ? "[dry-run] " : ""}The following packages will be updated:
|
|
@@ -1776,220 +1653,100 @@ async function confirmBump({
|
|
|
1776
1653
|
lernaJsonExists,
|
|
1777
1654
|
dryRun
|
|
1778
1655
|
});
|
|
1779
|
-
if (versionMode === "unified"
|
|
1656
|
+
if (versionMode === "unified") {
|
|
1657
|
+
if (!newVersion) {
|
|
1658
|
+
logger.error("Cannot confirm bump in unified mode without a new version");
|
|
1659
|
+
process.exit(1);
|
|
1660
|
+
}
|
|
1780
1661
|
displayUnifiedModePackages({ packages, newVersion, force });
|
|
1781
|
-
} else if (versionMode === "selective"
|
|
1662
|
+
} else if (versionMode === "selective") {
|
|
1663
|
+
if (!newVersion) {
|
|
1664
|
+
logger.error("Cannot confirm bump in selective mode without a new version");
|
|
1665
|
+
process.exit(1);
|
|
1666
|
+
}
|
|
1782
1667
|
displaySelectiveModePackages({ packages, newVersion, force });
|
|
1783
1668
|
} else if (versionMode === "independent") {
|
|
1784
|
-
displayIndependentModePackages({ packages, force
|
|
1669
|
+
displayIndependentModePackages({ packages, force });
|
|
1785
1670
|
}
|
|
1786
1671
|
try {
|
|
1787
1672
|
const confirmed = await confirm({
|
|
1788
1673
|
message: `${dryRun ? "[dry-run] " : ""}Do you want to proceed with these version updates?`,
|
|
1789
1674
|
default: true
|
|
1790
1675
|
});
|
|
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 [];
|
|
1676
|
+
if (!confirmed) {
|
|
1677
|
+
logger.log("");
|
|
1678
|
+
logger.fail("Bump refused");
|
|
1679
|
+
process.exit(0);
|
|
1680
|
+
}
|
|
1681
|
+
} catch (error) {
|
|
1682
|
+
const userHasExited = error instanceof Error && error.name === "ExitPromptError";
|
|
1683
|
+
if (userHasExited) {
|
|
1684
|
+
logger.log("");
|
|
1685
|
+
logger.fail("Bump cancelled");
|
|
1686
|
+
process.exit(0);
|
|
1687
|
+
}
|
|
1688
|
+
logger.fail("Error while confirming bump");
|
|
1689
|
+
process.exit(1);
|
|
1928
1690
|
}
|
|
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;
|
|
1691
|
+
logger.log("");
|
|
1943
1692
|
}
|
|
1944
|
-
function
|
|
1693
|
+
function getBumpedIndependentPackages({
|
|
1945
1694
|
packages,
|
|
1946
1695
|
dryRun
|
|
1947
1696
|
}) {
|
|
1948
1697
|
const bumpedPackages = [];
|
|
1949
1698
|
for (const pkgToBump of packages) {
|
|
1950
|
-
logger.debug(`Bumping ${pkgToBump.name} from ${pkgToBump.
|
|
1951
|
-
const result =
|
|
1699
|
+
logger.debug(`Bumping ${pkgToBump.name} from ${pkgToBump.version} to ${pkgToBump.newVersion} (reason: ${pkgToBump.reason})`);
|
|
1700
|
+
const result = getBumpedPackageIndependently({
|
|
1952
1701
|
pkg: pkgToBump,
|
|
1953
1702
|
dryRun
|
|
1954
1703
|
});
|
|
1955
1704
|
if (result.bumped) {
|
|
1956
1705
|
bumpedPackages.push({
|
|
1957
1706
|
...pkgToBump,
|
|
1958
|
-
version: result.
|
|
1707
|
+
version: result.oldVersion
|
|
1959
1708
|
});
|
|
1960
1709
|
}
|
|
1961
1710
|
}
|
|
1962
1711
|
return bumpedPackages;
|
|
1963
1712
|
}
|
|
1964
1713
|
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1714
|
+
function getIndependentTag({ version, name }) {
|
|
1715
|
+
return `${name}@${version}`;
|
|
1716
|
+
}
|
|
1717
|
+
async function getLastStableTag({ logLevel, cwd }) {
|
|
1718
|
+
const { stdout } = await execPromise(
|
|
1719
|
+
`git tag --sort=-creatordate | grep -E '^[^0-9]*[0-9]+\\.[0-9]+\\.[0-9]+$' | head -n 1`,
|
|
1720
|
+
{
|
|
1721
|
+
logLevel,
|
|
1722
|
+
noStderr: true,
|
|
1723
|
+
noStdout: true,
|
|
1724
|
+
noSuccess: true,
|
|
1725
|
+
cwd
|
|
1726
|
+
}
|
|
1727
|
+
);
|
|
1728
|
+
const lastTag = stdout.trim();
|
|
1729
|
+
logger.debug("Last stable tag:", lastTag || "No stable tags found");
|
|
1730
|
+
return lastTag;
|
|
1731
|
+
}
|
|
1732
|
+
async function getLastTag({ logLevel, cwd }) {
|
|
1982
1733
|
const { stdout } = await execPromise(`git tag --sort=-creatordate | head -n 1`, {
|
|
1983
|
-
logLevel
|
|
1734
|
+
logLevel,
|
|
1984
1735
|
noStderr: true,
|
|
1985
1736
|
noStdout: true,
|
|
1986
1737
|
noSuccess: true,
|
|
1987
|
-
cwd
|
|
1738
|
+
cwd
|
|
1988
1739
|
});
|
|
1989
|
-
lastTag = stdout.trim();
|
|
1740
|
+
const lastTag = stdout.trim();
|
|
1990
1741
|
logger.debug("Last tag:", lastTag || "No tags found");
|
|
1991
1742
|
return lastTag;
|
|
1992
1743
|
}
|
|
1744
|
+
function getLastRepoTag(options) {
|
|
1745
|
+
if (options?.onlyStable) {
|
|
1746
|
+
return getLastStableTag({ logLevel: options?.logLevel, cwd: options?.cwd });
|
|
1747
|
+
}
|
|
1748
|
+
return getLastTag({ logLevel: options?.logLevel, cwd: options?.cwd });
|
|
1749
|
+
}
|
|
1993
1750
|
async function getLastPackageTag({
|
|
1994
1751
|
packageName,
|
|
1995
1752
|
onlyStable,
|
|
@@ -2020,88 +1777,111 @@ async function getLastPackageTag({
|
|
|
2020
1777
|
return null;
|
|
2021
1778
|
}
|
|
2022
1779
|
}
|
|
2023
|
-
async function
|
|
1780
|
+
async function resolveFromTagIndependent({
|
|
2024
1781
|
cwd,
|
|
2025
|
-
|
|
1782
|
+
packageName,
|
|
2026
1783
|
graduating,
|
|
2027
|
-
newVersion,
|
|
2028
|
-
step,
|
|
2029
1784
|
logLevel
|
|
2030
1785
|
}) {
|
|
2031
|
-
let to;
|
|
2032
|
-
if (step === "bump") {
|
|
2033
|
-
to = getCurrentGitRef(cwd);
|
|
2034
|
-
} else {
|
|
2035
|
-
to = newVersion ? `${pkg.name}@${newVersion}` : getCurrentGitRef(cwd);
|
|
2036
|
-
}
|
|
2037
1786
|
const lastPackageTag = await getLastPackageTag({
|
|
2038
|
-
packageName
|
|
1787
|
+
packageName,
|
|
2039
1788
|
onlyStable: graduating,
|
|
2040
1789
|
logLevel
|
|
2041
1790
|
});
|
|
2042
1791
|
if (!lastPackageTag) {
|
|
2043
|
-
|
|
2044
|
-
return { from, to };
|
|
1792
|
+
return getFirstCommit(cwd);
|
|
2045
1793
|
}
|
|
2046
|
-
return
|
|
1794
|
+
return lastPackageTag;
|
|
2047
1795
|
}
|
|
2048
|
-
async function
|
|
1796
|
+
async function resolveFromTagUnified({
|
|
2049
1797
|
config,
|
|
2050
|
-
newVersion,
|
|
2051
1798
|
graduating,
|
|
2052
|
-
step,
|
|
2053
1799
|
logLevel
|
|
2054
1800
|
}) {
|
|
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
1801
|
const from = await getLastRepoTag({ onlyStable: graduating, logLevel }) || getFirstCommit(config.cwd);
|
|
2062
|
-
return
|
|
1802
|
+
return from;
|
|
2063
1803
|
}
|
|
2064
|
-
async function
|
|
1804
|
+
async function resolveFromTag({
|
|
2065
1805
|
config,
|
|
2066
1806
|
versionMode,
|
|
2067
1807
|
step,
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
newVersion,
|
|
1808
|
+
packageName,
|
|
1809
|
+
graduating,
|
|
2071
1810
|
logLevel
|
|
2072
1811
|
}) {
|
|
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
|
-
}
|
|
1812
|
+
let from;
|
|
2084
1813
|
if (versionMode === "independent") {
|
|
2085
|
-
|
|
1814
|
+
if (!packageName) {
|
|
1815
|
+
throw new Error("Package name is required for independent version mode");
|
|
1816
|
+
}
|
|
1817
|
+
from = await resolveFromTagIndependent({
|
|
2086
1818
|
cwd: config.cwd,
|
|
2087
|
-
|
|
1819
|
+
packageName,
|
|
1820
|
+
graduating,
|
|
1821
|
+
logLevel
|
|
1822
|
+
});
|
|
1823
|
+
} else {
|
|
1824
|
+
from = await resolveFromTagUnified({
|
|
1825
|
+
config,
|
|
2088
1826
|
graduating,
|
|
2089
|
-
newVersion,
|
|
2090
|
-
step,
|
|
2091
1827
|
logLevel
|
|
2092
1828
|
});
|
|
2093
|
-
logger.debug(`[${versionMode}](${step}) Using tags: ${tags2.from} \u2192 ${tags2.to}`);
|
|
2094
|
-
return tags2;
|
|
2095
1829
|
}
|
|
2096
|
-
|
|
1830
|
+
logger.debug(`[${versionMode}](${step}) Using from tag: ${from}`);
|
|
1831
|
+
return config.from || from;
|
|
1832
|
+
}
|
|
1833
|
+
function resolveToTag({
|
|
1834
|
+
config,
|
|
1835
|
+
versionMode,
|
|
1836
|
+
newVersion,
|
|
1837
|
+
step,
|
|
1838
|
+
packageName
|
|
1839
|
+
}) {
|
|
1840
|
+
const isUntaggedStep = step === "bump" || step === "changelog";
|
|
1841
|
+
let to;
|
|
1842
|
+
if (isUntaggedStep) {
|
|
1843
|
+
to = getCurrentGitRef(config.cwd);
|
|
1844
|
+
} else if (versionMode === "independent") {
|
|
1845
|
+
if (!packageName) {
|
|
1846
|
+
throw new Error("Package name is required for independent version mode");
|
|
1847
|
+
}
|
|
1848
|
+
if (!newVersion) {
|
|
1849
|
+
throw new Error("New version is required for independent version mode");
|
|
1850
|
+
}
|
|
1851
|
+
to = getIndependentTag({ version: newVersion, name: packageName });
|
|
1852
|
+
} else {
|
|
1853
|
+
to = newVersion ? config.templates.tagBody.replace("{{newVersion}}", newVersion) : getCurrentGitRef(config.cwd);
|
|
1854
|
+
}
|
|
1855
|
+
logger.debug(`[${versionMode}](${step}) Using to tag: ${to}`);
|
|
1856
|
+
return config.to || to;
|
|
1857
|
+
}
|
|
1858
|
+
async function resolveTags({
|
|
1859
|
+
config,
|
|
1860
|
+
step,
|
|
1861
|
+
pkg,
|
|
1862
|
+
newVersion
|
|
1863
|
+
}) {
|
|
1864
|
+
const versionMode = config.monorepo?.versionMode || "standalone";
|
|
1865
|
+
const logLevel = config.logLevel;
|
|
1866
|
+
logger.debug(`[${versionMode}](${step}) Resolving tags`);
|
|
1867
|
+
const releaseType = config.bump.type;
|
|
1868
|
+
const from = await resolveFromTag({
|
|
2097
1869
|
config,
|
|
2098
|
-
|
|
2099
|
-
graduating,
|
|
1870
|
+
versionMode,
|
|
2100
1871
|
step,
|
|
1872
|
+
packageName: pkg.name,
|
|
1873
|
+
graduating: isGraduating(pkg.version, releaseType),
|
|
2101
1874
|
logLevel
|
|
2102
1875
|
});
|
|
2103
|
-
|
|
2104
|
-
|
|
1876
|
+
const to = resolveToTag({
|
|
1877
|
+
config,
|
|
1878
|
+
versionMode,
|
|
1879
|
+
newVersion,
|
|
1880
|
+
step,
|
|
1881
|
+
packageName: pkg.name
|
|
1882
|
+
});
|
|
1883
|
+
logger.debug(`[${versionMode}](${step}) Using tags: ${from} \u2192 ${to}`);
|
|
1884
|
+
return { from, to };
|
|
2105
1885
|
}
|
|
2106
1886
|
|
|
2107
1887
|
let sessionOtp;
|
|
@@ -2120,7 +1900,8 @@ function detectPackageManager(cwd = process.cwd()) {
|
|
|
2120
1900
|
}
|
|
2121
1901
|
}
|
|
2122
1902
|
} catch (e) {
|
|
2123
|
-
|
|
1903
|
+
const errorString = e instanceof Error ? e.message : String(e);
|
|
1904
|
+
logger.debug(`Failed to parse package.json: ${errorString}`);
|
|
2124
1905
|
}
|
|
2125
1906
|
}
|
|
2126
1907
|
const lockFiles = {
|
|
@@ -2146,7 +1927,7 @@ function detectPackageManager(cwd = process.cwd()) {
|
|
|
2146
1927
|
logger.debug("No package manager detected, defaulting to npm");
|
|
2147
1928
|
return "npm";
|
|
2148
1929
|
} catch (error) {
|
|
2149
|
-
logger.
|
|
1930
|
+
logger.fail(`Error detecting package manager: ${error}, defaulting to npm`);
|
|
2150
1931
|
return "npm";
|
|
2151
1932
|
}
|
|
2152
1933
|
}
|
|
@@ -2180,23 +1961,13 @@ async function getPackagesToPublishInIndependentMode(sortedPackages, config) {
|
|
|
2180
1961
|
for (const pkg of sortedPackages) {
|
|
2181
1962
|
const { from, to } = await resolveTags({
|
|
2182
1963
|
config,
|
|
2183
|
-
versionMode: "independent",
|
|
2184
1964
|
step: "publish",
|
|
2185
1965
|
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
|
|
1966
|
+
newVersion: pkg.version
|
|
2196
1967
|
});
|
|
2197
|
-
if (commits.length > 0) {
|
|
1968
|
+
if (pkg.commits.length > 0) {
|
|
2198
1969
|
packagesToPublish.push(pkg);
|
|
2199
|
-
logger.debug(`${pkg.name}: ${commits.length} commit(s) since ${from} \u2192 ${to}`);
|
|
1970
|
+
logger.debug(`${pkg.name}: ${pkg.commits.length} commit(s) since ${from} \u2192 ${to}`);
|
|
2200
1971
|
}
|
|
2201
1972
|
}
|
|
2202
1973
|
return packagesToPublish;
|
|
@@ -2301,7 +2072,7 @@ async function publishPackage({
|
|
|
2301
2072
|
dryRun
|
|
2302
2073
|
}) {
|
|
2303
2074
|
const tag = determinePublishTag(pkg.version, config.publish.tag);
|
|
2304
|
-
const packageNameAndVersion =
|
|
2075
|
+
const packageNameAndVersion = getIndependentTag(pkg);
|
|
2305
2076
|
const baseCommand = packageManager === "yarn" && isYarnBerry() ? "yarn npm" : packageManager;
|
|
2306
2077
|
logger.debug(`Building publish command for ${pkg.name}`);
|
|
2307
2078
|
let dynamicOtp;
|
|
@@ -2342,198 +2113,412 @@ async function publishPackage({
|
|
|
2342
2113
|
}
|
|
2343
2114
|
}
|
|
2344
2115
|
|
|
2116
|
+
function readPackageJson(packagePath) {
|
|
2117
|
+
const packageJsonPath = join(packagePath, "package.json");
|
|
2118
|
+
if (!existsSync(packageJsonPath))
|
|
2119
|
+
throw new Error(`package.json not found at ${packageJsonPath}`);
|
|
2120
|
+
if (!statSync(packagePath).isDirectory())
|
|
2121
|
+
throw new Error(`Not a directory: ${packagePath}`);
|
|
2122
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
2123
|
+
if (!packageJson.name || !packageJson.version) {
|
|
2124
|
+
throw new Error(`Invalid package.json at ${packagePath}`);
|
|
2125
|
+
}
|
|
2126
|
+
return {
|
|
2127
|
+
name: packageJson.name,
|
|
2128
|
+
version: packageJson.version,
|
|
2129
|
+
private: packageJson.private || false,
|
|
2130
|
+
path: packagePath
|
|
2131
|
+
};
|
|
2132
|
+
}
|
|
2133
|
+
async function getRootPackage({
|
|
2134
|
+
config,
|
|
2135
|
+
force,
|
|
2136
|
+
from,
|
|
2137
|
+
to,
|
|
2138
|
+
suffix,
|
|
2139
|
+
changelog
|
|
2140
|
+
}) {
|
|
2141
|
+
try {
|
|
2142
|
+
const packageJson = readPackageJson(config.cwd);
|
|
2143
|
+
const commits = await getPackageCommits({
|
|
2144
|
+
pkg: packageJson,
|
|
2145
|
+
from,
|
|
2146
|
+
to,
|
|
2147
|
+
config,
|
|
2148
|
+
changelog
|
|
2149
|
+
});
|
|
2150
|
+
const releaseType = determineReleaseType({
|
|
2151
|
+
currentVersion: packageJson.version,
|
|
2152
|
+
commits,
|
|
2153
|
+
releaseType: config.bump.type,
|
|
2154
|
+
preid: config.bump.preid,
|
|
2155
|
+
types: config.types,
|
|
2156
|
+
force
|
|
2157
|
+
});
|
|
2158
|
+
if (!releaseType) {
|
|
2159
|
+
logger.fail("No commits require a version bump");
|
|
2160
|
+
process.exit(0);
|
|
2161
|
+
}
|
|
2162
|
+
const newVersion = getPackageNewVersion({
|
|
2163
|
+
currentVersion: packageJson.version,
|
|
2164
|
+
releaseType,
|
|
2165
|
+
preid: config.bump.preid,
|
|
2166
|
+
suffix
|
|
2167
|
+
});
|
|
2168
|
+
return {
|
|
2169
|
+
...packageJson,
|
|
2170
|
+
path: config.cwd,
|
|
2171
|
+
fromTag: from,
|
|
2172
|
+
commits,
|
|
2173
|
+
newVersion
|
|
2174
|
+
};
|
|
2175
|
+
} catch (error) {
|
|
2176
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2177
|
+
throw new Error(errorMessage);
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
function readPackages({
|
|
2181
|
+
cwd,
|
|
2182
|
+
patterns,
|
|
2183
|
+
ignorePackageNames
|
|
2184
|
+
}) {
|
|
2185
|
+
const packages = [];
|
|
2186
|
+
const foundPaths = /* @__PURE__ */ new Set();
|
|
2187
|
+
if (!patterns)
|
|
2188
|
+
patterns = ["."];
|
|
2189
|
+
logger.debug(`Getting packages from patterns: ${patterns.join(", ")}`);
|
|
2190
|
+
for (const pattern of patterns) {
|
|
2191
|
+
try {
|
|
2192
|
+
const matches = fastGlob.sync(pattern, {
|
|
2193
|
+
cwd,
|
|
2194
|
+
onlyDirectories: true,
|
|
2195
|
+
absolute: true,
|
|
2196
|
+
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"]
|
|
2197
|
+
});
|
|
2198
|
+
for (const matchPath of matches) {
|
|
2199
|
+
if (foundPaths.has(matchPath))
|
|
2200
|
+
continue;
|
|
2201
|
+
const packageBase = readPackageJson(matchPath);
|
|
2202
|
+
if (!packageBase || packageBase.private || ignorePackageNames?.includes(packageBase.name))
|
|
2203
|
+
continue;
|
|
2204
|
+
foundPaths.add(matchPath);
|
|
2205
|
+
packages.push({
|
|
2206
|
+
...packageBase,
|
|
2207
|
+
path: matchPath
|
|
2208
|
+
});
|
|
2209
|
+
}
|
|
2210
|
+
} catch (error) {
|
|
2211
|
+
logger.error(error);
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
return packages;
|
|
2215
|
+
}
|
|
2216
|
+
function getPackageReleaseType({
|
|
2217
|
+
pkg,
|
|
2218
|
+
config,
|
|
2219
|
+
force
|
|
2220
|
+
}) {
|
|
2221
|
+
const releaseType = config.bump.type;
|
|
2222
|
+
if (force) {
|
|
2223
|
+
return determineReleaseType({
|
|
2224
|
+
currentVersion: pkg.version,
|
|
2225
|
+
commits: pkg.commits,
|
|
2226
|
+
releaseType,
|
|
2227
|
+
preid: config.bump.preid,
|
|
2228
|
+
types: config.types,
|
|
2229
|
+
force
|
|
2230
|
+
});
|
|
2231
|
+
}
|
|
2232
|
+
if (pkg.reason === "dependency") {
|
|
2233
|
+
if (isStableReleaseType(releaseType))
|
|
2234
|
+
return "patch";
|
|
2235
|
+
if (isPrerelease(pkg.version))
|
|
2236
|
+
return "prerelease";
|
|
2237
|
+
return "prepatch";
|
|
2238
|
+
}
|
|
2239
|
+
return determineReleaseType({
|
|
2240
|
+
currentVersion: pkg.version,
|
|
2241
|
+
commits: pkg.commits,
|
|
2242
|
+
releaseType,
|
|
2243
|
+
preid: config.bump.preid,
|
|
2244
|
+
types: config.types,
|
|
2245
|
+
force
|
|
2246
|
+
});
|
|
2247
|
+
}
|
|
2248
|
+
async function getPackages({
|
|
2249
|
+
patterns,
|
|
2250
|
+
config,
|
|
2251
|
+
suffix,
|
|
2252
|
+
force
|
|
2253
|
+
}) {
|
|
2254
|
+
const readedPackages = readPackages({
|
|
2255
|
+
cwd: config.cwd,
|
|
2256
|
+
patterns,
|
|
2257
|
+
ignorePackageNames: config.monorepo?.ignorePackageNames
|
|
2258
|
+
});
|
|
2259
|
+
const packages = /* @__PURE__ */ new Map();
|
|
2260
|
+
const foundPaths = /* @__PURE__ */ new Set();
|
|
2261
|
+
if (!patterns)
|
|
2262
|
+
patterns = ["."];
|
|
2263
|
+
logger.debug(`Getting packages from patterns: ${patterns.join(", ")}`);
|
|
2264
|
+
const patternsSet = new Set(patterns);
|
|
2265
|
+
for (const pattern of patternsSet) {
|
|
2266
|
+
const matches = fastGlob.sync(pattern, {
|
|
2267
|
+
cwd: config.cwd,
|
|
2268
|
+
onlyDirectories: true,
|
|
2269
|
+
absolute: true,
|
|
2270
|
+
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**"]
|
|
2271
|
+
});
|
|
2272
|
+
for (const matchPath of matches) {
|
|
2273
|
+
if (foundPaths.has(matchPath))
|
|
2274
|
+
continue;
|
|
2275
|
+
const packageBase = readPackageJson(matchPath);
|
|
2276
|
+
if (packageBase.private) {
|
|
2277
|
+
logger.debug(`${packageBase.name} is private and will be ignored`);
|
|
2278
|
+
continue;
|
|
2279
|
+
}
|
|
2280
|
+
if (config.monorepo?.ignorePackageNames?.includes(packageBase.name)) {
|
|
2281
|
+
logger.debug(`${packageBase.name} ignored by config (monorepo.ignorePackageNames)`);
|
|
2282
|
+
continue;
|
|
2283
|
+
}
|
|
2284
|
+
if (!packageBase.version) {
|
|
2285
|
+
logger.warn(`${packageBase.name} has no version and will be ignored`);
|
|
2286
|
+
continue;
|
|
2287
|
+
}
|
|
2288
|
+
const { from, to } = await resolveTags({
|
|
2289
|
+
config,
|
|
2290
|
+
step: "bump",
|
|
2291
|
+
pkg: packageBase,
|
|
2292
|
+
newVersion: void 0
|
|
2293
|
+
});
|
|
2294
|
+
const commits = await getPackageCommits({
|
|
2295
|
+
pkg: packageBase,
|
|
2296
|
+
from,
|
|
2297
|
+
to,
|
|
2298
|
+
config,
|
|
2299
|
+
changelog: false
|
|
2300
|
+
});
|
|
2301
|
+
foundPaths.add(matchPath);
|
|
2302
|
+
const dependencies = getPackageDependencies({
|
|
2303
|
+
packagePath: matchPath,
|
|
2304
|
+
allPackageNames: new Set(readedPackages.map((p) => p.name)),
|
|
2305
|
+
dependencyTypes: config.bump?.dependencyTypes
|
|
2306
|
+
});
|
|
2307
|
+
packages.set(packageBase.name, {
|
|
2308
|
+
...packageBase,
|
|
2309
|
+
path: matchPath,
|
|
2310
|
+
fromTag: from,
|
|
2311
|
+
dependencies,
|
|
2312
|
+
commits,
|
|
2313
|
+
reason: commits.length > 0 ? "commits" : void 0,
|
|
2314
|
+
dependencyChain: void 0,
|
|
2315
|
+
newVersion: void 0
|
|
2316
|
+
});
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
const packagesArray = Array.from(packages.values());
|
|
2320
|
+
const packagesWithCommits = packagesArray.filter((p) => p.commits.length > 0);
|
|
2321
|
+
const expandedPackages = expandPackagesToBumpWithDependents({
|
|
2322
|
+
allPackages: packagesArray,
|
|
2323
|
+
packagesWithCommits
|
|
2324
|
+
});
|
|
2325
|
+
for (const pkg of expandedPackages) {
|
|
2326
|
+
packages.set(pkg.name, pkg);
|
|
2327
|
+
}
|
|
2328
|
+
for (const pkg of Array.from(packages.values())) {
|
|
2329
|
+
const releaseType = getPackageReleaseType({
|
|
2330
|
+
pkg,
|
|
2331
|
+
config,
|
|
2332
|
+
force
|
|
2333
|
+
});
|
|
2334
|
+
const newVersion = releaseType ? getPackageNewVersion({
|
|
2335
|
+
currentVersion: pkg.version,
|
|
2336
|
+
releaseType,
|
|
2337
|
+
preid: config.bump.preid,
|
|
2338
|
+
suffix
|
|
2339
|
+
}) : void 0;
|
|
2340
|
+
const graduating = releaseType && isGraduating(pkg.version, releaseType) || isChangedPreid(pkg.version, config.bump.preid);
|
|
2341
|
+
packages.set(pkg.name, {
|
|
2342
|
+
...pkg,
|
|
2343
|
+
newVersion,
|
|
2344
|
+
reason: pkg.reason || releaseType && graduating && "graduation" || void 0
|
|
2345
|
+
});
|
|
2346
|
+
}
|
|
2347
|
+
const packagesToBump = Array.from(packages.values()).filter((p) => p.reason || force);
|
|
2348
|
+
if (packagesToBump.length === 0) {
|
|
2349
|
+
logger.debug("No packages to bump");
|
|
2350
|
+
return [];
|
|
2351
|
+
}
|
|
2352
|
+
return packagesToBump;
|
|
2353
|
+
}
|
|
2354
|
+
function isAllowedCommit({
|
|
2355
|
+
commit,
|
|
2356
|
+
type,
|
|
2357
|
+
changelog
|
|
2358
|
+
}) {
|
|
2359
|
+
if (commit.type === "chore" && ["deps", "release"].includes(commit.scope) && !commit.isBreaking) {
|
|
2360
|
+
return false;
|
|
2361
|
+
}
|
|
2362
|
+
if (typeof type === "object") {
|
|
2363
|
+
return !!type.semver || changelog && !!type.title;
|
|
2364
|
+
}
|
|
2365
|
+
if (typeof type === "boolean") {
|
|
2366
|
+
return type;
|
|
2367
|
+
}
|
|
2368
|
+
return false;
|
|
2369
|
+
}
|
|
2370
|
+
async function getPackageCommits({
|
|
2371
|
+
pkg,
|
|
2372
|
+
from,
|
|
2373
|
+
to,
|
|
2374
|
+
config,
|
|
2375
|
+
changelog
|
|
2376
|
+
}) {
|
|
2377
|
+
logger.debug(`Analyzing commits for ${pkg.name} since ${from} to ${to}`);
|
|
2378
|
+
const changelogConfig = {
|
|
2379
|
+
...config,
|
|
2380
|
+
from,
|
|
2381
|
+
to
|
|
2382
|
+
};
|
|
2383
|
+
const rawCommits = await getGitDiff(from, to, changelogConfig.cwd);
|
|
2384
|
+
const allCommits = parseCommits(rawCommits, changelogConfig);
|
|
2385
|
+
const hasBreakingChanges = allCommits.some((commit) => commit.isBreaking);
|
|
2386
|
+
logger.debug(`Has breaking changes: ${hasBreakingChanges}`);
|
|
2387
|
+
const rootPackage = readPackageJson(changelogConfig.cwd);
|
|
2388
|
+
const commits = allCommits.filter((commit) => {
|
|
2389
|
+
const type = changelogConfig?.types[commit.type];
|
|
2390
|
+
if (!isAllowedCommit({ commit, type, changelog })) {
|
|
2391
|
+
return false;
|
|
2392
|
+
}
|
|
2393
|
+
if (pkg.path === changelogConfig.cwd || pkg.name === rootPackage.name) {
|
|
2394
|
+
return true;
|
|
2395
|
+
}
|
|
2396
|
+
const packageRelativePath = relative(changelogConfig.cwd, pkg.path);
|
|
2397
|
+
const scopeMatches = commit.scope === pkg.name;
|
|
2398
|
+
const bodyContainsPath = commit.body.includes(packageRelativePath);
|
|
2399
|
+
return scopeMatches || bodyContainsPath;
|
|
2400
|
+
});
|
|
2401
|
+
logger.debug(`Found ${commits.length} commit(s) for ${pkg.name} from ${from} to ${to}`);
|
|
2402
|
+
if (commits.length > 0) {
|
|
2403
|
+
logger.debug(`${pkg.name}: ${commits.length} commit(s) found`);
|
|
2404
|
+
} else {
|
|
2405
|
+
logger.debug(`${pkg.name}: No commits found`);
|
|
2406
|
+
}
|
|
2407
|
+
return commits;
|
|
2408
|
+
}
|
|
2409
|
+
function hasLernaJson(rootDir) {
|
|
2410
|
+
const lernaJsonPath = join(rootDir, "lerna.json");
|
|
2411
|
+
return existsSync(lernaJsonPath);
|
|
2412
|
+
}
|
|
2413
|
+
|
|
2345
2414
|
async function bumpUnifiedMode({
|
|
2346
2415
|
config,
|
|
2347
|
-
packages,
|
|
2348
2416
|
dryRun,
|
|
2349
2417
|
force,
|
|
2350
2418
|
suffix
|
|
2351
2419
|
}) {
|
|
2352
2420
|
logger.debug("Starting bump in unified mode");
|
|
2353
|
-
const
|
|
2354
|
-
const currentVersion = rootPackage.version;
|
|
2421
|
+
const rootPackageBase = readPackageJson(config.cwd);
|
|
2355
2422
|
const { from, to } = await resolveTags({
|
|
2356
2423
|
config,
|
|
2357
|
-
versionMode: "unified",
|
|
2358
2424
|
step: "bump",
|
|
2359
2425
|
newVersion: void 0,
|
|
2360
|
-
pkg:
|
|
2361
|
-
currentVersion,
|
|
2362
|
-
logLevel: config.logLevel
|
|
2426
|
+
pkg: rootPackageBase
|
|
2363
2427
|
});
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2428
|
+
const rootPackage = await getRootPackage({
|
|
2429
|
+
config,
|
|
2430
|
+
force,
|
|
2367
2431
|
from,
|
|
2368
2432
|
to,
|
|
2369
|
-
|
|
2433
|
+
suffix,
|
|
2370
2434
|
changelog: false
|
|
2371
2435
|
});
|
|
2372
|
-
|
|
2373
|
-
const
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2436
|
+
const currentVersion = rootPackage.version;
|
|
2437
|
+
const newVersion = rootPackage.newVersion;
|
|
2438
|
+
if (!newVersion) {
|
|
2439
|
+
throw new Error(`Could not determine a new version for ${rootPackage.name} (root)`);
|
|
2440
|
+
}
|
|
2441
|
+
logger.debug(`Bump from ${from} to ${to}`);
|
|
2442
|
+
logger.debug(`${currentVersion} \u2192 ${newVersion} (${config.monorepo?.versionMode || "standalone"} mode)`);
|
|
2443
|
+
const packages = await getPackages({
|
|
2378
2444
|
config,
|
|
2445
|
+
patterns: config.monorepo?.packages,
|
|
2446
|
+
suffix,
|
|
2379
2447
|
force
|
|
2380
2448
|
});
|
|
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
2449
|
if (!config.bump.yes) {
|
|
2399
2450
|
await confirmBump({
|
|
2400
2451
|
versionMode: "unified",
|
|
2401
|
-
config,
|
|
2402
2452
|
packages,
|
|
2453
|
+
config,
|
|
2403
2454
|
force,
|
|
2404
2455
|
currentVersion,
|
|
2405
2456
|
newVersion,
|
|
2406
2457
|
dryRun
|
|
2407
2458
|
});
|
|
2408
2459
|
} else {
|
|
2409
|
-
logger.info(`${
|
|
2460
|
+
logger.info(`${packages.length === 1 ? packages[0].name : packages.length} package(s) bumped from ${currentVersion} to ${newVersion} (${config.monorepo?.versionMode || "standalone"} mode)`);
|
|
2410
2461
|
}
|
|
2411
|
-
for (const pkg of
|
|
2462
|
+
for (const pkg of [rootPackage, ...packages]) {
|
|
2412
2463
|
writeVersion(pkg.path, newVersion, dryRun);
|
|
2413
2464
|
}
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
});
|
|
2421
|
-
}
|
|
2465
|
+
updateLernaVersion({
|
|
2466
|
+
rootDir: config.cwd,
|
|
2467
|
+
versionMode: config.monorepo?.versionMode,
|
|
2468
|
+
version: newVersion,
|
|
2469
|
+
dryRun
|
|
2470
|
+
});
|
|
2422
2471
|
if (!dryRun) {
|
|
2423
|
-
logger.info(`All ${
|
|
2472
|
+
logger.info(`All ${packages.length} package(s) bumped to ${newVersion}`);
|
|
2424
2473
|
}
|
|
2425
2474
|
return {
|
|
2426
2475
|
bumped: true,
|
|
2427
2476
|
oldVersion: currentVersion,
|
|
2428
2477
|
fromTag: from,
|
|
2429
2478
|
newVersion,
|
|
2479
|
+
rootPackage,
|
|
2430
2480
|
bumpedPackages: packages.map((pkg) => ({
|
|
2431
2481
|
...pkg,
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
fromTag: from
|
|
2482
|
+
oldVersion: pkg.version,
|
|
2483
|
+
newVersion,
|
|
2484
|
+
fromTag: from,
|
|
2485
|
+
reason: "commits"
|
|
2435
2486
|
}))
|
|
2436
2487
|
};
|
|
2437
2488
|
}
|
|
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
2489
|
async function bumpSelectiveMode({
|
|
2492
2490
|
config,
|
|
2493
|
-
packages,
|
|
2494
2491
|
dryRun,
|
|
2495
2492
|
force,
|
|
2496
2493
|
suffix
|
|
2497
2494
|
}) {
|
|
2498
2495
|
logger.debug("Starting bump in selective mode");
|
|
2499
|
-
const
|
|
2500
|
-
const currentVersion = rootPackage.version;
|
|
2496
|
+
const rootPackageBase = readPackageJson(config.cwd);
|
|
2501
2497
|
const { from, to } = await resolveTags({
|
|
2502
2498
|
config,
|
|
2503
|
-
versionMode: "selective",
|
|
2504
2499
|
step: "bump",
|
|
2505
|
-
|
|
2506
|
-
newVersion: void 0
|
|
2507
|
-
pkg: void 0,
|
|
2508
|
-
logLevel: config.logLevel
|
|
2500
|
+
pkg: rootPackageBase,
|
|
2501
|
+
newVersion: void 0
|
|
2509
2502
|
});
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2503
|
+
const rootPackage = await getRootPackage({
|
|
2504
|
+
config,
|
|
2505
|
+
force,
|
|
2513
2506
|
from,
|
|
2514
2507
|
to,
|
|
2515
|
-
|
|
2508
|
+
suffix,
|
|
2516
2509
|
changelog: false
|
|
2517
2510
|
});
|
|
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
|
-
});
|
|
2511
|
+
const currentVersion = rootPackage.version;
|
|
2512
|
+
const newVersion = rootPackage.newVersion;
|
|
2513
|
+
logger.debug(`Bump from ${currentVersion} to ${newVersion}`);
|
|
2529
2514
|
logger.debug("Determining packages to bump...");
|
|
2530
|
-
const
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2515
|
+
const packages = await getPackages({
|
|
2516
|
+
config,
|
|
2517
|
+
patterns: config.monorepo?.packages,
|
|
2518
|
+
suffix,
|
|
2519
|
+
force
|
|
2535
2520
|
});
|
|
2536
|
-
if (
|
|
2521
|
+
if (packages.length === 0) {
|
|
2537
2522
|
logger.debug("No packages have commits, skipping bump");
|
|
2538
2523
|
return { bumped: false };
|
|
2539
2524
|
}
|
|
@@ -2541,7 +2526,7 @@ async function bumpSelectiveMode({
|
|
|
2541
2526
|
await confirmBump({
|
|
2542
2527
|
versionMode: "selective",
|
|
2543
2528
|
config,
|
|
2544
|
-
packages
|
|
2529
|
+
packages,
|
|
2545
2530
|
force,
|
|
2546
2531
|
currentVersion,
|
|
2547
2532
|
newVersion,
|
|
@@ -2549,18 +2534,18 @@ async function bumpSelectiveMode({
|
|
|
2549
2534
|
});
|
|
2550
2535
|
} else {
|
|
2551
2536
|
if (force) {
|
|
2552
|
-
logger.info(`${
|
|
2537
|
+
logger.info(`${packages.length} package(s) bumped to ${newVersion} (force)`);
|
|
2553
2538
|
} else {
|
|
2554
|
-
const bumpedByCommits =
|
|
2555
|
-
const bumpedByDependency =
|
|
2539
|
+
const bumpedByCommits = packages.filter((p) => "reason" in p && p.reason === "commits").length;
|
|
2540
|
+
const bumpedByDependency = packages.filter((p) => "reason" in p && p.reason === "dependency").length;
|
|
2541
|
+
const bumpedByGraduation = packages.filter((p) => "reason" in p && p.reason === "graduation").length;
|
|
2556
2542
|
logger.info(
|
|
2557
|
-
`${currentVersion} \u2192 ${newVersion} (selective mode: ${bumpedByCommits} with commits, ${bumpedByDependency} as dependents)`
|
|
2543
|
+
`${currentVersion} \u2192 ${newVersion} (selective mode: ${bumpedByCommits} with commits, ${bumpedByDependency} as dependents, ${bumpedByGraduation} from graduation)`
|
|
2558
2544
|
);
|
|
2559
2545
|
}
|
|
2560
2546
|
}
|
|
2561
|
-
logger.debug(`Writing version to ${
|
|
2562
|
-
|
|
2563
|
-
for (const pkg of packagesToBump) {
|
|
2547
|
+
logger.debug(`Writing version to ${packages.length} package(s)`);
|
|
2548
|
+
for (const pkg of [rootPackage, ...packages]) {
|
|
2564
2549
|
writeVersion(pkg.path, newVersion, dryRun);
|
|
2565
2550
|
}
|
|
2566
2551
|
updateLernaVersion({
|
|
@@ -2571,19 +2556,76 @@ async function bumpSelectiveMode({
|
|
|
2571
2556
|
});
|
|
2572
2557
|
if (!dryRun) {
|
|
2573
2558
|
logger.info(
|
|
2574
|
-
`${
|
|
2559
|
+
`${packages.length} package(s) bumped to ${newVersion}`
|
|
2575
2560
|
);
|
|
2576
2561
|
}
|
|
2577
2562
|
return {
|
|
2578
2563
|
bumped: true,
|
|
2579
2564
|
oldVersion: currentVersion,
|
|
2565
|
+
rootPackage,
|
|
2580
2566
|
fromTag: from,
|
|
2581
2567
|
newVersion,
|
|
2582
|
-
bumpedPackages:
|
|
2568
|
+
bumpedPackages: packages.map((pkg) => ({
|
|
2583
2569
|
...pkg,
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2570
|
+
oldVersion: pkg.version,
|
|
2571
|
+
fromTag: from,
|
|
2572
|
+
newVersion
|
|
2573
|
+
}))
|
|
2574
|
+
};
|
|
2575
|
+
}
|
|
2576
|
+
async function bumpIndependentMode({
|
|
2577
|
+
config,
|
|
2578
|
+
dryRun,
|
|
2579
|
+
suffix,
|
|
2580
|
+
force
|
|
2581
|
+
}) {
|
|
2582
|
+
logger.debug("Starting bump in independent mode");
|
|
2583
|
+
const packagesToBump = await getPackages({
|
|
2584
|
+
config,
|
|
2585
|
+
patterns: config.monorepo?.packages,
|
|
2586
|
+
suffix,
|
|
2587
|
+
force
|
|
2588
|
+
});
|
|
2589
|
+
if (packagesToBump.length === 0) {
|
|
2590
|
+
logger.debug("No packages have commits");
|
|
2591
|
+
return { bumped: false };
|
|
2592
|
+
}
|
|
2593
|
+
if (!config.bump.yes) {
|
|
2594
|
+
await confirmBump({
|
|
2595
|
+
versionMode: "independent",
|
|
2596
|
+
config,
|
|
2597
|
+
packages: packagesToBump,
|
|
2598
|
+
force,
|
|
2599
|
+
dryRun
|
|
2600
|
+
});
|
|
2601
|
+
} else {
|
|
2602
|
+
const bumpedByCommits2 = packagesToBump.filter((p) => p.reason === "commits").length;
|
|
2603
|
+
const bumpedByDependency2 = packagesToBump.filter((p) => p.reason === "dependency").length;
|
|
2604
|
+
const bumpedByGraduation = packagesToBump.filter((p) => p.reason === "graduation").length;
|
|
2605
|
+
logger.info(
|
|
2606
|
+
`${bumpedByCommits2 + bumpedByDependency2 + bumpedByGraduation} package(s) will be bumped independently (${bumpedByCommits2} from commits, ${bumpedByDependency2} from dependencies, ${bumpedByGraduation} from graduation)`
|
|
2607
|
+
);
|
|
2608
|
+
}
|
|
2609
|
+
const bumpedPackages = getBumpedIndependentPackages({
|
|
2610
|
+
packages: packagesToBump,
|
|
2611
|
+
dryRun
|
|
2612
|
+
});
|
|
2613
|
+
const bumpedByCommits = bumpedPackages.filter(
|
|
2614
|
+
(p) => packagesToBump.find((pkg) => pkg.name === p.name)?.reason === "commits"
|
|
2615
|
+
).length;
|
|
2616
|
+
const bumpedByDependency = bumpedPackages.length - bumpedByCommits;
|
|
2617
|
+
if (bumpedPackages.length === 0) {
|
|
2618
|
+
logger.debug("No packages were bumped");
|
|
2619
|
+
} else {
|
|
2620
|
+
logger.info(
|
|
2621
|
+
`${dryRun ? "[dry-run] " : ""}${bumpedPackages.length} package(s) bumped independently (${bumpedByCommits} from commits, ${bumpedByDependency} from dependencies)`
|
|
2622
|
+
);
|
|
2623
|
+
}
|
|
2624
|
+
return {
|
|
2625
|
+
bumped: bumpedPackages.length > 0,
|
|
2626
|
+
bumpedPackages: bumpedPackages.map((pkg) => ({
|
|
2627
|
+
...pkg,
|
|
2628
|
+
oldVersion: pkg.version
|
|
2587
2629
|
}))
|
|
2588
2630
|
};
|
|
2589
2631
|
}
|
|
@@ -2613,7 +2655,7 @@ async function bump(options = {}) {
|
|
|
2613
2655
|
}
|
|
2614
2656
|
await fetchGitTags(config.cwd);
|
|
2615
2657
|
logger.info(`Version mode: ${config.monorepo?.versionMode || "standalone"}`);
|
|
2616
|
-
const packages =
|
|
2658
|
+
const packages = readPackages({
|
|
2617
2659
|
cwd: config.cwd,
|
|
2618
2660
|
patterns: config.monorepo?.packages,
|
|
2619
2661
|
ignorePackageNames: config.monorepo?.ignorePackageNames
|
|
@@ -2622,7 +2664,6 @@ async function bump(options = {}) {
|
|
|
2622
2664
|
let result;
|
|
2623
2665
|
const payload = {
|
|
2624
2666
|
config,
|
|
2625
|
-
packages,
|
|
2626
2667
|
dryRun,
|
|
2627
2668
|
force,
|
|
2628
2669
|
suffix: options.suffix
|
|
@@ -2651,17 +2692,20 @@ async function bump(options = {}) {
|
|
|
2651
2692
|
}
|
|
2652
2693
|
}
|
|
2653
2694
|
|
|
2654
|
-
function getPackagesToGenerateChangelogFor({
|
|
2695
|
+
async function getPackagesToGenerateChangelogFor({
|
|
2655
2696
|
config,
|
|
2656
|
-
|
|
2697
|
+
bumpResult,
|
|
2698
|
+
suffix,
|
|
2699
|
+
force
|
|
2657
2700
|
}) {
|
|
2658
|
-
if (bumpedPackages && bumpedPackages.length > 0) {
|
|
2659
|
-
return bumpedPackages;
|
|
2701
|
+
if (bumpResult?.bumpedPackages && bumpResult.bumpedPackages.length > 0) {
|
|
2702
|
+
return bumpResult.bumpedPackages;
|
|
2660
2703
|
}
|
|
2661
|
-
return getPackages({
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
2704
|
+
return await getPackages({
|
|
2705
|
+
config,
|
|
2706
|
+
patterns: config.monorepo?.packages,
|
|
2707
|
+
suffix,
|
|
2708
|
+
force
|
|
2665
2709
|
});
|
|
2666
2710
|
}
|
|
2667
2711
|
async function generateIndependentRootChangelog({
|
|
@@ -2674,39 +2718,16 @@ async function generateIndependentRootChangelog({
|
|
|
2674
2718
|
return;
|
|
2675
2719
|
}
|
|
2676
2720
|
logger.debug("Generating aggregated root changelog for independent mode");
|
|
2677
|
-
const rootPackage = getRootPackage(config.cwd);
|
|
2678
2721
|
const packageChangelogs = [];
|
|
2679
2722
|
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
2723
|
const changelog2 = await generateChangelog({
|
|
2699
|
-
config,
|
|
2700
2724
|
pkg,
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2725
|
+
config,
|
|
2726
|
+
dryRun,
|
|
2727
|
+
newVersion: isBumpedPackage(pkg) && pkg.newVersion || pkg.version
|
|
2704
2728
|
});
|
|
2705
2729
|
if (changelog2) {
|
|
2706
|
-
|
|
2707
|
-
packageChangelogs.push(`## ${pkg.name}@${pkg.version}
|
|
2708
|
-
|
|
2709
|
-
${cleanedChangelog}`);
|
|
2730
|
+
packageChangelogs.push(changelog2);
|
|
2710
2731
|
}
|
|
2711
2732
|
}
|
|
2712
2733
|
if (packageChangelogs.length === 0) {
|
|
@@ -2718,7 +2739,9 @@ ${cleanedChangelog}`);
|
|
|
2718
2739
|
|
|
2719
2740
|
${packageChangelogs.join("\n\n")}`;
|
|
2720
2741
|
logger.verbose(`Aggregated root changelog: ${aggregatedChangelog}`);
|
|
2742
|
+
const rootPackage = readPackageJson(config.cwd);
|
|
2721
2743
|
writeChangelogToFile({
|
|
2744
|
+
cwd: config.cwd,
|
|
2722
2745
|
pkg: rootPackage,
|
|
2723
2746
|
changelog: aggregatedChangelog,
|
|
2724
2747
|
dryRun
|
|
@@ -2727,41 +2750,43 @@ ${packageChangelogs.join("\n\n")}`;
|
|
|
2727
2750
|
}
|
|
2728
2751
|
async function generateSimpleRootChangelog({
|
|
2729
2752
|
config,
|
|
2730
|
-
dryRun
|
|
2753
|
+
dryRun,
|
|
2754
|
+
force,
|
|
2755
|
+
suffix,
|
|
2756
|
+
bumpResult
|
|
2731
2757
|
}) {
|
|
2732
2758
|
if (!config.changelog?.rootChangelog) {
|
|
2733
2759
|
logger.debug("Skipping root changelog generation");
|
|
2734
2760
|
return;
|
|
2735
2761
|
}
|
|
2736
2762
|
logger.debug("Generating simple root changelog");
|
|
2737
|
-
const
|
|
2763
|
+
const rootPackageRead = readPackageJson(config.cwd);
|
|
2738
2764
|
const { from, to } = await resolveTags({
|
|
2739
2765
|
config,
|
|
2740
|
-
versionMode: config.monorepo?.versionMode || "unified",
|
|
2741
2766
|
step: "changelog",
|
|
2742
|
-
currentVersion: rootPackage.version,
|
|
2743
2767
|
newVersion: void 0,
|
|
2744
|
-
pkg:
|
|
2745
|
-
logLevel: config.logLevel
|
|
2768
|
+
pkg: rootPackageRead
|
|
2746
2769
|
});
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
const rootCommits = await getPackageCommits({
|
|
2750
|
-
pkg: rootPackage,
|
|
2751
|
-
from,
|
|
2752
|
-
to,
|
|
2770
|
+
const fromTag = bumpResult?.fromTag || from;
|
|
2771
|
+
const rootPackage = bumpResult?.rootPackage || await getRootPackage({
|
|
2753
2772
|
config,
|
|
2754
|
-
|
|
2773
|
+
force,
|
|
2774
|
+
suffix,
|
|
2775
|
+
changelog: true,
|
|
2776
|
+
from: fromTag,
|
|
2777
|
+
to
|
|
2755
2778
|
});
|
|
2779
|
+
logger.debug(`Generating ${rootPackage.name} changelog (${fromTag}...${to})`);
|
|
2780
|
+
const newVersion = bumpResult?.newVersion || rootPackage.version;
|
|
2756
2781
|
const rootChangelog = await generateChangelog({
|
|
2757
2782
|
pkg: rootPackage,
|
|
2758
|
-
commits: rootCommits,
|
|
2759
2783
|
config,
|
|
2760
|
-
|
|
2761
|
-
|
|
2784
|
+
dryRun,
|
|
2785
|
+
newVersion
|
|
2762
2786
|
});
|
|
2763
2787
|
if (rootChangelog) {
|
|
2764
2788
|
writeChangelogToFile({
|
|
2789
|
+
cwd: config.cwd,
|
|
2765
2790
|
changelog: rootChangelog,
|
|
2766
2791
|
pkg: rootPackage,
|
|
2767
2792
|
dryRun
|
|
@@ -2791,56 +2816,57 @@ async function changelog(options = {}) {
|
|
|
2791
2816
|
try {
|
|
2792
2817
|
await executeHook("before:changelog", config, dryRun);
|
|
2793
2818
|
logger.start("Start generating changelogs");
|
|
2794
|
-
const packages = getPackagesToGenerateChangelogFor({
|
|
2795
|
-
config,
|
|
2796
|
-
bumpedPackages: options.bumpedPackages
|
|
2797
|
-
});
|
|
2798
2819
|
if (config.changelog?.rootChangelog && config.monorepo) {
|
|
2799
2820
|
if (config.monorepo.versionMode === "independent") {
|
|
2821
|
+
const packages2 = await getPackagesToGenerateChangelogFor({
|
|
2822
|
+
config,
|
|
2823
|
+
bumpResult: options.bumpResult,
|
|
2824
|
+
suffix: options.suffix,
|
|
2825
|
+
force: options.force ?? false
|
|
2826
|
+
});
|
|
2800
2827
|
await generateIndependentRootChangelog({
|
|
2801
|
-
packages,
|
|
2828
|
+
packages: packages2,
|
|
2802
2829
|
config,
|
|
2803
2830
|
dryRun
|
|
2804
2831
|
});
|
|
2805
2832
|
} else {
|
|
2806
2833
|
await generateSimpleRootChangelog({
|
|
2807
2834
|
config,
|
|
2808
|
-
dryRun
|
|
2835
|
+
dryRun,
|
|
2836
|
+
bumpResult: options.bumpResult,
|
|
2837
|
+
suffix: options.suffix,
|
|
2838
|
+
force: options.force ?? false
|
|
2809
2839
|
});
|
|
2810
2840
|
}
|
|
2811
2841
|
} else {
|
|
2812
2842
|
logger.debug("Skipping root changelog generation");
|
|
2813
2843
|
}
|
|
2814
2844
|
logger.debug("Generating package changelogs...");
|
|
2845
|
+
const packages = options.bumpResult?.bumpedPackages ? options.bumpResult.bumpedPackages : await getPackages({
|
|
2846
|
+
config,
|
|
2847
|
+
patterns: config.monorepo?.packages,
|
|
2848
|
+
suffix: options.suffix,
|
|
2849
|
+
force: options.force ?? false
|
|
2850
|
+
});
|
|
2815
2851
|
logger.debug(`Processing ${packages.length} package(s)`);
|
|
2816
2852
|
let generatedCount = 0;
|
|
2817
2853
|
for await (const pkg of packages) {
|
|
2818
2854
|
const { from, to } = await resolveTags({
|
|
2819
2855
|
config,
|
|
2820
|
-
versionMode: config.monorepo?.versionMode || "unified",
|
|
2821
2856
|
step: "changelog",
|
|
2822
|
-
currentVersion: pkg.version,
|
|
2823
|
-
newVersion: void 0,
|
|
2824
2857
|
pkg,
|
|
2825
|
-
|
|
2858
|
+
newVersion: void 0
|
|
2826
2859
|
});
|
|
2827
2860
|
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
2861
|
const changelog2 = await generateChangelog({
|
|
2836
2862
|
pkg,
|
|
2837
|
-
commits,
|
|
2838
2863
|
config,
|
|
2839
|
-
|
|
2840
|
-
|
|
2864
|
+
dryRun,
|
|
2865
|
+
newVersion: options.bumpResult?.bumpedPackages?.find((p) => p.name === pkg.name)?.newVersion
|
|
2841
2866
|
});
|
|
2842
2867
|
if (changelog2) {
|
|
2843
2868
|
writeChangelogToFile({
|
|
2869
|
+
cwd: config.cwd,
|
|
2844
2870
|
pkg,
|
|
2845
2871
|
changelog: changelog2,
|
|
2846
2872
|
dryRun
|
|
@@ -2889,7 +2915,7 @@ async function providerRelease(options = {}) {
|
|
|
2889
2915
|
configName: options.configName,
|
|
2890
2916
|
baseConfig: options.config,
|
|
2891
2917
|
overrides: {
|
|
2892
|
-
from: options.from
|
|
2918
|
+
from: options.from,
|
|
2893
2919
|
to: options.to,
|
|
2894
2920
|
tokens: {
|
|
2895
2921
|
github: options.token,
|
|
@@ -2903,12 +2929,12 @@ async function providerRelease(options = {}) {
|
|
|
2903
2929
|
logger.debug(`Dry run: ${dryRun}`);
|
|
2904
2930
|
logger.info(`Version mode: ${config.monorepo?.versionMode || "standalone"}`);
|
|
2905
2931
|
try {
|
|
2906
|
-
await executeHook("before:provider-release", config, dryRun);
|
|
2907
2932
|
const detectedProvider = options.provider || detectGitProvider();
|
|
2908
2933
|
providerReleaseSafetyCheck({ config, provider: detectedProvider });
|
|
2934
|
+
await executeHook("before:provider-release", config, dryRun);
|
|
2909
2935
|
logger.start("Start provider release");
|
|
2910
2936
|
if (!detectedProvider) {
|
|
2911
|
-
logger.
|
|
2937
|
+
logger.fail("Unable to detect Git provider. Skipping release publication.");
|
|
2912
2938
|
throw new Error("Unable to detect Git provider");
|
|
2913
2939
|
} else {
|
|
2914
2940
|
logger.info(
|
|
@@ -2917,19 +2943,21 @@ async function providerRelease(options = {}) {
|
|
|
2917
2943
|
}
|
|
2918
2944
|
let postedReleases = [];
|
|
2919
2945
|
const payload = {
|
|
2920
|
-
from: config.from,
|
|
2946
|
+
from: config.from || options.bumpResult?.fromTag,
|
|
2921
2947
|
to: config.to,
|
|
2922
2948
|
dryRun,
|
|
2923
2949
|
config,
|
|
2924
2950
|
logLevel: config.logLevel,
|
|
2925
|
-
bumpResult: options.bumpResult
|
|
2951
|
+
bumpResult: options.bumpResult,
|
|
2952
|
+
force: options.force ?? false,
|
|
2953
|
+
suffix: options.suffix
|
|
2926
2954
|
};
|
|
2927
2955
|
if (detectedProvider === "github") {
|
|
2928
2956
|
postedReleases = await github(payload);
|
|
2929
2957
|
} else if (detectedProvider === "gitlab") {
|
|
2930
2958
|
postedReleases = await gitlab(payload);
|
|
2931
2959
|
} else {
|
|
2932
|
-
logger.
|
|
2960
|
+
logger.error(`Unsupported Git provider: ${detectedProvider}`);
|
|
2933
2961
|
}
|
|
2934
2962
|
await executeHook("success:provider-release", config, dryRun);
|
|
2935
2963
|
return {
|
|
@@ -2973,17 +3001,17 @@ async function publish(options = {}) {
|
|
|
2973
3001
|
}
|
|
2974
3002
|
try {
|
|
2975
3003
|
await executeHook("before:publish", config, dryRun);
|
|
3004
|
+
const rootPackage = readPackageJson(config.cwd);
|
|
2976
3005
|
logger.start("Start publishing packages");
|
|
2977
|
-
const packages = options.bumpedPackages || getPackages({
|
|
2978
|
-
|
|
3006
|
+
const packages = options.bumpedPackages || await getPackages({
|
|
3007
|
+
config,
|
|
2979
3008
|
patterns: config.publish.packages ?? config.monorepo?.packages,
|
|
2980
|
-
|
|
3009
|
+
suffix: options.suffix,
|
|
3010
|
+
force: options.force ?? false
|
|
2981
3011
|
});
|
|
2982
|
-
const rootPackage = getRootPackage(config.cwd);
|
|
2983
3012
|
logger.debug(`Found ${packages.length} package(s)`);
|
|
2984
3013
|
logger.debug("Building dependency graph and sorting...");
|
|
2985
|
-
const
|
|
2986
|
-
const sortedPackages = topologicalSort(packagesWithDeps);
|
|
3014
|
+
const sortedPackages = topologicalSort(packages);
|
|
2987
3015
|
let publishedPackages = packages || [];
|
|
2988
3016
|
if (publishedPackages.length === 0 && config.monorepo?.versionMode === "independent") {
|
|
2989
3017
|
logger.debug("Determining packages to publish in independent mode...");
|
|
@@ -3000,7 +3028,7 @@ async function publish(options = {}) {
|
|
|
3000
3028
|
logger.info(`Publishing ${publishedPackages.length} package(s) (unified mode)`);
|
|
3001
3029
|
}
|
|
3002
3030
|
if (publishedPackages.length === 0) {
|
|
3003
|
-
logger.
|
|
3031
|
+
logger.fail("No packages need to be published");
|
|
3004
3032
|
return;
|
|
3005
3033
|
}
|
|
3006
3034
|
await executeBuildCmd({
|
|
@@ -3009,7 +3037,7 @@ async function publish(options = {}) {
|
|
|
3009
3037
|
});
|
|
3010
3038
|
for (const pkg of sortedPackages) {
|
|
3011
3039
|
if (publishedPackages.some((p) => p.name === pkg.name)) {
|
|
3012
|
-
logger.debug(`Publishing ${pkg
|
|
3040
|
+
logger.debug(`Publishing ${getIndependentTag(pkg)}...`);
|
|
3013
3041
|
await publishPackage({
|
|
3014
3042
|
pkg,
|
|
3015
3043
|
config,
|
|
@@ -3104,7 +3132,8 @@ async function release(options = {}) {
|
|
|
3104
3132
|
config,
|
|
3105
3133
|
force,
|
|
3106
3134
|
clean: config.release.clean,
|
|
3107
|
-
configName: options.configName
|
|
3135
|
+
configName: options.configName,
|
|
3136
|
+
suffix: options.suffix
|
|
3108
3137
|
});
|
|
3109
3138
|
if (!bumpResult.bumped) {
|
|
3110
3139
|
logger.debug("No packages bumped");
|
|
@@ -3118,10 +3147,12 @@ async function release(options = {}) {
|
|
|
3118
3147
|
dryRun,
|
|
3119
3148
|
formatCmd: config.changelog.formatCmd,
|
|
3120
3149
|
rootChangelog: config.changelog.rootChangelog,
|
|
3121
|
-
|
|
3150
|
+
bumpResult,
|
|
3122
3151
|
config,
|
|
3123
3152
|
logLevel: config.logLevel,
|
|
3124
|
-
configName: options.configName
|
|
3153
|
+
configName: options.configName,
|
|
3154
|
+
force,
|
|
3155
|
+
suffix: options.suffix
|
|
3125
3156
|
});
|
|
3126
3157
|
} else {
|
|
3127
3158
|
logger.info("Skipping changelog generation (--no-changelog)");
|
|
@@ -3164,7 +3195,9 @@ async function release(options = {}) {
|
|
|
3164
3195
|
bumpedPackages: bumpResult.bumpedPackages,
|
|
3165
3196
|
dryRun,
|
|
3166
3197
|
config,
|
|
3167
|
-
configName: options.configName
|
|
3198
|
+
configName: options.configName,
|
|
3199
|
+
suffix: options.suffix,
|
|
3200
|
+
force
|
|
3168
3201
|
});
|
|
3169
3202
|
} else {
|
|
3170
3203
|
logger.info("Skipping publish (--no-publish)");
|
|
@@ -3184,7 +3217,9 @@ async function release(options = {}) {
|
|
|
3184
3217
|
config,
|
|
3185
3218
|
logLevel: config.logLevel,
|
|
3186
3219
|
bumpResult,
|
|
3187
|
-
configName: options.configName
|
|
3220
|
+
configName: options.configName,
|
|
3221
|
+
force,
|
|
3222
|
+
suffix: options.suffix
|
|
3188
3223
|
});
|
|
3189
3224
|
provider = response.detectedProvider;
|
|
3190
3225
|
postedReleases = response.postedReleases;
|
|
@@ -3195,7 +3230,7 @@ async function release(options = {}) {
|
|
|
3195
3230
|
logger.info("Skipping release (--no-provider-release)");
|
|
3196
3231
|
}
|
|
3197
3232
|
const publishedPackageCount = publishResponse?.publishedPackages.length ?? 0;
|
|
3198
|
-
const versionDisplay = config.monorepo?.versionMode === "independent" ? `${bumpResult.bumpedPackages.length} packages bumped independently` : bumpResult.newVersion ||
|
|
3233
|
+
const versionDisplay = config.monorepo?.versionMode === "independent" ? `${bumpResult.bumpedPackages.length} packages bumped independently` : bumpResult.newVersion || readPackageJson(config.cwd).version;
|
|
3199
3234
|
logger.box(`Release workflow completed!
|
|
3200
3235
|
|
|
3201
3236
|
Version: ${versionDisplay}
|
|
@@ -3212,4 +3247,4 @@ Git provider: ${provider}`);
|
|
|
3212
3247
|
}
|
|
3213
3248
|
}
|
|
3214
3249
|
|
|
3215
|
-
export {
|
|
3250
|
+
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 };
|