relizy 0.3.0 → 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -1093
- package/dist/cli.mjs +18 -3
- package/dist/index.d.mts +391 -20
- package/dist/index.d.ts +391 -20
- package/dist/index.mjs +2 -2
- package/dist/shared/{relizy.B4guss__.mjs → relizy.C2HlcnZB.mjs} +2136 -1470
- package/package.json +20 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { logger, execPromise } from '@maz-ui/node';
|
|
2
|
+
import process$1 from 'node:process';
|
|
2
3
|
import { existsSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
3
4
|
import path, { join, relative } from 'node:path';
|
|
4
5
|
import { getGitDiff, parseCommits, formatCompareChanges, formatReference, resolveRepoConfig, getRepoConfig, createGithubRelease } from 'changelogen';
|
|
@@ -7,7 +8,6 @@ import { confirm, input } from '@inquirer/prompts';
|
|
|
7
8
|
import { upperFirst, formatJson } from '@maz-ui/utils';
|
|
8
9
|
import * as semver from 'semver';
|
|
9
10
|
import { execSync } from 'node:child_process';
|
|
10
|
-
import process$1, { exit } from 'node:process';
|
|
11
11
|
import { setupDotenv, loadConfig } from 'c12';
|
|
12
12
|
import { defu } from 'defu';
|
|
13
13
|
import { convert } from 'convert-gitmoji';
|
|
@@ -276,11 +276,11 @@ function getPackageReleaseType({
|
|
|
276
276
|
});
|
|
277
277
|
}
|
|
278
278
|
async function getPackages({
|
|
279
|
-
patterns,
|
|
280
279
|
config,
|
|
281
280
|
suffix,
|
|
282
281
|
force
|
|
283
282
|
}) {
|
|
283
|
+
const patterns = config.monorepo?.packages;
|
|
284
284
|
const readedPackages = readPackages({
|
|
285
285
|
cwd: config.cwd,
|
|
286
286
|
patterns,
|
|
@@ -476,7 +476,7 @@ async function executeHook(hook, config, dryRun, params) {
|
|
|
476
476
|
logger.info(`Executing hook ${hook}`);
|
|
477
477
|
const result = await hookInput(config, dryRun, params);
|
|
478
478
|
if (result)
|
|
479
|
-
logger.debug(`Hook ${hook} returned: ${result}`);
|
|
479
|
+
logger.debug(`Hook ${hook} returned: ${typeof result === "object" ? JSON.stringify(result) : result}`);
|
|
480
480
|
logger.info(`Hook ${hook} executed`);
|
|
481
481
|
return result;
|
|
482
482
|
}
|
|
@@ -489,62 +489,62 @@ async function executeHook(hook, config, dryRun, params) {
|
|
|
489
489
|
noStdout: true
|
|
490
490
|
});
|
|
491
491
|
if (result)
|
|
492
|
-
logger.debug(`Hook ${hook} returned: ${result}`);
|
|
492
|
+
logger.debug(`Hook ${hook} returned: ${typeof result === "object" ? JSON.stringify(result) : result}`);
|
|
493
493
|
logger.info(`Hook ${hook} executed`);
|
|
494
494
|
return result;
|
|
495
495
|
}
|
|
496
496
|
}
|
|
497
497
|
function isInCI() {
|
|
498
498
|
return Boolean(
|
|
499
|
-
process.env.CI === "true" || process.env.CONTINUOUS_INTEGRATION === "true" || process.env.GITHUB_ACTIONS === "true" || process.env.GITHUB_WORKFLOW || process.env.GITLAB_CI === "true" || process.env.CIRCLECI === "true" || process.env.TRAVIS === "true" || process.env.JENKINS_HOME || process.env.JENKINS_URL || process.env.BUILD_ID || process.env.TF_BUILD === "True" || process.env.AZURE_PIPELINES === "true" || process.env.TEAMCITY_VERSION || process.env.BITBUCKET_BUILD_NUMBER || process.env.DRONE === "true" || process.env.APPVEYOR === "True" || process.env.APPVEYOR === "true" || process.env.BUILDKITE === "true" || process.env.CODEBUILD_BUILD_ID || process.env.NETLIFY === "true" || process.env.VERCEL === "1" || process.env.HEROKU_TEST_RUN_ID || process.env.BUDDY === "true" || process.env.SEMAPHORE === "true" || process.env.CF_BUILD_ID || process.env.bamboo_buildKey || process.env.BUILD_ID && process.env.PROJECT_ID || process.env.SCREWDRIVER === "true" || process.env.STRIDER === "true"
|
|
499
|
+
process$1.env.CI === "true" || process$1.env.CONTINUOUS_INTEGRATION === "true" || process$1.env.GITHUB_ACTIONS === "true" || process$1.env.GITHUB_WORKFLOW || process$1.env.GITLAB_CI === "true" || process$1.env.CIRCLECI === "true" || process$1.env.TRAVIS === "true" || process$1.env.JENKINS_HOME || process$1.env.JENKINS_URL || process$1.env.BUILD_ID || process$1.env.TF_BUILD === "True" || process$1.env.AZURE_PIPELINES === "true" || process$1.env.TEAMCITY_VERSION || process$1.env.BITBUCKET_BUILD_NUMBER || process$1.env.DRONE === "true" || process$1.env.APPVEYOR === "True" || process$1.env.APPVEYOR === "true" || process$1.env.BUILDKITE === "true" || process$1.env.CODEBUILD_BUILD_ID || process$1.env.NETLIFY === "true" || process$1.env.VERCEL === "1" || process$1.env.HEROKU_TEST_RUN_ID || process$1.env.BUDDY === "true" || process$1.env.SEMAPHORE === "true" || process$1.env.CF_BUILD_ID || process$1.env.bamboo_buildKey || process$1.env.BUILD_ID && process$1.env.PROJECT_ID || process$1.env.SCREWDRIVER === "true" || process$1.env.STRIDER === "true"
|
|
500
500
|
);
|
|
501
501
|
}
|
|
502
502
|
function getCIName() {
|
|
503
|
-
if (process.env.GITHUB_ACTIONS === "true")
|
|
503
|
+
if (process$1.env.GITHUB_ACTIONS === "true")
|
|
504
504
|
return "GitHub Actions";
|
|
505
|
-
if (process.env.GITLAB_CI === "true")
|
|
505
|
+
if (process$1.env.GITLAB_CI === "true")
|
|
506
506
|
return "GitLab CI";
|
|
507
|
-
if (process.env.CIRCLECI === "true")
|
|
507
|
+
if (process$1.env.CIRCLECI === "true")
|
|
508
508
|
return "CircleCI";
|
|
509
|
-
if (process.env.TRAVIS === "true")
|
|
509
|
+
if (process$1.env.TRAVIS === "true")
|
|
510
510
|
return "Travis CI";
|
|
511
|
-
if (process.env.JENKINS_HOME || process.env.JENKINS_URL)
|
|
511
|
+
if (process$1.env.JENKINS_HOME || process$1.env.JENKINS_URL)
|
|
512
512
|
return "Jenkins";
|
|
513
|
-
if (process.env.TF_BUILD === "True")
|
|
513
|
+
if (process$1.env.TF_BUILD === "True")
|
|
514
514
|
return "Azure Pipelines";
|
|
515
|
-
if (process.env.TEAMCITY_VERSION)
|
|
515
|
+
if (process$1.env.TEAMCITY_VERSION)
|
|
516
516
|
return "TeamCity";
|
|
517
|
-
if (process.env.BITBUCKET_BUILD_NUMBER)
|
|
517
|
+
if (process$1.env.BITBUCKET_BUILD_NUMBER)
|
|
518
518
|
return "Bitbucket Pipelines";
|
|
519
|
-
if (process.env.DRONE === "true")
|
|
519
|
+
if (process$1.env.DRONE === "true")
|
|
520
520
|
return "Drone";
|
|
521
|
-
if (process.env.APPVEYOR)
|
|
521
|
+
if (process$1.env.APPVEYOR)
|
|
522
522
|
return "AppVeyor";
|
|
523
|
-
if (process.env.BUILDKITE === "true")
|
|
523
|
+
if (process$1.env.BUILDKITE === "true")
|
|
524
524
|
return "Buildkite";
|
|
525
|
-
if (process.env.CODEBUILD_BUILD_ID)
|
|
525
|
+
if (process$1.env.CODEBUILD_BUILD_ID)
|
|
526
526
|
return "AWS CodeBuild";
|
|
527
|
-
if (process.env.NETLIFY === "true")
|
|
527
|
+
if (process$1.env.NETLIFY === "true")
|
|
528
528
|
return "Netlify";
|
|
529
|
-
if (process.env.VERCEL === "1")
|
|
529
|
+
if (process$1.env.VERCEL === "1")
|
|
530
530
|
return "Vercel";
|
|
531
|
-
if (process.env.HEROKU_TEST_RUN_ID)
|
|
531
|
+
if (process$1.env.HEROKU_TEST_RUN_ID)
|
|
532
532
|
return "Heroku CI";
|
|
533
|
-
if (process.env.BUDDY === "true")
|
|
533
|
+
if (process$1.env.BUDDY === "true")
|
|
534
534
|
return "Buddy";
|
|
535
|
-
if (process.env.SEMAPHORE === "true")
|
|
535
|
+
if (process$1.env.SEMAPHORE === "true")
|
|
536
536
|
return "Semaphore";
|
|
537
|
-
if (process.env.CF_BUILD_ID)
|
|
537
|
+
if (process$1.env.CF_BUILD_ID)
|
|
538
538
|
return "Codefresh";
|
|
539
|
-
if (process.env.bamboo_buildKey)
|
|
539
|
+
if (process$1.env.bamboo_buildKey)
|
|
540
540
|
return "Bamboo";
|
|
541
|
-
if (process.env.BUILD_ID && process.env.PROJECT_ID)
|
|
541
|
+
if (process$1.env.BUILD_ID && process$1.env.PROJECT_ID)
|
|
542
542
|
return "Google Cloud Build";
|
|
543
|
-
if (process.env.SCREWDRIVER === "true")
|
|
543
|
+
if (process$1.env.SCREWDRIVER === "true")
|
|
544
544
|
return "Screwdriver";
|
|
545
|
-
if (process.env.STRIDER === "true")
|
|
545
|
+
if (process$1.env.STRIDER === "true")
|
|
546
546
|
return "Strider";
|
|
547
|
-
if (process.env.CI === "true")
|
|
547
|
+
if (process$1.env.CI === "true")
|
|
548
548
|
return "Unknown CI";
|
|
549
549
|
return null;
|
|
550
550
|
}
|
|
@@ -610,7 +610,6 @@ async function getPackagesOrBumpedPackages({
|
|
|
610
610
|
}
|
|
611
611
|
return await getPackages({
|
|
612
612
|
config,
|
|
613
|
-
patterns: config.monorepo?.packages,
|
|
614
613
|
suffix,
|
|
615
614
|
force
|
|
616
615
|
});
|
|
@@ -663,6 +662,9 @@ function detectGitProvider(cwd = process.cwd()) {
|
|
|
663
662
|
if (remoteUrl.includes("gitlab.com") || remoteUrl.includes("gitlab")) {
|
|
664
663
|
return "gitlab";
|
|
665
664
|
}
|
|
665
|
+
if (remoteUrl.includes("bitbucket.org") || remoteUrl.includes("bitbucket")) {
|
|
666
|
+
return "bitbucket";
|
|
667
|
+
}
|
|
666
668
|
return null;
|
|
667
669
|
} catch {
|
|
668
670
|
return null;
|
|
@@ -670,7 +672,7 @@ function detectGitProvider(cwd = process.cwd()) {
|
|
|
670
672
|
}
|
|
671
673
|
function parseGitRemoteUrl(remoteUrl) {
|
|
672
674
|
const sshRegex = /git@[\w.-]+:([\w.-]+)\/([\w.-]+?)(?:\.git)?$/;
|
|
673
|
-
const httpsRegex = /https?:\/\/[\w.-]+\/(
|
|
675
|
+
const httpsRegex = /https?:\/\/[\w.-]+\/(.+?)\/([^/]+?)(?:\.git)?$/;
|
|
674
676
|
const sshMatch = remoteUrl.match(sshRegex);
|
|
675
677
|
if (sshMatch) {
|
|
676
678
|
return {
|
|
@@ -906,7 +908,8 @@ async function generateMarkDown({
|
|
|
906
908
|
config,
|
|
907
909
|
from,
|
|
908
910
|
to,
|
|
909
|
-
isFirstCommit
|
|
911
|
+
isFirstCommit,
|
|
912
|
+
minify
|
|
910
913
|
}) {
|
|
911
914
|
const typeGroups = groupBy(commits, "type");
|
|
912
915
|
const markdown = [];
|
|
@@ -919,7 +922,7 @@ async function generateMarkDown({
|
|
|
919
922
|
const versionTitle = updatedConfig.to;
|
|
920
923
|
const changelogTitle = `${updatedConfig.from}...${updatedConfig.to}`;
|
|
921
924
|
markdown.push("", `## ${changelogTitle}`, "");
|
|
922
|
-
if (updatedConfig.repo && updatedConfig.from && versionTitle) {
|
|
925
|
+
if (updatedConfig.repo && updatedConfig.from && versionTitle && !minify) {
|
|
923
926
|
const formattedCompareLink = formatCompareChanges(versionTitle, {
|
|
924
927
|
...updatedConfig,
|
|
925
928
|
from: isFirstCommit ? getFirstCommit(updatedConfig.cwd) : updatedConfig.from
|
|
@@ -936,7 +939,11 @@ async function generateMarkDown({
|
|
|
936
939
|
}
|
|
937
940
|
markdown.push("", `### ${updatedConfig.types[type]?.title}`, "");
|
|
938
941
|
for (const commit of group.reverse()) {
|
|
939
|
-
const line = formatCommit(
|
|
942
|
+
const line = formatCommit({
|
|
943
|
+
commit,
|
|
944
|
+
config: updatedConfig,
|
|
945
|
+
minify
|
|
946
|
+
});
|
|
940
947
|
markdown.push(line);
|
|
941
948
|
if (commit.isBreaking) {
|
|
942
949
|
breakingChanges.push(line);
|
|
@@ -948,7 +955,7 @@ async function generateMarkDown({
|
|
|
948
955
|
}
|
|
949
956
|
const _authors = /* @__PURE__ */ new Map();
|
|
950
957
|
for (const commit of commits) {
|
|
951
|
-
if (!commit.author) {
|
|
958
|
+
if (!commit.author || minify) {
|
|
952
959
|
continue;
|
|
953
960
|
}
|
|
954
961
|
const name = formatName(commit.author.name);
|
|
@@ -1028,9 +1035,9 @@ function getCommitBody(commit) {
|
|
|
1028
1035
|
${indentedBody}
|
|
1029
1036
|
`;
|
|
1030
1037
|
}
|
|
1031
|
-
function formatCommit(commit, config) {
|
|
1032
|
-
const body = config.changelog.includeCommitBody ? getCommitBody(commit) : "";
|
|
1033
|
-
return `- ${commit.scope ? `**${commit.scope.trim()}:** ` : ""}${commit.isBreaking ? "\u26A0\uFE0F " : ""}${upperFirst(commit.description)}${formatReferences(commit.references, config)}${body}`;
|
|
1038
|
+
function formatCommit({ commit, config, minify }) {
|
|
1039
|
+
const body = config.changelog.includeCommitBody && !minify ? getCommitBody(commit) : "";
|
|
1040
|
+
return `- ${commit.scope ? `**${commit.scope.trim()}:** ` : ""}${commit.isBreaking ? "\u26A0\uFE0F " : ""}${upperFirst(commit.description)}${minify ? "" : formatReferences(commit.references, config)}${body}`;
|
|
1034
1041
|
}
|
|
1035
1042
|
function formatReferences(references, config) {
|
|
1036
1043
|
const pr = references.filter((ref) => ref.type === "pull-request");
|
|
@@ -1055,1475 +1062,1500 @@ function groupBy(items, key) {
|
|
|
1055
1062
|
return groups;
|
|
1056
1063
|
}
|
|
1057
1064
|
|
|
1058
|
-
function
|
|
1059
|
-
|
|
1065
|
+
function isGraduatingToStableBetweenVersion(version, newVersion) {
|
|
1066
|
+
const isSameBase = semver.major(version) === semver.major(newVersion) && semver.minor(version) === semver.minor(newVersion) && semver.patch(version) === semver.patch(newVersion);
|
|
1067
|
+
const fromPrerelease = semver.prerelease(version) !== null;
|
|
1068
|
+
const toStable = semver.prerelease(newVersion) === null;
|
|
1069
|
+
return isSameBase && fromPrerelease && toStable;
|
|
1060
1070
|
}
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1071
|
+
function determineSemverChange(commits, types) {
|
|
1072
|
+
let [hasMajor, hasMinor, hasPatch] = [false, false, false];
|
|
1073
|
+
for (const commit of commits) {
|
|
1074
|
+
const commitType = types[commit.type];
|
|
1075
|
+
if (!commitType) {
|
|
1076
|
+
continue;
|
|
1077
|
+
}
|
|
1078
|
+
const semverType = commitType.semver;
|
|
1079
|
+
if (semverType === "major" || commit.isBreaking) {
|
|
1080
|
+
hasMajor = true;
|
|
1081
|
+
} else if (semverType === "minor") {
|
|
1082
|
+
hasMinor = true;
|
|
1083
|
+
} else if (semverType === "patch") {
|
|
1084
|
+
hasPatch = true;
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
return hasMajor ? "major" : hasMinor ? "minor" : hasPatch ? "patch" : void 0;
|
|
1088
|
+
}
|
|
1089
|
+
function detectReleaseTypeFromCommits(commits, types) {
|
|
1090
|
+
return determineSemverChange(commits, types);
|
|
1091
|
+
}
|
|
1092
|
+
function validatePrereleaseDowngrade(currentVersion, targetPreid, configuredType) {
|
|
1093
|
+
if (configuredType !== "prerelease" || !targetPreid || !isPrerelease(currentVersion)) {
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
const testVersion = semver.inc(currentVersion, "prerelease", targetPreid);
|
|
1097
|
+
const isNotUpgrade = testVersion && !semver.gt(testVersion, currentVersion);
|
|
1098
|
+
if (isNotUpgrade) {
|
|
1099
|
+
throw new Error(`Unable to graduate from ${currentVersion} to ${testVersion}, it's not a valid prerelease`);
|
|
1100
|
+
}
|
|
1101
|
+
}
|
|
1102
|
+
function handleStableVersionWithReleaseType(commits, types, force) {
|
|
1103
|
+
if (!commits?.length && !force) {
|
|
1104
|
+
logger.debug('No commits found for stable version with "release" type, skipping bump');
|
|
1105
|
+
return void 0;
|
|
1106
|
+
}
|
|
1107
|
+
const detectedType = commits?.length ? detectReleaseTypeFromCommits(commits, types) : void 0;
|
|
1108
|
+
if (!detectedType && !force) {
|
|
1109
|
+
logger.debug("No significant commits found, skipping bump");
|
|
1110
|
+
return void 0;
|
|
1111
|
+
}
|
|
1112
|
+
logger.debug(`Auto-detected release type from commits: ${detectedType}`);
|
|
1113
|
+
return detectedType;
|
|
1114
|
+
}
|
|
1115
|
+
function handleStableVersionWithPrereleaseType(commits, types, force) {
|
|
1116
|
+
if (!commits?.length && !force) {
|
|
1117
|
+
logger.debug('No commits found for stable version with "prerelease" type, skipping bump');
|
|
1118
|
+
return void 0;
|
|
1119
|
+
}
|
|
1120
|
+
const detectedType = commits?.length ? detectReleaseTypeFromCommits(commits, types) : void 0;
|
|
1121
|
+
if (!detectedType) {
|
|
1122
|
+
logger.debug("No significant commits found, using prepatch as default");
|
|
1123
|
+
return "prepatch";
|
|
1124
|
+
}
|
|
1125
|
+
const prereleaseType = `pre${detectedType}`;
|
|
1126
|
+
logger.debug(`Auto-detected prerelease type from commits: ${prereleaseType}`);
|
|
1127
|
+
return prereleaseType;
|
|
1128
|
+
}
|
|
1129
|
+
function handlePrereleaseVersionToStable(currentVersion) {
|
|
1130
|
+
logger.debug(`Graduating from prerelease ${currentVersion} to stable release`);
|
|
1131
|
+
return "release";
|
|
1132
|
+
}
|
|
1133
|
+
function handlePrereleaseVersionWithPrereleaseType({ currentVersion, preid, commits, force }) {
|
|
1134
|
+
const currentPreid = getPreid(currentVersion);
|
|
1135
|
+
const hasChangedPreid = preid && currentPreid && currentPreid !== preid;
|
|
1136
|
+
if (hasChangedPreid) {
|
|
1137
|
+
const testVersion = semver.inc(currentVersion, "prerelease", preid);
|
|
1138
|
+
if (!testVersion) {
|
|
1139
|
+
throw new Error(`Unable to change preid from ${currentPreid} to ${preid} for version ${currentVersion}`);
|
|
1140
|
+
}
|
|
1141
|
+
const isUpgrade = semver.gt(testVersion, currentVersion);
|
|
1142
|
+
if (!isUpgrade) {
|
|
1143
|
+
throw new Error(`Unable to change preid from ${currentVersion} to ${testVersion}, it's not a valid upgrade (cannot downgrade from ${currentPreid} to ${preid})`);
|
|
1144
|
+
}
|
|
1145
|
+
return "prerelease";
|
|
1146
|
+
}
|
|
1147
|
+
if (!commits?.length && !force) {
|
|
1148
|
+
logger.debug("No commits found for prerelease version, skipping bump");
|
|
1149
|
+
return void 0;
|
|
1150
|
+
}
|
|
1151
|
+
logger.debug(`Incrementing prerelease version: ${currentVersion}`);
|
|
1152
|
+
return "prerelease";
|
|
1153
|
+
}
|
|
1154
|
+
function handleExplicitReleaseType({
|
|
1155
|
+
releaseType,
|
|
1156
|
+
currentVersion
|
|
1066
1157
|
}) {
|
|
1067
|
-
|
|
1068
|
-
const
|
|
1069
|
-
if (
|
|
1070
|
-
|
|
1158
|
+
const isCurrentPrerelease = isPrerelease(currentVersion);
|
|
1159
|
+
const isGraduatingToStable = isCurrentPrerelease && isStableReleaseType(releaseType);
|
|
1160
|
+
if (isGraduatingToStable) {
|
|
1161
|
+
logger.debug(`Graduating from prerelease ${currentVersion} to stable with type: ${releaseType}`);
|
|
1162
|
+
} else {
|
|
1163
|
+
logger.debug(`Using explicit release type: ${releaseType}`);
|
|
1071
1164
|
}
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1165
|
+
return releaseType;
|
|
1166
|
+
}
|
|
1167
|
+
function determineReleaseType({
|
|
1168
|
+
currentVersion,
|
|
1169
|
+
commits,
|
|
1170
|
+
releaseType,
|
|
1171
|
+
preid,
|
|
1172
|
+
types,
|
|
1173
|
+
force
|
|
1174
|
+
}) {
|
|
1175
|
+
if (releaseType === "release" && preid) {
|
|
1176
|
+
throw new Error('You cannot use a "release" type with a "preid", to use a preid you must use a "prerelease" type');
|
|
1075
1177
|
}
|
|
1076
|
-
|
|
1077
|
-
|
|
1178
|
+
validatePrereleaseDowngrade(currentVersion, preid, releaseType);
|
|
1179
|
+
if (force) {
|
|
1180
|
+
logger.debug(`Force flag enabled, using configured type: ${releaseType}`);
|
|
1181
|
+
return releaseType;
|
|
1078
1182
|
}
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
from: fromTag,
|
|
1084
|
-
to: toTag
|
|
1085
|
-
};
|
|
1086
|
-
const generatedChangelog = await generateMarkDown({
|
|
1087
|
-
commits: pkg.commits,
|
|
1088
|
-
config,
|
|
1089
|
-
from: fromTag,
|
|
1090
|
-
isFirstCommit,
|
|
1091
|
-
to: toTag
|
|
1092
|
-
});
|
|
1093
|
-
let changelog = generatedChangelog;
|
|
1094
|
-
if (pkg.commits.length === 0) {
|
|
1095
|
-
changelog = `${changelog}
|
|
1096
|
-
|
|
1097
|
-
${config.templates.emptyChangelogContent}`;
|
|
1183
|
+
const isCurrentPrerelease = isPrerelease(currentVersion);
|
|
1184
|
+
if (!isCurrentPrerelease) {
|
|
1185
|
+
if (releaseType === "release") {
|
|
1186
|
+
return handleStableVersionWithReleaseType(commits, types, force);
|
|
1098
1187
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
});
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1188
|
+
if (releaseType === "prerelease") {
|
|
1189
|
+
return handleStableVersionWithPrereleaseType(commits, types, force);
|
|
1190
|
+
}
|
|
1191
|
+
return handleExplicitReleaseType({ releaseType, currentVersion });
|
|
1192
|
+
}
|
|
1193
|
+
if (releaseType === "release") {
|
|
1194
|
+
return handlePrereleaseVersionToStable(currentVersion);
|
|
1195
|
+
}
|
|
1196
|
+
if (releaseType === "prerelease") {
|
|
1197
|
+
return handlePrereleaseVersionWithPrereleaseType({ currentVersion, preid, commits, force });
|
|
1198
|
+
}
|
|
1199
|
+
return handleExplicitReleaseType({ releaseType, currentVersion });
|
|
1200
|
+
}
|
|
1201
|
+
function writeVersion(pkgPath, newVersion, dryRun = false) {
|
|
1202
|
+
const packageJsonPath = join(pkgPath, "package.json");
|
|
1203
|
+
try {
|
|
1204
|
+
logger.debug(`Writing ${newVersion} to ${pkgPath}`);
|
|
1205
|
+
const content = readFileSync(packageJsonPath, "utf8");
|
|
1206
|
+
const packageJson = JSON.parse(content);
|
|
1207
|
+
const oldVersion = packageJson.version;
|
|
1208
|
+
packageJson.version = newVersion;
|
|
1112
1209
|
if (dryRun) {
|
|
1113
|
-
logger.
|
|
1210
|
+
logger.debug(`[dry-run] Updated ${packageJson.name}: ${oldVersion} \u2192 ${newVersion}`);
|
|
1211
|
+
return;
|
|
1114
1212
|
}
|
|
1115
|
-
|
|
1213
|
+
writeFileSync(packageJsonPath, `${formatJson(packageJson)}
|
|
1214
|
+
`, "utf8");
|
|
1215
|
+
logger.debug(`Updated ${packageJson.name}: ${oldVersion} \u2192 ${newVersion}`);
|
|
1116
1216
|
} catch (error) {
|
|
1117
|
-
throw new Error(`
|
|
1217
|
+
throw new Error(`Unable to write version to ${packageJsonPath}: ${error}`);
|
|
1118
1218
|
}
|
|
1119
1219
|
}
|
|
1120
|
-
function
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1220
|
+
function getPackageNewVersion({
|
|
1221
|
+
name,
|
|
1222
|
+
currentVersion,
|
|
1223
|
+
releaseType,
|
|
1224
|
+
preid,
|
|
1225
|
+
suffix
|
|
1125
1226
|
}) {
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1227
|
+
let newVersion = semver.inc(currentVersion, releaseType, preid);
|
|
1228
|
+
if (!newVersion) {
|
|
1229
|
+
throw new Error(`Unable to bump "${name}" version "${currentVersion}" with release type "${releaseType}"
|
|
1230
|
+
|
|
1231
|
+
You should use an explicit release type (use flag: --major, --minor, --patch, --premajor, --preminor, --prepatch, --prerelease)`);
|
|
1130
1232
|
}
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
let updatedChangelog;
|
|
1134
|
-
if (titleIndex !== -1) {
|
|
1135
|
-
const beforeTitle = lines.slice(0, titleIndex + 1);
|
|
1136
|
-
const afterTitle = lines.slice(titleIndex + 1);
|
|
1137
|
-
updatedChangelog = [...beforeTitle, "", changelog, "", ...afterTitle].join("\n");
|
|
1138
|
-
} else {
|
|
1139
|
-
const title = "# Changelog\n";
|
|
1140
|
-
updatedChangelog = `${title}
|
|
1141
|
-
${changelog}
|
|
1142
|
-
${existingChangelog}`;
|
|
1233
|
+
if (isPrereleaseReleaseType(releaseType) && suffix) {
|
|
1234
|
+
newVersion = newVersion.replace(/\.(\d+)$/, `.${suffix}`);
|
|
1143
1235
|
}
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
} else {
|
|
1148
|
-
logger.debug(`Writing changelog to ${changelogPath}`);
|
|
1149
|
-
writeFileSync(changelogPath, updatedChangelog, "utf8");
|
|
1150
|
-
logger.info(`Changelog updated for ${pkg.name} (${"newVersion" in pkg && pkg.newVersion || pkg.version})`);
|
|
1236
|
+
const isValidVersion = semver.gt(newVersion, currentVersion);
|
|
1237
|
+
if (!isValidVersion) {
|
|
1238
|
+
throw new Error(`Unable to bump "${name}" version "${currentVersion}" to "${newVersion}", new version is not greater than current version`);
|
|
1151
1239
|
}
|
|
1240
|
+
if (isGraduating(currentVersion, releaseType)) {
|
|
1241
|
+
logger.info(`Graduating "${name}" from prerelease ${currentVersion} to stable ${newVersion}`);
|
|
1242
|
+
}
|
|
1243
|
+
if (isChangedPreid(currentVersion, preid)) {
|
|
1244
|
+
logger.debug(`Graduating "${name}" from ${getPreid(currentVersion)} to ${preid}`);
|
|
1245
|
+
}
|
|
1246
|
+
return newVersion;
|
|
1152
1247
|
}
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
docs: { title: "\u{1F4D6} Documentation", semver: "patch" },
|
|
1163
|
-
build: { title: "\u{1F4E6} Build", semver: "patch" },
|
|
1164
|
-
types: { title: "\u{1F30A} Types", semver: "patch" },
|
|
1165
|
-
chore: { title: "\u{1F3E1} Chore" },
|
|
1166
|
-
examples: { title: "\u{1F3C0} Examples" },
|
|
1167
|
-
test: { title: "\u2705 Tests" },
|
|
1168
|
-
style: { title: "\u{1F3A8} Styles" },
|
|
1169
|
-
ci: { title: "\u{1F916} CI" }
|
|
1170
|
-
},
|
|
1171
|
-
templates: {
|
|
1172
|
-
commitMessage: "chore(release): bump version to {{newVersion}}",
|
|
1173
|
-
tagMessage: "Bump version to {{newVersion}}",
|
|
1174
|
-
tagBody: "v{{newVersion}}",
|
|
1175
|
-
emptyChangelogContent: "No relevant changes for this release"
|
|
1176
|
-
},
|
|
1177
|
-
excludeAuthors: [],
|
|
1178
|
-
noAuthors: false,
|
|
1179
|
-
bump: {
|
|
1180
|
-
type: "release",
|
|
1181
|
-
clean: true,
|
|
1182
|
-
dependencyTypes: ["dependencies"],
|
|
1183
|
-
yes: false
|
|
1184
|
-
},
|
|
1185
|
-
changelog: {
|
|
1186
|
-
rootChangelog: true,
|
|
1187
|
-
includeCommitBody: true
|
|
1188
|
-
},
|
|
1189
|
-
publish: {
|
|
1190
|
-
private: false,
|
|
1191
|
-
args: [],
|
|
1192
|
-
token: process$1.env.RELIZY_NPM_TOKEN || process$1.env.NPM_TOKEN || process$1.env.NODE_AUTH_TOKEN,
|
|
1193
|
-
registry: "https://registry.npmjs.org/",
|
|
1194
|
-
safetyCheck: false
|
|
1195
|
-
},
|
|
1196
|
-
tokens: {
|
|
1197
|
-
registry: process$1.env.RELIZY_NPM_TOKEN || process$1.env.NPM_TOKEN || process$1.env.NODE_AUTH_TOKEN,
|
|
1198
|
-
gitlab: process$1.env.RELIZY_GITLAB_TOKEN || process$1.env.GITLAB_TOKEN || process$1.env.GITLAB_API_TOKEN || process$1.env.CI_JOB_TOKEN,
|
|
1199
|
-
github: process$1.env.RELIZY_GITHUB_TOKEN || process$1.env.GITHUB_TOKEN || process$1.env.GH_TOKEN
|
|
1200
|
-
},
|
|
1201
|
-
scopeMap: {},
|
|
1202
|
-
release: {
|
|
1203
|
-
commit: true,
|
|
1204
|
-
publish: true,
|
|
1205
|
-
changelog: true,
|
|
1206
|
-
push: true,
|
|
1207
|
-
clean: true,
|
|
1208
|
-
providerRelease: true,
|
|
1209
|
-
noVerify: false,
|
|
1210
|
-
gitTag: true
|
|
1211
|
-
},
|
|
1212
|
-
logLevel: "default",
|
|
1213
|
-
safetyCheck: true
|
|
1214
|
-
};
|
|
1215
|
-
}
|
|
1216
|
-
function setupLogger(logLevel) {
|
|
1217
|
-
if (logLevel) {
|
|
1218
|
-
logger.setLevel(logLevel);
|
|
1219
|
-
logger.debug(`Log level set to: ${logLevel}`);
|
|
1248
|
+
function updateLernaVersion({
|
|
1249
|
+
rootDir,
|
|
1250
|
+
versionMode,
|
|
1251
|
+
version,
|
|
1252
|
+
dryRun = false
|
|
1253
|
+
}) {
|
|
1254
|
+
const lernaJsonExists = hasLernaJson(rootDir);
|
|
1255
|
+
if (!lernaJsonExists) {
|
|
1256
|
+
return;
|
|
1220
1257
|
}
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
const resolvedRepoConfig = await resolveRepoConfig(cwd);
|
|
1225
|
-
config.repo = {
|
|
1226
|
-
...resolvedRepoConfig,
|
|
1227
|
-
provider: resolvedRepoConfig.provider
|
|
1228
|
-
};
|
|
1258
|
+
const lernaJsonPath = join(rootDir, "lerna.json");
|
|
1259
|
+
if (!existsSync(lernaJsonPath)) {
|
|
1260
|
+
return;
|
|
1229
1261
|
}
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1262
|
+
try {
|
|
1263
|
+
logger.debug("Updating lerna.json version");
|
|
1264
|
+
const content = readFileSync(lernaJsonPath, "utf8");
|
|
1265
|
+
const lernaJson = JSON.parse(content);
|
|
1266
|
+
const oldVersion = lernaJson.version;
|
|
1267
|
+
if (lernaJson.version === "independent" || versionMode === "independent") {
|
|
1268
|
+
logger.debug("Lerna version is independent or version mode is independent, skipping update");
|
|
1269
|
+
return;
|
|
1270
|
+
}
|
|
1271
|
+
lernaJson.version = version;
|
|
1272
|
+
if (dryRun) {
|
|
1273
|
+
logger.info(`[dry-run] update lerna.json: ${oldVersion} \u2192 ${version}`);
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
writeFileSync(lernaJsonPath, `${formatJson(lernaJson)}
|
|
1277
|
+
`, "utf8");
|
|
1278
|
+
logger.success(`Updated lerna.json: ${oldVersion} \u2192 ${version}`);
|
|
1279
|
+
} catch (error) {
|
|
1280
|
+
logger.fail(`Unable to update lerna.json: ${error}`);
|
|
1236
1281
|
}
|
|
1237
|
-
return config;
|
|
1238
1282
|
}
|
|
1239
|
-
|
|
1240
|
-
const
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
const defaultConfig = getDefaultConfig();
|
|
1244
|
-
const overridesConfig = defu(options?.overrides, options?.baseConfig);
|
|
1245
|
-
const results = await loadConfig({
|
|
1246
|
-
dotenv: true,
|
|
1247
|
-
cwd,
|
|
1248
|
-
name: configFile,
|
|
1249
|
-
packageJson: true,
|
|
1250
|
-
defaults: defaultConfig,
|
|
1251
|
-
overrides: overridesConfig
|
|
1252
|
-
});
|
|
1253
|
-
if (typeof results._configFile !== "string") {
|
|
1254
|
-
logger.debug(`No config file found with name "${configFile}"`);
|
|
1255
|
-
if (options?.configFile) {
|
|
1256
|
-
logger.error(`No config file found with name "${configFile}"`);
|
|
1257
|
-
process$1.exit(1);
|
|
1258
|
-
}
|
|
1283
|
+
function extractVersionFromPackageTag(tag) {
|
|
1284
|
+
const atIndex = tag.lastIndexOf("@");
|
|
1285
|
+
if (atIndex === -1) {
|
|
1286
|
+
return null;
|
|
1259
1287
|
}
|
|
1260
|
-
|
|
1261
|
-
logger.verbose("User config:", formatJson(results.config.changelog));
|
|
1262
|
-
const resolvedConfig = await resolveConfig(results.config, cwd);
|
|
1263
|
-
logger.debug("Resolved config:", formatJson(resolvedConfig));
|
|
1264
|
-
return resolvedConfig;
|
|
1288
|
+
return tag.slice(atIndex + 1);
|
|
1265
1289
|
}
|
|
1266
|
-
function
|
|
1267
|
-
|
|
1290
|
+
function isPrerelease(version) {
|
|
1291
|
+
if (!version)
|
|
1292
|
+
return false;
|
|
1293
|
+
const prerelease = semver.prerelease(version);
|
|
1294
|
+
return prerelease ? prerelease.length > 0 : false;
|
|
1268
1295
|
}
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1296
|
+
function isStableReleaseType(releaseType) {
|
|
1297
|
+
const stableTypes = ["release", "major", "minor", "patch"];
|
|
1298
|
+
return stableTypes.includes(releaseType);
|
|
1299
|
+
}
|
|
1300
|
+
function isPrereleaseReleaseType(releaseType) {
|
|
1301
|
+
const prereleaseTypes = ["prerelease", "premajor", "preminor", "prepatch"];
|
|
1302
|
+
return prereleaseTypes.includes(releaseType);
|
|
1303
|
+
}
|
|
1304
|
+
function isGraduating(currentVersion, releaseType) {
|
|
1305
|
+
return isPrerelease(currentVersion) && isStableReleaseType(releaseType);
|
|
1306
|
+
}
|
|
1307
|
+
function getPreid(version) {
|
|
1308
|
+
if (!version)
|
|
1309
|
+
return null;
|
|
1310
|
+
const prerelease = semver.prerelease(version);
|
|
1311
|
+
if (!prerelease || prerelease.length === 0) {
|
|
1312
|
+
return null;
|
|
1284
1313
|
}
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
});
|
|
1291
|
-
logger.info(`Creating ${packages.length} GitHub release(s)`);
|
|
1292
|
-
const postedReleases = [];
|
|
1293
|
-
for (const pkg of packages) {
|
|
1294
|
-
const newVersion = isBumpedPackage(pkg) && pkg.newVersion || pkg.version;
|
|
1295
|
-
const from = config.from || pkg.fromTag;
|
|
1296
|
-
const to = config.to || getIndependentTag({ version: newVersion, name: pkg.name });
|
|
1297
|
-
if (!from) {
|
|
1298
|
-
logger.warn(`No from tag found for ${pkg.name}, skipping release`);
|
|
1299
|
-
continue;
|
|
1300
|
-
}
|
|
1301
|
-
const toTag = dryRun ? "HEAD" : to;
|
|
1302
|
-
logger.debug(`Processing ${pkg.name}: ${from} \u2192 ${toTag}`);
|
|
1303
|
-
const changelog = await generateChangelog({
|
|
1304
|
-
pkg,
|
|
1305
|
-
config,
|
|
1306
|
-
dryRun,
|
|
1307
|
-
newVersion
|
|
1308
|
-
});
|
|
1309
|
-
const releaseBody = changelog.split("\n").slice(2).join("\n");
|
|
1310
|
-
const release = {
|
|
1311
|
-
tag_name: to,
|
|
1312
|
-
name: to,
|
|
1313
|
-
body: releaseBody,
|
|
1314
|
-
prerelease: isPrerelease(newVersion)
|
|
1315
|
-
};
|
|
1316
|
-
logger.debug(`Creating release for ${to}${release.prerelease ? " (prerelease)" : ""}`);
|
|
1317
|
-
if (dryRun) {
|
|
1318
|
-
logger.info(`[dry-run] Publish GitHub release for ${to}`);
|
|
1319
|
-
postedReleases.push({
|
|
1320
|
-
name: pkg.name,
|
|
1321
|
-
tag: release.tag_name,
|
|
1322
|
-
version: newVersion,
|
|
1323
|
-
prerelease: release.prerelease
|
|
1324
|
-
});
|
|
1325
|
-
} else {
|
|
1326
|
-
logger.debug(`Publishing release ${to} to GitHub...`);
|
|
1327
|
-
await createGithubRelease({
|
|
1328
|
-
...config,
|
|
1329
|
-
from,
|
|
1330
|
-
to,
|
|
1331
|
-
repo: repoConfig
|
|
1332
|
-
}, release);
|
|
1333
|
-
postedReleases.push({
|
|
1334
|
-
name: pkg.name,
|
|
1335
|
-
tag: release.tag_name,
|
|
1336
|
-
version: newVersion,
|
|
1337
|
-
prerelease: release.prerelease
|
|
1338
|
-
});
|
|
1339
|
-
}
|
|
1314
|
+
return prerelease[0];
|
|
1315
|
+
}
|
|
1316
|
+
function isChangedPreid(currentVersion, targetPreid) {
|
|
1317
|
+
if (!targetPreid || !isPrerelease(currentVersion)) {
|
|
1318
|
+
return false;
|
|
1340
1319
|
}
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
logger.success(`Releases ${postedReleases.map((r) => r.tag).join(", ")} published to GitHub!`);
|
|
1320
|
+
const currentPreid = getPreid(currentVersion);
|
|
1321
|
+
if (!currentPreid) {
|
|
1322
|
+
return false;
|
|
1345
1323
|
}
|
|
1346
|
-
return
|
|
1324
|
+
return currentPreid !== targetPreid;
|
|
1347
1325
|
}
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
dryRun
|
|
1351
|
-
rootPackage,
|
|
1352
|
-
bumpResult
|
|
1326
|
+
function getBumpedPackageIndependently({
|
|
1327
|
+
pkg,
|
|
1328
|
+
dryRun
|
|
1353
1329
|
}) {
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
if (!config.tokens.github && !config.repo?.token) {
|
|
1360
|
-
throw new Error("No GitHub token specified. Set GITHUB_TOKEN or GH_TOKEN environment variable.");
|
|
1361
|
-
}
|
|
1362
|
-
const newVersion = bumpResult?.newVersion || rootPackage.version;
|
|
1363
|
-
const to = config.to || config.templates.tagBody.replace("{{newVersion}}", newVersion);
|
|
1364
|
-
const changelog = await generateChangelog({
|
|
1365
|
-
pkg: rootPackage,
|
|
1366
|
-
config,
|
|
1367
|
-
dryRun,
|
|
1368
|
-
newVersion
|
|
1369
|
-
});
|
|
1370
|
-
const releaseBody = changelog.split("\n").slice(2).join("\n");
|
|
1371
|
-
const release = {
|
|
1372
|
-
tag_name: to,
|
|
1373
|
-
name: to,
|
|
1374
|
-
body: releaseBody,
|
|
1375
|
-
prerelease: isPrerelease(to)
|
|
1376
|
-
};
|
|
1377
|
-
logger.debug(`Creating release for ${to}${release.prerelease ? " (prerelease)" : ""}`);
|
|
1378
|
-
logger.debug("Release details:", formatJson({
|
|
1379
|
-
tag_name: release.tag_name,
|
|
1380
|
-
name: release.name,
|
|
1381
|
-
prerelease: release.prerelease
|
|
1382
|
-
}));
|
|
1383
|
-
if (dryRun) {
|
|
1384
|
-
logger.info("[dry-run] Publish GitHub release for", release.tag_name);
|
|
1385
|
-
} else {
|
|
1386
|
-
logger.debug("Publishing release to GitHub...");
|
|
1387
|
-
await createGithubRelease({
|
|
1388
|
-
...config,
|
|
1389
|
-
from: bumpResult?.bumped && bumpResult.fromTag || "v0.0.0",
|
|
1390
|
-
to,
|
|
1391
|
-
repo: repoConfig
|
|
1392
|
-
}, release);
|
|
1330
|
+
logger.debug(`Analyzing ${pkg.name}`);
|
|
1331
|
+
const currentVersion = pkg.version || "0.0.0";
|
|
1332
|
+
const newVersion = pkg.newVersion;
|
|
1333
|
+
if (!newVersion) {
|
|
1334
|
+
return { bumped: false };
|
|
1393
1335
|
}
|
|
1394
|
-
logger.
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
tag: to,
|
|
1398
|
-
version: to,
|
|
1399
|
-
prerelease: release.prerelease
|
|
1400
|
-
}];
|
|
1336
|
+
logger.debug(`Bumping ${pkg.name} from ${currentVersion} to ${newVersion}`);
|
|
1337
|
+
writeVersion(pkg.path, newVersion, dryRun);
|
|
1338
|
+
return { bumped: true, newVersion, oldVersion: currentVersion };
|
|
1401
1339
|
}
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
});
|
|
1418
|
-
if (config.monorepo?.versionMode === "independent") {
|
|
1419
|
-
return await githubIndependentMode({
|
|
1420
|
-
config,
|
|
1421
|
-
dryRun,
|
|
1422
|
-
bumpResult: options.bumpResult,
|
|
1423
|
-
force: options.force ?? false,
|
|
1424
|
-
suffix: options.suffix
|
|
1425
|
-
});
|
|
1426
|
-
}
|
|
1427
|
-
const rootPackageBase = readPackageJson(config.cwd);
|
|
1428
|
-
if (!rootPackageBase) {
|
|
1429
|
-
throw new Error("Failed to read root package.json");
|
|
1340
|
+
function displayRootAndLernaUpdates({
|
|
1341
|
+
versionMode,
|
|
1342
|
+
currentVersion,
|
|
1343
|
+
newVersion,
|
|
1344
|
+
dryRun,
|
|
1345
|
+
lernaJsonExists
|
|
1346
|
+
}) {
|
|
1347
|
+
if (versionMode !== "independent" && currentVersion && newVersion) {
|
|
1348
|
+
logger.log(`${dryRun ? "[dry-run] " : ""}Root package.json: ${currentVersion} \u2192 ${newVersion}`);
|
|
1349
|
+
logger.log("");
|
|
1350
|
+
if (lernaJsonExists) {
|
|
1351
|
+
logger.log(`${dryRun ? "[dry-run] " : ""}lerna.json: ${currentVersion} \u2192 ${newVersion}`);
|
|
1352
|
+
logger.log("");
|
|
1430
1353
|
}
|
|
1431
|
-
const newVersion = options.bumpResult?.newVersion || rootPackageBase.version;
|
|
1432
|
-
const { from, to } = await resolveTags({
|
|
1433
|
-
config,
|
|
1434
|
-
step: "provider-release",
|
|
1435
|
-
newVersion,
|
|
1436
|
-
pkg: rootPackageBase
|
|
1437
|
-
});
|
|
1438
|
-
const rootPackage = options.bumpResult?.rootPackage || await getRootPackage({
|
|
1439
|
-
config,
|
|
1440
|
-
force: options.force ?? false,
|
|
1441
|
-
suffix: options.suffix,
|
|
1442
|
-
changelog: true,
|
|
1443
|
-
from,
|
|
1444
|
-
to
|
|
1445
|
-
});
|
|
1446
|
-
return await githubUnified({
|
|
1447
|
-
config,
|
|
1448
|
-
dryRun,
|
|
1449
|
-
rootPackage,
|
|
1450
|
-
bumpResult: options.bumpResult
|
|
1451
|
-
});
|
|
1452
|
-
} catch (error) {
|
|
1453
|
-
logger.error("Error publishing GitHub release:", error);
|
|
1454
|
-
throw error;
|
|
1455
1354
|
}
|
|
1456
1355
|
}
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
dryRun
|
|
1356
|
+
function displayUnifiedModePackages({
|
|
1357
|
+
packages,
|
|
1358
|
+
newVersion,
|
|
1359
|
+
force
|
|
1462
1360
|
}) {
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
const payload = {
|
|
1479
|
-
tag_name: release.tag_name,
|
|
1480
|
-
name: release.name || release.tag_name,
|
|
1481
|
-
description: release.description || "",
|
|
1482
|
-
ref: release.ref || "main"
|
|
1483
|
-
};
|
|
1484
|
-
try {
|
|
1485
|
-
if (dryRun) {
|
|
1486
|
-
logger.info("[dry-run] GitLab release:", formatJson(payload));
|
|
1487
|
-
return {
|
|
1488
|
-
tag_name: release.tag_name,
|
|
1489
|
-
name: release.name || release.tag_name,
|
|
1490
|
-
description: release.description || "",
|
|
1491
|
-
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1492
|
-
released_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1493
|
-
_links: {
|
|
1494
|
-
self: `${apiUrl}/${encodeURIComponent(release.tag_name)}`
|
|
1495
|
-
}
|
|
1496
|
-
};
|
|
1497
|
-
}
|
|
1498
|
-
logger.debug(`POST GitLab release to ${apiUrl} with payload: ${formatJson(payload)}`);
|
|
1499
|
-
const response = await fetch(apiUrl, {
|
|
1500
|
-
method: "POST",
|
|
1501
|
-
headers: {
|
|
1502
|
-
"Content-Type": "application/json",
|
|
1503
|
-
"PRIVATE-TOKEN": token || ""
|
|
1504
|
-
},
|
|
1505
|
-
body: JSON.stringify(payload)
|
|
1361
|
+
logger.log(`${packages.length} package(s):`);
|
|
1362
|
+
packages.forEach((pkg) => {
|
|
1363
|
+
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion} (${pkg.commits.length} commits) ${force ? "(force)" : ""}`);
|
|
1364
|
+
});
|
|
1365
|
+
logger.log("");
|
|
1366
|
+
}
|
|
1367
|
+
function displaySelectiveModePackages({
|
|
1368
|
+
packages,
|
|
1369
|
+
newVersion,
|
|
1370
|
+
force
|
|
1371
|
+
}) {
|
|
1372
|
+
if (force) {
|
|
1373
|
+
logger.log(`${packages.length} package(s):`);
|
|
1374
|
+
packages.forEach((pkg) => {
|
|
1375
|
+
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion} (force)`);
|
|
1506
1376
|
});
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1377
|
+
logger.log("");
|
|
1378
|
+
} else {
|
|
1379
|
+
const packagesWithCommits = packages.filter((p) => "reason" in p && p.reason === "commits");
|
|
1380
|
+
const packagesAsDependents = packages.filter((p) => "reason" in p && p.reason === "dependency");
|
|
1381
|
+
const packagesAsGraduation = packages.filter((p) => "reason" in p && p.reason === "graduation");
|
|
1382
|
+
if (packagesWithCommits.length > 0) {
|
|
1383
|
+
logger.log(`${packagesWithCommits.length} package(s) with commits:`);
|
|
1384
|
+
packagesWithCommits.forEach((pkg) => {
|
|
1385
|
+
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion} (${pkg.commits.length} commits) ${force ? "(force)" : ""}`);
|
|
1386
|
+
});
|
|
1387
|
+
logger.log("");
|
|
1388
|
+
}
|
|
1389
|
+
if (packagesAsDependents.length > 0) {
|
|
1390
|
+
logger.log(`${packagesAsDependents.length} dependent package(s):`);
|
|
1391
|
+
packagesAsDependents.forEach((pkg) => {
|
|
1392
|
+
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion} ${force ? "(force)" : ""}`);
|
|
1393
|
+
});
|
|
1394
|
+
logger.log("");
|
|
1395
|
+
}
|
|
1396
|
+
if (packagesAsGraduation.length > 0) {
|
|
1397
|
+
logger.log(`${packagesAsGraduation.length} graduation package(s):`);
|
|
1398
|
+
packagesAsGraduation.forEach((pkg) => {
|
|
1399
|
+
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion} ${force ? "(force)" : ""}`);
|
|
1400
|
+
});
|
|
1401
|
+
logger.log("");
|
|
1510
1402
|
}
|
|
1511
|
-
const result = await response.json();
|
|
1512
|
-
logger.debug(`Created GitLab release: ${result._links.self}`);
|
|
1513
|
-
return result;
|
|
1514
|
-
} catch (error) {
|
|
1515
|
-
logger.error("Failed to create GitLab release:", error);
|
|
1516
|
-
throw error;
|
|
1517
1403
|
}
|
|
1518
1404
|
}
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
dryRun,
|
|
1522
|
-
bumpResult,
|
|
1523
|
-
suffix,
|
|
1405
|
+
function displayIndependentModePackages({
|
|
1406
|
+
packages,
|
|
1524
1407
|
force
|
|
1525
1408
|
}) {
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
suffix,
|
|
1531
|
-
force
|
|
1532
|
-
});
|
|
1533
|
-
logger.info(`Creating ${packages.length} GitLab release(s) for independent packages`);
|
|
1534
|
-
logger.debug("Getting current branch...");
|
|
1535
|
-
const { stdout: currentBranch } = await execPromise("git rev-parse --abbrev-ref HEAD", {
|
|
1536
|
-
noSuccess: true,
|
|
1537
|
-
noStdout: true,
|
|
1538
|
-
logLevel: config.logLevel,
|
|
1539
|
-
cwd: config.cwd
|
|
1540
|
-
});
|
|
1541
|
-
const postedReleases = [];
|
|
1542
|
-
for (const pkg of packages) {
|
|
1543
|
-
const newVersion = isBumpedPackage(pkg) && pkg.newVersion || pkg.version;
|
|
1544
|
-
const from = config.from || pkg.fromTag;
|
|
1545
|
-
const to = getIndependentTag({ version: newVersion, name: pkg.name });
|
|
1546
|
-
if (!from) {
|
|
1547
|
-
logger.warn(`No from tag found for ${pkg.name}, skipping release`);
|
|
1548
|
-
continue;
|
|
1549
|
-
}
|
|
1550
|
-
logger.debug(`Processing ${pkg.name}: ${from} \u2192 ${to}`);
|
|
1551
|
-
const changelog = await generateChangelog({
|
|
1552
|
-
pkg,
|
|
1553
|
-
config,
|
|
1554
|
-
dryRun,
|
|
1555
|
-
newVersion
|
|
1409
|
+
if (force) {
|
|
1410
|
+
logger.log(`${packages.length} package(s):`);
|
|
1411
|
+
packages.forEach((pkg) => {
|
|
1412
|
+
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion} (force)`);
|
|
1556
1413
|
});
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1414
|
+
logger.log("");
|
|
1415
|
+
} else {
|
|
1416
|
+
const packagesWithCommits = packages.filter((p) => "reason" in p && p.reason === "commits");
|
|
1417
|
+
const packagesAsDependents = packages.filter((p) => "reason" in p && p.reason === "dependency");
|
|
1418
|
+
const packagesAsGraduation = packages.filter((p) => "reason" in p && p.reason === "graduation");
|
|
1419
|
+
if (packagesWithCommits.length > 0) {
|
|
1420
|
+
logger.log(`${packagesWithCommits.length} package(s) with commits:`);
|
|
1421
|
+
packagesWithCommits.forEach((pkg) => {
|
|
1422
|
+
pkg.newVersion && logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion} (${pkg.commits.length} commits) ${force ? "(force)" : ""}`);
|
|
1423
|
+
});
|
|
1424
|
+
logger.log("");
|
|
1560
1425
|
}
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
description: releaseBody,
|
|
1566
|
-
ref: currentBranch.trim()
|
|
1567
|
-
};
|
|
1568
|
-
logger.debug(`Creating release for ${to} (ref: ${release.ref})`);
|
|
1569
|
-
if (dryRun) {
|
|
1570
|
-
logger.info(`[dry-run] Publish GitLab release for ${to}`);
|
|
1571
|
-
} else {
|
|
1572
|
-
logger.debug(`Publishing release ${to} to GitLab...`);
|
|
1573
|
-
await createGitlabRelease({
|
|
1574
|
-
config,
|
|
1575
|
-
release,
|
|
1576
|
-
dryRun
|
|
1426
|
+
if (packagesAsDependents.length > 0) {
|
|
1427
|
+
logger.log(`${packagesAsDependents.length} dependent package(s):`);
|
|
1428
|
+
packagesAsDependents.forEach((pkg) => {
|
|
1429
|
+
pkg.newVersion && logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion} ${force ? "(force)" : ""}`);
|
|
1577
1430
|
});
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1431
|
+
logger.log("");
|
|
1432
|
+
}
|
|
1433
|
+
if (packagesAsGraduation.length > 0) {
|
|
1434
|
+
logger.log(`${packagesAsGraduation.length} graduation package(s):`);
|
|
1435
|
+
packagesAsGraduation.forEach((pkg) => {
|
|
1436
|
+
pkg.newVersion && logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion} ${force ? "(force)" : ""}`);
|
|
1583
1437
|
});
|
|
1438
|
+
logger.log("");
|
|
1584
1439
|
}
|
|
1585
1440
|
}
|
|
1586
|
-
if (postedReleases.length === 0) {
|
|
1587
|
-
logger.warn("No releases created");
|
|
1588
|
-
} else {
|
|
1589
|
-
logger.success(`Releases ${postedReleases.map((r) => r.tag).join(", ")} published to GitLab!`);
|
|
1590
|
-
}
|
|
1591
|
-
return postedReleases;
|
|
1592
1441
|
}
|
|
1593
|
-
async function
|
|
1442
|
+
async function confirmBump({
|
|
1443
|
+
versionMode,
|
|
1594
1444
|
config,
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1445
|
+
packages,
|
|
1446
|
+
force,
|
|
1447
|
+
currentVersion,
|
|
1448
|
+
newVersion,
|
|
1449
|
+
dryRun
|
|
1598
1450
|
}) {
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
const changelog = await generateChangelog({
|
|
1603
|
-
pkg: rootPackage,
|
|
1604
|
-
config,
|
|
1605
|
-
dryRun,
|
|
1606
|
-
newVersion
|
|
1607
|
-
});
|
|
1608
|
-
const releaseBody = changelog.split("\n").slice(2).join("\n");
|
|
1609
|
-
logger.debug("Getting current branch...");
|
|
1610
|
-
const { stdout: currentBranch } = await execPromise("git rev-parse --abbrev-ref HEAD", {
|
|
1611
|
-
noSuccess: true,
|
|
1612
|
-
noStdout: true,
|
|
1613
|
-
logLevel: config.logLevel,
|
|
1614
|
-
cwd: config.cwd
|
|
1615
|
-
});
|
|
1616
|
-
const release = {
|
|
1617
|
-
tag_name: to,
|
|
1618
|
-
name: to,
|
|
1619
|
-
description: releaseBody,
|
|
1620
|
-
ref: currentBranch.trim()
|
|
1621
|
-
};
|
|
1622
|
-
logger.info(`Creating release for ${to} (ref: ${release.ref})`);
|
|
1623
|
-
logger.debug("Release details:", formatJson({
|
|
1624
|
-
tag_name: release.tag_name,
|
|
1625
|
-
name: release.name,
|
|
1626
|
-
ref: release.ref
|
|
1627
|
-
}));
|
|
1628
|
-
if (dryRun) {
|
|
1629
|
-
logger.info("[dry-run] Publish GitLab release for", release.tag_name);
|
|
1630
|
-
} else {
|
|
1631
|
-
logger.debug("Publishing release to GitLab...");
|
|
1632
|
-
await createGitlabRelease({
|
|
1633
|
-
config,
|
|
1634
|
-
release,
|
|
1635
|
-
dryRun
|
|
1636
|
-
});
|
|
1451
|
+
if (packages.length === 0) {
|
|
1452
|
+
logger.debug("No packages to bump");
|
|
1453
|
+
return;
|
|
1637
1454
|
}
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
baseConfig: options.config,
|
|
1653
|
-
overrides: {
|
|
1654
|
-
from: options.from,
|
|
1655
|
-
to: options.to,
|
|
1656
|
-
logLevel: options.logLevel,
|
|
1657
|
-
tokens: {
|
|
1658
|
-
gitlab: options.token
|
|
1659
|
-
}
|
|
1660
|
-
}
|
|
1661
|
-
});
|
|
1662
|
-
if (config.monorepo?.versionMode === "independent") {
|
|
1663
|
-
return await gitlabIndependentMode({
|
|
1664
|
-
config,
|
|
1665
|
-
dryRun,
|
|
1666
|
-
bumpResult: options.bumpResult,
|
|
1667
|
-
suffix: options.suffix,
|
|
1668
|
-
force: options.force ?? false
|
|
1669
|
-
});
|
|
1670
|
-
}
|
|
1671
|
-
const rootPackageBase = readPackageJson(config.cwd);
|
|
1672
|
-
if (!rootPackageBase) {
|
|
1673
|
-
throw new Error("Failed to read root package.json");
|
|
1455
|
+
const lernaJsonExists = hasLernaJson(config.cwd);
|
|
1456
|
+
logger.log("");
|
|
1457
|
+
logger.info(`${dryRun ? "[dry-run] " : ""}The following packages will be updated:
|
|
1458
|
+
`);
|
|
1459
|
+
displayRootAndLernaUpdates({
|
|
1460
|
+
versionMode,
|
|
1461
|
+
currentVersion,
|
|
1462
|
+
newVersion,
|
|
1463
|
+
lernaJsonExists,
|
|
1464
|
+
dryRun
|
|
1465
|
+
});
|
|
1466
|
+
if (versionMode === "unified") {
|
|
1467
|
+
if (!newVersion) {
|
|
1468
|
+
throw new Error("Cannot confirm bump in unified mode without a new version");
|
|
1674
1469
|
}
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
to
|
|
1689
|
-
});
|
|
1690
|
-
logger.debug(`Root package: ${getIndependentTag({ name: rootPackage.name, version: newVersion })}`);
|
|
1691
|
-
return await gitlabUnified({
|
|
1692
|
-
config,
|
|
1693
|
-
dryRun,
|
|
1694
|
-
rootPackage,
|
|
1695
|
-
bumpResult: options.bumpResult
|
|
1470
|
+
displayUnifiedModePackages({ packages, newVersion, force });
|
|
1471
|
+
} else if (versionMode === "selective") {
|
|
1472
|
+
if (!newVersion) {
|
|
1473
|
+
throw new Error("Cannot confirm bump in selective mode without a new version");
|
|
1474
|
+
}
|
|
1475
|
+
displaySelectiveModePackages({ packages, newVersion, force });
|
|
1476
|
+
} else if (versionMode === "independent") {
|
|
1477
|
+
displayIndependentModePackages({ packages, force });
|
|
1478
|
+
}
|
|
1479
|
+
try {
|
|
1480
|
+
const confirmed = await confirm({
|
|
1481
|
+
message: `${dryRun ? "[dry-run] " : ""}Do you want to proceed with these version updates?`,
|
|
1482
|
+
default: true
|
|
1696
1483
|
});
|
|
1484
|
+
if (!confirmed) {
|
|
1485
|
+
logger.log("");
|
|
1486
|
+
logger.fail("Bump refused");
|
|
1487
|
+
process.exit(0);
|
|
1488
|
+
}
|
|
1697
1489
|
} catch (error) {
|
|
1698
|
-
|
|
1699
|
-
|
|
1490
|
+
const userHasExited = error instanceof Error && error.name === "ExitPromptError";
|
|
1491
|
+
if (userHasExited) {
|
|
1492
|
+
logger.log("");
|
|
1493
|
+
logger.fail("Bump cancelled");
|
|
1494
|
+
process.exit(0);
|
|
1495
|
+
}
|
|
1496
|
+
logger.fail("Error while confirming bump");
|
|
1497
|
+
process.exit(1);
|
|
1700
1498
|
}
|
|
1499
|
+
logger.log("");
|
|
1701
1500
|
}
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
const
|
|
1707
|
-
|
|
1708
|
-
}
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
if (
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
hasMajor = true;
|
|
1719
|
-
} else if (semverType === "minor") {
|
|
1720
|
-
hasMinor = true;
|
|
1721
|
-
} else if (semverType === "patch") {
|
|
1722
|
-
hasPatch = true;
|
|
1501
|
+
function getBumpedIndependentPackages({
|
|
1502
|
+
packages,
|
|
1503
|
+
dryRun
|
|
1504
|
+
}) {
|
|
1505
|
+
const bumpedPackages = [];
|
|
1506
|
+
for (const pkgToBump of packages) {
|
|
1507
|
+
logger.debug(`Bumping ${pkgToBump.name} from ${pkgToBump.version} to ${pkgToBump.newVersion} (reason: ${pkgToBump.reason})`);
|
|
1508
|
+
const result = getBumpedPackageIndependently({
|
|
1509
|
+
pkg: pkgToBump,
|
|
1510
|
+
dryRun
|
|
1511
|
+
});
|
|
1512
|
+
if (result.bumped) {
|
|
1513
|
+
bumpedPackages.push({
|
|
1514
|
+
...pkgToBump,
|
|
1515
|
+
version: result.oldVersion
|
|
1516
|
+
});
|
|
1723
1517
|
}
|
|
1724
1518
|
}
|
|
1725
|
-
return
|
|
1519
|
+
return bumpedPackages;
|
|
1726
1520
|
}
|
|
1727
|
-
function
|
|
1728
|
-
return
|
|
1521
|
+
function shouldFilterPrereleaseTags(currentVersion, graduating) {
|
|
1522
|
+
return !isPrerelease(currentVersion) && !graduating;
|
|
1729
1523
|
}
|
|
1730
|
-
function
|
|
1731
|
-
if (
|
|
1732
|
-
return;
|
|
1524
|
+
function extractVersionFromTag(tag, packageName) {
|
|
1525
|
+
if (!tag) {
|
|
1526
|
+
return null;
|
|
1733
1527
|
}
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1528
|
+
if (packageName) {
|
|
1529
|
+
const prefix = `${packageName}@`;
|
|
1530
|
+
if (tag.startsWith(prefix)) {
|
|
1531
|
+
return tag.slice(prefix.length);
|
|
1532
|
+
}
|
|
1738
1533
|
}
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
logger.debug('No commits found for stable version with "release" type, skipping bump');
|
|
1743
|
-
return void 0;
|
|
1534
|
+
const atIndex = tag.lastIndexOf("@");
|
|
1535
|
+
if (atIndex !== -1) {
|
|
1536
|
+
return tag.slice(atIndex + 1);
|
|
1744
1537
|
}
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
logger.debug("No significant commits found, skipping bump");
|
|
1748
|
-
return void 0;
|
|
1538
|
+
if (tag.startsWith("v") && /^v\d/.test(tag)) {
|
|
1539
|
+
return tag.slice(1);
|
|
1749
1540
|
}
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
}
|
|
1753
|
-
function handleStableVersionWithPrereleaseType(commits, types, force) {
|
|
1754
|
-
if (!commits?.length && !force) {
|
|
1755
|
-
logger.debug('No commits found for stable version with "prerelease" type, skipping bump');
|
|
1756
|
-
return void 0;
|
|
1541
|
+
if (/^\d+\.\d+\.\d+/.test(tag)) {
|
|
1542
|
+
return tag;
|
|
1757
1543
|
}
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1544
|
+
return null;
|
|
1545
|
+
}
|
|
1546
|
+
function isTagVersionCompatibleWithCurrent(tagVersion, currentVersion) {
|
|
1547
|
+
try {
|
|
1548
|
+
const tagMajor = semver.major(tagVersion);
|
|
1549
|
+
const currentMajor = semver.major(currentVersion);
|
|
1550
|
+
return tagMajor <= currentMajor;
|
|
1551
|
+
} catch {
|
|
1552
|
+
return false;
|
|
1762
1553
|
}
|
|
1763
|
-
const prereleaseType = `pre${detectedType}`;
|
|
1764
|
-
logger.debug(`Auto-detected prerelease type from commits: ${prereleaseType}`);
|
|
1765
|
-
return prereleaseType;
|
|
1766
1554
|
}
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
return
|
|
1555
|
+
|
|
1556
|
+
function getIndependentTag({ version, name }) {
|
|
1557
|
+
return `${name}@${version}`;
|
|
1770
1558
|
}
|
|
1771
|
-
function
|
|
1772
|
-
const
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
if (!isUpgrade) {
|
|
1781
|
-
throw new Error(`Unable to change preid from ${currentVersion} to ${testVersion}, it's not a valid upgrade (cannot downgrade from ${currentPreid} to ${preid})`);
|
|
1559
|
+
async function getLastStableTag({ logLevel, cwd }) {
|
|
1560
|
+
const { stdout } = await execPromise(
|
|
1561
|
+
`git tag --sort=-creatordate | grep -E '^[^0-9]*[0-9]+\\.[0-9]+\\.[0-9]+$' | head -n 1`,
|
|
1562
|
+
{
|
|
1563
|
+
logLevel,
|
|
1564
|
+
noStderr: true,
|
|
1565
|
+
noStdout: true,
|
|
1566
|
+
noSuccess: true,
|
|
1567
|
+
cwd
|
|
1782
1568
|
}
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
return void 0;
|
|
1788
|
-
}
|
|
1789
|
-
logger.debug(`Incrementing prerelease version: ${currentVersion}`);
|
|
1790
|
-
return "prerelease";
|
|
1569
|
+
);
|
|
1570
|
+
const lastTag = stdout.trim();
|
|
1571
|
+
logger.debug("Last stable tag:", lastTag || "No stable tags found");
|
|
1572
|
+
return lastTag;
|
|
1791
1573
|
}
|
|
1792
|
-
function
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1574
|
+
async function getLastTag({ logLevel, cwd }) {
|
|
1575
|
+
const { stdout } = await execPromise(`git tag --sort=-creatordate | head -n 1`, {
|
|
1576
|
+
logLevel,
|
|
1577
|
+
noStderr: true,
|
|
1578
|
+
noStdout: true,
|
|
1579
|
+
noSuccess: true,
|
|
1580
|
+
cwd
|
|
1581
|
+
});
|
|
1582
|
+
const lastTag = stdout.trim();
|
|
1583
|
+
logger.debug("Last tag:", lastTag || "No tags found");
|
|
1584
|
+
return lastTag;
|
|
1585
|
+
}
|
|
1586
|
+
async function getAllRecentRepoTags(options) {
|
|
1587
|
+
const limit = options?.limit;
|
|
1588
|
+
try {
|
|
1589
|
+
const { stdout } = await execPromise(
|
|
1590
|
+
`git tag --sort=-creatordate | head -n ${limit}`,
|
|
1591
|
+
{
|
|
1592
|
+
logLevel: options?.logLevel,
|
|
1593
|
+
noStderr: true,
|
|
1594
|
+
noStdout: true,
|
|
1595
|
+
noSuccess: true,
|
|
1596
|
+
cwd: options?.cwd
|
|
1597
|
+
}
|
|
1598
|
+
);
|
|
1599
|
+
const tags = stdout.trim().split("\n").filter((tag) => tag.length > 0);
|
|
1600
|
+
logger.debug(`Retrieved ${tags.length} recent repo tags`);
|
|
1601
|
+
return tags;
|
|
1602
|
+
} catch {
|
|
1603
|
+
return [];
|
|
1802
1604
|
}
|
|
1803
|
-
return releaseType;
|
|
1804
1605
|
}
|
|
1805
|
-
function
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
types,
|
|
1811
|
-
force
|
|
1606
|
+
async function getAllRecentPackageTags({
|
|
1607
|
+
packageName,
|
|
1608
|
+
limit = 50,
|
|
1609
|
+
logLevel,
|
|
1610
|
+
cwd
|
|
1812
1611
|
}) {
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
return
|
|
1830
|
-
}
|
|
1831
|
-
if (releaseType === "release") {
|
|
1832
|
-
return handlePrereleaseVersionToStable(currentVersion);
|
|
1833
|
-
}
|
|
1834
|
-
if (releaseType === "prerelease") {
|
|
1835
|
-
return handlePrereleaseVersionWithPrereleaseType({ currentVersion, preid, commits, force });
|
|
1612
|
+
try {
|
|
1613
|
+
const escapedPackageName = packageName.replace(/[@/]/g, "\\$&");
|
|
1614
|
+
const { stdout } = await execPromise(
|
|
1615
|
+
`git tag --sort=-creatordate | grep -E '^${escapedPackageName}@' | head -n ${limit}`,
|
|
1616
|
+
{
|
|
1617
|
+
logLevel,
|
|
1618
|
+
noStderr: true,
|
|
1619
|
+
noStdout: true,
|
|
1620
|
+
noSuccess: true,
|
|
1621
|
+
cwd
|
|
1622
|
+
}
|
|
1623
|
+
);
|
|
1624
|
+
const tags = stdout.trim().split("\n").filter((tag) => tag.length > 0);
|
|
1625
|
+
logger.debug(`Retrieved ${tags.length} recent tags for package ${packageName}`);
|
|
1626
|
+
return tags;
|
|
1627
|
+
} catch {
|
|
1628
|
+
return [];
|
|
1836
1629
|
}
|
|
1837
|
-
return handleExplicitReleaseType({ releaseType, currentVersion });
|
|
1838
1630
|
}
|
|
1839
|
-
function
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
if (
|
|
1848
|
-
logger.
|
|
1849
|
-
return;
|
|
1631
|
+
function filterCompatibleTags({
|
|
1632
|
+
tags,
|
|
1633
|
+
currentVersion,
|
|
1634
|
+
onlyStable,
|
|
1635
|
+
packageName
|
|
1636
|
+
}) {
|
|
1637
|
+
const filtered = tags.filter((tag) => {
|
|
1638
|
+
const tagVersion = extractVersionFromTag(tag, packageName);
|
|
1639
|
+
if (!tagVersion) {
|
|
1640
|
+
logger.debug(`Skipping tag ${tag}: cannot extract version`);
|
|
1641
|
+
return false;
|
|
1850
1642
|
}
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1643
|
+
if (onlyStable && isPrerelease(tagVersion)) {
|
|
1644
|
+
logger.debug(`Skipping tag ${tag}: prerelease version ${tagVersion} (onlyStable=${onlyStable})`);
|
|
1645
|
+
return false;
|
|
1646
|
+
}
|
|
1647
|
+
if (!isTagVersionCompatibleWithCurrent(tagVersion, currentVersion)) {
|
|
1648
|
+
logger.debug(`Skipping tag ${tag}: version ${tagVersion} has higher major than current ${currentVersion}`);
|
|
1649
|
+
return false;
|
|
1650
|
+
}
|
|
1651
|
+
logger.debug(`Tag ${tag} with version ${tagVersion} is compatible`);
|
|
1652
|
+
return true;
|
|
1653
|
+
});
|
|
1654
|
+
logger.debug(`Filtered ${tags.length} tags down to ${filtered.length} compatible tags`);
|
|
1655
|
+
return filtered;
|
|
1656
|
+
}
|
|
1657
|
+
function getLastRepoTag(options) {
|
|
1658
|
+
if (options?.currentVersion) {
|
|
1659
|
+
return getLastRepoTagWithFiltering({
|
|
1660
|
+
currentVersion: options.currentVersion,
|
|
1661
|
+
onlyStable: options.onlyStable ?? false,
|
|
1662
|
+
logLevel: options.logLevel,
|
|
1663
|
+
cwd: options.cwd
|
|
1664
|
+
});
|
|
1856
1665
|
}
|
|
1666
|
+
if (options?.onlyStable) {
|
|
1667
|
+
return getLastStableTag({ logLevel: options?.logLevel, cwd: options?.cwd });
|
|
1668
|
+
}
|
|
1669
|
+
return getLastTag({ logLevel: options?.logLevel, cwd: options?.cwd });
|
|
1857
1670
|
}
|
|
1858
|
-
function
|
|
1859
|
-
name,
|
|
1671
|
+
async function getLastRepoTagWithFiltering({
|
|
1860
1672
|
currentVersion,
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1673
|
+
onlyStable,
|
|
1674
|
+
logLevel,
|
|
1675
|
+
cwd
|
|
1864
1676
|
}) {
|
|
1865
|
-
|
|
1866
|
-
if (
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
You should use an explicit release type (use flag: --major, --minor, --patch, --premajor, --preminor, --prepatch, --prerelease)`);
|
|
1870
|
-
}
|
|
1871
|
-
if (isPrereleaseReleaseType(releaseType) && suffix) {
|
|
1872
|
-
newVersion = newVersion.replace(/\.(\d+)$/, `.${suffix}`);
|
|
1873
|
-
}
|
|
1874
|
-
const isValidVersion = semver.gt(newVersion, currentVersion);
|
|
1875
|
-
if (!isValidVersion) {
|
|
1876
|
-
throw new Error(`Unable to bump "${name}" version "${currentVersion}" to "${newVersion}", new version is not greater than current version`);
|
|
1877
|
-
}
|
|
1878
|
-
if (isGraduating(currentVersion, releaseType)) {
|
|
1879
|
-
logger.info(`Graduating "${name}" from prerelease ${currentVersion} to stable ${newVersion}`);
|
|
1677
|
+
const recentTags = await getAllRecentRepoTags({ limit: 50, logLevel, cwd });
|
|
1678
|
+
if (recentTags.length === 0) {
|
|
1679
|
+
logger.debug("No tags found in repository");
|
|
1680
|
+
return null;
|
|
1880
1681
|
}
|
|
1881
|
-
|
|
1882
|
-
|
|
1682
|
+
const compatibleTags = filterCompatibleTags({
|
|
1683
|
+
tags: recentTags,
|
|
1684
|
+
currentVersion,
|
|
1685
|
+
onlyStable
|
|
1686
|
+
});
|
|
1687
|
+
if (compatibleTags.length === 0) {
|
|
1688
|
+
logger.debug("No compatible tags found");
|
|
1689
|
+
return null;
|
|
1883
1690
|
}
|
|
1884
|
-
|
|
1691
|
+
const lastTag = compatibleTags[0];
|
|
1692
|
+
logger.debug(`Last compatible repo tag: ${lastTag}`);
|
|
1693
|
+
return lastTag;
|
|
1885
1694
|
}
|
|
1886
|
-
function
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1695
|
+
async function getLastPackageTag({
|
|
1696
|
+
packageName,
|
|
1697
|
+
onlyStable,
|
|
1698
|
+
currentVersion,
|
|
1699
|
+
logLevel,
|
|
1700
|
+
cwd
|
|
1891
1701
|
}) {
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1702
|
+
if (currentVersion) {
|
|
1703
|
+
return getLastPackageTagWithFiltering({
|
|
1704
|
+
packageName,
|
|
1705
|
+
currentVersion,
|
|
1706
|
+
onlyStable: onlyStable ?? false,
|
|
1707
|
+
logLevel,
|
|
1708
|
+
cwd
|
|
1709
|
+
});
|
|
1899
1710
|
}
|
|
1900
1711
|
try {
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
return;
|
|
1908
|
-
}
|
|
1909
|
-
lernaJson.version = version;
|
|
1910
|
-
if (dryRun) {
|
|
1911
|
-
logger.info(`[dry-run] update lerna.json: ${oldVersion} \u2192 ${version}`);
|
|
1912
|
-
return;
|
|
1712
|
+
const escapedPackageName = packageName.replace(/[@/]/g, "\\$&");
|
|
1713
|
+
let grepPattern;
|
|
1714
|
+
if (onlyStable) {
|
|
1715
|
+
grepPattern = `^${escapedPackageName}@[0-9]+\\.[0-9]+\\.[0-9]+$`;
|
|
1716
|
+
} else {
|
|
1717
|
+
grepPattern = `^${escapedPackageName}@`;
|
|
1913
1718
|
}
|
|
1914
|
-
|
|
1915
|
-
`,
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1719
|
+
const { stdout } = await execPromise(
|
|
1720
|
+
`git tag --sort=-creatordate | grep -E '${grepPattern}' | sed -n '1p'`,
|
|
1721
|
+
{
|
|
1722
|
+
logLevel,
|
|
1723
|
+
noStderr: true,
|
|
1724
|
+
noStdout: true,
|
|
1725
|
+
noSuccess: true,
|
|
1726
|
+
cwd
|
|
1727
|
+
}
|
|
1728
|
+
);
|
|
1729
|
+
const tag = stdout.trim();
|
|
1730
|
+
return tag || null;
|
|
1731
|
+
} catch {
|
|
1924
1732
|
return null;
|
|
1925
1733
|
}
|
|
1926
|
-
return tag.slice(atIndex + 1);
|
|
1927
|
-
}
|
|
1928
|
-
function isPrerelease(version) {
|
|
1929
|
-
if (!version)
|
|
1930
|
-
return false;
|
|
1931
|
-
const prerelease = semver.prerelease(version);
|
|
1932
|
-
return prerelease ? prerelease.length > 0 : false;
|
|
1933
|
-
}
|
|
1934
|
-
function isStableReleaseType(releaseType) {
|
|
1935
|
-
const stableTypes = ["release", "major", "minor", "patch"];
|
|
1936
|
-
return stableTypes.includes(releaseType);
|
|
1937
|
-
}
|
|
1938
|
-
function isPrereleaseReleaseType(releaseType) {
|
|
1939
|
-
const prereleaseTypes = ["prerelease", "premajor", "preminor", "prepatch"];
|
|
1940
|
-
return prereleaseTypes.includes(releaseType);
|
|
1941
1734
|
}
|
|
1942
|
-
function
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1735
|
+
async function getLastPackageTagWithFiltering({
|
|
1736
|
+
packageName,
|
|
1737
|
+
currentVersion,
|
|
1738
|
+
onlyStable,
|
|
1739
|
+
logLevel,
|
|
1740
|
+
cwd
|
|
1741
|
+
}) {
|
|
1742
|
+
const recentTags = await getAllRecentPackageTags({
|
|
1743
|
+
packageName,
|
|
1744
|
+
limit: 50,
|
|
1745
|
+
logLevel,
|
|
1746
|
+
cwd
|
|
1747
|
+
});
|
|
1748
|
+
if (recentTags.length === 0) {
|
|
1749
|
+
logger.debug(`No tags found for package ${packageName}`);
|
|
1950
1750
|
return null;
|
|
1951
1751
|
}
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
}
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
return
|
|
1961
|
-
}
|
|
1962
|
-
return currentPreid !== targetPreid;
|
|
1963
|
-
}
|
|
1964
|
-
function getBumpedPackageIndependently({
|
|
1965
|
-
pkg,
|
|
1966
|
-
dryRun
|
|
1967
|
-
}) {
|
|
1968
|
-
logger.debug(`Analyzing ${pkg.name}`);
|
|
1969
|
-
const currentVersion = pkg.version || "0.0.0";
|
|
1970
|
-
const newVersion = pkg.newVersion;
|
|
1971
|
-
if (!newVersion) {
|
|
1972
|
-
return { bumped: false };
|
|
1752
|
+
const compatibleTags = filterCompatibleTags({
|
|
1753
|
+
tags: recentTags,
|
|
1754
|
+
currentVersion,
|
|
1755
|
+
onlyStable,
|
|
1756
|
+
packageName
|
|
1757
|
+
});
|
|
1758
|
+
if (compatibleTags.length === 0) {
|
|
1759
|
+
logger.debug(`No compatible tags found for package ${packageName}`);
|
|
1760
|
+
return null;
|
|
1973
1761
|
}
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
return
|
|
1762
|
+
const lastTag = compatibleTags[0];
|
|
1763
|
+
logger.debug(`Last compatible package tag for ${packageName}: ${lastTag}`);
|
|
1764
|
+
return lastTag;
|
|
1977
1765
|
}
|
|
1978
|
-
function
|
|
1979
|
-
|
|
1766
|
+
async function resolveFromTagIndependent({
|
|
1767
|
+
cwd,
|
|
1768
|
+
packageName,
|
|
1980
1769
|
currentVersion,
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
lernaJsonExists
|
|
1770
|
+
graduating,
|
|
1771
|
+
logLevel
|
|
1984
1772
|
}) {
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1773
|
+
const filterPrereleases = shouldFilterPrereleaseTags(currentVersion, graduating);
|
|
1774
|
+
const onlyStable = graduating || filterPrereleases;
|
|
1775
|
+
const lastPackageTag = await getLastPackageTag({
|
|
1776
|
+
packageName,
|
|
1777
|
+
currentVersion,
|
|
1778
|
+
onlyStable,
|
|
1779
|
+
logLevel,
|
|
1780
|
+
cwd
|
|
1781
|
+
});
|
|
1782
|
+
if (!lastPackageTag) {
|
|
1783
|
+
return getFirstCommit(cwd);
|
|
1992
1784
|
}
|
|
1785
|
+
return lastPackageTag;
|
|
1993
1786
|
}
|
|
1994
|
-
function
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1787
|
+
async function resolveFromTagUnified({
|
|
1788
|
+
config,
|
|
1789
|
+
currentVersion,
|
|
1790
|
+
graduating,
|
|
1791
|
+
logLevel
|
|
1998
1792
|
}) {
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
1793
|
+
const filterPrereleases = shouldFilterPrereleaseTags(currentVersion, graduating);
|
|
1794
|
+
const onlyStable = graduating || filterPrereleases;
|
|
1795
|
+
const from = await getLastRepoTag({
|
|
1796
|
+
currentVersion,
|
|
1797
|
+
onlyStable,
|
|
1798
|
+
logLevel,
|
|
1799
|
+
cwd: config.cwd
|
|
1800
|
+
}) || getFirstCommit(config.cwd);
|
|
1801
|
+
return from;
|
|
2004
1802
|
}
|
|
2005
|
-
function
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
1803
|
+
async function resolveFromTag({
|
|
1804
|
+
config,
|
|
1805
|
+
versionMode,
|
|
1806
|
+
step,
|
|
1807
|
+
packageName,
|
|
1808
|
+
currentVersion,
|
|
1809
|
+
graduating,
|
|
1810
|
+
logLevel
|
|
2009
1811
|
}) {
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
1812
|
+
let from;
|
|
1813
|
+
if (versionMode === "independent") {
|
|
1814
|
+
if (!packageName) {
|
|
1815
|
+
throw new Error("Package name is required for independent version mode");
|
|
1816
|
+
}
|
|
1817
|
+
from = await resolveFromTagIndependent({
|
|
1818
|
+
cwd: config.cwd,
|
|
1819
|
+
packageName,
|
|
1820
|
+
currentVersion,
|
|
1821
|
+
graduating,
|
|
1822
|
+
logLevel
|
|
2014
1823
|
});
|
|
2015
|
-
logger.log("");
|
|
2016
1824
|
} else {
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion} (${pkg.commits.length} commits) ${force ? "(force)" : ""}`);
|
|
2024
|
-
});
|
|
2025
|
-
logger.log("");
|
|
2026
|
-
}
|
|
2027
|
-
if (packagesAsDependents.length > 0) {
|
|
2028
|
-
logger.log(`${packagesAsDependents.length} dependent package(s):`);
|
|
2029
|
-
packagesAsDependents.forEach((pkg) => {
|
|
2030
|
-
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion} ${force ? "(force)" : ""}`);
|
|
2031
|
-
});
|
|
2032
|
-
logger.log("");
|
|
2033
|
-
}
|
|
2034
|
-
if (packagesAsGraduation.length > 0) {
|
|
2035
|
-
logger.log(`${packagesAsGraduation.length} graduation package(s):`);
|
|
2036
|
-
packagesAsGraduation.forEach((pkg) => {
|
|
2037
|
-
logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${newVersion} ${force ? "(force)" : ""}`);
|
|
2038
|
-
});
|
|
2039
|
-
logger.log("");
|
|
2040
|
-
}
|
|
1825
|
+
from = await resolveFromTagUnified({
|
|
1826
|
+
config,
|
|
1827
|
+
currentVersion,
|
|
1828
|
+
graduating,
|
|
1829
|
+
logLevel
|
|
1830
|
+
});
|
|
2041
1831
|
}
|
|
1832
|
+
logger.debug(`[${versionMode}](${step}) Using from tag: ${from}`);
|
|
1833
|
+
return config.from || from;
|
|
2042
1834
|
}
|
|
2043
|
-
function
|
|
2044
|
-
|
|
2045
|
-
|
|
1835
|
+
function resolveToTag({
|
|
1836
|
+
config,
|
|
1837
|
+
versionMode,
|
|
1838
|
+
newVersion,
|
|
1839
|
+
step,
|
|
1840
|
+
packageName
|
|
2046
1841
|
}) {
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
const packagesWithCommits = packages.filter((p) => "reason" in p && p.reason === "commits");
|
|
2055
|
-
const packagesAsDependents = packages.filter((p) => "reason" in p && p.reason === "dependency");
|
|
2056
|
-
const packagesAsGraduation = packages.filter((p) => "reason" in p && p.reason === "graduation");
|
|
2057
|
-
if (packagesWithCommits.length > 0) {
|
|
2058
|
-
logger.log(`${packagesWithCommits.length} package(s) with commits:`);
|
|
2059
|
-
packagesWithCommits.forEach((pkg) => {
|
|
2060
|
-
pkg.newVersion && logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion} (${pkg.commits.length} commits) ${force ? "(force)" : ""}`);
|
|
2061
|
-
});
|
|
2062
|
-
logger.log("");
|
|
2063
|
-
}
|
|
2064
|
-
if (packagesAsDependents.length > 0) {
|
|
2065
|
-
logger.log(`${packagesAsDependents.length} dependent package(s):`);
|
|
2066
|
-
packagesAsDependents.forEach((pkg) => {
|
|
2067
|
-
pkg.newVersion && logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion} ${force ? "(force)" : ""}`);
|
|
2068
|
-
});
|
|
2069
|
-
logger.log("");
|
|
1842
|
+
const isUntaggedStep = step === "bump" || step === "changelog";
|
|
1843
|
+
let to;
|
|
1844
|
+
if (isUntaggedStep) {
|
|
1845
|
+
to = getCurrentGitRef(config.cwd);
|
|
1846
|
+
} else if (versionMode === "independent") {
|
|
1847
|
+
if (!packageName) {
|
|
1848
|
+
throw new Error("Package name is required for independent version mode");
|
|
2070
1849
|
}
|
|
2071
|
-
if (
|
|
2072
|
-
|
|
2073
|
-
packagesAsGraduation.forEach((pkg) => {
|
|
2074
|
-
pkg.newVersion && logger.log(` \u2022 ${pkg.name}: ${pkg.version} \u2192 ${pkg.newVersion} ${force ? "(force)" : ""}`);
|
|
2075
|
-
});
|
|
2076
|
-
logger.log("");
|
|
1850
|
+
if (!newVersion) {
|
|
1851
|
+
throw new Error("New version is required for independent version mode");
|
|
2077
1852
|
}
|
|
1853
|
+
to = getIndependentTag({ version: newVersion, name: packageName });
|
|
1854
|
+
} else {
|
|
1855
|
+
to = newVersion ? config.templates.tagBody.replace("{{newVersion}}", newVersion) : getCurrentGitRef(config.cwd);
|
|
2078
1856
|
}
|
|
1857
|
+
logger.debug(`[${versionMode}](${step}) Using to tag: ${to}`);
|
|
1858
|
+
return config.to || to;
|
|
2079
1859
|
}
|
|
2080
|
-
async function
|
|
2081
|
-
versionMode,
|
|
1860
|
+
async function resolveTags({
|
|
2082
1861
|
config,
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
newVersion,
|
|
2087
|
-
dryRun
|
|
1862
|
+
step,
|
|
1863
|
+
pkg,
|
|
1864
|
+
newVersion
|
|
2088
1865
|
}) {
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
const
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
1866
|
+
const versionMode = config.monorepo?.versionMode || "standalone";
|
|
1867
|
+
const logLevel = config.logLevel;
|
|
1868
|
+
logger.debug(`[${versionMode}](${step}) Resolving tags`);
|
|
1869
|
+
const releaseType = config.bump.type;
|
|
1870
|
+
const graduating = typeof newVersion === "string" ? isGraduatingToStableBetweenVersion(pkg.version, newVersion) : isGraduating(pkg.version, releaseType);
|
|
1871
|
+
const from = await resolveFromTag({
|
|
1872
|
+
config,
|
|
1873
|
+
versionMode,
|
|
1874
|
+
step,
|
|
1875
|
+
packageName: pkg.name,
|
|
1876
|
+
currentVersion: pkg.version,
|
|
1877
|
+
graduating,
|
|
1878
|
+
logLevel
|
|
1879
|
+
});
|
|
1880
|
+
const to = resolveToTag({
|
|
1881
|
+
config,
|
|
2098
1882
|
versionMode,
|
|
2099
|
-
currentVersion,
|
|
2100
1883
|
newVersion,
|
|
2101
|
-
|
|
2102
|
-
|
|
1884
|
+
step,
|
|
1885
|
+
packageName: pkg.name
|
|
2103
1886
|
});
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
1887
|
+
logger.debug(`[${versionMode}](${step}) Using tags: ${from} \u2192 ${to}`);
|
|
1888
|
+
return { from, to };
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
function fromTagIsFirstCommit(fromTag, cwd) {
|
|
1892
|
+
return fromTag === getFirstCommit(cwd);
|
|
1893
|
+
}
|
|
1894
|
+
async function generateChangelog({
|
|
1895
|
+
pkg,
|
|
1896
|
+
config,
|
|
1897
|
+
dryRun,
|
|
1898
|
+
newVersion,
|
|
1899
|
+
minify
|
|
1900
|
+
}) {
|
|
1901
|
+
let fromTag = config.from || pkg.fromTag || getFirstCommit(config.cwd);
|
|
1902
|
+
const isFirstCommit = fromTagIsFirstCommit(fromTag, config.cwd);
|
|
1903
|
+
if (isFirstCommit) {
|
|
1904
|
+
fromTag = config.monorepo?.versionMode === "independent" ? getIndependentTag({ version: "0.0.0", name: pkg.name }) : config.templates.tagBody.replace("{{newVersion}}", "0.0.0");
|
|
1905
|
+
}
|
|
1906
|
+
let toTag = config.to;
|
|
1907
|
+
if (!toTag) {
|
|
1908
|
+
toTag = config.monorepo?.versionMode === "independent" ? getIndependentTag({ version: newVersion, name: pkg.name }) : config.templates.tagBody.replace("{{newVersion}}", newVersion);
|
|
2116
1909
|
}
|
|
1910
|
+
if (!toTag) {
|
|
1911
|
+
throw new Error(`No tag found for ${pkg.name}`);
|
|
1912
|
+
}
|
|
1913
|
+
logger.debug(`Generating changelog for ${pkg.name} - from ${fromTag} to ${toTag}`);
|
|
2117
1914
|
try {
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
1915
|
+
config = {
|
|
1916
|
+
...config,
|
|
1917
|
+
from: fromTag,
|
|
1918
|
+
to: toTag
|
|
1919
|
+
};
|
|
1920
|
+
const generatedChangelog = await generateMarkDown({
|
|
1921
|
+
commits: pkg.commits,
|
|
1922
|
+
config,
|
|
1923
|
+
from: fromTag,
|
|
1924
|
+
isFirstCommit,
|
|
1925
|
+
to: toTag,
|
|
1926
|
+
minify
|
|
2121
1927
|
});
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
1928
|
+
let changelog = generatedChangelog;
|
|
1929
|
+
if (pkg.commits.length === 0) {
|
|
1930
|
+
changelog = `${changelog}
|
|
1931
|
+
|
|
1932
|
+
${config.templates.emptyChangelogContent}`;
|
|
1933
|
+
}
|
|
1934
|
+
const changelogResult = await executeHook("generate:changelog", config, dryRun, {
|
|
1935
|
+
commits: pkg.commits,
|
|
1936
|
+
changelog
|
|
1937
|
+
});
|
|
1938
|
+
changelog = changelogResult || changelog;
|
|
1939
|
+
logger.verbose(`Output changelog for ${pkg.name}:
|
|
1940
|
+
${changelog}`);
|
|
1941
|
+
logger.debug(`Changelog generated for ${pkg.name} (${pkg.commits.length} commits)`);
|
|
1942
|
+
logger.verbose(`Final changelog for ${pkg.name}:
|
|
1943
|
+
|
|
1944
|
+
${changelog}
|
|
1945
|
+
|
|
1946
|
+
`);
|
|
1947
|
+
if (dryRun) {
|
|
1948
|
+
logger.info(`[dry-run] ${pkg.name} - Generate changelog ${fromTag}...${toTag}`);
|
|
2126
1949
|
}
|
|
1950
|
+
return changelog;
|
|
2127
1951
|
} catch (error) {
|
|
2128
|
-
|
|
2129
|
-
if (userHasExited) {
|
|
2130
|
-
logger.log("");
|
|
2131
|
-
logger.fail("Bump cancelled");
|
|
2132
|
-
process.exit(0);
|
|
2133
|
-
}
|
|
2134
|
-
logger.fail("Error while confirming bump");
|
|
2135
|
-
process.exit(1);
|
|
1952
|
+
throw new Error(`Error generating changelog for ${pkg.name} (${fromTag}...${toTag}): ${error}`);
|
|
2136
1953
|
}
|
|
2137
|
-
logger.log("");
|
|
2138
1954
|
}
|
|
2139
|
-
function
|
|
2140
|
-
|
|
2141
|
-
|
|
1955
|
+
function writeChangelogToFile({
|
|
1956
|
+
cwd,
|
|
1957
|
+
pkg,
|
|
1958
|
+
changelog,
|
|
1959
|
+
dryRun = false
|
|
2142
1960
|
}) {
|
|
2143
|
-
const
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
pkg: pkgToBump,
|
|
2148
|
-
dryRun
|
|
2149
|
-
});
|
|
2150
|
-
if (result.bumped) {
|
|
2151
|
-
bumpedPackages.push({
|
|
2152
|
-
...pkgToBump,
|
|
2153
|
-
version: result.oldVersion
|
|
2154
|
-
});
|
|
2155
|
-
}
|
|
2156
|
-
}
|
|
2157
|
-
return bumpedPackages;
|
|
2158
|
-
}
|
|
2159
|
-
function shouldFilterPrereleaseTags(currentVersion, graduating) {
|
|
2160
|
-
return !isPrerelease(currentVersion) && !graduating;
|
|
2161
|
-
}
|
|
2162
|
-
function extractVersionFromTag(tag, packageName) {
|
|
2163
|
-
if (!tag) {
|
|
2164
|
-
return null;
|
|
2165
|
-
}
|
|
2166
|
-
if (packageName) {
|
|
2167
|
-
const prefix = `${packageName}@`;
|
|
2168
|
-
if (tag.startsWith(prefix)) {
|
|
2169
|
-
return tag.slice(prefix.length);
|
|
2170
|
-
}
|
|
2171
|
-
}
|
|
2172
|
-
const atIndex = tag.lastIndexOf("@");
|
|
2173
|
-
if (atIndex !== -1) {
|
|
2174
|
-
return tag.slice(atIndex + 1);
|
|
2175
|
-
}
|
|
2176
|
-
if (tag.startsWith("v") && /^v\d/.test(tag)) {
|
|
2177
|
-
return tag.slice(1);
|
|
1961
|
+
const changelogPath = join(pkg.path, "CHANGELOG.md");
|
|
1962
|
+
let existingChangelog = "";
|
|
1963
|
+
if (existsSync(changelogPath)) {
|
|
1964
|
+
existingChangelog = readFileSync(changelogPath, "utf8");
|
|
2178
1965
|
}
|
|
2179
|
-
|
|
2180
|
-
|
|
1966
|
+
const lines = existingChangelog.split("\n");
|
|
1967
|
+
const titleIndex = lines.findIndex((line) => line.startsWith("# "));
|
|
1968
|
+
let updatedChangelog;
|
|
1969
|
+
if (titleIndex !== -1) {
|
|
1970
|
+
const beforeTitle = lines.slice(0, titleIndex + 1);
|
|
1971
|
+
const afterTitle = lines.slice(titleIndex + 1);
|
|
1972
|
+
updatedChangelog = [...beforeTitle, "", changelog, "", ...afterTitle].join("\n");
|
|
1973
|
+
} else {
|
|
1974
|
+
const title = "# Changelog\n";
|
|
1975
|
+
updatedChangelog = `${title}
|
|
1976
|
+
${changelog}
|
|
1977
|
+
${existingChangelog}`;
|
|
2181
1978
|
}
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
} catch {
|
|
2190
|
-
return false;
|
|
1979
|
+
if (dryRun) {
|
|
1980
|
+
const relativeChangelogPath = relative(cwd, changelogPath);
|
|
1981
|
+
logger.info(`[dry-run] ${pkg.name} - Write changelog to ${relativeChangelogPath}`);
|
|
1982
|
+
} else {
|
|
1983
|
+
logger.debug(`Writing changelog to ${changelogPath}`);
|
|
1984
|
+
writeFileSync(changelogPath, updatedChangelog, "utf8");
|
|
1985
|
+
logger.info(`Changelog updated for ${pkg.name} (${"newVersion" in pkg && pkg.newVersion || pkg.version})`);
|
|
2191
1986
|
}
|
|
2192
1987
|
}
|
|
2193
1988
|
|
|
2194
|
-
function
|
|
2195
|
-
return
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
1989
|
+
function getDefaultConfig() {
|
|
1990
|
+
return {
|
|
1991
|
+
cwd: process$1.cwd(),
|
|
1992
|
+
types: {
|
|
1993
|
+
feat: { title: "\u{1F680} Enhancements", semver: "minor" },
|
|
1994
|
+
perf: { title: "\u{1F525} Performance", semver: "patch" },
|
|
1995
|
+
fix: { title: "\u{1FA79} Fixes", semver: "patch" },
|
|
1996
|
+
refactor: { title: "\u{1F485} Refactors", semver: "patch" },
|
|
1997
|
+
docs: { title: "\u{1F4D6} Documentation", semver: "patch" },
|
|
1998
|
+
build: { title: "\u{1F4E6} Build", semver: "patch" },
|
|
1999
|
+
types: { title: "\u{1F30A} Types", semver: "patch" },
|
|
2000
|
+
chore: { title: "\u{1F3E1} Chore" },
|
|
2001
|
+
examples: { title: "\u{1F3C0} Examples" },
|
|
2002
|
+
test: { title: "\u2705 Tests" },
|
|
2003
|
+
style: { title: "\u{1F3A8} Styles" },
|
|
2004
|
+
ci: { title: "\u{1F916} CI" }
|
|
2005
|
+
},
|
|
2006
|
+
templates: {
|
|
2007
|
+
commitMessage: "chore(release): bump version to {{newVersion}}",
|
|
2008
|
+
tagMessage: "Bump version to {{newVersion}}",
|
|
2009
|
+
tagBody: "v{{newVersion}}",
|
|
2010
|
+
emptyChangelogContent: "No relevant changes for this release",
|
|
2011
|
+
twitterMessage: "\u{1F680} {{projectName}} {{version}} is out!\n\n{{changelog}}\n\n{{releaseUrl}}\n{{changelogUrl}}",
|
|
2012
|
+
slackMessage: void 0
|
|
2013
|
+
// Use rich blocks format by default (no template)
|
|
2014
|
+
},
|
|
2015
|
+
excludeAuthors: [],
|
|
2016
|
+
noAuthors: false,
|
|
2017
|
+
bump: {
|
|
2018
|
+
type: "release",
|
|
2019
|
+
clean: true,
|
|
2020
|
+
dependencyTypes: ["dependencies"],
|
|
2021
|
+
yes: false
|
|
2022
|
+
},
|
|
2023
|
+
changelog: {
|
|
2024
|
+
rootChangelog: true,
|
|
2025
|
+
includeCommitBody: true
|
|
2026
|
+
},
|
|
2027
|
+
publish: {
|
|
2028
|
+
private: false,
|
|
2029
|
+
args: [],
|
|
2030
|
+
token: process$1.env.RELIZY_NPM_TOKEN || process$1.env.NPM_TOKEN || process$1.env.NODE_AUTH_TOKEN,
|
|
2031
|
+
registry: "https://registry.npmjs.org/",
|
|
2032
|
+
safetyCheck: false
|
|
2033
|
+
},
|
|
2034
|
+
tokens: {
|
|
2035
|
+
registry: process$1.env.RELIZY_NPM_TOKEN || process$1.env.NPM_TOKEN || process$1.env.NODE_AUTH_TOKEN,
|
|
2036
|
+
gitlab: process$1.env.RELIZY_GITLAB_TOKEN || process$1.env.GITLAB_TOKEN || process$1.env.GITLAB_API_TOKEN || process$1.env.CI_JOB_TOKEN,
|
|
2037
|
+
github: process$1.env.RELIZY_GITHUB_TOKEN || process$1.env.GITHUB_TOKEN || process$1.env.GH_TOKEN,
|
|
2038
|
+
twitter: {
|
|
2039
|
+
apiKey: process$1.env.RELIZY_TWITTER_API_KEY || process$1.env.TWITTER_API_KEY,
|
|
2040
|
+
apiKeySecret: process$1.env.RELIZY_TWITTER_API_KEY_SECRET || process$1.env.TWITTER_API_KEY_SECRET,
|
|
2041
|
+
accessToken: process$1.env.RELIZY_TWITTER_ACCESS_TOKEN || process$1.env.TWITTER_ACCESS_TOKEN,
|
|
2042
|
+
accessTokenSecret: process$1.env.RELIZY_TWITTER_ACCESS_TOKEN_SECRET || process$1.env.TWITTER_ACCESS_TOKEN_SECRET
|
|
2043
|
+
},
|
|
2044
|
+
slack: process$1.env.RELIZY_SLACK_TOKEN || process$1.env.SLACK_TOKEN
|
|
2045
|
+
},
|
|
2046
|
+
scopeMap: {},
|
|
2047
|
+
release: {
|
|
2048
|
+
commit: true,
|
|
2049
|
+
publish: true,
|
|
2050
|
+
changelog: true,
|
|
2051
|
+
push: true,
|
|
2052
|
+
clean: true,
|
|
2053
|
+
providerRelease: true,
|
|
2054
|
+
noVerify: false,
|
|
2055
|
+
gitTag: true,
|
|
2056
|
+
social: true
|
|
2057
|
+
},
|
|
2058
|
+
social: {
|
|
2059
|
+
twitter: {
|
|
2060
|
+
enabled: false,
|
|
2061
|
+
onlyStable: true
|
|
2062
|
+
},
|
|
2063
|
+
slack: {
|
|
2064
|
+
enabled: false,
|
|
2065
|
+
onlyStable: true
|
|
2066
|
+
}
|
|
2067
|
+
},
|
|
2068
|
+
logLevel: "default",
|
|
2069
|
+
safetyCheck: true
|
|
2070
|
+
};
|
|
2211
2071
|
}
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
logLevel
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
noSuccess: true,
|
|
2218
|
-
cwd
|
|
2219
|
-
});
|
|
2220
|
-
const lastTag = stdout.trim();
|
|
2221
|
-
logger.debug("Last tag:", lastTag || "No tags found");
|
|
2222
|
-
return lastTag;
|
|
2072
|
+
function setupLogger(logLevel) {
|
|
2073
|
+
if (logLevel) {
|
|
2074
|
+
logger.setLevel(logLevel);
|
|
2075
|
+
logger.debug(`Log level set to: ${logLevel}`);
|
|
2076
|
+
}
|
|
2223
2077
|
}
|
|
2224
|
-
async function
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
logger.debug(`Retrieved ${tags.length} recent repo tags`);
|
|
2239
|
-
return tags;
|
|
2240
|
-
} catch {
|
|
2241
|
-
return [];
|
|
2078
|
+
async function resolveConfig(config, cwd) {
|
|
2079
|
+
if (!config.repo) {
|
|
2080
|
+
const resolvedRepoConfig = await resolveRepoConfig(cwd);
|
|
2081
|
+
config.repo = {
|
|
2082
|
+
...resolvedRepoConfig,
|
|
2083
|
+
provider: resolvedRepoConfig.provider
|
|
2084
|
+
};
|
|
2085
|
+
}
|
|
2086
|
+
if (typeof config.repo === "string") {
|
|
2087
|
+
const resolvedRepoConfig = getRepoConfig(config.repo);
|
|
2088
|
+
config.repo = {
|
|
2089
|
+
...resolvedRepoConfig,
|
|
2090
|
+
provider: resolvedRepoConfig.provider
|
|
2091
|
+
};
|
|
2242
2092
|
}
|
|
2093
|
+
return config;
|
|
2243
2094
|
}
|
|
2244
|
-
async function
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
return tags;
|
|
2265
|
-
} catch {
|
|
2266
|
-
return [];
|
|
2095
|
+
async function loadRelizyConfig(options) {
|
|
2096
|
+
const cwd = options?.overrides?.cwd ?? process$1.cwd();
|
|
2097
|
+
await setupDotenv({ cwd });
|
|
2098
|
+
const configFile = options?.configFile ?? "relizy";
|
|
2099
|
+
const defaultConfig = getDefaultConfig();
|
|
2100
|
+
const overridesConfig = defu(options?.overrides, options?.baseConfig);
|
|
2101
|
+
const results = await loadConfig({
|
|
2102
|
+
dotenv: true,
|
|
2103
|
+
cwd,
|
|
2104
|
+
name: configFile,
|
|
2105
|
+
packageJson: true,
|
|
2106
|
+
defaults: defaultConfig,
|
|
2107
|
+
overrides: overridesConfig
|
|
2108
|
+
});
|
|
2109
|
+
if (typeof results._configFile !== "string") {
|
|
2110
|
+
logger.debug(`No config file found with name "${configFile}"`);
|
|
2111
|
+
if (options?.configFile) {
|
|
2112
|
+
logger.error(`No config file found with name "${configFile}"`);
|
|
2113
|
+
process$1.exit(1);
|
|
2114
|
+
}
|
|
2267
2115
|
}
|
|
2116
|
+
setupLogger(options?.overrides?.logLevel || results.config.logLevel);
|
|
2117
|
+
logger.verbose("User config:", formatJson(results.config.changelog));
|
|
2118
|
+
const resolvedConfig = await resolveConfig(results.config, cwd);
|
|
2119
|
+
logger.debug("Resolved config:", formatJson(resolvedConfig));
|
|
2120
|
+
return resolvedConfig;
|
|
2268
2121
|
}
|
|
2269
|
-
function
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2122
|
+
function defineConfig(config) {
|
|
2123
|
+
return config;
|
|
2124
|
+
}
|
|
2125
|
+
|
|
2126
|
+
async function githubIndependentMode({
|
|
2127
|
+
config,
|
|
2128
|
+
dryRun,
|
|
2129
|
+
bumpResult,
|
|
2130
|
+
force,
|
|
2131
|
+
suffix
|
|
2274
2132
|
}) {
|
|
2275
|
-
const
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
}
|
|
2289
|
-
logger.debug(`Tag ${tag} with version ${tagVersion} is compatible`);
|
|
2290
|
-
return true;
|
|
2133
|
+
const repoConfig = config.repo;
|
|
2134
|
+
if (!repoConfig) {
|
|
2135
|
+
throw new Error("No repository configuration found. Please check your changelog config.");
|
|
2136
|
+
}
|
|
2137
|
+
logger.debug(`GitHub token: ${config.tokens.github || config.repo?.token ? "\u2713 provided" : "\u2717 missing"}`);
|
|
2138
|
+
if (!config.tokens.github && !config.repo?.token) {
|
|
2139
|
+
throw new Error("No GitHub token specified. Set GITHUB_TOKEN or GH_TOKEN environment variable.");
|
|
2140
|
+
}
|
|
2141
|
+
const packages = await getPackagesOrBumpedPackages({
|
|
2142
|
+
config,
|
|
2143
|
+
bumpResult,
|
|
2144
|
+
suffix,
|
|
2145
|
+
force
|
|
2291
2146
|
});
|
|
2292
|
-
logger.
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2147
|
+
logger.info(`Creating ${packages.length} GitHub release(s)`);
|
|
2148
|
+
const postedReleases = [];
|
|
2149
|
+
for (const pkg of packages) {
|
|
2150
|
+
const newVersion = isBumpedPackage(pkg) && pkg.newVersion || pkg.version;
|
|
2151
|
+
const from = config.from || pkg.fromTag;
|
|
2152
|
+
const to = config.to || getIndependentTag({ version: newVersion, name: pkg.name });
|
|
2153
|
+
if (!from) {
|
|
2154
|
+
logger.warn(`No from tag found for ${pkg.name}, skipping release`);
|
|
2155
|
+
continue;
|
|
2156
|
+
}
|
|
2157
|
+
const toTag = dryRun ? "HEAD" : to;
|
|
2158
|
+
logger.debug(`Processing ${pkg.name}: ${from} \u2192 ${toTag}`);
|
|
2159
|
+
const changelog = await generateChangelog({
|
|
2160
|
+
pkg,
|
|
2161
|
+
config,
|
|
2162
|
+
dryRun,
|
|
2163
|
+
newVersion
|
|
2302
2164
|
});
|
|
2165
|
+
const releaseBody = changelog.split("\n").slice(2).join("\n");
|
|
2166
|
+
const release = {
|
|
2167
|
+
tag_name: to,
|
|
2168
|
+
name: to,
|
|
2169
|
+
body: releaseBody,
|
|
2170
|
+
prerelease: isPrerelease(newVersion)
|
|
2171
|
+
};
|
|
2172
|
+
logger.debug(`Creating release for ${to}${release.prerelease ? " (prerelease)" : ""}`);
|
|
2173
|
+
if (dryRun) {
|
|
2174
|
+
logger.info(`[dry-run] Publish GitHub release for ${to}`);
|
|
2175
|
+
postedReleases.push({
|
|
2176
|
+
name: pkg.name,
|
|
2177
|
+
tag: release.tag_name,
|
|
2178
|
+
version: newVersion,
|
|
2179
|
+
prerelease: release.prerelease
|
|
2180
|
+
});
|
|
2181
|
+
} else {
|
|
2182
|
+
logger.debug(`Publishing release ${to} to GitHub...`);
|
|
2183
|
+
await createGithubRelease({
|
|
2184
|
+
...config,
|
|
2185
|
+
from,
|
|
2186
|
+
to,
|
|
2187
|
+
repo: repoConfig
|
|
2188
|
+
}, release);
|
|
2189
|
+
postedReleases.push({
|
|
2190
|
+
name: pkg.name,
|
|
2191
|
+
tag: release.tag_name,
|
|
2192
|
+
version: newVersion,
|
|
2193
|
+
prerelease: release.prerelease
|
|
2194
|
+
});
|
|
2195
|
+
}
|
|
2303
2196
|
}
|
|
2304
|
-
if (
|
|
2305
|
-
|
|
2197
|
+
if (postedReleases.length === 0) {
|
|
2198
|
+
logger.warn("No releases created");
|
|
2199
|
+
} else {
|
|
2200
|
+
logger.success(`Releases ${postedReleases.map((r) => r.tag).join(", ")} published to GitHub!`);
|
|
2306
2201
|
}
|
|
2307
|
-
return
|
|
2202
|
+
return postedReleases;
|
|
2308
2203
|
}
|
|
2309
|
-
async function
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2204
|
+
async function githubUnified({
|
|
2205
|
+
config,
|
|
2206
|
+
dryRun,
|
|
2207
|
+
rootPackage,
|
|
2208
|
+
bumpResult
|
|
2314
2209
|
}) {
|
|
2315
|
-
const
|
|
2316
|
-
if (
|
|
2317
|
-
|
|
2318
|
-
return null;
|
|
2210
|
+
const repoConfig = config.repo;
|
|
2211
|
+
if (!repoConfig) {
|
|
2212
|
+
throw new Error("No repository configuration found. Please check your changelog config.");
|
|
2319
2213
|
}
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2214
|
+
logger.debug(`GitHub token: ${config.tokens.github || config.repo?.token ? "\u2713 provided" : "\u2717 missing"}`);
|
|
2215
|
+
if (!config.tokens.github && !config.repo?.token) {
|
|
2216
|
+
throw new Error("No GitHub token specified. Set GITHUB_TOKEN or GH_TOKEN environment variable.");
|
|
2217
|
+
}
|
|
2218
|
+
const newVersion = bumpResult?.newVersion || rootPackage.version;
|
|
2219
|
+
const to = config.to || config.templates.tagBody.replace("{{newVersion}}", newVersion);
|
|
2220
|
+
const changelog = await generateChangelog({
|
|
2221
|
+
pkg: rootPackage,
|
|
2222
|
+
config,
|
|
2223
|
+
dryRun,
|
|
2224
|
+
newVersion
|
|
2324
2225
|
});
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2226
|
+
const releaseBody = changelog.split("\n").slice(2).join("\n");
|
|
2227
|
+
const release = {
|
|
2228
|
+
tag_name: to,
|
|
2229
|
+
name: to,
|
|
2230
|
+
body: releaseBody,
|
|
2231
|
+
prerelease: isPrerelease(to)
|
|
2232
|
+
};
|
|
2233
|
+
logger.debug(`Creating release for ${to}${release.prerelease ? " (prerelease)" : ""}`);
|
|
2234
|
+
logger.debug("Release details:", formatJson({
|
|
2235
|
+
tag_name: release.tag_name,
|
|
2236
|
+
name: release.name,
|
|
2237
|
+
prerelease: release.prerelease
|
|
2238
|
+
}));
|
|
2239
|
+
if (dryRun) {
|
|
2240
|
+
logger.info("[dry-run] Publish GitHub release for", release.tag_name);
|
|
2241
|
+
} else {
|
|
2242
|
+
logger.debug("Publishing release to GitHub...");
|
|
2243
|
+
const releaseConfig = {
|
|
2244
|
+
...config,
|
|
2245
|
+
from: bumpResult?.bumped && bumpResult.fromTag || "v0.0.0",
|
|
2246
|
+
to,
|
|
2247
|
+
repo: repoConfig
|
|
2248
|
+
};
|
|
2249
|
+
await createGithubRelease(releaseConfig, release);
|
|
2328
2250
|
}
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2251
|
+
logger.success(`Release ${to} published to GitHub!`);
|
|
2252
|
+
return [{
|
|
2253
|
+
name: to,
|
|
2254
|
+
tag: to,
|
|
2255
|
+
version: to,
|
|
2256
|
+
prerelease: release.prerelease
|
|
2257
|
+
}];
|
|
2332
2258
|
}
|
|
2333
|
-
async function
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2259
|
+
async function github(options) {
|
|
2260
|
+
logger.debug("Config:", options);
|
|
2261
|
+
try {
|
|
2262
|
+
const dryRun = options.dryRun ?? false;
|
|
2263
|
+
logger.debug(`Dry run: ${dryRun}`);
|
|
2264
|
+
const config = await loadRelizyConfig({
|
|
2265
|
+
configFile: options.configName,
|
|
2266
|
+
baseConfig: options.config,
|
|
2267
|
+
overrides: {
|
|
2268
|
+
from: options.from,
|
|
2269
|
+
to: options.to,
|
|
2270
|
+
logLevel: options.logLevel,
|
|
2271
|
+
tokens: {
|
|
2272
|
+
github: options.token
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
});
|
|
2276
|
+
if (config.monorepo?.versionMode === "independent") {
|
|
2277
|
+
return await githubIndependentMode({
|
|
2278
|
+
config,
|
|
2279
|
+
dryRun,
|
|
2280
|
+
bumpResult: options.bumpResult,
|
|
2281
|
+
force: options.force ?? false,
|
|
2282
|
+
suffix: options.suffix
|
|
2283
|
+
});
|
|
2284
|
+
}
|
|
2285
|
+
const rootPackageBase = readPackageJson(config.cwd);
|
|
2286
|
+
if (!rootPackageBase) {
|
|
2287
|
+
throw new Error("Failed to read root package.json");
|
|
2288
|
+
}
|
|
2289
|
+
const newVersion = options.bumpResult?.newVersion || rootPackageBase.version;
|
|
2290
|
+
const { from, to } = await resolveTags({
|
|
2291
|
+
config,
|
|
2292
|
+
step: "provider-release",
|
|
2293
|
+
newVersion,
|
|
2294
|
+
pkg: rootPackageBase
|
|
2295
|
+
});
|
|
2296
|
+
const rootPackage = options.bumpResult?.rootPackage || await getRootPackage({
|
|
2297
|
+
config,
|
|
2298
|
+
force: options.force ?? false,
|
|
2299
|
+
suffix: options.suffix,
|
|
2300
|
+
changelog: true,
|
|
2301
|
+
from,
|
|
2302
|
+
to
|
|
2303
|
+
});
|
|
2304
|
+
return await githubUnified({
|
|
2305
|
+
config,
|
|
2306
|
+
dryRun,
|
|
2307
|
+
rootPackage,
|
|
2308
|
+
bumpResult: options.bumpResult
|
|
2347
2309
|
});
|
|
2310
|
+
} catch (error) {
|
|
2311
|
+
logger.error("Error publishing GitHub release:", error);
|
|
2312
|
+
throw error;
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
|
|
2316
|
+
async function createGitlabRelease({
|
|
2317
|
+
config,
|
|
2318
|
+
release,
|
|
2319
|
+
dryRun
|
|
2320
|
+
}) {
|
|
2321
|
+
const token = config.tokens.gitlab || config.repo?.token;
|
|
2322
|
+
if (!token && !dryRun) {
|
|
2323
|
+
throw new Error(
|
|
2324
|
+
"No GitLab token found. Set GITLAB_TOKEN or CI_JOB_TOKEN environment variable or configure tokens.gitlab"
|
|
2325
|
+
);
|
|
2326
|
+
}
|
|
2327
|
+
const repoConfig = config.repo?.repo;
|
|
2328
|
+
if (!repoConfig) {
|
|
2329
|
+
throw new Error("No repository URL found in config");
|
|
2348
2330
|
}
|
|
2331
|
+
logger.debug(`Parsed repository URL: ${repoConfig}`);
|
|
2332
|
+
const projectPath = encodeURIComponent(repoConfig);
|
|
2333
|
+
const gitlabDomain = config.repo?.domain || "gitlab.com";
|
|
2334
|
+
const apiUrl = `https://${gitlabDomain}/api/v4/projects/${projectPath}/releases`;
|
|
2335
|
+
logger.info(`Creating GitLab release at: ${apiUrl}`);
|
|
2336
|
+
const payload = {
|
|
2337
|
+
tag_name: release.tag_name,
|
|
2338
|
+
name: release.name || release.tag_name,
|
|
2339
|
+
description: release.description || "",
|
|
2340
|
+
ref: release.ref || "main"
|
|
2341
|
+
};
|
|
2349
2342
|
try {
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2343
|
+
if (dryRun) {
|
|
2344
|
+
logger.info("[dry-run] GitLab release:", formatJson(payload));
|
|
2345
|
+
return {
|
|
2346
|
+
tag_name: release.tag_name,
|
|
2347
|
+
name: release.name || release.tag_name,
|
|
2348
|
+
description: release.description || "",
|
|
2349
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2350
|
+
released_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2351
|
+
_links: {
|
|
2352
|
+
self: `${apiUrl}/${encodeURIComponent(release.tag_name)}`
|
|
2353
|
+
}
|
|
2354
|
+
};
|
|
2356
2355
|
}
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
)
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2356
|
+
logger.debug(`POST GitLab release to ${apiUrl} with payload: ${formatJson(payload)}`);
|
|
2357
|
+
const response = await fetch(apiUrl, {
|
|
2358
|
+
method: "POST",
|
|
2359
|
+
headers: {
|
|
2360
|
+
"Content-Type": "application/json",
|
|
2361
|
+
"PRIVATE-TOKEN": token || ""
|
|
2362
|
+
},
|
|
2363
|
+
body: JSON.stringify(payload)
|
|
2364
|
+
});
|
|
2365
|
+
if (!response.ok) {
|
|
2366
|
+
const errorText = await response.text();
|
|
2367
|
+
throw new Error(`GitLab API error (${response.status}): ${errorText}`);
|
|
2368
|
+
}
|
|
2369
|
+
const result = await response.json();
|
|
2370
|
+
logger.debug(`Created GitLab release: ${result._links.self}`);
|
|
2371
|
+
return result;
|
|
2372
|
+
} catch (error) {
|
|
2373
|
+
logger.error("Failed to create GitLab release:", error);
|
|
2374
|
+
throw error;
|
|
2371
2375
|
}
|
|
2372
2376
|
}
|
|
2373
|
-
async function
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2377
|
+
async function gitlabIndependentMode({
|
|
2378
|
+
config,
|
|
2379
|
+
dryRun,
|
|
2380
|
+
bumpResult,
|
|
2381
|
+
suffix,
|
|
2382
|
+
force
|
|
2379
2383
|
}) {
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2384
|
+
logger.debug(`GitLab token: ${config.tokens.gitlab || config.repo?.token ? "\u2713 provided" : "\u2717 missing"}`);
|
|
2385
|
+
const packages = await getPackagesOrBumpedPackages({
|
|
2386
|
+
config,
|
|
2387
|
+
bumpResult,
|
|
2388
|
+
suffix,
|
|
2389
|
+
force
|
|
2385
2390
|
});
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
onlyStable,
|
|
2394
|
-
packageName
|
|
2391
|
+
logger.info(`Creating ${packages.length} GitLab release(s) for independent packages`);
|
|
2392
|
+
logger.debug("Getting current branch...");
|
|
2393
|
+
const { stdout: currentBranch } = await execPromise("git rev-parse --abbrev-ref HEAD", {
|
|
2394
|
+
noSuccess: true,
|
|
2395
|
+
noStdout: true,
|
|
2396
|
+
logLevel: config.logLevel,
|
|
2397
|
+
cwd: config.cwd
|
|
2395
2398
|
});
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
+
const postedReleases = [];
|
|
2400
|
+
for (const pkg of packages) {
|
|
2401
|
+
const newVersion = isBumpedPackage(pkg) && pkg.newVersion || pkg.version;
|
|
2402
|
+
const from = config.from || pkg.fromTag;
|
|
2403
|
+
const to = getIndependentTag({ version: newVersion, name: pkg.name });
|
|
2404
|
+
if (!from) {
|
|
2405
|
+
logger.warn(`No from tag found for ${pkg.name}, skipping release`);
|
|
2406
|
+
continue;
|
|
2407
|
+
}
|
|
2408
|
+
logger.debug(`Processing ${pkg.name}: ${from} \u2192 ${to}`);
|
|
2409
|
+
const changelog = await generateChangelog({
|
|
2410
|
+
pkg,
|
|
2411
|
+
config,
|
|
2412
|
+
dryRun,
|
|
2413
|
+
newVersion
|
|
2414
|
+
});
|
|
2415
|
+
if (!changelog) {
|
|
2416
|
+
logger.warn(`No changelog found for ${pkg.name}`);
|
|
2417
|
+
continue;
|
|
2418
|
+
}
|
|
2419
|
+
const releaseBody = changelog.split("\n").slice(2).join("\n");
|
|
2420
|
+
const release = {
|
|
2421
|
+
tag_name: to,
|
|
2422
|
+
name: to,
|
|
2423
|
+
description: releaseBody,
|
|
2424
|
+
ref: currentBranch.trim()
|
|
2425
|
+
};
|
|
2426
|
+
logger.debug(`Creating release for ${to} (ref: ${release.ref})`);
|
|
2427
|
+
if (dryRun) {
|
|
2428
|
+
logger.info(`[dry-run] Publish GitLab release for ${to}`);
|
|
2429
|
+
} else {
|
|
2430
|
+
logger.debug(`Publishing release ${to} to GitLab...`);
|
|
2431
|
+
await createGitlabRelease({
|
|
2432
|
+
config,
|
|
2433
|
+
release,
|
|
2434
|
+
dryRun
|
|
2435
|
+
});
|
|
2436
|
+
postedReleases.push({
|
|
2437
|
+
name: pkg.name,
|
|
2438
|
+
tag: release.tag_name,
|
|
2439
|
+
version: newVersion,
|
|
2440
|
+
prerelease: isPrerelease(newVersion)
|
|
2441
|
+
});
|
|
2442
|
+
}
|
|
2399
2443
|
}
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
}
|
|
2404
|
-
async function resolveFromTagIndependent({
|
|
2405
|
-
cwd,
|
|
2406
|
-
packageName,
|
|
2407
|
-
currentVersion,
|
|
2408
|
-
graduating,
|
|
2409
|
-
logLevel
|
|
2410
|
-
}) {
|
|
2411
|
-
const filterPrereleases = shouldFilterPrereleaseTags(currentVersion, graduating);
|
|
2412
|
-
const onlyStable = graduating || filterPrereleases;
|
|
2413
|
-
const lastPackageTag = await getLastPackageTag({
|
|
2414
|
-
packageName,
|
|
2415
|
-
currentVersion,
|
|
2416
|
-
onlyStable,
|
|
2417
|
-
logLevel,
|
|
2418
|
-
cwd
|
|
2419
|
-
});
|
|
2420
|
-
if (!lastPackageTag) {
|
|
2421
|
-
return getFirstCommit(cwd);
|
|
2444
|
+
if (postedReleases.length === 0) {
|
|
2445
|
+
logger.warn("No releases created");
|
|
2446
|
+
} else {
|
|
2447
|
+
logger.success(`Releases ${postedReleases.map((r) => r.tag).join(", ")} published to GitLab!`);
|
|
2422
2448
|
}
|
|
2423
|
-
return
|
|
2449
|
+
return postedReleases;
|
|
2424
2450
|
}
|
|
2425
|
-
async function
|
|
2451
|
+
async function gitlabUnified({
|
|
2426
2452
|
config,
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2453
|
+
dryRun,
|
|
2454
|
+
rootPackage,
|
|
2455
|
+
bumpResult
|
|
2430
2456
|
}) {
|
|
2431
|
-
|
|
2432
|
-
const
|
|
2433
|
-
const
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2457
|
+
logger.debug(`GitLab token: ${config.tokens.gitlab || config.repo?.token ? "\u2713 provided" : "\u2717 missing"}`);
|
|
2458
|
+
const newVersion = bumpResult?.newVersion || rootPackage.newVersion || rootPackage.version;
|
|
2459
|
+
const to = config.templates.tagBody.replace("{{newVersion}}", newVersion);
|
|
2460
|
+
const changelog = await generateChangelog({
|
|
2461
|
+
pkg: rootPackage,
|
|
2462
|
+
config,
|
|
2463
|
+
dryRun,
|
|
2464
|
+
newVersion
|
|
2465
|
+
});
|
|
2466
|
+
const releaseBody = changelog.split("\n").slice(2).join("\n");
|
|
2467
|
+
logger.debug("Getting current branch...");
|
|
2468
|
+
const { stdout: currentBranch } = await execPromise("git rev-parse --abbrev-ref HEAD", {
|
|
2469
|
+
noSuccess: true,
|
|
2470
|
+
noStdout: true,
|
|
2471
|
+
logLevel: config.logLevel,
|
|
2437
2472
|
cwd: config.cwd
|
|
2438
|
-
})
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
if (
|
|
2452
|
-
|
|
2453
|
-
throw new Error("Package name is required for independent version mode");
|
|
2454
|
-
}
|
|
2455
|
-
from = await resolveFromTagIndependent({
|
|
2456
|
-
cwd: config.cwd,
|
|
2457
|
-
packageName,
|
|
2458
|
-
currentVersion,
|
|
2459
|
-
graduating,
|
|
2460
|
-
logLevel
|
|
2461
|
-
});
|
|
2473
|
+
});
|
|
2474
|
+
const release = {
|
|
2475
|
+
tag_name: to,
|
|
2476
|
+
name: to,
|
|
2477
|
+
description: releaseBody,
|
|
2478
|
+
ref: currentBranch.trim()
|
|
2479
|
+
};
|
|
2480
|
+
logger.info(`Creating release for ${to} (ref: ${release.ref})`);
|
|
2481
|
+
logger.debug("Release details:", formatJson({
|
|
2482
|
+
tag_name: release.tag_name,
|
|
2483
|
+
name: release.name,
|
|
2484
|
+
ref: release.ref
|
|
2485
|
+
}));
|
|
2486
|
+
if (dryRun) {
|
|
2487
|
+
logger.info("[dry-run] Publish GitLab release for", release.tag_name);
|
|
2462
2488
|
} else {
|
|
2463
|
-
|
|
2489
|
+
logger.debug("Publishing release to GitLab...");
|
|
2490
|
+
await createGitlabRelease({
|
|
2464
2491
|
config,
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
logLevel
|
|
2492
|
+
release,
|
|
2493
|
+
dryRun
|
|
2468
2494
|
});
|
|
2469
2495
|
}
|
|
2470
|
-
logger.
|
|
2471
|
-
return
|
|
2496
|
+
logger.success(`Release ${to} published to GitLab!`);
|
|
2497
|
+
return [{
|
|
2498
|
+
name: to,
|
|
2499
|
+
tag: to,
|
|
2500
|
+
version: to,
|
|
2501
|
+
prerelease: isPrerelease(newVersion)
|
|
2502
|
+
}];
|
|
2472
2503
|
}
|
|
2473
|
-
function
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2504
|
+
async function gitlab(options = {}) {
|
|
2505
|
+
try {
|
|
2506
|
+
const dryRun = options.dryRun ?? false;
|
|
2507
|
+
logger.debug(`Dry run: ${dryRun}`);
|
|
2508
|
+
const config = await loadRelizyConfig({
|
|
2509
|
+
configFile: options.configName,
|
|
2510
|
+
baseConfig: options.config,
|
|
2511
|
+
overrides: {
|
|
2512
|
+
from: options.from,
|
|
2513
|
+
to: options.to,
|
|
2514
|
+
logLevel: options.logLevel,
|
|
2515
|
+
tokens: {
|
|
2516
|
+
gitlab: options.token
|
|
2517
|
+
}
|
|
2518
|
+
}
|
|
2519
|
+
});
|
|
2520
|
+
if (config.monorepo?.versionMode === "independent") {
|
|
2521
|
+
return await gitlabIndependentMode({
|
|
2522
|
+
config,
|
|
2523
|
+
dryRun,
|
|
2524
|
+
bumpResult: options.bumpResult,
|
|
2525
|
+
suffix: options.suffix,
|
|
2526
|
+
force: options.force ?? false
|
|
2527
|
+
});
|
|
2487
2528
|
}
|
|
2488
|
-
|
|
2489
|
-
|
|
2529
|
+
const rootPackageBase = readPackageJson(config.cwd);
|
|
2530
|
+
if (!rootPackageBase) {
|
|
2531
|
+
throw new Error("Failed to read root package.json");
|
|
2490
2532
|
}
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2533
|
+
const newVersion = options.bumpResult?.newVersion || rootPackageBase.version;
|
|
2534
|
+
const { from, to } = await resolveTags({
|
|
2535
|
+
config,
|
|
2536
|
+
step: "provider-release",
|
|
2537
|
+
newVersion,
|
|
2538
|
+
pkg: rootPackageBase
|
|
2539
|
+
});
|
|
2540
|
+
const rootPackage = options.bumpResult?.rootPackage || await getRootPackage({
|
|
2541
|
+
config,
|
|
2542
|
+
force: options.force ?? false,
|
|
2543
|
+
suffix: options.suffix,
|
|
2544
|
+
changelog: true,
|
|
2545
|
+
from,
|
|
2546
|
+
to
|
|
2547
|
+
});
|
|
2548
|
+
logger.debug(`Root package: ${getIndependentTag({ name: rootPackage.name, version: newVersion })}`);
|
|
2549
|
+
return await gitlabUnified({
|
|
2550
|
+
config,
|
|
2551
|
+
dryRun,
|
|
2552
|
+
rootPackage,
|
|
2553
|
+
bumpResult: options.bumpResult
|
|
2554
|
+
});
|
|
2555
|
+
} catch (error) {
|
|
2556
|
+
logger.error("Error publishing GitLab release:", error);
|
|
2557
|
+
throw error;
|
|
2494
2558
|
}
|
|
2495
|
-
logger.debug(`[${versionMode}](${step}) Using to tag: ${to}`);
|
|
2496
|
-
return config.to || to;
|
|
2497
|
-
}
|
|
2498
|
-
async function resolveTags({
|
|
2499
|
-
config,
|
|
2500
|
-
step,
|
|
2501
|
-
pkg,
|
|
2502
|
-
newVersion
|
|
2503
|
-
}) {
|
|
2504
|
-
const versionMode = config.monorepo?.versionMode || "standalone";
|
|
2505
|
-
const logLevel = config.logLevel;
|
|
2506
|
-
logger.debug(`[${versionMode}](${step}) Resolving tags`);
|
|
2507
|
-
const releaseType = config.bump.type;
|
|
2508
|
-
const graduating = typeof newVersion === "string" ? isGraduatingToStableBetweenVersion(pkg.version, newVersion) : isGraduating(pkg.version, releaseType);
|
|
2509
|
-
const from = await resolveFromTag({
|
|
2510
|
-
config,
|
|
2511
|
-
versionMode,
|
|
2512
|
-
step,
|
|
2513
|
-
packageName: pkg.name,
|
|
2514
|
-
currentVersion: pkg.version,
|
|
2515
|
-
graduating,
|
|
2516
|
-
logLevel
|
|
2517
|
-
});
|
|
2518
|
-
const to = resolveToTag({
|
|
2519
|
-
config,
|
|
2520
|
-
versionMode,
|
|
2521
|
-
newVersion,
|
|
2522
|
-
step,
|
|
2523
|
-
packageName: pkg.name
|
|
2524
|
-
});
|
|
2525
|
-
logger.debug(`[${versionMode}](${step}) Using tags: ${from} \u2192 ${to}`);
|
|
2526
|
-
return { from, to };
|
|
2527
2559
|
}
|
|
2528
2560
|
|
|
2529
2561
|
let sessionOtp;
|
|
@@ -2712,7 +2744,7 @@ async function handleOtpError() {
|
|
|
2712
2744
|
logger.debug("OTP received, retrying publish...");
|
|
2713
2745
|
return otp;
|
|
2714
2746
|
} catch (promptError) {
|
|
2715
|
-
logger.
|
|
2747
|
+
logger.fail("Failed to get OTP");
|
|
2716
2748
|
throw promptError;
|
|
2717
2749
|
}
|
|
2718
2750
|
}
|
|
@@ -2756,69 +2788,362 @@ function getAuthCommand({
|
|
|
2756
2788
|
});
|
|
2757
2789
|
return `${packageManager} ${args.join(" ")}`;
|
|
2758
2790
|
}
|
|
2759
|
-
function getPublishCommand({
|
|
2760
|
-
packageManager,
|
|
2761
|
-
tag,
|
|
2762
|
-
config,
|
|
2763
|
-
otp,
|
|
2764
|
-
dryRun
|
|
2791
|
+
function getPublishCommand({
|
|
2792
|
+
packageManager,
|
|
2793
|
+
tag,
|
|
2794
|
+
config,
|
|
2795
|
+
otp,
|
|
2796
|
+
dryRun
|
|
2797
|
+
}) {
|
|
2798
|
+
const args = getCommandArgs({
|
|
2799
|
+
packageManager,
|
|
2800
|
+
tag,
|
|
2801
|
+
config,
|
|
2802
|
+
otp,
|
|
2803
|
+
dryRun,
|
|
2804
|
+
type: "publish"
|
|
2805
|
+
});
|
|
2806
|
+
const baseCommand = packageManager === "yarn" && isYarnBerry() ? "yarn npm" : packageManager;
|
|
2807
|
+
return `${baseCommand} ${args.join(" ")}`;
|
|
2808
|
+
}
|
|
2809
|
+
async function publishPackage({
|
|
2810
|
+
pkg,
|
|
2811
|
+
config,
|
|
2812
|
+
packageManager,
|
|
2813
|
+
dryRun
|
|
2814
|
+
}) {
|
|
2815
|
+
const tag = determinePublishTag(pkg.newVersion || pkg.version, config.publish.tag);
|
|
2816
|
+
const packageNameAndVersion = getIndependentTag({ name: pkg.name, version: pkg.newVersion || pkg.version });
|
|
2817
|
+
logger.debug(`Building publish command for ${pkg.name}`);
|
|
2818
|
+
let dynamicOtp;
|
|
2819
|
+
const maxAttempts = 2;
|
|
2820
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
2821
|
+
try {
|
|
2822
|
+
const command = getPublishCommand({
|
|
2823
|
+
packageManager,
|
|
2824
|
+
tag,
|
|
2825
|
+
config,
|
|
2826
|
+
otp: dynamicOtp,
|
|
2827
|
+
dryRun
|
|
2828
|
+
});
|
|
2829
|
+
process.chdir(pkg.path);
|
|
2830
|
+
await executePublishCommand({
|
|
2831
|
+
command,
|
|
2832
|
+
packageNameAndVersion,
|
|
2833
|
+
packageManager,
|
|
2834
|
+
pkg,
|
|
2835
|
+
config,
|
|
2836
|
+
dryRun,
|
|
2837
|
+
tag
|
|
2838
|
+
});
|
|
2839
|
+
if (dynamicOtp && !sessionOtp) {
|
|
2840
|
+
sessionOtp = dynamicOtp;
|
|
2841
|
+
logger.debug("OTP stored for session");
|
|
2842
|
+
}
|
|
2843
|
+
return;
|
|
2844
|
+
} catch (error) {
|
|
2845
|
+
if (isOtpError(error) && attempt < maxAttempts - 1) {
|
|
2846
|
+
dynamicOtp = await handleOtpError();
|
|
2847
|
+
} else {
|
|
2848
|
+
logger.error(`Failed to publish ${packageNameAndVersion}:`, error);
|
|
2849
|
+
throw error;
|
|
2850
|
+
}
|
|
2851
|
+
} finally {
|
|
2852
|
+
process.chdir(config.cwd);
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
}
|
|
2856
|
+
|
|
2857
|
+
function extractChangelogSummary(changelog, maxLength = 150) {
|
|
2858
|
+
if (changelog.trim() === "") {
|
|
2859
|
+
return "";
|
|
2860
|
+
}
|
|
2861
|
+
const cleaned = changelog.split("\n").filter((line) => !line.startsWith("#")).join("\n").trim();
|
|
2862
|
+
let cleanedResult = cleaned;
|
|
2863
|
+
if (cleanedResult.endsWith("?") || cleanedResult.endsWith("!") || cleanedResult.endsWith(".")) {
|
|
2864
|
+
cleanedResult = cleanedResult.slice(0, -1);
|
|
2865
|
+
}
|
|
2866
|
+
const sentences = cleanedResult.split(/[.!?]\s+/);
|
|
2867
|
+
let summary = "";
|
|
2868
|
+
for (const sentence of sentences) {
|
|
2869
|
+
if ((summary + sentence).length > maxLength || sentence.trim() === "") {
|
|
2870
|
+
break;
|
|
2871
|
+
}
|
|
2872
|
+
summary += `${sentence}. `;
|
|
2873
|
+
}
|
|
2874
|
+
return summary.trim() || cleaned.substring(0, maxLength);
|
|
2875
|
+
}
|
|
2876
|
+
function getReleaseUrl(config, tag) {
|
|
2877
|
+
const repo = config.repo;
|
|
2878
|
+
if (!repo?.domain || !repo?.repo) {
|
|
2879
|
+
return void 0;
|
|
2880
|
+
}
|
|
2881
|
+
const provider = repo.provider || "github";
|
|
2882
|
+
if (provider === "github") {
|
|
2883
|
+
return `https://${repo.domain}/${repo.repo}/releases/tag/${tag}`;
|
|
2884
|
+
} else if (provider === "gitlab") {
|
|
2885
|
+
return `https://${repo.domain}/${repo.repo}/-/releases/${tag}`;
|
|
2886
|
+
} else if (provider === "bitbucket") {
|
|
2887
|
+
return `https://${repo.domain}/${repo.repo}/commits/tag/${tag}`;
|
|
2888
|
+
}
|
|
2889
|
+
return void 0;
|
|
2890
|
+
}
|
|
2891
|
+
|
|
2892
|
+
function getSlackToken(options) {
|
|
2893
|
+
const { socialCredentials, tokenCredential } = options;
|
|
2894
|
+
const token = socialCredentials?.token || tokenCredential;
|
|
2895
|
+
if (!token) {
|
|
2896
|
+
return null;
|
|
2897
|
+
}
|
|
2898
|
+
return token;
|
|
2899
|
+
}
|
|
2900
|
+
function formatChangelogForSlack(changelog, maxLength = 500) {
|
|
2901
|
+
let formatted = changelog.replace(/^### (.+)$/gm, "*$1*").replace(/^## (.+)$/gm, "*$1*").replace(/^# (.+)$/gm, "*$1*").replace(/\*\*(.+?)\*\*/g, "*$1*");
|
|
2902
|
+
const linkPattern = /\[([^\]]*)]\(([^)]*)\)/g;
|
|
2903
|
+
formatted = formatted.replace(linkPattern, (_, text, url) => `<${url}|${text}>`);
|
|
2904
|
+
if (formatted.length > maxLength) {
|
|
2905
|
+
formatted = `${formatted.substring(0, maxLength - 3)}...`;
|
|
2906
|
+
}
|
|
2907
|
+
return formatted;
|
|
2908
|
+
}
|
|
2909
|
+
function formatSlackMessage({ projectName, version, changelog, releaseUrl, changelogUrl, template }) {
|
|
2910
|
+
if (template) {
|
|
2911
|
+
const summary = extractChangelogSummary(changelog, 500);
|
|
2912
|
+
let message = template.replace("{{projectName}}", projectName).replace("{{version}}", version).replace("{{changelog}}", summary);
|
|
2913
|
+
if (releaseUrl) {
|
|
2914
|
+
message = message.replace("{{releaseUrl}}", releaseUrl);
|
|
2915
|
+
} else {
|
|
2916
|
+
message = message.replace("{{releaseUrl}}", "").trim();
|
|
2917
|
+
}
|
|
2918
|
+
if (changelogUrl) {
|
|
2919
|
+
message = message.replace("{{changelogUrl}}", changelogUrl);
|
|
2920
|
+
} else {
|
|
2921
|
+
message = message.replace("{{changelogUrl}}", "").trim();
|
|
2922
|
+
}
|
|
2923
|
+
return [
|
|
2924
|
+
{
|
|
2925
|
+
type: "section",
|
|
2926
|
+
text: {
|
|
2927
|
+
type: "mrkdwn",
|
|
2928
|
+
text: message
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
];
|
|
2932
|
+
}
|
|
2933
|
+
const blocks = [
|
|
2934
|
+
{
|
|
2935
|
+
type: "header",
|
|
2936
|
+
text: {
|
|
2937
|
+
type: "plain_text",
|
|
2938
|
+
text: `\u{1F680} ${projectName} ${version} is out!`,
|
|
2939
|
+
emoji: true
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2942
|
+
];
|
|
2943
|
+
const formattedChangelog = formatChangelogForSlack(changelog, 500);
|
|
2944
|
+
if (formattedChangelog) {
|
|
2945
|
+
blocks.push({
|
|
2946
|
+
type: "section",
|
|
2947
|
+
text: {
|
|
2948
|
+
type: "mrkdwn",
|
|
2949
|
+
text: formattedChangelog
|
|
2950
|
+
}
|
|
2951
|
+
});
|
|
2952
|
+
}
|
|
2953
|
+
blocks.push({
|
|
2954
|
+
type: "divider"
|
|
2955
|
+
});
|
|
2956
|
+
const elements = [];
|
|
2957
|
+
if (releaseUrl) {
|
|
2958
|
+
elements.push({
|
|
2959
|
+
type: "button",
|
|
2960
|
+
text: {
|
|
2961
|
+
type: "plain_text",
|
|
2962
|
+
text: "\u{1F4E6} View Release",
|
|
2963
|
+
emoji: true
|
|
2964
|
+
},
|
|
2965
|
+
url: releaseUrl,
|
|
2966
|
+
action_id: "view_release"
|
|
2967
|
+
});
|
|
2968
|
+
}
|
|
2969
|
+
if (changelogUrl) {
|
|
2970
|
+
elements.push({
|
|
2971
|
+
type: "button",
|
|
2972
|
+
text: {
|
|
2973
|
+
type: "plain_text",
|
|
2974
|
+
text: "\u{1F4CB} Full Changelog",
|
|
2975
|
+
emoji: true
|
|
2976
|
+
},
|
|
2977
|
+
url: changelogUrl,
|
|
2978
|
+
action_id: "view_changelog"
|
|
2979
|
+
});
|
|
2980
|
+
}
|
|
2981
|
+
if (elements.length > 0) {
|
|
2982
|
+
blocks.push({
|
|
2983
|
+
type: "actions",
|
|
2984
|
+
elements
|
|
2985
|
+
});
|
|
2986
|
+
}
|
|
2987
|
+
return blocks;
|
|
2988
|
+
}
|
|
2989
|
+
async function postReleaseToSlack({
|
|
2990
|
+
version,
|
|
2991
|
+
projectName,
|
|
2992
|
+
changelog,
|
|
2993
|
+
releaseUrl,
|
|
2994
|
+
changelogUrl,
|
|
2995
|
+
channel,
|
|
2996
|
+
token,
|
|
2997
|
+
template,
|
|
2998
|
+
dryRun = false
|
|
2999
|
+
}) {
|
|
3000
|
+
logger.debug("Preparing Slack post...");
|
|
3001
|
+
const blocks = formatSlackMessage({
|
|
3002
|
+
template,
|
|
3003
|
+
projectName,
|
|
3004
|
+
version,
|
|
3005
|
+
changelog,
|
|
3006
|
+
releaseUrl,
|
|
3007
|
+
changelogUrl
|
|
3008
|
+
});
|
|
3009
|
+
logger.debug(`Message blocks (${blocks.length} blocks)`);
|
|
3010
|
+
if (dryRun) {
|
|
3011
|
+
logger.info("[dry-run] Would post to Slack:", JSON.stringify(blocks, null, 2));
|
|
3012
|
+
return;
|
|
3013
|
+
}
|
|
3014
|
+
try {
|
|
3015
|
+
const { WebClient } = await import('@slack/web-api');
|
|
3016
|
+
const client = new WebClient(token);
|
|
3017
|
+
logger.debug(`Posting message to Slack channel: ${channel}`);
|
|
3018
|
+
const result = await client.chat.postMessage({
|
|
3019
|
+
channel,
|
|
3020
|
+
blocks,
|
|
3021
|
+
text: `${projectName} ${version} is out!`
|
|
3022
|
+
// Fallback text for notifications
|
|
3023
|
+
});
|
|
3024
|
+
logger.success(`Message posted successfully! Channel: ${result.channel}, Timestamp: ${result.ts}`);
|
|
3025
|
+
return result;
|
|
3026
|
+
} catch (error) {
|
|
3027
|
+
if (error.code === "ERR_MODULE_NOT_FOUND" || error.message?.includes("@slack/web-api")) {
|
|
3028
|
+
logger.error("Slack Web API dependency not found. Please install it with: pnpm add @slack/web-api");
|
|
3029
|
+
throw new Error("Missing dependency: @slack/web-api. Install it with: pnpm add @slack/web-api");
|
|
3030
|
+
}
|
|
3031
|
+
logger.error("Failed to post message:", error.message || error);
|
|
3032
|
+
if (error.data) {
|
|
3033
|
+
logger.error("Slack API error:", error.data.error);
|
|
3034
|
+
switch (error.data.error) {
|
|
3035
|
+
case "channel_not_found":
|
|
3036
|
+
throw new Error("Slack channel not found. Make sure the channel ID or name is correct.");
|
|
3037
|
+
case "not_in_channel":
|
|
3038
|
+
throw new Error("Bot is not in the channel. Invite the bot to the channel first.");
|
|
3039
|
+
case "invalid_auth":
|
|
3040
|
+
throw new Error("Invalid Slack token. Check your credentials.");
|
|
3041
|
+
case "missing_scope":
|
|
3042
|
+
throw new Error('Missing required OAuth scope. The bot needs "chat:write" permission.');
|
|
3043
|
+
default:
|
|
3044
|
+
throw error;
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
throw error;
|
|
3048
|
+
}
|
|
3049
|
+
}
|
|
3050
|
+
|
|
3051
|
+
function getTwitterCredentials({ socialCredentials, tokenCredentials }) {
|
|
3052
|
+
const apiKey = socialCredentials?.apiKey || tokenCredentials?.apiKey;
|
|
3053
|
+
const apiKeySecret = socialCredentials?.apiKeySecret || tokenCredentials?.apiKeySecret;
|
|
3054
|
+
const accessToken = socialCredentials?.accessToken || tokenCredentials?.accessToken;
|
|
3055
|
+
const accessTokenSecret = socialCredentials?.accessTokenSecret || tokenCredentials?.accessTokenSecret;
|
|
3056
|
+
if (!apiKey || !apiKeySecret || !accessToken || !accessTokenSecret) {
|
|
3057
|
+
logger.warn("Twitter is enabled but credentials are missing.");
|
|
3058
|
+
logger.log("Set the following environment variables or configure them in social.twitter.credentials or tokens.twitter:");
|
|
3059
|
+
logger.log(" - TWITTER_API_KEY or RELIZY_TWITTER_API_KEY");
|
|
3060
|
+
logger.log(" - TWITTER_API_KEY_SECRET or RELIZY_TWITTER_API_KEY_SECRET");
|
|
3061
|
+
logger.log(" - TWITTER_ACCESS_TOKEN or RELIZY_TWITTER_ACCESS_TOKEN");
|
|
3062
|
+
logger.log(" - TWITTER_ACCESS_TOKEN_SECRET or RELIZY_TWITTER_ACCESS_TOKEN_SECRET");
|
|
3063
|
+
logger.info("Skipping Twitter post");
|
|
3064
|
+
return null;
|
|
3065
|
+
}
|
|
3066
|
+
return {
|
|
3067
|
+
apiKey,
|
|
3068
|
+
apiKeySecret,
|
|
3069
|
+
accessToken,
|
|
3070
|
+
accessTokenSecret
|
|
3071
|
+
};
|
|
3072
|
+
}
|
|
3073
|
+
function formatTweetMessage({ template, projectName, version, changelog, releaseUrl, changelogUrl }) {
|
|
3074
|
+
const TWITTER_MAX_LENGTH = 280;
|
|
3075
|
+
const ELLIPSIS = "...";
|
|
3076
|
+
let templateWithValues = template.replace("{{projectName}}", projectName).replace("{{version}}", version);
|
|
3077
|
+
if (releaseUrl) {
|
|
3078
|
+
templateWithValues = templateWithValues.replace("{{releaseUrl}}", releaseUrl);
|
|
3079
|
+
} else {
|
|
3080
|
+
templateWithValues = templateWithValues.replace("{{releaseUrl}}", "");
|
|
3081
|
+
}
|
|
3082
|
+
if (changelogUrl) {
|
|
3083
|
+
templateWithValues = templateWithValues.replace("{{changelogUrl}}", changelogUrl);
|
|
3084
|
+
} else {
|
|
3085
|
+
templateWithValues = templateWithValues.replace("{{changelogUrl}}", "");
|
|
3086
|
+
}
|
|
3087
|
+
const templateWithoutChangelog = templateWithValues.replace("{{changelog}}", "");
|
|
3088
|
+
const availableForChangelog = TWITTER_MAX_LENGTH - templateWithoutChangelog.length;
|
|
3089
|
+
let finalChangelog = changelog;
|
|
3090
|
+
if (changelog.length > availableForChangelog) {
|
|
3091
|
+
const maxLength = Math.max(0, availableForChangelog - ELLIPSIS.length);
|
|
3092
|
+
finalChangelog = changelog.substring(0, maxLength) + ELLIPSIS;
|
|
3093
|
+
}
|
|
3094
|
+
let message = templateWithValues.replace("{{changelog}}", finalChangelog).trim();
|
|
3095
|
+
if (message.length > TWITTER_MAX_LENGTH) {
|
|
3096
|
+
message = message.substring(0, TWITTER_MAX_LENGTH - ELLIPSIS.length) + ELLIPSIS;
|
|
3097
|
+
}
|
|
3098
|
+
return message;
|
|
3099
|
+
}
|
|
3100
|
+
async function postReleaseToTwitter({
|
|
3101
|
+
version,
|
|
3102
|
+
projectName,
|
|
3103
|
+
changelog,
|
|
3104
|
+
releaseUrl,
|
|
3105
|
+
changelogUrl,
|
|
3106
|
+
credentials,
|
|
3107
|
+
template,
|
|
3108
|
+
dryRun = false
|
|
2765
3109
|
}) {
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
3110
|
+
logger.debug("Preparing Twitter post...");
|
|
3111
|
+
const changelogSummary = extractChangelogSummary(changelog, 150);
|
|
3112
|
+
const message = formatTweetMessage({
|
|
3113
|
+
template,
|
|
3114
|
+
projectName,
|
|
3115
|
+
version,
|
|
3116
|
+
changelog: changelogSummary,
|
|
3117
|
+
releaseUrl,
|
|
3118
|
+
changelogUrl
|
|
2773
3119
|
});
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
await executePublishCommand({
|
|
2799
|
-
command,
|
|
2800
|
-
packageNameAndVersion,
|
|
2801
|
-
packageManager,
|
|
2802
|
-
pkg,
|
|
2803
|
-
config,
|
|
2804
|
-
dryRun,
|
|
2805
|
-
tag
|
|
2806
|
-
});
|
|
2807
|
-
if (dynamicOtp && !sessionOtp) {
|
|
2808
|
-
sessionOtp = dynamicOtp;
|
|
2809
|
-
logger.debug("OTP stored for session");
|
|
2810
|
-
}
|
|
2811
|
-
return;
|
|
2812
|
-
} catch (error) {
|
|
2813
|
-
if (isOtpError(error) && attempt < maxAttempts - 1) {
|
|
2814
|
-
dynamicOtp = await handleOtpError();
|
|
2815
|
-
} else {
|
|
2816
|
-
logger.error(`Failed to publish ${packageNameAndVersion}:`, error);
|
|
2817
|
-
throw error;
|
|
2818
|
-
}
|
|
2819
|
-
} finally {
|
|
2820
|
-
process.chdir(config.cwd);
|
|
3120
|
+
logger.debug(`Tweet message (${message.length} chars):
|
|
3121
|
+
${message}`);
|
|
3122
|
+
if (dryRun) {
|
|
3123
|
+
logger.info("[dry-run] Would post tweet:", message);
|
|
3124
|
+
return;
|
|
3125
|
+
}
|
|
3126
|
+
try {
|
|
3127
|
+
const { TwitterApi } = await import('twitter-api-v2');
|
|
3128
|
+
const client = new TwitterApi({
|
|
3129
|
+
appKey: credentials.apiKey,
|
|
3130
|
+
appSecret: credentials.apiKeySecret,
|
|
3131
|
+
accessToken: credentials.accessToken,
|
|
3132
|
+
accessSecret: credentials.accessTokenSecret
|
|
3133
|
+
});
|
|
3134
|
+
const rwClient = client.readWrite;
|
|
3135
|
+
logger.debug(`Posting tweet: ${message}`);
|
|
3136
|
+
const tweet = await rwClient.v2.tweet(message);
|
|
3137
|
+
logger.info(`Tweet posted successfully! Tweet ID: ${tweet.data.id}`);
|
|
3138
|
+
logger.info(`Tweet URL: https://twitter.com/i/web/status/${tweet.data.id}`);
|
|
3139
|
+
return tweet;
|
|
3140
|
+
} catch (error) {
|
|
3141
|
+
if (error.code === "ERR_MODULE_NOT_FOUND" || error.message?.includes("twitter-api-v2")) {
|
|
3142
|
+
logger.error("Twitter API dependency not found. Please install it with: pnpm add twitter-api-v2");
|
|
3143
|
+
throw new Error("Missing dependency: twitter-api-v2. Install it with: pnpm add twitter-api-v2");
|
|
2821
3144
|
}
|
|
3145
|
+
logger.error("Failed to post tweet:", error.message || error);
|
|
3146
|
+
throw error;
|
|
2822
3147
|
}
|
|
2823
3148
|
}
|
|
2824
3149
|
|
|
@@ -2856,7 +3181,6 @@ async function bumpUnifiedMode({
|
|
|
2856
3181
|
logger.debug(`${currentVersion} \u2192 ${newVersion} (${config.monorepo?.versionMode || "standalone"} mode)`);
|
|
2857
3182
|
const packages = await getPackages({
|
|
2858
3183
|
config,
|
|
2859
|
-
patterns: config.monorepo?.packages,
|
|
2860
3184
|
suffix,
|
|
2861
3185
|
force
|
|
2862
3186
|
});
|
|
@@ -2877,7 +3201,8 @@ async function bumpUnifiedMode({
|
|
|
2877
3201
|
} else {
|
|
2878
3202
|
logger.info(`${packages.length === 1 ? packages[0].name : packages.length} package(s) bumped from ${currentVersion} to ${newVersion} (${config.monorepo?.versionMode || "standalone"} mode)`);
|
|
2879
3203
|
}
|
|
2880
|
-
|
|
3204
|
+
const packagesToWrite = [rootPackage, ...packages];
|
|
3205
|
+
for (const pkg of packagesToWrite) {
|
|
2881
3206
|
writeVersion(pkg.path, newVersion, dryRun);
|
|
2882
3207
|
}
|
|
2883
3208
|
updateLernaVersion({
|
|
@@ -2938,7 +3263,6 @@ async function bumpSelectiveMode({
|
|
|
2938
3263
|
logger.debug("Determining packages to bump...");
|
|
2939
3264
|
const packages = await getPackages({
|
|
2940
3265
|
config,
|
|
2941
|
-
patterns: config.monorepo?.packages,
|
|
2942
3266
|
suffix,
|
|
2943
3267
|
force
|
|
2944
3268
|
});
|
|
@@ -2969,7 +3293,8 @@ async function bumpSelectiveMode({
|
|
|
2969
3293
|
}
|
|
2970
3294
|
}
|
|
2971
3295
|
logger.debug(`Writing version to ${packages.length} package(s)`);
|
|
2972
|
-
|
|
3296
|
+
const packagesToWrite = [rootPackage, ...packages];
|
|
3297
|
+
for (const pkg of packagesToWrite) {
|
|
2973
3298
|
writeVersion(pkg.path, newVersion, dryRun);
|
|
2974
3299
|
}
|
|
2975
3300
|
updateLernaVersion({
|
|
@@ -3006,7 +3331,6 @@ async function bumpIndependentMode({
|
|
|
3006
3331
|
logger.debug("Starting bump in independent mode");
|
|
3007
3332
|
const packagesToBump = await getPackages({
|
|
3008
3333
|
config,
|
|
3009
|
-
patterns: config.monorepo?.packages,
|
|
3010
3334
|
suffix,
|
|
3011
3335
|
force
|
|
3012
3336
|
});
|
|
@@ -3078,7 +3402,7 @@ async function bump(options = {}) {
|
|
|
3078
3402
|
checkGitStatusIfDirty();
|
|
3079
3403
|
}
|
|
3080
3404
|
await fetchGitTags(config.cwd);
|
|
3081
|
-
logger.
|
|
3405
|
+
logger.debug(`Version mode: ${config.monorepo?.versionMode || "standalone"}`);
|
|
3082
3406
|
const packages = readPackages({
|
|
3083
3407
|
cwd: config.cwd,
|
|
3084
3408
|
patterns: config.monorepo?.packages,
|
|
@@ -3104,7 +3428,7 @@ async function bump(options = {}) {
|
|
|
3104
3428
|
logger.success(`${dryRun ? "[dry-run] " : ""}Version bump completed (${resultLog} package${resultLog === 1 || typeof resultLog === "string" ? "" : "s"} bumped)`);
|
|
3105
3429
|
} else {
|
|
3106
3430
|
logger.fail("No packages to bump, no relevant commits found");
|
|
3107
|
-
exit(1);
|
|
3431
|
+
process$1.exit(1);
|
|
3108
3432
|
}
|
|
3109
3433
|
await executeHook("success:bump", config, dryRun);
|
|
3110
3434
|
return result;
|
|
@@ -3227,20 +3551,20 @@ async function changelog(options = {}) {
|
|
|
3227
3551
|
});
|
|
3228
3552
|
const dryRun = options.dryRun ?? false;
|
|
3229
3553
|
logger.debug(`Dry run: ${dryRun}`);
|
|
3230
|
-
logger.
|
|
3554
|
+
logger.debug(`Version mode: ${config.monorepo?.versionMode || "standalone"}`);
|
|
3231
3555
|
try {
|
|
3232
3556
|
await executeHook("before:changelog", config, dryRun);
|
|
3233
3557
|
logger.start("Start generating changelogs");
|
|
3558
|
+
const packages = await getPackagesOrBumpedPackages({
|
|
3559
|
+
config,
|
|
3560
|
+
bumpResult: options.bumpResult,
|
|
3561
|
+
suffix: options.suffix,
|
|
3562
|
+
force: options.force ?? false
|
|
3563
|
+
});
|
|
3234
3564
|
if (config.changelog?.rootChangelog && config.monorepo) {
|
|
3235
3565
|
if (config.monorepo.versionMode === "independent") {
|
|
3236
|
-
const packages2 = await getPackagesOrBumpedPackages({
|
|
3237
|
-
config,
|
|
3238
|
-
bumpResult: options.bumpResult,
|
|
3239
|
-
suffix: options.suffix,
|
|
3240
|
-
force: options.force ?? false
|
|
3241
|
-
});
|
|
3242
3566
|
await generateIndependentRootChangelog({
|
|
3243
|
-
packages
|
|
3567
|
+
packages,
|
|
3244
3568
|
config,
|
|
3245
3569
|
dryRun
|
|
3246
3570
|
});
|
|
@@ -3257,12 +3581,6 @@ async function changelog(options = {}) {
|
|
|
3257
3581
|
logger.debug("Skipping root changelog generation");
|
|
3258
3582
|
}
|
|
3259
3583
|
logger.debug("Generating package changelogs...");
|
|
3260
|
-
const packages = await getPackagesOrBumpedPackages({
|
|
3261
|
-
config,
|
|
3262
|
-
bumpResult: options.bumpResult,
|
|
3263
|
-
suffix: options.suffix,
|
|
3264
|
-
force: options.force ?? false
|
|
3265
|
-
});
|
|
3266
3584
|
logger.debug(`Processing ${packages.length} package(s)`);
|
|
3267
3585
|
let generatedCount = 0;
|
|
3268
3586
|
for await (const pkg of packages) {
|
|
@@ -3309,22 +3627,28 @@ async function changelog(options = {}) {
|
|
|
3309
3627
|
|
|
3310
3628
|
function providerReleaseSafetyCheck({ config, provider }) {
|
|
3311
3629
|
if (!config.safetyCheck || !config.release.providerRelease) {
|
|
3630
|
+
logger.debug("Safety check disabled or provider release disabled");
|
|
3312
3631
|
return;
|
|
3313
3632
|
}
|
|
3633
|
+
logger.debug("Start checking provider release config");
|
|
3314
3634
|
const internalProvider = provider || config.repo?.provider || detectGitProvider();
|
|
3635
|
+
if (internalProvider === "bitbucket") {
|
|
3636
|
+
logger.warn("Bitbucket does not support releases via API");
|
|
3637
|
+
logger.info("Relizy will skip the release creation step for Bitbucket");
|
|
3638
|
+
return;
|
|
3639
|
+
}
|
|
3315
3640
|
let token;
|
|
3316
3641
|
if (internalProvider === "github") {
|
|
3317
3642
|
token = config.tokens?.github || config.repo?.token;
|
|
3318
3643
|
} else if (internalProvider === "gitlab") {
|
|
3319
3644
|
token = config.tokens?.gitlab || config.repo?.token;
|
|
3320
3645
|
} else {
|
|
3321
|
-
|
|
3322
|
-
process.exit(1);
|
|
3646
|
+
throw new Error(`Unsupported Git provider: ${internalProvider || "unknown"}`);
|
|
3323
3647
|
}
|
|
3324
3648
|
if (!token) {
|
|
3325
|
-
|
|
3326
|
-
process.exit(1);
|
|
3649
|
+
throw new Error(`No token provided for ${internalProvider || "unknown"} - The release will not be published - Please refer to the documentation: https://louismazel.github.io/relizy/guide/installation#environment-setup`);
|
|
3327
3650
|
}
|
|
3651
|
+
logger.info("provider release config checked successfully");
|
|
3328
3652
|
}
|
|
3329
3653
|
async function providerRelease(options = {}) {
|
|
3330
3654
|
const config = await loadRelizyConfig({
|
|
@@ -3343,9 +3667,10 @@ async function providerRelease(options = {}) {
|
|
|
3343
3667
|
});
|
|
3344
3668
|
const dryRun = options.dryRun ?? false;
|
|
3345
3669
|
logger.debug(`Dry run: ${dryRun}`);
|
|
3346
|
-
logger.
|
|
3670
|
+
logger.debug(`Version mode: ${config.monorepo?.versionMode || "standalone"}`);
|
|
3671
|
+
let detectedProvider = null;
|
|
3347
3672
|
try {
|
|
3348
|
-
|
|
3673
|
+
detectedProvider = options.provider || detectGitProvider();
|
|
3349
3674
|
providerReleaseSafetyCheck({ config, provider: detectedProvider });
|
|
3350
3675
|
await executeHook("before:provider-release", config, dryRun);
|
|
3351
3676
|
logger.start("Start provider release");
|
|
@@ -3358,6 +3683,16 @@ async function providerRelease(options = {}) {
|
|
|
3358
3683
|
);
|
|
3359
3684
|
}
|
|
3360
3685
|
let postedReleases = [];
|
|
3686
|
+
if (detectedProvider === "bitbucket") {
|
|
3687
|
+
logger.warn("\u26A0\uFE0F Bitbucket does not support releases via API");
|
|
3688
|
+
logger.info("Skipping release creation for Bitbucket");
|
|
3689
|
+
logger.info("Git tags will still be created during the commit step");
|
|
3690
|
+
await executeHook("success:provider-release", config, dryRun);
|
|
3691
|
+
return {
|
|
3692
|
+
detectedProvider,
|
|
3693
|
+
postedReleases: []
|
|
3694
|
+
};
|
|
3695
|
+
}
|
|
3361
3696
|
const payload = {
|
|
3362
3697
|
from: config.from || options.bumpResult?.fromTag,
|
|
3363
3698
|
to: config.to,
|
|
@@ -3385,20 +3720,24 @@ async function providerRelease(options = {}) {
|
|
|
3385
3720
|
logger.error("Error publishing releases!\n\n", error);
|
|
3386
3721
|
}
|
|
3387
3722
|
await executeHook("error:provider-release", config, dryRun);
|
|
3388
|
-
|
|
3723
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3724
|
+
return {
|
|
3725
|
+
detectedProvider: detectedProvider || "github",
|
|
3726
|
+
postedReleases: [],
|
|
3727
|
+
error: errorMessage
|
|
3728
|
+
};
|
|
3389
3729
|
}
|
|
3390
3730
|
}
|
|
3391
3731
|
|
|
3392
3732
|
async function publishSafetyCheck({ config }) {
|
|
3393
|
-
logger.debug("[publish-safety-check] Running publish safety check");
|
|
3394
3733
|
if (!config.safetyCheck || !config.release.publish || !config.publish.safetyCheck) {
|
|
3395
|
-
logger.debug("
|
|
3734
|
+
logger.debug("Safety check disabled or publish disabled");
|
|
3396
3735
|
return;
|
|
3397
3736
|
}
|
|
3737
|
+
logger.debug("Start checking auth config to package registry");
|
|
3398
3738
|
const packageManager = config.publish.packageManager || detectPackageManager(config.cwd);
|
|
3399
3739
|
if (!packageManager) {
|
|
3400
|
-
|
|
3401
|
-
process.exit(1);
|
|
3740
|
+
throw new Error("Unable to detect package manager");
|
|
3402
3741
|
}
|
|
3403
3742
|
const isPnpmOrNpm = packageManager === "pnpm" || packageManager === "npm";
|
|
3404
3743
|
if (isPnpmOrNpm) {
|
|
@@ -3408,7 +3747,7 @@ async function publishSafetyCheck({ config }) {
|
|
|
3408
3747
|
otp: config.publish.otp
|
|
3409
3748
|
});
|
|
3410
3749
|
try {
|
|
3411
|
-
logger.debug("
|
|
3750
|
+
logger.debug("Authenticating to package registry...");
|
|
3412
3751
|
await execPromise(authCommand, {
|
|
3413
3752
|
cwd: config.cwd,
|
|
3414
3753
|
noStderr: true,
|
|
@@ -3416,10 +3755,9 @@ async function publishSafetyCheck({ config }) {
|
|
|
3416
3755
|
logLevel: config.logLevel,
|
|
3417
3756
|
noSuccess: true
|
|
3418
3757
|
});
|
|
3419
|
-
logger.info("
|
|
3758
|
+
logger.info("Successfully authenticated to package registry");
|
|
3420
3759
|
} catch (error) {
|
|
3421
|
-
|
|
3422
|
-
process.exit(1);
|
|
3760
|
+
throw new Error("Failed to authenticate to package registry", { cause: error });
|
|
3423
3761
|
}
|
|
3424
3762
|
}
|
|
3425
3763
|
}
|
|
@@ -3444,7 +3782,7 @@ async function publish(options = {}) {
|
|
|
3444
3782
|
logger.debug(`Dry run: ${dryRun}`);
|
|
3445
3783
|
const packageManager = config.publish.packageManager || detectPackageManager(config.cwd);
|
|
3446
3784
|
logger.debug(`Package manager: ${packageManager}`);
|
|
3447
|
-
logger.
|
|
3785
|
+
logger.debug(`Version mode: ${config.monorepo?.versionMode || "standalone"}`);
|
|
3448
3786
|
if (config.publish.registry) {
|
|
3449
3787
|
logger.debug(`Registry: ${config.publish.registry}`);
|
|
3450
3788
|
}
|
|
@@ -3519,6 +3857,286 @@ async function publish(options = {}) {
|
|
|
3519
3857
|
}
|
|
3520
3858
|
}
|
|
3521
3859
|
|
|
3860
|
+
function socialSafetyCheck({ config }) {
|
|
3861
|
+
const socialMediaDisabled = !config.release.social && !config.social.twitter.enabled && !config.social.slack.enabled;
|
|
3862
|
+
if (!config.safetyCheck || socialMediaDisabled) {
|
|
3863
|
+
logger.debug("Safety check disabled or social disabled");
|
|
3864
|
+
return;
|
|
3865
|
+
}
|
|
3866
|
+
logger.debug("Start checking social config");
|
|
3867
|
+
const errors = {
|
|
3868
|
+
twitter: false,
|
|
3869
|
+
slack: false
|
|
3870
|
+
};
|
|
3871
|
+
const twitterConfig = config.social?.twitter;
|
|
3872
|
+
if (twitterConfig?.enabled) {
|
|
3873
|
+
const credentials = getTwitterCredentials({
|
|
3874
|
+
socialCredentials: twitterConfig.credentials,
|
|
3875
|
+
tokenCredentials: config.tokens?.twitter
|
|
3876
|
+
});
|
|
3877
|
+
if (!credentials) {
|
|
3878
|
+
errors.twitter = true;
|
|
3879
|
+
}
|
|
3880
|
+
}
|
|
3881
|
+
const slackConfig = config.social?.slack;
|
|
3882
|
+
if (slackConfig?.enabled) {
|
|
3883
|
+
const token = getSlackToken({
|
|
3884
|
+
socialCredentials: slackConfig.credentials,
|
|
3885
|
+
tokenCredential: config.tokens?.slack
|
|
3886
|
+
});
|
|
3887
|
+
if (!token) {
|
|
3888
|
+
logger.log("Slack is enabled but credentials are missing.");
|
|
3889
|
+
logger.log("Set the following environment variables or configure them in social.slack.credentials or tokens.slack:");
|
|
3890
|
+
logger.log(" - SLACK_TOKEN or RELIZY_SLACK_TOKEN");
|
|
3891
|
+
errors.slack = true;
|
|
3892
|
+
}
|
|
3893
|
+
if (!slackConfig.channel) {
|
|
3894
|
+
logger.warn("Slack is enabled but no channel is configured.");
|
|
3895
|
+
logger.log('Set the channel in social.slack.channel (e.g., "#releases" or "C1234567890")');
|
|
3896
|
+
errors.slack = true;
|
|
3897
|
+
}
|
|
3898
|
+
}
|
|
3899
|
+
if (errors.twitter || errors.slack) {
|
|
3900
|
+
throw new Error("Social config checked with errors");
|
|
3901
|
+
}
|
|
3902
|
+
logger.info("Social config checked successfully");
|
|
3903
|
+
}
|
|
3904
|
+
async function handleTwitterPost({
|
|
3905
|
+
config,
|
|
3906
|
+
changelog,
|
|
3907
|
+
dryRun,
|
|
3908
|
+
newVersion,
|
|
3909
|
+
tag
|
|
3910
|
+
}) {
|
|
3911
|
+
const twitterConfig = config.social?.twitter;
|
|
3912
|
+
if (!twitterConfig?.enabled) {
|
|
3913
|
+
logger.debug("Twitter posting is disabled in configuration");
|
|
3914
|
+
return { success: true, response: void 0 };
|
|
3915
|
+
}
|
|
3916
|
+
logger.debug("Twitter posting is enabled");
|
|
3917
|
+
try {
|
|
3918
|
+
const credentials = getTwitterCredentials({
|
|
3919
|
+
socialCredentials: twitterConfig.credentials,
|
|
3920
|
+
tokenCredentials: config.tokens?.twitter
|
|
3921
|
+
});
|
|
3922
|
+
if (!credentials) {
|
|
3923
|
+
return { success: false, error: "Twitter credentials not found" };
|
|
3924
|
+
}
|
|
3925
|
+
logger.debug("Credentials found \u2713");
|
|
3926
|
+
logger.debug("Preparing tweet for release");
|
|
3927
|
+
const onlyStable = twitterConfig.onlyStable;
|
|
3928
|
+
if (onlyStable && isPrerelease(newVersion)) {
|
|
3929
|
+
logger.info(`Skipping Twitter post for prerelease version ${newVersion} (social.twitter.onlyStable is enabled)`);
|
|
3930
|
+
return { success: true, response: void 0 };
|
|
3931
|
+
}
|
|
3932
|
+
await executeHook("before:twitter", config, dryRun);
|
|
3933
|
+
try {
|
|
3934
|
+
const rootPackageBase = readPackageJson(config.cwd);
|
|
3935
|
+
if (!rootPackageBase) {
|
|
3936
|
+
throw new Error("Failed to read root package.json");
|
|
3937
|
+
}
|
|
3938
|
+
logger.debug(`Project: ${rootPackageBase.name}`);
|
|
3939
|
+
const releaseUrl = getReleaseUrl(config, tag);
|
|
3940
|
+
logger.debug(`Release URL: ${releaseUrl || "none"}`);
|
|
3941
|
+
const changelogUrl = config.social?.changelogUrl;
|
|
3942
|
+
logger.debug(`Changelog URL: ${changelogUrl || "none"}`);
|
|
3943
|
+
logger.debug(`Changelog generated (${changelog.length} chars)`);
|
|
3944
|
+
const changelogSummary = extractChangelogSummary(changelog, 150);
|
|
3945
|
+
logger.debug(`Changelog summary: ${changelogSummary.substring(0, 50)}...`);
|
|
3946
|
+
const response = await postReleaseToTwitter({
|
|
3947
|
+
template: config.social.twitter.template || config.templates.twitterMessage,
|
|
3948
|
+
version: newVersion,
|
|
3949
|
+
projectName: rootPackageBase.name,
|
|
3950
|
+
changelog: changelogSummary,
|
|
3951
|
+
releaseUrl,
|
|
3952
|
+
changelogUrl,
|
|
3953
|
+
credentials,
|
|
3954
|
+
dryRun
|
|
3955
|
+
});
|
|
3956
|
+
await executeHook("success:twitter", config, dryRun);
|
|
3957
|
+
return { success: true, response };
|
|
3958
|
+
} catch (error) {
|
|
3959
|
+
await executeHook("error:twitter", config, dryRun);
|
|
3960
|
+
logger.error("Error posting to Twitter:", error);
|
|
3961
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3962
|
+
return { success: false, error: `Error posting to Twitter: ${errorMessage}` };
|
|
3963
|
+
}
|
|
3964
|
+
} catch (error) {
|
|
3965
|
+
logger.error("Error during Twitter posting:", error);
|
|
3966
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3967
|
+
return { success: false, error: `Error during Twitter posting: ${errorMessage}` };
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3970
|
+
async function handleSlackPost({
|
|
3971
|
+
config,
|
|
3972
|
+
changelog,
|
|
3973
|
+
dryRun,
|
|
3974
|
+
newVersion,
|
|
3975
|
+
tag
|
|
3976
|
+
}) {
|
|
3977
|
+
const slackConfig = config.social?.slack;
|
|
3978
|
+
if (!slackConfig?.enabled) {
|
|
3979
|
+
logger.debug("Slack posting is disabled in configuration");
|
|
3980
|
+
return { success: true, response: void 0 };
|
|
3981
|
+
}
|
|
3982
|
+
logger.debug("Slack posting is enabled");
|
|
3983
|
+
try {
|
|
3984
|
+
const token = getSlackToken({
|
|
3985
|
+
socialCredentials: slackConfig.credentials,
|
|
3986
|
+
tokenCredential: config.tokens?.slack
|
|
3987
|
+
});
|
|
3988
|
+
if (!token) {
|
|
3989
|
+
logger.warn("Slack token not found. Set SLACK_TOKEN or RELIZY_SLACK_TOKEN environment variable or configure it in social.slack.credentials or tokens.slack.");
|
|
3990
|
+
logger.info("Skipping Slack post");
|
|
3991
|
+
return { success: false, error: "Slack token not found" };
|
|
3992
|
+
}
|
|
3993
|
+
logger.debug("Token found \u2713");
|
|
3994
|
+
if (!slackConfig.channel) {
|
|
3995
|
+
logger.warn("Slack channel not configured. Set it in social.slack.channel.");
|
|
3996
|
+
logger.info("Skipping Slack post");
|
|
3997
|
+
return { success: false, error: "Slack channel not configured" };
|
|
3998
|
+
}
|
|
3999
|
+
logger.debug(`Channel configured: ${slackConfig.channel}`);
|
|
4000
|
+
logger.debug(`Preparing Slack message for release: ${tag} (${newVersion})`);
|
|
4001
|
+
const onlyStable = slackConfig.onlyStable ?? true;
|
|
4002
|
+
if (onlyStable && isPrerelease(newVersion)) {
|
|
4003
|
+
logger.info(`Skipping Slack post for prerelease version ${newVersion} (social.slack.onlyStable is enabled)`);
|
|
4004
|
+
return { success: true, response: void 0 };
|
|
4005
|
+
}
|
|
4006
|
+
try {
|
|
4007
|
+
await executeHook("before:slack", config, dryRun);
|
|
4008
|
+
const rootPackageBase = readPackageJson(config.cwd);
|
|
4009
|
+
if (!rootPackageBase) {
|
|
4010
|
+
throw new Error("Failed to read root package.json");
|
|
4011
|
+
}
|
|
4012
|
+
logger.debug(`Project: ${rootPackageBase.name}`);
|
|
4013
|
+
const releaseUrl = getReleaseUrl(config, tag);
|
|
4014
|
+
logger.debug(`Release URL: ${releaseUrl || "none"}`);
|
|
4015
|
+
const changelogUrl = config.social?.changelogUrl;
|
|
4016
|
+
logger.debug(`Changelog URL: ${changelogUrl || "none"}`);
|
|
4017
|
+
logger.debug(`Changelog generated (${changelog.length} chars)`);
|
|
4018
|
+
const template = slackConfig.template || config.templates.slackMessage;
|
|
4019
|
+
const response = await postReleaseToSlack({
|
|
4020
|
+
version: newVersion,
|
|
4021
|
+
projectName: rootPackageBase.name,
|
|
4022
|
+
changelog,
|
|
4023
|
+
releaseUrl,
|
|
4024
|
+
changelogUrl,
|
|
4025
|
+
channel: slackConfig.channel,
|
|
4026
|
+
token,
|
|
4027
|
+
template,
|
|
4028
|
+
dryRun
|
|
4029
|
+
});
|
|
4030
|
+
await executeHook("success:slack", config, dryRun);
|
|
4031
|
+
return { success: true, response };
|
|
4032
|
+
} catch (error) {
|
|
4033
|
+
await executeHook("error:slack", config, dryRun);
|
|
4034
|
+
logger.error("Error posting to Slack:", error);
|
|
4035
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4036
|
+
return { success: false, error: `Error posting to Slack: ${errorMessage}` };
|
|
4037
|
+
}
|
|
4038
|
+
} catch (error) {
|
|
4039
|
+
logger.error("Error during Slack posting:", error);
|
|
4040
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4041
|
+
return { success: false, error: `Error during Slack posting: ${errorMessage}` };
|
|
4042
|
+
}
|
|
4043
|
+
}
|
|
4044
|
+
async function social(options = {}) {
|
|
4045
|
+
try {
|
|
4046
|
+
const dryRun = options.dryRun ?? false;
|
|
4047
|
+
logger.debug(`Dry run: ${dryRun}`);
|
|
4048
|
+
const config = await loadRelizyConfig({
|
|
4049
|
+
configFile: options.configName,
|
|
4050
|
+
baseConfig: options.config,
|
|
4051
|
+
overrides: {
|
|
4052
|
+
from: options.from,
|
|
4053
|
+
to: options.to,
|
|
4054
|
+
logLevel: options.logLevel
|
|
4055
|
+
}
|
|
4056
|
+
});
|
|
4057
|
+
logger.debug(`Version mode: ${config.monorepo?.versionMode || "standalone"}`);
|
|
4058
|
+
socialSafetyCheck({ config });
|
|
4059
|
+
if (!config.release.social && !config.social?.twitter?.enabled && !config.social?.slack?.enabled) {
|
|
4060
|
+
logger.warn("Social media posting is disabled in configuration.");
|
|
4061
|
+
logger.info("Enable it with release.social: true or social.twitter.enabled: true or social.slack.enabled: true");
|
|
4062
|
+
return { results: [], hasErrors: false };
|
|
4063
|
+
}
|
|
4064
|
+
await executeHook("before:social", config, dryRun);
|
|
4065
|
+
const rootPackageRead = readPackageJson(config.cwd);
|
|
4066
|
+
if (!rootPackageRead) {
|
|
4067
|
+
throw new Error("Failed to read root package.json");
|
|
4068
|
+
}
|
|
4069
|
+
const newVersion = options.bumpResult?.newVersion || rootPackageRead.version;
|
|
4070
|
+
const { from, to } = await resolveTags({
|
|
4071
|
+
config,
|
|
4072
|
+
step: "social",
|
|
4073
|
+
newVersion,
|
|
4074
|
+
pkg: rootPackageRead
|
|
4075
|
+
});
|
|
4076
|
+
const fromTag = options.bumpResult?.fromTag || from;
|
|
4077
|
+
const rootPackage = options.bumpResult?.rootPackage || await getRootPackage({
|
|
4078
|
+
config,
|
|
4079
|
+
force: false,
|
|
4080
|
+
suffix: void 0,
|
|
4081
|
+
changelog: true,
|
|
4082
|
+
from: fromTag,
|
|
4083
|
+
to
|
|
4084
|
+
});
|
|
4085
|
+
const changelog = await generateChangelog({
|
|
4086
|
+
pkg: rootPackage,
|
|
4087
|
+
config,
|
|
4088
|
+
dryRun,
|
|
4089
|
+
newVersion,
|
|
4090
|
+
minify: true
|
|
4091
|
+
});
|
|
4092
|
+
const twitterResponse = await handleTwitterPost({
|
|
4093
|
+
config,
|
|
4094
|
+
changelog,
|
|
4095
|
+
dryRun,
|
|
4096
|
+
newVersion,
|
|
4097
|
+
tag: to
|
|
4098
|
+
});
|
|
4099
|
+
const slackResponse = await handleSlackPost({
|
|
4100
|
+
config,
|
|
4101
|
+
changelog,
|
|
4102
|
+
dryRun,
|
|
4103
|
+
newVersion,
|
|
4104
|
+
tag: to
|
|
4105
|
+
});
|
|
4106
|
+
const results = [];
|
|
4107
|
+
if (config.social?.twitter?.enabled) {
|
|
4108
|
+
results.push({
|
|
4109
|
+
platform: "twitter",
|
|
4110
|
+
success: twitterResponse.success,
|
|
4111
|
+
error: twitterResponse.success ? void 0 : twitterResponse.error
|
|
4112
|
+
});
|
|
4113
|
+
}
|
|
4114
|
+
if (config.social?.slack?.enabled) {
|
|
4115
|
+
results.push({
|
|
4116
|
+
platform: "slack",
|
|
4117
|
+
success: slackResponse.success,
|
|
4118
|
+
error: slackResponse.success ? void 0 : slackResponse.error
|
|
4119
|
+
});
|
|
4120
|
+
}
|
|
4121
|
+
const hasErrors = results.some((r) => !r.success);
|
|
4122
|
+
if (hasErrors) {
|
|
4123
|
+
await executeHook("error:social", config, dryRun);
|
|
4124
|
+
logger.warn("Some social media posts failed");
|
|
4125
|
+
} else {
|
|
4126
|
+
logger.success("Social media posts completed!");
|
|
4127
|
+
await executeHook("success:social", config, dryRun);
|
|
4128
|
+
}
|
|
4129
|
+
return { results, hasErrors };
|
|
4130
|
+
} catch (error) {
|
|
4131
|
+
logger.error("Error during social media posting:", error);
|
|
4132
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
4133
|
+
return {
|
|
4134
|
+
results: [{ platform: "unknown", success: false, error: errorMessage }],
|
|
4135
|
+
hasErrors: true
|
|
4136
|
+
};
|
|
4137
|
+
}
|
|
4138
|
+
}
|
|
4139
|
+
|
|
3522
4140
|
function getReleaseConfig(options = {}) {
|
|
3523
4141
|
return loadRelizyConfig({
|
|
3524
4142
|
configFile: options.configName,
|
|
@@ -3556,7 +4174,8 @@ function getReleaseConfig(options = {}) {
|
|
|
3556
4174
|
noVerify: options.noVerify,
|
|
3557
4175
|
providerRelease: options.providerRelease,
|
|
3558
4176
|
clean: options.clean,
|
|
3559
|
-
gitTag: options.gitTag
|
|
4177
|
+
gitTag: options.gitTag,
|
|
4178
|
+
social: options.social
|
|
3560
4179
|
},
|
|
3561
4180
|
safetyCheck: options.safetyCheck
|
|
3562
4181
|
}
|
|
@@ -3569,8 +4188,19 @@ async function releaseSafetyCheck({
|
|
|
3569
4188
|
if (!config.safetyCheck) {
|
|
3570
4189
|
return;
|
|
3571
4190
|
}
|
|
3572
|
-
|
|
3573
|
-
|
|
4191
|
+
logger.box("Safety checks");
|
|
4192
|
+
logger.start("Start safety checks");
|
|
4193
|
+
try {
|
|
4194
|
+
await Promise.all([
|
|
4195
|
+
providerReleaseSafetyCheck({ config, provider }),
|
|
4196
|
+
publishSafetyCheck({ config }),
|
|
4197
|
+
socialSafetyCheck({ config })
|
|
4198
|
+
]);
|
|
4199
|
+
logger.success("Safety checks passed");
|
|
4200
|
+
} catch (error) {
|
|
4201
|
+
logger.error("Safety checks failed");
|
|
4202
|
+
throw error;
|
|
4203
|
+
}
|
|
3574
4204
|
}
|
|
3575
4205
|
async function release(options = {}) {
|
|
3576
4206
|
const dryRun = options.dryRun ?? false;
|
|
@@ -3583,7 +4213,7 @@ async function release(options = {}) {
|
|
|
3583
4213
|
await releaseSafetyCheck({ config, provider: options.provider });
|
|
3584
4214
|
try {
|
|
3585
4215
|
await executeHook("before:release", config, dryRun);
|
|
3586
|
-
logger.box("
|
|
4216
|
+
logger.box("Bump versions");
|
|
3587
4217
|
const bumpResult = await bump({
|
|
3588
4218
|
type: config.bump.type,
|
|
3589
4219
|
preid: config.bump.preid,
|
|
@@ -3598,7 +4228,7 @@ async function release(options = {}) {
|
|
|
3598
4228
|
logger.debug("No packages bumped");
|
|
3599
4229
|
return;
|
|
3600
4230
|
}
|
|
3601
|
-
logger.box("
|
|
4231
|
+
logger.box("Generate changelogs");
|
|
3602
4232
|
if (config.release.changelog) {
|
|
3603
4233
|
await changelog({
|
|
3604
4234
|
from: config.from,
|
|
@@ -3616,7 +4246,7 @@ async function release(options = {}) {
|
|
|
3616
4246
|
} else {
|
|
3617
4247
|
logger.info("Skipping changelog generation (--no-changelog)");
|
|
3618
4248
|
}
|
|
3619
|
-
logger.box("
|
|
4249
|
+
logger.box("Publish packages to registry");
|
|
3620
4250
|
let publishResponse;
|
|
3621
4251
|
if (config.release.publish) {
|
|
3622
4252
|
try {
|
|
@@ -3630,17 +4260,18 @@ async function release(options = {}) {
|
|
|
3630
4260
|
config,
|
|
3631
4261
|
configName: options.configName,
|
|
3632
4262
|
suffix: options.suffix,
|
|
3633
|
-
force
|
|
4263
|
+
force,
|
|
4264
|
+
safetyCheck: false
|
|
3634
4265
|
});
|
|
3635
4266
|
} catch (error) {
|
|
3636
|
-
logger.
|
|
4267
|
+
logger.fail("Publish failed, rolling back modified files...");
|
|
3637
4268
|
await rollbackModifiedFiles({ config });
|
|
3638
4269
|
throw error;
|
|
3639
4270
|
}
|
|
3640
4271
|
} else {
|
|
3641
4272
|
logger.info("Skipping publish (--no-publish)");
|
|
3642
4273
|
}
|
|
3643
|
-
logger.box("
|
|
4274
|
+
logger.box("Commit changes and create tag");
|
|
3644
4275
|
let createdTags = [];
|
|
3645
4276
|
if (config.release.commit) {
|
|
3646
4277
|
createdTags = await createCommitAndTags({
|
|
@@ -3654,7 +4285,7 @@ async function release(options = {}) {
|
|
|
3654
4285
|
} else {
|
|
3655
4286
|
logger.info("Skipping commit and tag (--no-commit)");
|
|
3656
4287
|
}
|
|
3657
|
-
logger.box("
|
|
4288
|
+
logger.box("Push changes and tags");
|
|
3658
4289
|
if (config.release.push && config.release.commit) {
|
|
3659
4290
|
await executeHook("before:push", config, dryRun);
|
|
3660
4291
|
try {
|
|
@@ -3674,40 +4305,75 @@ async function release(options = {}) {
|
|
|
3674
4305
|
}
|
|
3675
4306
|
let provider = config.repo?.provider;
|
|
3676
4307
|
let postedReleases = [];
|
|
3677
|
-
|
|
4308
|
+
let providerError;
|
|
4309
|
+
logger.box("Publish Git release");
|
|
3678
4310
|
if (config.release.providerRelease) {
|
|
3679
4311
|
logger.debug(`Provider from config: ${provider}`);
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
logger.error("Error during release publication:", error);
|
|
3698
|
-
}
|
|
4312
|
+
const response = await providerRelease({
|
|
4313
|
+
from: config.from,
|
|
4314
|
+
to: config.to,
|
|
4315
|
+
token: options.token,
|
|
4316
|
+
provider,
|
|
4317
|
+
dryRun,
|
|
4318
|
+
config,
|
|
4319
|
+
logLevel: config.logLevel,
|
|
4320
|
+
bumpResult,
|
|
4321
|
+
configName: options.configName,
|
|
4322
|
+
force,
|
|
4323
|
+
suffix: options.suffix,
|
|
4324
|
+
safetyCheck: false
|
|
4325
|
+
});
|
|
4326
|
+
provider = response.detectedProvider;
|
|
4327
|
+
postedReleases = response.postedReleases;
|
|
4328
|
+
providerError = response.error;
|
|
3699
4329
|
} else {
|
|
3700
4330
|
logger.info("Skipping release (--no-provider-release)");
|
|
3701
4331
|
}
|
|
4332
|
+
logger.box("Post release to social media");
|
|
4333
|
+
let socialResults;
|
|
4334
|
+
if (config.release.social && (config.social?.twitter?.enabled || config.social?.slack?.enabled)) {
|
|
4335
|
+
socialResults = await social({
|
|
4336
|
+
from: config.from,
|
|
4337
|
+
to: config.to,
|
|
4338
|
+
config,
|
|
4339
|
+
configName: options.configName,
|
|
4340
|
+
bumpResult,
|
|
4341
|
+
dryRun,
|
|
4342
|
+
logLevel: config.logLevel,
|
|
4343
|
+
safetyCheck: false
|
|
4344
|
+
// Already checked in releaseSafetyCheck
|
|
4345
|
+
});
|
|
4346
|
+
} else {
|
|
4347
|
+
logger.info("Skipping social media posts (--no-social or no social media enabled)");
|
|
4348
|
+
}
|
|
3702
4349
|
const publishedPackageCount = publishResponse?.publishedPackages.length ?? 0;
|
|
3703
4350
|
const versionDisplay = config.monorepo?.versionMode === "independent" ? `${bumpResult.bumpedPackages.length} packages bumped independently` : bumpResult.newVersion || readPackageJson(config.cwd)?.version;
|
|
4351
|
+
let providerDisplay = "Disabled";
|
|
4352
|
+
if (config.release.providerRelease) {
|
|
4353
|
+
if (providerError) {
|
|
4354
|
+
providerDisplay = `Failed: ${providerError}`;
|
|
4355
|
+
} else {
|
|
4356
|
+
providerDisplay = `${postedReleases.length} release${postedReleases.length !== 1 ? "s" : ""}`;
|
|
4357
|
+
}
|
|
4358
|
+
}
|
|
4359
|
+
let socialDisplay = "Disabled";
|
|
4360
|
+
if (config.release.social && socialResults) {
|
|
4361
|
+
if (socialResults.hasErrors) {
|
|
4362
|
+
const failed = socialResults.results.filter((r) => !r.success).map((r) => r.platform);
|
|
4363
|
+
const succeeded = socialResults.results.filter((r) => r.success).map((r) => r.platform);
|
|
4364
|
+
socialDisplay = `${succeeded.length} succeeded, ${failed.length} failed (${failed.join(", ")})`;
|
|
4365
|
+
} else {
|
|
4366
|
+
socialDisplay = `${socialResults.results.length} succeeded`;
|
|
4367
|
+
}
|
|
4368
|
+
}
|
|
3704
4369
|
logger.box(`Release workflow completed!
|
|
3705
4370
|
|
|
3706
4371
|
Version: ${versionDisplay ?? "Unknown"}
|
|
3707
|
-
Tag(s): ${createdTags
|
|
4372
|
+
Tag(s): ${createdTags?.length ? createdTags.join(", ") : "None"}
|
|
3708
4373
|
Pushed: ${config.release.push ? "Yes" : "Disabled"}
|
|
3709
4374
|
Published packages: ${config.release.publish ? publishedPackageCount : "Disabled"}
|
|
3710
|
-
|
|
4375
|
+
Provider release: ${providerDisplay}
|
|
4376
|
+
Social media: ${socialDisplay}
|
|
3711
4377
|
Git provider: ${provider}`);
|
|
3712
4378
|
await executeHook("success:release", config, dryRun);
|
|
3713
4379
|
} catch (error) {
|
|
@@ -3717,4 +4383,4 @@ Git provider: ${provider}`);
|
|
|
3717
4383
|
}
|
|
3718
4384
|
}
|
|
3719
4385
|
|
|
3720
|
-
export {
|
|
4386
|
+
export { getLastTag as $, rollbackModifiedFiles as A, getFirstCommit as B, getCurrentGitBranch as C, getCurrentGitRef as D, github as E, createGitlabRelease as F, gitlab as G, detectPackageManager as H, determinePublishTag as I, getPackagesToPublishInSelectiveMode as J, getPackagesToPublishInIndependentMode as K, getAuthCommand as L, publishPackage as M, readPackageJson as N, getRootPackage as O, readPackages as P, getPackages as Q, getPackageCommits as R, hasLernaJson as S, getSlackToken as T, formatChangelogForSlack as U, formatSlackMessage as V, postReleaseToSlack as W, extractChangelogSummary as X, getReleaseUrl as Y, getIndependentTag as Z, getLastStableTag as _, providerRelease as a, getLastRepoTag as a0, getLastPackageTag as a1, resolveTags as a2, getTwitterCredentials as a3, formatTweetMessage as a4, postReleaseToTwitter as a5, executeHook as a6, isInCI as a7, getCIName as a8, executeFormatCmd as a9, executeBuildCmd as aa, isBumpedPackage as ab, getPackagesOrBumpedPackages as ac, isGraduatingToStableBetweenVersion as ad, determineSemverChange as ae, determineReleaseType as af, writeVersion as ag, getPackageNewVersion as ah, updateLernaVersion as ai, extractVersionFromPackageTag as aj, isPrerelease as ak, isStableReleaseType as al, isPrereleaseReleaseType as am, isGraduating as an, getPreid as ao, isChangedPreid as ap, getBumpedPackageIndependently as aq, confirmBump as ar, getBumpedIndependentPackages as as, shouldFilterPrereleaseTags as at, extractVersionFromTag as au, isTagVersionCompatibleWithCurrent as av, bump as b, changelog as c, publishSafetyCheck as d, publish as e, social as f, generateChangelog as g, getDefaultConfig as h, defineConfig as i, getPackageDependencies as j, getDependentsOf as k, loadRelizyConfig as l, expandPackagesToBumpWithDependents as m, getGitStatus as n, checkGitStatusIfDirty as o, providerReleaseSafetyCheck as p, fetchGitTags as q, release as r, socialSafetyCheck as s, topologicalSort as t, detectGitProvider as u, parseGitRemoteUrl as v, writeChangelogToFile as w, getModifiedReleaseFilePatterns as x, createCommitAndTags as y, pushCommitAndTags as z };
|