From 601bbd35d969167c5b54cb0e8bad2be0a2165705 Mon Sep 17 00:00:00 2001 From: Davi Kawasaki Date: Tue, 5 Jan 2021 08:50:34 -0300 Subject: [PATCH] perf: refactor nextPreVersion to reduce cognitive complexity (#35) --- lib/updateDeps.js | 70 ++++++++++++++++++++++++------------- test/lib/updateDeps.test.js | 30 +++++++++++++++- 2 files changed, 75 insertions(+), 25 deletions(-) diff --git a/lib/updateDeps.js b/lib/updateDeps.js index 025e953..2475d79 100644 --- a/lib/updateDeps.js +++ b/lib/updateDeps.js @@ -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. @@ -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; }; /** @@ -283,6 +304,7 @@ const auditManifestChanges = (actualManifest, path) => { module.exports = { getNextVersion, getNextPreVersion, + getPreReleaseTag, updateManifestDeps, resolveReleaseType, resolveNextVersion, diff --git a/test/lib/updateDeps.test.js b/test/lib/updateDeps.test.js index 4f5cb72..7653ed8 100644 --- a/test/lib/updateDeps.test.js +++ b/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 @@ -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); + }); + }); +});