package-versioner 0.7.1 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -6
- package/dist/index.cjs +358 -134
- package/dist/index.js +358 -134
- package/docs/versioning.md +182 -16
- package/package-versioner.schema.json +10 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -105,7 +105,23 @@ function extractChangelogEntriesFromCommits(projectDir, revisionRange) {
|
|
|
105
105
|
const commits = output.split("---COMMIT_DELIMITER---").filter((commit) => commit.trim() !== "");
|
|
106
106
|
return commits.map((commit) => parseCommitMessage(commit)).filter((entry) => entry !== null);
|
|
107
107
|
} catch (error) {
|
|
108
|
-
|
|
108
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
109
|
+
if (errorMessage.includes("ambiguous argument") && errorMessage.includes("unknown revision")) {
|
|
110
|
+
const tagName = revisionRange.split("..")[0] || revisionRange;
|
|
111
|
+
if (tagName.startsWith("v") && !tagName.includes("@")) {
|
|
112
|
+
log(
|
|
113
|
+
`Error: Tag "${tagName}" not found. If you're using package-specific tags (like "package-name@v1.0.0"), you may need to configure "tagTemplate" in your version.config.json to use: \${packageName}@\${prefix}\${version}`,
|
|
114
|
+
"error"
|
|
115
|
+
);
|
|
116
|
+
} else {
|
|
117
|
+
log(
|
|
118
|
+
`Error: Tag or revision "${tagName}" not found in the repository. Please check if this tag exists or if you need to fetch it from the remote.`,
|
|
119
|
+
"error"
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
log(`Error extracting commits: ${errorMessage}`, "error");
|
|
124
|
+
}
|
|
109
125
|
return [];
|
|
110
126
|
}
|
|
111
127
|
}
|
|
@@ -750,43 +766,48 @@ async function createGitCommitAndTag(files, nextTag, commitMessage, skipHooks, d
|
|
|
750
766
|
|
|
751
767
|
// src/git/tagsAndBranches.ts
|
|
752
768
|
import { getSemverTags } from "git-semver-tags";
|
|
769
|
+
import semver from "semver";
|
|
753
770
|
|
|
754
771
|
// src/utils/formatting.ts
|
|
755
772
|
function escapeRegExp(string) {
|
|
756
773
|
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
757
774
|
}
|
|
758
|
-
function
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
if (
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
}
|
|
775
|
-
function formatCommitMessage(template, version, packageName, scope) {
|
|
776
|
-
return createTemplateString(template, {
|
|
777
|
-
version,
|
|
778
|
-
scope,
|
|
779
|
-
packageName: packageName || ""
|
|
780
|
-
});
|
|
775
|
+
function formatVersionPrefix(prefix) {
|
|
776
|
+
return prefix.endsWith("/") ? prefix.slice(0, -1) : prefix;
|
|
777
|
+
}
|
|
778
|
+
function formatTag(version, prefix, packageName, template, packageSpecificTags) {
|
|
779
|
+
if ((template == null ? void 0 : template.includes("${packageName}")) && !packageName) {
|
|
780
|
+
log(
|
|
781
|
+
'Warning: Your tagTemplate contains ${packageName} but no package name is available.\nThis will result in an empty package name in the tag (e.g., "@v1.0.0" instead of "my-package@v1.0.0").\n\nTo fix this:\n\u2022 If using synced mode: Set "packageSpecificTags": true in your config to enable package names in tags\n\u2022 If you want global tags: Remove ${packageName} from your tagTemplate (e.g., use "${prefix}${version}")\n\u2022 If using single/async mode: Ensure your package.json has a valid "name" field',
|
|
782
|
+
"warning"
|
|
783
|
+
);
|
|
784
|
+
}
|
|
785
|
+
if (template) {
|
|
786
|
+
return template.replace(/\$\{version\}/g, version).replace(/\$\{prefix\}/g, prefix).replace(/\$\{packageName\}/g, packageName || "");
|
|
787
|
+
}
|
|
788
|
+
if (packageSpecificTags && packageName) {
|
|
789
|
+
return `${packageName}@${prefix}${version}`;
|
|
790
|
+
}
|
|
791
|
+
return `${prefix}${version}`;
|
|
781
792
|
}
|
|
782
|
-
function
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
793
|
+
function formatCommitMessage(template, version, packageName, additionalContext) {
|
|
794
|
+
if (template.includes("${packageName}") && !packageName) {
|
|
795
|
+
log(
|
|
796
|
+
'Warning: Your commitMessage template contains ${packageName} but no package name is available.\nThis will result in an empty package name in the commit message (e.g., "Release @v1.0.0").\n\nTo fix this:\n\u2022 If using synced mode: Set "packageSpecificTags": true to enable package names in commits\n\u2022 If you want generic commit messages: Remove ${packageName} from your commitMessage template\n\u2022 If using single/async mode: Ensure your package.json has a valid "name" field',
|
|
797
|
+
"warning"
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
let result = template.replace(/\$\{version\}/g, version).replace(/\$\{packageName\}/g, packageName || "");
|
|
801
|
+
if (additionalContext) {
|
|
802
|
+
for (const [key, value] of Object.entries(additionalContext)) {
|
|
803
|
+
const placeholder = `\${${key}}`;
|
|
804
|
+
result = result.replace(
|
|
805
|
+
new RegExp(placeholder.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"),
|
|
806
|
+
value
|
|
807
|
+
);
|
|
786
808
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
}, template);
|
|
809
|
+
}
|
|
810
|
+
return result;
|
|
790
811
|
}
|
|
791
812
|
|
|
792
813
|
// src/git/tagsAndBranches.ts
|
|
@@ -801,10 +822,29 @@ function getCommitsLength(pkgRoot) {
|
|
|
801
822
|
return 0;
|
|
802
823
|
}
|
|
803
824
|
}
|
|
804
|
-
async function getLatestTag() {
|
|
825
|
+
async function getLatestTag(versionPrefix) {
|
|
805
826
|
try {
|
|
806
|
-
const tags = await getSemverTags({
|
|
807
|
-
|
|
827
|
+
const tags = await getSemverTags({
|
|
828
|
+
tagPrefix: versionPrefix
|
|
829
|
+
});
|
|
830
|
+
if (tags.length === 0) {
|
|
831
|
+
return "";
|
|
832
|
+
}
|
|
833
|
+
const chronologicalLatest = tags[0];
|
|
834
|
+
const sortedTags = [...tags].sort((a, b) => {
|
|
835
|
+
const versionA = semver.clean(a) || "0.0.0";
|
|
836
|
+
const versionB = semver.clean(b) || "0.0.0";
|
|
837
|
+
return semver.rcompare(versionA, versionB);
|
|
838
|
+
});
|
|
839
|
+
const semanticLatest = sortedTags[0];
|
|
840
|
+
if (semanticLatest !== chronologicalLatest) {
|
|
841
|
+
log(
|
|
842
|
+
`Tag ordering differs: chronological latest is ${chronologicalLatest}, semantic latest is ${semanticLatest}`,
|
|
843
|
+
"debug"
|
|
844
|
+
);
|
|
845
|
+
log(`Using semantic latest (${semanticLatest}) to handle out-of-order tag creation`, "info");
|
|
846
|
+
}
|
|
847
|
+
return semanticLatest;
|
|
808
848
|
} catch (error) {
|
|
809
849
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
810
850
|
log(`Failed to get latest tag: ${errorMessage}`, "error");
|
|
@@ -829,56 +869,122 @@ async function lastMergeBranchName(branches, baseBranch) {
|
|
|
829
869
|
return null;
|
|
830
870
|
}
|
|
831
871
|
}
|
|
832
|
-
async function getLatestTagForPackage(packageName, versionPrefix) {
|
|
872
|
+
async function getLatestTagForPackage(packageName, versionPrefix, options) {
|
|
833
873
|
try {
|
|
874
|
+
const tagTemplate = (options == null ? void 0 : options.tagTemplate) || "${prefix}${version}";
|
|
875
|
+
const packageSpecificTags = (options == null ? void 0 : options.packageSpecificTags) ?? false;
|
|
834
876
|
const escapedPackageName = escapeRegExp(packageName);
|
|
877
|
+
const escapedPrefix = versionPrefix ? escapeRegExp(versionPrefix) : "";
|
|
835
878
|
log(
|
|
836
|
-
`Looking for tags for package ${packageName} with prefix ${versionPrefix || "none"}`,
|
|
879
|
+
`Looking for tags for package ${packageName} with prefix ${versionPrefix || "none"}, packageSpecificTags: ${packageSpecificTags}`,
|
|
837
880
|
"debug"
|
|
838
881
|
);
|
|
839
882
|
const allTags = await getSemverTags({
|
|
840
883
|
tagPrefix: versionPrefix
|
|
841
884
|
});
|
|
842
885
|
log(`Retrieved ${allTags.length} tags: ${allTags.join(", ")}`, "debug");
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
886
|
+
if (packageSpecificTags) {
|
|
887
|
+
const packageTagPattern = escapeRegExp(tagTemplate).replace(/\\\$\\\{packageName\\\}/g, `(?:${escapedPackageName})`).replace(/\\\$\\\{prefix\\\}/g, `(?:${escapedPrefix})`).replace(/\\\$\\\{version\\\}/g, "(?:[0-9]+\\.[0-9]+\\.[0-9]+(?:-[a-zA-Z0-9.-]+)?)");
|
|
888
|
+
log(`Using package tag pattern: ${packageTagPattern}`, "debug");
|
|
889
|
+
const packageTagRegex = new RegExp(`^${packageTagPattern}$`);
|
|
890
|
+
let packageTags = allTags.filter((tag) => packageTagRegex.test(tag));
|
|
847
891
|
if (packageTags.length > 0) {
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
"
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
892
|
+
const chronologicalFirst = packageTags[0];
|
|
893
|
+
const sortedPackageTags2 = [...packageTags].sort((a, b) => {
|
|
894
|
+
let versionA = "";
|
|
895
|
+
let versionB = "";
|
|
896
|
+
if (a.includes("@")) {
|
|
897
|
+
const afterAt = a.split("@")[1] || "";
|
|
898
|
+
versionA = afterAt.replace(new RegExp(`^${escapeRegExp(versionPrefix || "")}`), "");
|
|
899
|
+
} else {
|
|
900
|
+
versionA = a.replace(new RegExp(`^${escapeRegExp(packageName)}`), "").replace(new RegExp(`^${escapeRegExp(versionPrefix || "")}`), "");
|
|
901
|
+
}
|
|
902
|
+
if (b.includes("@")) {
|
|
903
|
+
const afterAtB = b.split("@")[1] || "";
|
|
904
|
+
versionB = afterAtB.replace(new RegExp(`^${escapeRegExp(versionPrefix || "")}`), "");
|
|
905
|
+
} else {
|
|
906
|
+
versionB = b.replace(new RegExp(`^${escapeRegExp(packageName)}`), "").replace(new RegExp(`^${escapeRegExp(versionPrefix || "")}`), "");
|
|
907
|
+
}
|
|
908
|
+
const cleanVersionA = semver.clean(versionA) || "0.0.0";
|
|
909
|
+
const cleanVersionB = semver.clean(versionB) || "0.0.0";
|
|
910
|
+
return semver.rcompare(cleanVersionA, cleanVersionB);
|
|
911
|
+
});
|
|
912
|
+
log(`Found ${packageTags.length} package tags using configured pattern`, "debug");
|
|
913
|
+
log(`Using semantically latest tag: ${sortedPackageTags2[0]}`, "debug");
|
|
914
|
+
if (sortedPackageTags2[0] !== chronologicalFirst) {
|
|
915
|
+
log(
|
|
916
|
+
`Package tag ordering differs: chronological first is ${chronologicalFirst}, semantic latest is ${sortedPackageTags2[0]}`,
|
|
917
|
+
"debug"
|
|
918
|
+
);
|
|
919
|
+
}
|
|
920
|
+
return sortedPackageTags2[0];
|
|
921
|
+
}
|
|
922
|
+
if (versionPrefix) {
|
|
923
|
+
const pattern1 = new RegExp(`^${escapedPackageName}@${escapeRegExp(versionPrefix)}`);
|
|
924
|
+
packageTags = allTags.filter((tag) => pattern1.test(tag));
|
|
925
|
+
if (packageTags.length > 0) {
|
|
926
|
+
const sortedPackageTags2 = [...packageTags].sort((a, b) => {
|
|
927
|
+
const afterAt = a.split("@")[1] || "";
|
|
928
|
+
const versionA = afterAt.replace(
|
|
929
|
+
new RegExp(`^${escapeRegExp(versionPrefix || "")}`),
|
|
930
|
+
""
|
|
931
|
+
);
|
|
932
|
+
const afterAtB = b.split("@")[1] || "";
|
|
933
|
+
const versionB = afterAtB.replace(
|
|
934
|
+
new RegExp(`^${escapeRegExp(versionPrefix || "")}`),
|
|
935
|
+
""
|
|
936
|
+
);
|
|
937
|
+
const cleanVersionA = semver.clean(versionA) || "0.0.0";
|
|
938
|
+
const cleanVersionB = semver.clean(versionB) || "0.0.0";
|
|
939
|
+
return semver.rcompare(cleanVersionA, cleanVersionB);
|
|
940
|
+
});
|
|
941
|
+
log(
|
|
942
|
+
`Found ${packageTags.length} package tags using pattern: packageName@${versionPrefix}...`,
|
|
943
|
+
"debug"
|
|
944
|
+
);
|
|
945
|
+
log(`Using semantically latest tag: ${sortedPackageTags2[0]}`, "debug");
|
|
946
|
+
return sortedPackageTags2[0];
|
|
947
|
+
}
|
|
854
948
|
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
949
|
+
if (versionPrefix) {
|
|
950
|
+
const pattern2 = new RegExp(`^${escapeRegExp(versionPrefix)}${escapedPackageName}@`);
|
|
951
|
+
packageTags = allTags.filter((tag) => pattern2.test(tag));
|
|
952
|
+
if (packageTags.length > 0) {
|
|
953
|
+
const sortedPackageTags2 = [...packageTags].sort((a, b) => {
|
|
954
|
+
const versionA = semver.clean(a.split("@")[1] || "") || "0.0.0";
|
|
955
|
+
const versionB = semver.clean(b.split("@")[1] || "") || "0.0.0";
|
|
956
|
+
return semver.rcompare(versionA, versionB);
|
|
957
|
+
});
|
|
958
|
+
log(
|
|
959
|
+
`Found ${packageTags.length} package tags using pattern: ${versionPrefix}packageName@...`,
|
|
960
|
+
"debug"
|
|
961
|
+
);
|
|
962
|
+
log(`Using semantically latest tag: ${sortedPackageTags2[0]}`, "debug");
|
|
963
|
+
return sortedPackageTags2[0];
|
|
964
|
+
}
|
|
866
965
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
966
|
+
const pattern3 = new RegExp(`^${escapedPackageName}@`);
|
|
967
|
+
packageTags = allTags.filter((tag) => pattern3.test(tag));
|
|
968
|
+
if (packageTags.length === 0) {
|
|
969
|
+
log("No matching tags found for pattern: packageName@version", "debug");
|
|
970
|
+
if (allTags.length > 0) {
|
|
971
|
+
log(`Available tags: ${allTags.join(", ")}`, "debug");
|
|
972
|
+
} else {
|
|
973
|
+
log("No tags available in the repository", "debug");
|
|
974
|
+
}
|
|
975
|
+
return "";
|
|
877
976
|
}
|
|
878
|
-
|
|
879
|
-
|
|
977
|
+
const sortedPackageTags = [...packageTags].sort((a, b) => {
|
|
978
|
+
const versionA = semver.clean(a.split("@")[1] || "") || "0.0.0";
|
|
979
|
+
const versionB = semver.clean(b.split("@")[1] || "") || "0.0.0";
|
|
980
|
+
return semver.rcompare(versionA, versionB);
|
|
981
|
+
});
|
|
982
|
+
log(`Found ${packageTags.length} package tags for ${packageName}`, "debug");
|
|
983
|
+
log(`Using semantically latest tag: ${sortedPackageTags[0]}`, "debug");
|
|
984
|
+
return sortedPackageTags[0];
|
|
880
985
|
}
|
|
881
|
-
|
|
986
|
+
log(`Package-specific tags disabled for ${packageName}, falling back to global tags`, "debug");
|
|
987
|
+
return "";
|
|
882
988
|
} catch (error) {
|
|
883
989
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
884
990
|
log(`Failed to get latest tag for package ${packageName}: ${errorMessage}`, "error");
|
|
@@ -981,6 +1087,7 @@ function updatePackageVersion(packagePath, version) {
|
|
|
981
1087
|
}
|
|
982
1088
|
|
|
983
1089
|
// src/package/packageProcessor.ts
|
|
1090
|
+
import { execSync as execSync4 } from "child_process";
|
|
984
1091
|
import * as fs8 from "fs";
|
|
985
1092
|
import path6 from "path";
|
|
986
1093
|
import { exit } from "process";
|
|
@@ -1313,7 +1420,7 @@ function capitalizeFirstLetter(input) {
|
|
|
1313
1420
|
// src/core/versionCalculator.ts
|
|
1314
1421
|
import { cwd as cwd3 } from "process";
|
|
1315
1422
|
import { Bumper } from "conventional-recommended-bump";
|
|
1316
|
-
import
|
|
1423
|
+
import semver3 from "semver";
|
|
1317
1424
|
|
|
1318
1425
|
// src/utils/manifestHelpers.ts
|
|
1319
1426
|
import fs6 from "fs";
|
|
@@ -1374,7 +1481,7 @@ function throwIfNoManifestsFound(packageDir) {
|
|
|
1374
1481
|
|
|
1375
1482
|
// src/utils/versionUtils.ts
|
|
1376
1483
|
import fs7 from "fs";
|
|
1377
|
-
import
|
|
1484
|
+
import semver2 from "semver";
|
|
1378
1485
|
import * as TOML2 from "smol-toml";
|
|
1379
1486
|
var STANDARD_BUMP_TYPES = ["major", "minor", "patch"];
|
|
1380
1487
|
function normalizePrereleaseIdentifier(prereleaseIdentifier, config) {
|
|
@@ -1387,58 +1494,116 @@ function normalizePrereleaseIdentifier(prereleaseIdentifier, config) {
|
|
|
1387
1494
|
return void 0;
|
|
1388
1495
|
}
|
|
1389
1496
|
function bumpVersion(currentVersion, bumpType, prereleaseIdentifier) {
|
|
1390
|
-
if (prereleaseIdentifier && STANDARD_BUMP_TYPES.includes(bumpType) && !
|
|
1497
|
+
if (prereleaseIdentifier && STANDARD_BUMP_TYPES.includes(bumpType) && !semver2.prerelease(currentVersion)) {
|
|
1391
1498
|
const preBumpType = `pre${bumpType}`;
|
|
1392
1499
|
log(
|
|
1393
1500
|
`Creating prerelease version with identifier '${prereleaseIdentifier}' using ${preBumpType}`,
|
|
1394
1501
|
"debug"
|
|
1395
1502
|
);
|
|
1396
|
-
return
|
|
1503
|
+
return semver2.inc(currentVersion, preBumpType, prereleaseIdentifier) || "";
|
|
1397
1504
|
}
|
|
1398
|
-
if (
|
|
1399
|
-
const parsed =
|
|
1505
|
+
if (semver2.prerelease(currentVersion) && STANDARD_BUMP_TYPES.includes(bumpType)) {
|
|
1506
|
+
const parsed = semver2.parse(currentVersion);
|
|
1400
1507
|
if (!parsed) {
|
|
1401
|
-
return
|
|
1508
|
+
return semver2.inc(currentVersion, bumpType) || "";
|
|
1402
1509
|
}
|
|
1403
1510
|
if (bumpType === "major" && parsed.minor === 0 && parsed.patch === 0 || bumpType === "minor" && parsed.patch === 0 || bumpType === "patch") {
|
|
1404
1511
|
log(`Cleaning prerelease identifier from ${currentVersion} for ${bumpType} bump`, "debug");
|
|
1405
1512
|
return `${parsed.major}.${parsed.minor}.${parsed.patch}`;
|
|
1406
1513
|
}
|
|
1407
1514
|
log(`Standard increment for ${currentVersion} with ${bumpType} bump`, "debug");
|
|
1408
|
-
return
|
|
1515
|
+
return semver2.inc(currentVersion, bumpType) || "";
|
|
1409
1516
|
}
|
|
1410
|
-
return
|
|
1517
|
+
return semver2.inc(currentVersion, bumpType, prereleaseIdentifier) || "";
|
|
1411
1518
|
}
|
|
1412
1519
|
|
|
1413
1520
|
// src/core/versionCalculator.ts
|
|
1414
1521
|
async function calculateVersion(config, options) {
|
|
1415
1522
|
const {
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
versionPrefix
|
|
1523
|
+
type: configType,
|
|
1524
|
+
preset = "angular",
|
|
1525
|
+
versionPrefix,
|
|
1526
|
+
prereleaseIdentifier: configPrereleaseIdentifier,
|
|
1419
1527
|
branchPattern,
|
|
1420
|
-
baseBranch
|
|
1421
|
-
|
|
1528
|
+
baseBranch
|
|
1529
|
+
} = config;
|
|
1530
|
+
const {
|
|
1531
|
+
latestTag,
|
|
1532
|
+
name,
|
|
1422
1533
|
path: pkgPath,
|
|
1423
|
-
|
|
1534
|
+
type: optionsType,
|
|
1535
|
+
prereleaseIdentifier: optionsPrereleaseIdentifier
|
|
1424
1536
|
} = options;
|
|
1425
|
-
const
|
|
1537
|
+
const type = optionsType || configType;
|
|
1538
|
+
const prereleaseIdentifier = optionsPrereleaseIdentifier || configPrereleaseIdentifier;
|
|
1426
1539
|
const initialVersion = "0.1.0";
|
|
1540
|
+
const hasNoTags = !latestTag || latestTag.trim() === "";
|
|
1427
1541
|
const normalizedPrereleaseId = normalizePrereleaseIdentifier(prereleaseIdentifier, config);
|
|
1428
1542
|
try {
|
|
1429
1543
|
let determineTagSearchPattern2 = function(packageName, prefix) {
|
|
1430
|
-
if (packageName) {
|
|
1431
|
-
|
|
1432
|
-
const escapedPrefix = escapeRegExp(prefix);
|
|
1433
|
-
return `${escapedPackageName}[@]?${escapedPrefix}`;
|
|
1544
|
+
if (!packageName) {
|
|
1545
|
+
return prefix;
|
|
1434
1546
|
}
|
|
1435
|
-
return
|
|
1547
|
+
return `${packageName}@${prefix}`;
|
|
1548
|
+
}, escapeRegExp3 = function(string) {
|
|
1549
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1436
1550
|
};
|
|
1437
|
-
var determineTagSearchPattern = determineTagSearchPattern2;
|
|
1438
|
-
const
|
|
1439
|
-
const originalPrefix = versionPrefix;
|
|
1551
|
+
var determineTagSearchPattern = determineTagSearchPattern2, escapeRegExp2 = escapeRegExp3;
|
|
1552
|
+
const originalPrefix = versionPrefix || "";
|
|
1440
1553
|
const tagSearchPattern = determineTagSearchPattern2(name, originalPrefix);
|
|
1441
|
-
const escapedTagPattern =
|
|
1554
|
+
const escapedTagPattern = escapeRegExp3(tagSearchPattern);
|
|
1555
|
+
if (!hasNoTags && pkgPath) {
|
|
1556
|
+
const packageDir = pkgPath || cwd3();
|
|
1557
|
+
const manifestResult = getVersionFromManifests(packageDir);
|
|
1558
|
+
if (manifestResult.manifestFound && manifestResult.version) {
|
|
1559
|
+
const cleanedTag = semver3.clean(latestTag) || latestTag;
|
|
1560
|
+
const tagVersion = semver3.clean(cleanedTag.replace(new RegExp(`^${escapedTagPattern}`), "")) || "0.0.0";
|
|
1561
|
+
const packageVersion = manifestResult.version;
|
|
1562
|
+
if (semver3.gt(packageVersion, tagVersion)) {
|
|
1563
|
+
log(
|
|
1564
|
+
`Warning: Version mismatch detected!
|
|
1565
|
+
\u2022 ${manifestResult.manifestType} version: ${packageVersion}
|
|
1566
|
+
\u2022 Latest Git tag version: ${tagVersion} (from ${latestTag})
|
|
1567
|
+
\u2022 Package version is AHEAD of Git tags
|
|
1568
|
+
|
|
1569
|
+
This usually happens when:
|
|
1570
|
+
\u2022 A version was released but the tag wasn't pushed to the remote repository
|
|
1571
|
+
\u2022 The ${manifestResult.manifestType} was manually updated without creating a corresponding tag
|
|
1572
|
+
\u2022 You're running in CI and the latest tag isn't available yet
|
|
1573
|
+
|
|
1574
|
+
The tool will use the Git tag version (${tagVersion}) as the base for calculation.
|
|
1575
|
+
Expected next version will be based on ${tagVersion}, not ${packageVersion}.
|
|
1576
|
+
|
|
1577
|
+
To fix this mismatch:
|
|
1578
|
+
\u2022 Push missing tags: git push origin --tags
|
|
1579
|
+
\u2022 Or use package version as base by ensuring tags are up to date`,
|
|
1580
|
+
"warning"
|
|
1581
|
+
);
|
|
1582
|
+
} else if (semver3.gt(tagVersion, packageVersion)) {
|
|
1583
|
+
log(
|
|
1584
|
+
`Warning: Version mismatch detected!
|
|
1585
|
+
\u2022 ${manifestResult.manifestType} version: ${packageVersion}
|
|
1586
|
+
\u2022 Latest Git tag version: ${tagVersion} (from ${latestTag})
|
|
1587
|
+
\u2022 Git tag version is AHEAD of package version
|
|
1588
|
+
|
|
1589
|
+
This usually happens when:
|
|
1590
|
+
\u2022 A release was tagged but the ${manifestResult.manifestType} wasn't updated
|
|
1591
|
+
\u2022 You're on an older branch that hasn't been updated with the latest version
|
|
1592
|
+
\u2022 Automated release process created tags but didn't update manifest files
|
|
1593
|
+
\u2022 You pulled tags but not the corresponding commits that update the package version
|
|
1594
|
+
|
|
1595
|
+
The tool will use the Git tag version (${tagVersion}) as the base for calculation.
|
|
1596
|
+
This will likely result in a version that's already been released.
|
|
1597
|
+
|
|
1598
|
+
To fix this mismatch:
|
|
1599
|
+
\u2022 Update ${manifestResult.manifestType}: Set version to ${tagVersion} or higher
|
|
1600
|
+
\u2022 Or checkout the branch/commit that corresponds to the tag
|
|
1601
|
+
\u2022 Or ensure your branch is up to date with the latest changes`,
|
|
1602
|
+
"warning"
|
|
1603
|
+
);
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1442
1607
|
const specifiedType = type;
|
|
1443
1608
|
if (specifiedType) {
|
|
1444
1609
|
if (hasNoTags) {
|
|
@@ -1450,9 +1615,9 @@ async function calculateVersion(config, options) {
|
|
|
1450
1615
|
initialVersion
|
|
1451
1616
|
);
|
|
1452
1617
|
}
|
|
1453
|
-
const cleanedTag =
|
|
1454
|
-
const currentVersion =
|
|
1455
|
-
if (STANDARD_BUMP_TYPES.includes(specifiedType) && (
|
|
1618
|
+
const cleanedTag = semver3.clean(latestTag) || latestTag;
|
|
1619
|
+
const currentVersion = semver3.clean(cleanedTag.replace(new RegExp(`^${escapedTagPattern}`), "")) || "0.0.0";
|
|
1620
|
+
if (STANDARD_BUMP_TYPES.includes(specifiedType) && (semver3.prerelease(currentVersion) || normalizedPrereleaseId)) {
|
|
1456
1621
|
log(
|
|
1457
1622
|
normalizedPrereleaseId ? `Creating prerelease version with identifier '${normalizedPrereleaseId}' using ${specifiedType}` : `Cleaning prerelease identifier from ${currentVersion} for ${specifiedType} bump`,
|
|
1458
1623
|
"debug"
|
|
@@ -1490,8 +1655,8 @@ async function calculateVersion(config, options) {
|
|
|
1490
1655
|
initialVersion
|
|
1491
1656
|
);
|
|
1492
1657
|
}
|
|
1493
|
-
const cleanedTag =
|
|
1494
|
-
const currentVersion =
|
|
1658
|
+
const cleanedTag = semver3.clean(latestTag) || latestTag;
|
|
1659
|
+
const currentVersion = semver3.clean(cleanedTag.replace(new RegExp(`^${escapedTagPattern}`), "")) || "0.0.0";
|
|
1495
1660
|
log(`Applying ${branchVersionType} bump based on branch pattern`, "debug");
|
|
1496
1661
|
return bumpVersion(currentVersion, branchVersionType, normalizedPrereleaseId);
|
|
1497
1662
|
}
|
|
@@ -1529,7 +1694,7 @@ async function calculateVersion(config, options) {
|
|
|
1529
1694
|
);
|
|
1530
1695
|
return "";
|
|
1531
1696
|
}
|
|
1532
|
-
const currentVersion =
|
|
1697
|
+
const currentVersion = semver3.clean(latestTag.replace(new RegExp(`^${escapedTagPattern}`), "")) || "0.0.0";
|
|
1533
1698
|
return bumpVersion(currentVersion, releaseTypeFromCommits, normalizedPrereleaseId);
|
|
1534
1699
|
} catch (error) {
|
|
1535
1700
|
log(`Failed to calculate version for ${name || "project"}`, "error");
|
|
@@ -1574,7 +1739,7 @@ function calculateNextVersion(version, manifestType, name, releaseType, prerelea
|
|
|
1574
1739
|
`No tags found for ${name || "package"}, using ${manifestType} version: ${version} as base`,
|
|
1575
1740
|
"info"
|
|
1576
1741
|
);
|
|
1577
|
-
if (STANDARD_BUMP_TYPES.includes(releaseType) && (
|
|
1742
|
+
if (STANDARD_BUMP_TYPES.includes(releaseType) && (semver3.prerelease(version) || prereleaseIdentifier)) {
|
|
1578
1743
|
log(
|
|
1579
1744
|
prereleaseIdentifier ? `Creating prerelease version with identifier '${prereleaseIdentifier}' using ${releaseType}` : `Cleaning prerelease identifier from ${version} for ${releaseType} bump`,
|
|
1580
1745
|
"debug"
|
|
@@ -1585,13 +1750,39 @@ function calculateNextVersion(version, manifestType, name, releaseType, prerelea
|
|
|
1585
1750
|
return result || initialVersion;
|
|
1586
1751
|
}
|
|
1587
1752
|
|
|
1753
|
+
// src/utils/packageMatching.ts
|
|
1754
|
+
function matchesPackageTarget(packageName, target) {
|
|
1755
|
+
if (packageName === target) {
|
|
1756
|
+
return true;
|
|
1757
|
+
}
|
|
1758
|
+
if (target.endsWith("/*")) {
|
|
1759
|
+
const scope = target.slice(0, -2);
|
|
1760
|
+
if (scope.startsWith("@")) {
|
|
1761
|
+
return packageName.startsWith(`${scope}/`);
|
|
1762
|
+
}
|
|
1763
|
+
return packageName.startsWith(`${scope}/`);
|
|
1764
|
+
}
|
|
1765
|
+
if (target === "*") {
|
|
1766
|
+
return true;
|
|
1767
|
+
}
|
|
1768
|
+
return false;
|
|
1769
|
+
}
|
|
1770
|
+
function shouldProcessPackage(packageName, targets = [], skip = []) {
|
|
1771
|
+
if (skip.includes(packageName)) {
|
|
1772
|
+
return false;
|
|
1773
|
+
}
|
|
1774
|
+
if (targets.length === 0) {
|
|
1775
|
+
return true;
|
|
1776
|
+
}
|
|
1777
|
+
return targets.some((target) => matchesPackageTarget(packageName, target));
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1588
1780
|
// src/package/packageProcessor.ts
|
|
1589
1781
|
var PackageProcessor = class {
|
|
1590
1782
|
skip;
|
|
1591
1783
|
targets;
|
|
1592
1784
|
versionPrefix;
|
|
1593
1785
|
tagTemplate;
|
|
1594
|
-
packageTagTemplate;
|
|
1595
1786
|
commitMessageTemplate;
|
|
1596
1787
|
dryRun;
|
|
1597
1788
|
skipHooks;
|
|
@@ -1604,7 +1795,6 @@ var PackageProcessor = class {
|
|
|
1604
1795
|
this.targets = options.targets || [];
|
|
1605
1796
|
this.versionPrefix = options.versionPrefix || "v";
|
|
1606
1797
|
this.tagTemplate = options.tagTemplate;
|
|
1607
|
-
this.packageTagTemplate = options.packageTagTemplate;
|
|
1608
1798
|
this.commitMessageTemplate = options.commitMessageTemplate || "";
|
|
1609
1799
|
this.dryRun = options.dryRun || false;
|
|
1610
1800
|
this.skipHooks = options.skipHooks || false;
|
|
@@ -1632,18 +1822,15 @@ var PackageProcessor = class {
|
|
|
1632
1822
|
const pkgsToConsider = packages.filter((pkg) => {
|
|
1633
1823
|
var _a2;
|
|
1634
1824
|
const pkgName = pkg.packageJson.name;
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
const isTargeted = this.targets.includes(pkgName);
|
|
1643
|
-
if (!isTargeted) {
|
|
1644
|
-
log(`Package ${pkgName} not in target list, skipping.`, "info");
|
|
1825
|
+
const shouldProcess = shouldProcessPackage(pkgName, this.targets, this.skip);
|
|
1826
|
+
if (!shouldProcess) {
|
|
1827
|
+
if ((_a2 = this.skip) == null ? void 0 : _a2.includes(pkgName)) {
|
|
1828
|
+
log(`Skipping package ${pkgName} as it's in the skip list.`, "info");
|
|
1829
|
+
} else {
|
|
1830
|
+
log(`Package ${pkgName} not in target list, skipping.`, "info");
|
|
1831
|
+
}
|
|
1645
1832
|
}
|
|
1646
|
-
return
|
|
1833
|
+
return shouldProcess;
|
|
1647
1834
|
});
|
|
1648
1835
|
log(`Found ${pkgsToConsider.length} targeted package(s) to process after filtering.`, "info");
|
|
1649
1836
|
if (pkgsToConsider.length === 0) {
|
|
@@ -1656,7 +1843,10 @@ var PackageProcessor = class {
|
|
|
1656
1843
|
const formattedPrefix = formatVersionPrefix(this.versionPrefix);
|
|
1657
1844
|
let latestTagResult = "";
|
|
1658
1845
|
try {
|
|
1659
|
-
latestTagResult = await getLatestTagForPackage(name, this.versionPrefix
|
|
1846
|
+
latestTagResult = await getLatestTagForPackage(name, this.versionPrefix, {
|
|
1847
|
+
tagTemplate: this.tagTemplate,
|
|
1848
|
+
packageSpecificTags: this.fullConfig.packageSpecificTags
|
|
1849
|
+
});
|
|
1660
1850
|
} catch (error) {
|
|
1661
1851
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1662
1852
|
log(
|
|
@@ -1710,7 +1900,24 @@ var PackageProcessor = class {
|
|
|
1710
1900
|
if (this.fullConfig.updateChangelog !== false) {
|
|
1711
1901
|
let changelogEntries = [];
|
|
1712
1902
|
try {
|
|
1713
|
-
|
|
1903
|
+
let revisionRange = latestTag;
|
|
1904
|
+
if (latestTag) {
|
|
1905
|
+
try {
|
|
1906
|
+
execSync4(`git rev-parse --verify "${latestTag}"`, {
|
|
1907
|
+
cwd: pkgPath,
|
|
1908
|
+
stdio: "ignore"
|
|
1909
|
+
});
|
|
1910
|
+
} catch {
|
|
1911
|
+
log(
|
|
1912
|
+
`Tag ${latestTag} doesn't exist, using recent commits from HEAD for changelog`,
|
|
1913
|
+
"debug"
|
|
1914
|
+
);
|
|
1915
|
+
revisionRange = "HEAD~10..HEAD";
|
|
1916
|
+
}
|
|
1917
|
+
} else {
|
|
1918
|
+
revisionRange = "HEAD~10..HEAD";
|
|
1919
|
+
}
|
|
1920
|
+
changelogEntries = extractChangelogEntriesFromCommits(pkgPath, revisionRange);
|
|
1714
1921
|
if (changelogEntries.length === 0) {
|
|
1715
1922
|
changelogEntries = [
|
|
1716
1923
|
{
|
|
@@ -1788,7 +1995,7 @@ var PackageProcessor = class {
|
|
|
1788
1995
|
this.versionPrefix,
|
|
1789
1996
|
name,
|
|
1790
1997
|
this.tagTemplate,
|
|
1791
|
-
this.
|
|
1998
|
+
this.fullConfig.packageSpecificTags
|
|
1792
1999
|
);
|
|
1793
2000
|
const tagMessage = `chore(release): ${name} ${nextVersion}`;
|
|
1794
2001
|
addTag(packageTag);
|
|
@@ -1874,16 +2081,9 @@ var PackageProcessor = class {
|
|
|
1874
2081
|
};
|
|
1875
2082
|
|
|
1876
2083
|
// src/core/versionStrategies.ts
|
|
1877
|
-
function
|
|
1878
|
-
var _a;
|
|
2084
|
+
function shouldProcessPackage2(pkg, config, targets = []) {
|
|
1879
2085
|
const pkgName = pkg.packageJson.name;
|
|
1880
|
-
|
|
1881
|
-
return false;
|
|
1882
|
-
}
|
|
1883
|
-
if (!targets || targets.length === 0) {
|
|
1884
|
-
return true;
|
|
1885
|
-
}
|
|
1886
|
-
return targets.includes(pkgName);
|
|
2086
|
+
return shouldProcessPackage(pkgName, targets, config.skip);
|
|
1887
2087
|
}
|
|
1888
2088
|
function createSyncedStrategy(config) {
|
|
1889
2089
|
return async (packages) => {
|
|
@@ -1939,6 +2139,7 @@ function createSyncedStrategy(config) {
|
|
|
1939
2139
|
}
|
|
1940
2140
|
const files = [];
|
|
1941
2141
|
const updatedPackages = [];
|
|
2142
|
+
const processedPaths = /* @__PURE__ */ new Set();
|
|
1942
2143
|
try {
|
|
1943
2144
|
if (packages.root) {
|
|
1944
2145
|
const rootPkgPath = path7.join(packages.root, "package.json");
|
|
@@ -1946,6 +2147,7 @@ function createSyncedStrategy(config) {
|
|
|
1946
2147
|
updatePackageVersion(rootPkgPath, nextVersion);
|
|
1947
2148
|
files.push(rootPkgPath);
|
|
1948
2149
|
updatedPackages.push("root");
|
|
2150
|
+
processedPaths.add(rootPkgPath);
|
|
1949
2151
|
}
|
|
1950
2152
|
} else {
|
|
1951
2153
|
log("Root package path is undefined, skipping root package.json update", "warning");
|
|
@@ -1955,13 +2157,17 @@ function createSyncedStrategy(config) {
|
|
|
1955
2157
|
log(`Failed to update root package.json: ${errMessage}`, "error");
|
|
1956
2158
|
}
|
|
1957
2159
|
for (const pkg of packages.packages) {
|
|
1958
|
-
if (!
|
|
2160
|
+
if (!shouldProcessPackage2(pkg, config)) {
|
|
1959
2161
|
continue;
|
|
1960
2162
|
}
|
|
1961
2163
|
const packageJsonPath = path7.join(pkg.dir, "package.json");
|
|
2164
|
+
if (processedPaths.has(packageJsonPath)) {
|
|
2165
|
+
continue;
|
|
2166
|
+
}
|
|
1962
2167
|
updatePackageVersion(packageJsonPath, nextVersion);
|
|
1963
2168
|
files.push(packageJsonPath);
|
|
1964
2169
|
updatedPackages.push(pkg.packageJson.name);
|
|
2170
|
+
processedPaths.add(packageJsonPath);
|
|
1965
2171
|
}
|
|
1966
2172
|
if (updatedPackages.length > 0) {
|
|
1967
2173
|
log(`Updated ${updatedPackages.length} package(s) to version ${nextVersion}`, "success");
|
|
@@ -1969,8 +2175,25 @@ function createSyncedStrategy(config) {
|
|
|
1969
2175
|
log("No packages were updated", "warning");
|
|
1970
2176
|
return;
|
|
1971
2177
|
}
|
|
1972
|
-
|
|
1973
|
-
|
|
2178
|
+
let tagPackageName = null;
|
|
2179
|
+
let commitPackageName = void 0;
|
|
2180
|
+
if (config.packageSpecificTags && packages.packages.length === 1) {
|
|
2181
|
+
tagPackageName = packages.packages[0].packageJson.name;
|
|
2182
|
+
commitPackageName = packages.packages[0].packageJson.name;
|
|
2183
|
+
}
|
|
2184
|
+
const nextTag = formatTag(
|
|
2185
|
+
nextVersion,
|
|
2186
|
+
formattedPrefix,
|
|
2187
|
+
tagPackageName,
|
|
2188
|
+
tagTemplate,
|
|
2189
|
+
config.packageSpecificTags || false
|
|
2190
|
+
);
|
|
2191
|
+
const formattedCommitMessage = formatCommitMessage(
|
|
2192
|
+
commitMessage,
|
|
2193
|
+
nextVersion,
|
|
2194
|
+
commitPackageName,
|
|
2195
|
+
void 0
|
|
2196
|
+
);
|
|
1974
2197
|
await createGitCommitAndTag(files, nextTag, formattedCommitMessage, skipHooks, dryRun);
|
|
1975
2198
|
} catch (error) {
|
|
1976
2199
|
if (error instanceof VersionError || error instanceof GitError) {
|
|
@@ -1991,7 +2214,6 @@ function createSingleStrategy(config) {
|
|
|
1991
2214
|
mainPackage,
|
|
1992
2215
|
versionPrefix,
|
|
1993
2216
|
tagTemplate,
|
|
1994
|
-
packageTagTemplate,
|
|
1995
2217
|
commitMessage = "chore(release): ${version}",
|
|
1996
2218
|
dryRun,
|
|
1997
2219
|
skipHooks
|
|
@@ -2013,7 +2235,10 @@ function createSingleStrategy(config) {
|
|
|
2013
2235
|
}
|
|
2014
2236
|
const pkgPath = pkg.dir;
|
|
2015
2237
|
const formattedPrefix = formatVersionPrefix(versionPrefix || "v");
|
|
2016
|
-
let latestTagResult = await getLatestTagForPackage(packageName, formattedPrefix
|
|
2238
|
+
let latestTagResult = await getLatestTagForPackage(packageName, formattedPrefix, {
|
|
2239
|
+
tagTemplate,
|
|
2240
|
+
packageSpecificTags: config.packageSpecificTags
|
|
2241
|
+
});
|
|
2017
2242
|
if (!latestTagResult) {
|
|
2018
2243
|
const globalTagResult = await getLatestTag();
|
|
2019
2244
|
latestTagResult = globalTagResult || "";
|
|
@@ -2044,7 +2269,7 @@ function createSingleStrategy(config) {
|
|
|
2044
2269
|
formattedPrefix,
|
|
2045
2270
|
packageName,
|
|
2046
2271
|
tagTemplate,
|
|
2047
|
-
|
|
2272
|
+
config.packageSpecificTags
|
|
2048
2273
|
);
|
|
2049
2274
|
const formattedCommitMessage = formatCommitMessage(commitMessage, nextVersion, packageName);
|
|
2050
2275
|
await createGitCommitAndTag(
|
|
@@ -2077,7 +2302,6 @@ function createAsyncStrategy(config) {
|
|
|
2077
2302
|
targets: config.packages || [],
|
|
2078
2303
|
versionPrefix: config.versionPrefix || "v",
|
|
2079
2304
|
tagTemplate: config.tagTemplate,
|
|
2080
|
-
packageTagTemplate: config.packageTagTemplate,
|
|
2081
2305
|
commitMessageTemplate: config.commitMessage || "",
|
|
2082
2306
|
dryRun: config.dryRun || false,
|
|
2083
2307
|
skipHooks: config.skipHooks || false,
|