Skip to content

Commit 6481a59

Browse files
authored
fix: local dependencies correct bump from release to prerelease (#34)
1 parent 3bfed38 commit 6481a59

File tree

9 files changed

+415
-10829
lines changed

9 files changed

+415
-10829
lines changed

lib/createInlinePluginCreator.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ function createInlinePluginCreator(packages, multiContext, synchronizer, flags)
8888
const analyzeCommits = async (pluginOptions, context) => {
8989
const firstParentBranch = flags.firstParent ? context.branch.name : undefined;
9090
pkg._preRelease = context.branch.prerelease || null;
91+
pkg._branch = context.branch.name;
9192

9293
// Filter commits by directory.
9394
commits = await getCommitsFiltered(cwd, dir, context.lastRelease.gitHead, firstParentBranch);

lib/git.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
const execa = require("execa");
2+
3+
/**
4+
* Get all the tags for a given branch.
5+
*
6+
* @param {String} branch The branch for which to retrieve the tags.
7+
* @param {Object} [execaOptions] Options to pass to `execa`.
8+
* @param {Array<String>} filters List of prefixes/sufixes to be checked inside tags.
9+
*
10+
* @return {Array<String>} List of git tags.
11+
* @throws {Error} If the `git` command fails.
12+
* @internal
13+
*/
14+
function getTags(branch, execaOptions, filters) {
15+
let tags = execa.sync("git", ["tag", "--merged", branch], execaOptions).stdout;
16+
tags = tags
17+
.split("\n")
18+
.map((tag) => tag.trim())
19+
.filter(Boolean);
20+
21+
if (!filters || !filters.length) return tags;
22+
23+
const validateSubstr = (t, f) => !!f.find((v) => t.includes(v));
24+
25+
return tags.filter((tag) => validateSubstr(tag, filters));
26+
}
27+
28+
module.exports = {
29+
getTags,
30+
};

lib/updateDeps.js

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ const semver = require("semver");
33
const { isObject, isEqual, transform } = require("lodash");
44
const recognizeFormat = require("./recognizeFormat");
55
const getManifest = require("./getManifest");
6+
const { getHighestVersion, getLatestVersion } = require("./utils");
7+
const { getTags } = require("./git");
68
const debug = require("debug")("msr:updateDeps");
79

810
/**
@@ -24,13 +26,58 @@ const getNextVersion = (pkg) => {
2426
* Resolve next package version on prereleases.
2527
*
2628
* @param {Package} pkg Package object.
29+
* @param {Array<string>} tags Override list of tags from specific pkg and branch.
2730
* @returns {string|undefined} Next pkg version.
2831
* @internal
2932
*/
30-
const getNextPreVersion = (pkg) => {
33+
const getNextPreVersion = (pkg, tags) => {
34+
const tagFilters = [pkg._preRelease];
3135
const lastVersion = pkg._lastRelease && pkg._lastRelease.version;
36+
const version = `1.0.0-${pkg._preRelease}.1`;
3237

33-
return lastVersion ? semver.inc(lastVersion, "prerelease", pkg._preRelease) : `1.0.0-${pkg._preRelease}.1`;
38+
if (pkg.name) tagFilters.push(pkg.name);
39+
if (!tags || !tags.length) tags = getTags(pkg._branch, { cwd: "." }, tagFilters);
40+
41+
if (lastVersion) {
42+
const { prerelease } = semver.parse(lastVersion);
43+
const lastPreRelTag = prerelease[0] || null;
44+
45+
// If there was a change in the prerelease tag (e.g. dev to rc), start semver from scratch with the new prerelease tag
46+
if (lastPreRelTag && lastPreRelTag !== pkg._preRelease) {
47+
return version;
48+
}
49+
50+
return _nextPreHighestVersion(tags, lastVersion, pkg._nextType, pkg._preRelease);
51+
}
52+
53+
return version;
54+
};
55+
56+
/**
57+
* Resolve next prerelease highest version from tags or major/minor/patch.
58+
*
59+
* @param {Array} tags List of all released tags from package.
60+
* @param {string} lastVersion Last package version released.
61+
* @param {string} pkgNextType Next type evaluated for the next package type.
62+
* @param {string} pkgPreRelease Package prerelease suffix.
63+
* @returns {string|undefined} Next pkg version.
64+
* @internal
65+
*/
66+
const _nextPreHighestVersion = (tags, lastVersion, pkgNextType, pkgPreRelease) => {
67+
if (semver.prerelease(lastVersion)) {
68+
const latestVerTags = getLatestVersion(tags, { withPrerelease: true });
69+
// Bump the latest version from tags if:
70+
// 1. There is a tag list and a latest version result from the list
71+
// 2. The last prerelease tag exists and is the same
72+
const bumpLatestVerTags = latestVerTags ? semver.inc(latestVerTags, "prerelease", pkgPreRelease) : null;
73+
const bumpLastVer = semver.inc(lastVersion, "prerelease", pkgPreRelease);
74+
75+
return bumpLatestVerTags ? getHighestVersion(bumpLastVer, bumpLatestVerTags) : bumpLastVer;
76+
} else {
77+
const { major, minor, patch } = semver.parse(lastVersion);
78+
// Case when last version was a normal release and now it needs to be a prerelease
79+
return `${semver.inc(`${major}.${minor}.${patch}`, pkgNextType || "patch")}-${pkgPreRelease}.1`;
80+
}
3481
};
3582

3683
/**

lib/utils.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* Lifted and tweaked from semantic-release because we follow how they bump their packages/dependencies.
3+
* https://github.com/semantic-release/semantic-release/blob/master/lib/utils.js
4+
*/
5+
6+
const { gt, lt, prerelease, rcompare } = require("semver");
7+
8+
/**
9+
* Get tag objects and convert them to a list of stringified versions.
10+
* @param {array} tags Tags as object list.
11+
* @returns {array} Tags as string list.
12+
* @internal
13+
*/
14+
function tagsToVersions(tags) {
15+
if (!tags) return [];
16+
return tags.map(({ version }) => version);
17+
}
18+
19+
/**
20+
* HOC that applies highest/lowest semver function.
21+
* @param {Function} predicate High order function to be called.
22+
* @param {string|undefined} version1 Version 1 to be compared with.
23+
* @param {string|undefined} version2 Version 2 to be compared with.
24+
* @returns {string|undefined} Highest or lowest version.
25+
* @internal
26+
*/
27+
const _selectVersionBy = (predicate, version1, version2) => {
28+
if (predicate && version1 && version2) {
29+
return predicate(version1, version2) ? version1 : version2;
30+
}
31+
return version1 || version2;
32+
};
33+
34+
/**
35+
* Gets highest semver function binding gt to the HOC selectVersionBy.
36+
*/
37+
const getHighestVersion = _selectVersionBy.bind(null, gt);
38+
39+
/**
40+
* Gets lowest semver function binding gt to the HOC selectVersionBy.
41+
*/
42+
const getLowestVersion = _selectVersionBy.bind(null, lt);
43+
44+
/**
45+
* Retrieve the latest version from a list of versions.
46+
* @param {array} versions Versions as string list.
47+
* @param {bool|undefined} withPrerelease Prerelease flag.
48+
* @returns {string|undefined} Latest version.
49+
* @internal
50+
*/
51+
function getLatestVersion(versions, withPrerelease) {
52+
return versions.filter((version) => withPrerelease || !prerelease(version)).sort(rcompare)[0];
53+
}
54+
55+
module.exports = {
56+
tagsToVersions,
57+
getHighestVersion,
58+
getLowestVersion,
59+
getLatestVersion,
60+
};

0 commit comments

Comments
 (0)