Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: local dependencies correct bump from release to prerelease #34

Merged
merged 19 commits into from
Jan 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
fd8fcad
feat(helpers/file): added file creation on list of folders
davikawasaki Dec 23, 2020
da7b781
feat(helpers/git): added release branch creation on git init origin e…
davikawasaki Dec 23, 2020
4850de3
feat(prerelease): enabled correct prerelease updates on dependencies
davikawasaki Dec 23, 2020
de5265e
chore(update-deps): reducing cognitive complexity
davikawasaki Dec 23, 2020
fa57c5a
test(update-deps): setting nextVersion as last param on test cases
davikawasaki Dec 23, 2020
eedf2f2
Merge branch 'master' of https://github.com/qiwi/multi-semantic-relea…
davikawasaki Dec 30, 2020
fc378b4
test: added fixture for 2 packages only
davikawasaki Dec 30, 2020
a8e40c8
chore: updated package lock
davikawasaki Dec 30, 2020
cadc3a8
fix: avoid local dep bump when it's not updated
davikawasaki Dec 30, 2020
d6b4ed2
chore: package update + changelog merge
davikawasaki Jan 4, 2021
54c7af8
feat: branch name available at pkg level
davikawasaki Jan 4, 2021
ac4962b
feat: git module to get filtered tags from a branch
davikawasaki Jan 4, 2021
7d299d8
feat: tweak utils from semantic-release
davikawasaki Jan 4, 2021
a654af5
fix: getNextPreVersion updated to cover edge cases
davikawasaki Jan 4, 2021
a1fedc7
test: covers semantic release on a release-prerelease branch change
davikawasaki Jan 4, 2021
2632492
chore: reducing code complexity
davikawasaki Jan 4, 2021
97c21aa
fix: refactor validateSubstr fn
davikawasaki Jan 5, 2021
5533a08
fix: refactor highest/lowest fn, fail fast on tagsToVersions
davikawasaki Jan 5, 2021
4f55c95
fix: reducing code cognitive complexity on getNextPreVersion
davikawasaki Jan 5, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/createInlinePluginCreator.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ function createInlinePluginCreator(packages, multiContext, synchronizer, flags)
const analyzeCommits = async (pluginOptions, context) => {
const firstParentBranch = flags.firstParent ? context.branch.name : undefined;
pkg._preRelease = context.branch.prerelease || null;
pkg._branch = context.branch.name;

// Filter commits by directory.
commits = await getCommitsFiltered(cwd, dir, context.lastRelease.gitHead, firstParentBranch);
Expand Down
30 changes: 30 additions & 0 deletions lib/git.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const execa = require("execa");

/**
* Get all the tags for a given branch.
*
* @param {String} branch The branch for which to retrieve the tags.
* @param {Object} [execaOptions] Options to pass to `execa`.
* @param {Array<String>} filters List of prefixes/sufixes to be checked inside tags.
*
* @return {Array<String>} List of git tags.
* @throws {Error} If the `git` command fails.
* @internal
*/
function getTags(branch, execaOptions, filters) {
let tags = execa.sync("git", ["tag", "--merged", branch], execaOptions).stdout;
tags = tags
.split("\n")
.map((tag) => tag.trim())
.filter(Boolean);

if (!filters || !filters.length) return tags;

const validateSubstr = (t, f) => !!f.find((v) => t.includes(v));

return tags.filter((tag) => validateSubstr(tag, filters));
}

module.exports = {
getTags,
};
51 changes: 49 additions & 2 deletions lib/updateDeps.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ const semver = require("semver");
const { isObject, isEqual, transform } = require("lodash");
const recognizeFormat = require("./recognizeFormat");
const getManifest = require("./getManifest");
const { getHighestVersion, getLatestVersion } = require("./utils");
const { getTags } = require("./git");
const debug = require("debug")("msr:updateDeps");

/**
Expand All @@ -24,13 +26,58 @@ const getNextVersion = (pkg) => {
* Resolve next package version on prereleases.
*
* @param {Package} pkg Package object.
* @param {Array<string>} tags Override list of tags from specific pkg and branch.
* @returns {string|undefined} Next pkg version.
* @internal
*/
const getNextPreVersion = (pkg) => {
const getNextPreVersion = (pkg, tags) => {
const tagFilters = [pkg._preRelease];
const lastVersion = pkg._lastRelease && pkg._lastRelease.version;
const version = `1.0.0-${pkg._preRelease}.1`;

return lastVersion ? semver.inc(lastVersion, "prerelease", pkg._preRelease) : `1.0.0-${pkg._preRelease}.1`;
if (pkg.name) tagFilters.push(pkg.name);
if (!tags || !tags.length) tags = getTags(pkg._branch, { cwd: "." }, tagFilters);

if (lastVersion) {
const { prerelease } = semver.parse(lastVersion);
const lastPreRelTag = prerelease[0] || null;

// If there was a change in the prerelease tag (e.g. dev to rc), start semver from scratch with the new prerelease tag
if (lastPreRelTag && lastPreRelTag !== pkg._preRelease) {
return version;
}

return _nextPreHighestVersion(tags, lastVersion, pkg._nextType, pkg._preRelease);
}

return version;
};

/**
* Resolve next prerelease highest version from tags or major/minor/patch.
*
* @param {Array} tags List of all released tags from package.
* @param {string} lastVersion Last package version released.
* @param {string} pkgNextType Next type evaluated for the next package type.
* @param {string} pkgPreRelease Package prerelease suffix.
* @returns {string|undefined} Next pkg version.
* @internal
*/
const _nextPreHighestVersion = (tags, lastVersion, pkgNextType, pkgPreRelease) => {
if (semver.prerelease(lastVersion)) {
const latestVerTags = getLatestVersion(tags, { withPrerelease: true });
// Bump the latest version from tags if:
// 1. There is a tag list and a latest version result from the list
// 2. The last prerelease tag exists and is the same
const bumpLatestVerTags = latestVerTags ? semver.inc(latestVerTags, "prerelease", pkgPreRelease) : null;
const bumpLastVer = semver.inc(lastVersion, "prerelease", pkgPreRelease);

return bumpLatestVerTags ? getHighestVersion(bumpLastVer, bumpLatestVerTags) : bumpLastVer;
} else {
const { major, minor, patch } = semver.parse(lastVersion);
// Case when last version was a normal release and now it needs to be a prerelease
return `${semver.inc(`${major}.${minor}.${patch}`, pkgNextType || "patch")}-${pkgPreRelease}.1`;
}
};

/**
Expand Down
60 changes: 60 additions & 0 deletions lib/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* Lifted and tweaked from semantic-release because we follow how they bump their packages/dependencies.
* https://github.com/semantic-release/semantic-release/blob/master/lib/utils.js
*/

const { gt, lt, prerelease, rcompare } = require("semver");

/**
* Get tag objects and convert them to a list of stringified versions.
* @param {array} tags Tags as object list.
* @returns {array} Tags as string list.
* @internal
*/
function tagsToVersions(tags) {
if (!tags) return [];
return tags.map(({ version }) => version);
}

/**
* HOC that applies highest/lowest semver function.
* @param {Function} predicate High order function to be called.
* @param {string|undefined} version1 Version 1 to be compared with.
* @param {string|undefined} version2 Version 2 to be compared with.
* @returns {string|undefined} Highest or lowest version.
* @internal
*/
const _selectVersionBy = (predicate, version1, version2) => {
if (predicate && version1 && version2) {
return predicate(version1, version2) ? version1 : version2;
}
return version1 || version2;
};

/**
* Gets highest semver function binding gt to the HOC selectVersionBy.
*/
const getHighestVersion = _selectVersionBy.bind(null, gt);

/**
* Gets lowest semver function binding gt to the HOC selectVersionBy.
*/
const getLowestVersion = _selectVersionBy.bind(null, lt);

/**
* Retrieve the latest version from a list of versions.
* @param {array} versions Versions as string list.
* @param {bool|undefined} withPrerelease Prerelease flag.
* @returns {string|undefined} Latest version.
* @internal
*/
function getLatestVersion(versions, withPrerelease) {
return versions.filter((version) => withPrerelease || !prerelease(version)).sort(rcompare)[0];
}

module.exports = {
tagsToVersions,
getHighestVersion,
getLowestVersion,
getLatestVersion,
};
Loading