diff --git a/README.md b/README.md index 5dafbd1..a575ea5 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,10 @@ CLI flag options: --sequential-init Avoid hypothetical concurrent initialization collisions. --first-parent Apply commit filtering to current branch only. --ignore-private Exclude private packages. True by default. - --ignore-packages Packages list to be ignored on bumping process (append to the ones that already exist at package.json workspaces) + --ignore-packages Packages list to be ignored on bumping process (append to the ones that already exist at package.json workspaces) --deps.bump Define deps version updating rule. Allowed: override, satisfy, inherit. --deps.release Define release type for dependent package if any of its deps changes. Supported values: patch, minor, major, inherit. + --deps.prefix Optional prefix to be attached to the next version if `--deps.bump` set to `override`. Supported values: '^' | '~'` | '' (empty string, default). --tag-format Format to use for creating tag names. Should include "name" and "version" vars. Default: "${name}@${version}" generates "package-name@1.0.0" --help Help info. diff --git a/bin/cli.js b/bin/cli.js index 1554050..b840817 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -18,6 +18,7 @@ const cli = meow( --first-parent Apply commit filtering to current branch only. --deps.bump Define deps version updating rule. Allowed: override, satisfy, inherit. --deps.release Define release type for dependent package if any of its deps changes. Supported values: patch, minor, major, inherit. + --deps.prefix Optional prefix to be attached to the next dep version if '--deps.bump' set to 'override'. Supported values: '^' | '~' | '' (empty string as default). --ignore-packages Packages list to be ignored on bumping process --ignore-private Exclude private packages. Enabled by default, pass 'no-ignore-private' to disable. --tag-format Format to use for creating tag names. Should include "name" and "version" vars. Default: "\${name}@\${version}" generates "package-name@1.0.0" @@ -56,6 +57,10 @@ const cli = meow( type: "string", default: "patch", }, + "deps.prefix": { + type: "string", + default: "", + }, ignorePrivate: { type: "boolean", default: true, diff --git a/lib/createInlinePluginCreator.js b/lib/createInlinePluginCreator.js index dd03817..d6f9c5c 100644 --- a/lib/createInlinePluginCreator.js +++ b/lib/createInlinePluginCreator.js @@ -92,7 +92,7 @@ function createInlinePluginCreator(packages, multiContext, flags) { pkg._analyzed = true; // Make sure type is "patch" if the package has any deps that have been changed. - pkg._nextType = resolveReleaseType(pkg, flags.deps.bump, flags.deps.release); + pkg._nextType = resolveReleaseType(pkg, flags.deps.bump, flags.deps.release, [], flags.deps.prefix); debug(debugPrefix, "commits analyzed"); debug(debugPrefix, `release type: ${pkg._nextType}`); diff --git a/lib/updateDeps.js b/lib/updateDeps.js index 55e0c56..cb61921 100644 --- a/lib/updateDeps.js +++ b/lib/updateDeps.js @@ -142,12 +142,13 @@ const _nextPreHighestVersion = (latestTag, lastVersion, pkgPreRelease) => { * @param {string|undefined} bumpStrategy Dependency resolution strategy: override, satisfy, inherit. * @param {string|undefined} releaseStrategy Release type triggered by deps updating: patch, minor, major, inherit. * @param {Package[]} ignore=[] Packages to ignore (to prevent infinite loops). + * @param {string} prefix Dependency version prefix to be attached if `bumpStrategy='override'`. ^ | ~ | '' (defaults to empty string) * @returns {string|undefined} Resolved release type. * @internal */ -const resolveReleaseType = (pkg, bumpStrategy = "override", releaseStrategy = "patch", ignore = []) => { +const resolveReleaseType = (pkg, bumpStrategy = "override", releaseStrategy = "patch", ignore = [], prefix = "") => { // NOTE This fn also updates pkg deps, so it must be invoked anyway. - const dependentReleaseType = getDependentRelease(pkg, bumpStrategy, releaseStrategy, ignore); + const dependentReleaseType = getDependentRelease(pkg, bumpStrategy, releaseStrategy, ignore, prefix); // Release type found by commitAnalyzer. if (pkg._nextType) { @@ -175,10 +176,11 @@ const resolveReleaseType = (pkg, bumpStrategy = "override", releaseStrategy = "p * @param {string} bumpStrategy Dependency resolution strategy: override, satisfy, inherit. * @param {string} releaseStrategy Release type triggered by deps updating: patch, minor, major, inherit. * @param {Package[]} ignore Packages to ignore (to prevent infinite loops). + * @param {string} prefix Dependency version prefix to be attached if `bumpStrategy='override'`. ^ | ~ | '' (defaults to empty string) * @returns {string|undefined} Returns the highest release type if found, undefined otherwise * @internal */ -const getDependentRelease = (pkg, bumpStrategy, releaseStrategy, ignore) => { +const getDependentRelease = (pkg, bumpStrategy, releaseStrategy, ignore, prefix) => { const severityOrder = ["patch", "minor", "major"]; const { localDeps, manifest = {} } = pkg; const lastVersion = pkg._lastRelease && pkg._lastRelease.version; @@ -190,7 +192,7 @@ const getDependentRelease = (pkg, bumpStrategy, releaseStrategy, ignore) => { return false; } - const resolvedVersion = resolveNextVersion(currentVersion, nextVersion, releaseStrategy); + const resolvedVersion = resolveNextVersion(currentVersion, nextVersion, releaseStrategy, prefix); if (currentVersion !== resolvedVersion) { scope[name] = resolvedVersion; return true; @@ -206,7 +208,7 @@ const getDependentRelease = (pkg, bumpStrategy, releaseStrategy, ignore) => { // Has changed if... // 1. Any local dep package itself has changed // 2. Any local dep package has local deps that have changed. - const nextType = resolveReleaseType(p, bumpStrategy, releaseStrategy,[...ignore, pkg]); + const nextType = resolveReleaseType(p, bumpStrategy, releaseStrategy,[...ignore, pkg], prefix); const nextVersion = nextType // Update the nextVersion only if there is a next type to be bumped @@ -214,10 +216,9 @@ const getDependentRelease = (pkg, bumpStrategy, releaseStrategy, ignore) => { // Set the nextVersion fallback to the last local dependency package last version : p._lastRelease && p._lastRelease.version - // 3. And this change should correspond to manifest updating rule. + // 3. And this change should correspond to the manifest updating rule. const requireRelease = scopes .reduce((res, scope) => bumpDependency(scope, p.name, nextVersion) || res, !lastVersion) - return requireRelease && (severityOrder.indexOf(nextType) > severityOrder.indexOf(releaseType)) ? nextType : releaseType; @@ -230,10 +231,11 @@ const getDependentRelease = (pkg, bumpStrategy, releaseStrategy, ignore) => { * @param {string} currentVersion Current dep version * @param {string} nextVersion Next release type: patch, minor, major * @param {string|undefined} strategy Resolution strategy: inherit, override, satisfy + * @param {string} prefix Dependency version prefix to be attached if `bumpStrategy='override'`. ^ | ~ | '' (defaults to empty string) * @returns {string} Next dependency version * @internal */ -const resolveNextVersion = (currentVersion, nextVersion, strategy = "override") => { +const resolveNextVersion = (currentVersion, nextVersion, strategy = "override", prefix = "") => { // Check the next pkg version against its current references. // If it matches (`*` matches to any, `1.1.0` matches `1.1.x`, `1.5.0` matches to `^1.0.0` and so on) // release will not be triggered, if not `override` strategy will be applied instead. @@ -260,7 +262,7 @@ const resolveNextVersion = (currentVersion, nextVersion, strategy = "override") // "override" // By default next package version would be set as is for the all dependants. - return nextVersion; + return prefix + nextVersion; }; /** diff --git a/test/lib/updateDeps.test.js b/test/lib/updateDeps.test.js index 0bd8470..fa7e8c8 100644 --- a/test/lib/updateDeps.test.js +++ b/test/lib/updateDeps.test.js @@ -148,6 +148,34 @@ describe("resolveReleaseType()", () => { }); }); +it("`override` + `prefix` injects carets to the manifest", () => { + const pkgB = { name: "b", _nextType: false, localDeps: [], _lastRelease: { version: "1.0.0" } }; + const pkgC = { name: "c", _nextType: "minor", localDeps: [], _lastRelease: { version: "1.0.0" } }; + const pkgD = { name: "d", _nextType: "patch", localDeps: [], _lastRelease: { version: "1.0.0" } }; + const pkgA = { + name: "a", + manifest: { dependencies: { b: "1.0.0", c: "1.0.0", d: "1.0.0" } }, + _nextType: false, + localDeps: [pkgB, pkgC, pkgD], + }; + const pkg = { + name: "root", + manifest: { dependencies: { a: "1.0.0" } }, + _nextType: undefined, + localDeps: [pkgA], + }; + + const type = resolveReleaseType(pkg, "override", "patch", [], "^"); + + expect(type).toBe("patch"); + expect(pkg._nextType).toBe("patch"); + + expect(pkg.manifest.dependencies.a).toBe("^1.0.0"); + expect(pkgA.manifest.dependencies.b).toBe("^1.0.0"); + expect(pkgA.manifest.dependencies.c).toBe("^1.1.0"); + expect(pkgA.manifest.dependencies.d).toBe("^1.0.1"); +}); + describe("getNextVersion()", () => { // prettier-ignore const cases = [