Skip to content

Commit

Permalink
perf: refactor nextPreVersion to reduce cognitive complexity (qiwi#35)
Browse files Browse the repository at this point in the history
  • Loading branch information
davikawasaki committed Jan 5, 2021
1 parent ef1208a commit 601bbd3
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 25 deletions.
70 changes: 46 additions & 24 deletions lib/updateDeps.js
Expand Up @@ -35,26 +35,36 @@ const getNextPreVersion = (pkg, tags) => {
const lastVersion = pkg._lastRelease && pkg._lastRelease.version;
const version = `1.0.0-${pkg._preRelease}.1`;

// Extract tags:
// 1. Set filter to extract only package tags
// 2. Get tags from a branch considering the filters established
// TODO: replace {cwd: '.'} with multiContext.cwd
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;
const lastPreRelTag = getPreReleaseTag(lastVersion);
const isNewPreRelTag = lastPreRelTag && lastPreRelTag !== pkg._preRelease;

// 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 isNewPreRelTag || !lastVersion
? `1.0.0-${pkg._preRelease}.1`
: _nextPreVersionCases(tags, lastVersion, pkg._nextType, pkg._preRelease);
};

return version;
/**
* Parse the prerelease tag from a semver version.
*
* @param {string} version Semver version in a string format.
* @returns {string|null} preReleaseTag Version prerelease tag or null.
* @internal
*/
const getPreReleaseTag = (version) => {
const parsed = semver.parse(version);
if (!parsed) return null;
return parsed.prerelease[0] || null;
};

/**
* Resolve next prerelease highest version from tags or major/minor/patch.
* Resolve next prerelease special cases: 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.
Expand All @@ -63,21 +73,32 @@ const getNextPreVersion = (pkg, tags) => {
* @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 _nextPreVersionCases = (tags, lastVersion, pkgNextType, pkgPreRelease) => {
// Case 1: Normal release on last version and is now converted to a prerelease
if (!semver.prerelease(lastVersion)) {
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`;
}

// Case 2: Validates version with tags
const latestTag = getLatestVersion(tags, { withPrerelease: true });
return _nextPreHighestVersion(latestTag, lastVersion, pkgPreRelease);
};

/**
* Resolve next prerelease comparing bumped tags versions with last version.
*
* @param {string|null} latestTag Last released tag from branch or null if non-existent.
* @param {string} lastVersion Last version released.
* @param {string} pkgPreRelease Prerelease tag from package to-be-released.
* @returns {string} Next pkg version.
* @internal
*/
const _nextPreHighestVersion = (latestTag, lastVersion, pkgPreRelease) => {
const bumpFromTags = latestTag ? semver.inc(latestTag, "prerelease", pkgPreRelease) : null;
const bumpFromLast = semver.inc(lastVersion, "prerelease", pkgPreRelease);

return bumpFromTags ? getHighestVersion(bumpFromLast, bumpFromTags) : bumpFromLast;
};

/**
Expand Down Expand Up @@ -283,6 +304,7 @@ const auditManifestChanges = (actualManifest, path) => {
module.exports = {
getNextVersion,
getNextPreVersion,
getPreReleaseTag,
updateManifestDeps,
resolveReleaseType,
resolveNextVersion,
Expand Down
30 changes: 29 additions & 1 deletion test/lib/updateDeps.test.js
@@ -1,4 +1,10 @@
const { resolveReleaseType, resolveNextVersion, getNextVersion, getNextPreVersion } = require("../../lib/updateDeps");
const {
resolveReleaseType,
resolveNextVersion,
getNextVersion,
getNextPreVersion,
getPreReleaseTag,
} = require("../../lib/updateDeps");

describe("resolveNextVersion()", () => {
// prettier-ignore
Expand Down Expand Up @@ -197,3 +203,25 @@ describe("getNextPreVersion()", () => {
});
});
});

describe("getPreReleaseTag()", () => {
// prettier-ignore
const cases = [
[undefined, null],
[null, null],
["1.0.0-rc.0", "rc"],
["1.0.0-dev.0", "dev"],
["1.0.0-dev.2", "dev"],
["1.1.0-beta.0", "beta"],
["11.0.0", null],
["11.1.0", null],
["11.0.1", null],
]

cases.forEach(([version, preReleaseTag]) => {
it(`${version} gives ${preReleaseTag}`, () => {
// prettier-ignore
expect(getPreReleaseTag(version)).toBe(preReleaseTag);
});
});
});

0 comments on commit 601bbd3

Please sign in to comment.