diff --git a/packages/bump-monorepo-packages/README.md b/packages/bump-monorepo-packages/README.md index 141ed7b4..a9c120f4 100644 --- a/packages/bump-monorepo-packages/README.md +++ b/packages/bump-monorepo-packages/README.md @@ -14,6 +14,8 @@ node scripts/bump-packages/bump-packages.js The "bump packages" commit message can be overriden by setting the `LAST_BUMP_COMMIT_MESSAGE` env var. By default is: `chore(ci): bump packages`. +Packages can be excluded from the automatic version bump by adding them to the `SKIP_BUMP_PACKAGES` env var. For example: `export SKIP_BUMP_PACKAGES="package1,package2"`. This can be used in case some of the packages are versioned manually. + ## What it does The command performs the following steps: diff --git a/packages/bump-monorepo-packages/src/bump-packages.js b/packages/bump-monorepo-packages/src/bump-packages.js index 6c2d8906..8ebe134d 100755 --- a/packages/bump-monorepo-packages/src/bump-packages.js +++ b/packages/bump-monorepo-packages/src/bump-packages.js @@ -17,6 +17,18 @@ const { PassThrough } = require('stream'); const LAST_BUMP_COMMIT_MESSAGE = process.env.LAST_BUMP_COMMIT_MESSAGE || 'chore(ci): bump packages'; +function shouldSkipPackage(packageName) { + const skippedPackages = (process.env.SKIP_BUMP_PACKAGES || '').split(','); + const shouldSkip = skippedPackages.includes(packageName); + + console.log('Should skip', packageName, { + packages: skippedPackages, + shouldSkip, + }); + + return shouldSkip; +} + async function main() { try { await fs.stat('./package.json'); @@ -81,7 +93,7 @@ async function getCommits({ path, range }) { function updateDeps(packageJson, newVersions) { console.debug(`[${packageJson.name}]`, 'updateDeps', newVersions); - const newPackageJson = { ...packageJson }; + const newPackageJson = JSON.parse(JSON.stringify(packageJson)); let inc; @@ -119,7 +131,20 @@ function updateDeps(packageJson, newVersions) { version ); - dependenciesSection[depName] = version; + const oldDepRange = dependenciesSection[depName]; + + // we try to preserve some of the ranges specified in the + // original package.json as that may be useful for external dependants. + // The default for ranges we can't recognize is a caret range. + const newDepRange = /^\d\.\d\.\d/.exec(oldDepRange) + ? version + : oldDepRange === '*' + ? '*' + : oldDepRange.startsWith('~') + ? `~${version}` + : `^${version}`; + + dependenciesSection[depName] = newDepRange; // we increment the package version based on the bump on dependencies: // if a devDependency was bumped, regardless of the increment we increment of a @@ -232,24 +257,27 @@ async function processPackage(packagePath, newVersions, options) { const packageJsonAfterDepBump = updateDeps(packageJson, newVersions); - const conventionalVersion = await bumpVersionBasedOnCommits( - packagePath, - packageJson.version, - options - ); + let newVersion = packageJson.version; + + // if the package is in the skip list we still update its dependencies + // but we keep its version to the old one + if (!shouldSkipPackage(packageJson.name)) { + const conventionalVersion = await bumpVersionBasedOnCommits( + packagePath, + packageJson.version, + options + ); + + newVersion = semver.gt(conventionalVersion, packageJsonAfterDepBump.version) + ? conventionalVersion + : packageJsonAfterDepBump.version; - const newVersion = semver.gt( - conventionalVersion, - packageJsonAfterDepBump.version - ) - ? conventionalVersion - : packageJsonAfterDepBump.version; - - if (semver.gt(newVersion, packageJson.version)) { - newVersions[packageJson.name] = { - version: newVersion, - bump: semver.diff(newVersion, packageJson.version), - }; + if (semver.gt(newVersion, packageJson.version)) { + newVersions[packageJson.name] = { + version: newVersion, + bump: semver.diff(newVersion, packageJson.version), + }; + } } const newPackageJson = { ...packageJsonAfterDepBump, version: newVersion }; diff --git a/packages/bump-monorepo-packages/src/bump-packages.spec.js b/packages/bump-monorepo-packages/src/bump-packages.spec.js index 7a2c07b2..b09a9a75 100644 --- a/packages/bump-monorepo-packages/src/bump-packages.spec.js +++ b/packages/bump-monorepo-packages/src/bump-packages.spec.js @@ -268,4 +268,85 @@ describe('bump-packages', function () { require('./fixtures/bump-package-1-breaking.json') ); }); + + it('skips bumping packages listed in SKIP_BUMP_PACKAGES', function () { + const skipBkp = process.env.SKIP_BUMP_PACKAGES; + try { + process.env.SKIP_BUMP_PACKAGES = 'package6'; + makeBumpCommit(); + commitPackageChange('package5', 'chore: some change'); + commitPackageChange('package6', 'chore: some change'); + runBumpVersion(); + const manifests = readAllManifests(); + assert.deepStrictEqual( + manifests, + require('./fixtures/skip-packages.json') + ); + } finally { + process.env.SKIP_BUMP_PACKAGES = skipBkp; + } + }); + + it('skips bumping packages listed in SKIP_BUMP_PACKAGES, keeps other bumps', function () { + const skipBkp = process.env.SKIP_BUMP_PACKAGES; + try { + process.env.SKIP_BUMP_PACKAGES = 'package5'; + makeBumpCommit(); + commitPackageChange('package5', 'chore: some change'); + commitPackageChange('package6', 'chore: some change'); + runBumpVersion(); + const manifests = readAllManifests(); + assert.deepStrictEqual( + manifests, + require('./fixtures/skip-packages-keep-unskipped.json') + ); + } finally { + process.env.SKIP_BUMP_PACKAGES = skipBkp; + } + }); + + it('preserves caret ranges', function () { + addPackage({ + name: 'package7', + devDependencies: { package6: '^1.0.0' }, + }); + + makeBumpCommit(); + commitPackageChange('package6', 'chore: some change'); + runBumpVersion(); + const manifests = readAllManifests(); + assert.deepStrictEqual( + manifests, + require('./fixtures/preserve-caret.json') + ); + }); + + it('preserves tilde ranges', function () { + addPackage({ + name: 'package7', + devDependencies: { package6: '~1.0.0' }, + }); + + makeBumpCommit(); + commitPackageChange('package6', 'chore: some change'); + runBumpVersion(); + const manifests = readAllManifests(); + assert.deepStrictEqual( + manifests, + require('./fixtures/preserve-tilde.json') + ); + }); + + it('preserves star ranges', function () { + addPackage({ + name: 'package7', + devDependencies: { package6: '*' }, + }); + + makeBumpCommit(); + commitPackageChange('package6', 'chore: some change'); + runBumpVersion(); + const manifests = readAllManifests(); + assert.deepStrictEqual(manifests, require('./fixtures/preserve-star.json')); + }); }); diff --git a/packages/bump-monorepo-packages/src/fixtures/preserve-caret.json b/packages/bump-monorepo-packages/src/fixtures/preserve-caret.json new file mode 100644 index 00000000..7341c757 --- /dev/null +++ b/packages/bump-monorepo-packages/src/fixtures/preserve-caret.json @@ -0,0 +1,163 @@ +{ + "package1": { + "version": "1.0.0", + "name": "package1" + }, + "package2": { + "version": "1.0.0", + "name": "package2", + "devDependencies": { + "package1": "1.0.0" + } + }, + "package3": { + "version": "1.0.0", + "name": "package3", + "private": true, + "devDependencies": { + "package1": "1.0.0" + } + }, + "package4": { + "version": "1.0.0", + "name": "package4", + "dependencies": { + "package3": "1.0.0" + } + }, + "package5": { + "version": "1.0.0", + "name": "package5", + "dependencies": { + "package1": "1.0.0" + } + }, + "package6": { + "version": "1.0.1", + "name": "package6", + "devDependencies": { + "package5": "1.0.0" + } + }, + "lock": { + "name": "test-repo", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "test-repo", + "version": "1.0.0", + "workspaces": ["packages/*"] + }, + "node_modules/package1": { + "resolved": "packages/package1", + "link": true + }, + "node_modules/package2": { + "resolved": "packages/package2", + "link": true + }, + "node_modules/package3": { + "resolved": "packages/package3", + "link": true + }, + "node_modules/package4": { + "resolved": "packages/package4", + "link": true + }, + "node_modules/package5": { + "resolved": "packages/package5", + "link": true + }, + "node_modules/package6": { + "resolved": "packages/package6", + "link": true + }, + "node_modules/package7": { + "resolved": "packages/package7", + "link": true + }, + "packages/package1": { + "version": "1.0.0" + }, + "packages/package2": { + "version": "1.0.0", + "devDependencies": { + "package1": "1.0.0" + } + }, + "packages/package3": { + "version": "1.0.0", + "devDependencies": { + "package1": "1.0.0" + } + }, + "packages/package4": { + "version": "1.0.0", + "dependencies": { + "package3": "1.0.0" + } + }, + "packages/package5": { + "version": "1.0.0", + "dependencies": { + "package1": "1.0.0" + } + }, + "packages/package6": { + "version": "1.0.1", + "devDependencies": { + "package5": "1.0.0" + } + }, + "packages/package7": { + "version": "1.0.1", + "devDependencies": { + "package6": "^1.0.1" + } + } + }, + "dependencies": { + "package1": { + "version": "file:packages/package1" + }, + "package2": { + "version": "file:packages/package2", + "requires": { + "package1": "1.0.0" + } + }, + "package3": { + "version": "file:packages/package3", + "requires": { + "package1": "1.0.0" + } + }, + "package4": { + "version": "file:packages/package4", + "requires": { + "package3": "1.0.0" + } + }, + "package5": { + "version": "file:packages/package5", + "requires": { + "package1": "1.0.0" + } + }, + "package6": { + "version": "file:packages/package6", + "requires": { + "package5": "1.0.0" + } + }, + "package7": { + "version": "file:packages/package7", + "requires": { + "package6": "^1.0.1" + } + } + } + } +} diff --git a/packages/bump-monorepo-packages/src/fixtures/preserve-star.json b/packages/bump-monorepo-packages/src/fixtures/preserve-star.json new file mode 100644 index 00000000..e3b5b6e3 --- /dev/null +++ b/packages/bump-monorepo-packages/src/fixtures/preserve-star.json @@ -0,0 +1,163 @@ +{ + "package1": { + "version": "1.0.0", + "name": "package1" + }, + "package2": { + "version": "1.0.0", + "name": "package2", + "devDependencies": { + "package1": "1.0.0" + } + }, + "package3": { + "version": "1.0.0", + "name": "package3", + "private": true, + "devDependencies": { + "package1": "1.0.0" + } + }, + "package4": { + "version": "1.0.0", + "name": "package4", + "dependencies": { + "package3": "1.0.0" + } + }, + "package5": { + "version": "1.0.0", + "name": "package5", + "dependencies": { + "package1": "1.0.0" + } + }, + "package6": { + "version": "1.0.1", + "name": "package6", + "devDependencies": { + "package5": "1.0.0" + } + }, + "lock": { + "name": "test-repo", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "test-repo", + "version": "1.0.0", + "workspaces": ["packages/*"] + }, + "node_modules/package1": { + "resolved": "packages/package1", + "link": true + }, + "node_modules/package2": { + "resolved": "packages/package2", + "link": true + }, + "node_modules/package3": { + "resolved": "packages/package3", + "link": true + }, + "node_modules/package4": { + "resolved": "packages/package4", + "link": true + }, + "node_modules/package5": { + "resolved": "packages/package5", + "link": true + }, + "node_modules/package6": { + "resolved": "packages/package6", + "link": true + }, + "node_modules/package7": { + "resolved": "packages/package7", + "link": true + }, + "packages/package1": { + "version": "1.0.0" + }, + "packages/package2": { + "version": "1.0.0", + "devDependencies": { + "package1": "1.0.0" + } + }, + "packages/package3": { + "version": "1.0.0", + "devDependencies": { + "package1": "1.0.0" + } + }, + "packages/package4": { + "version": "1.0.0", + "dependencies": { + "package3": "1.0.0" + } + }, + "packages/package5": { + "version": "1.0.0", + "dependencies": { + "package1": "1.0.0" + } + }, + "packages/package6": { + "version": "1.0.1", + "devDependencies": { + "package5": "1.0.0" + } + }, + "packages/package7": { + "version": "1.0.1", + "devDependencies": { + "package6": "*" + } + } + }, + "dependencies": { + "package1": { + "version": "file:packages/package1" + }, + "package2": { + "version": "file:packages/package2", + "requires": { + "package1": "1.0.0" + } + }, + "package3": { + "version": "file:packages/package3", + "requires": { + "package1": "1.0.0" + } + }, + "package4": { + "version": "file:packages/package4", + "requires": { + "package3": "1.0.0" + } + }, + "package5": { + "version": "file:packages/package5", + "requires": { + "package1": "1.0.0" + } + }, + "package6": { + "version": "file:packages/package6", + "requires": { + "package5": "1.0.0" + } + }, + "package7": { + "version": "file:packages/package7", + "requires": { + "package6": "*" + } + } + } + } +} diff --git a/packages/bump-monorepo-packages/src/fixtures/preserve-tilde.json b/packages/bump-monorepo-packages/src/fixtures/preserve-tilde.json new file mode 100644 index 00000000..f61cd98d --- /dev/null +++ b/packages/bump-monorepo-packages/src/fixtures/preserve-tilde.json @@ -0,0 +1,163 @@ +{ + "package1": { + "version": "1.0.0", + "name": "package1" + }, + "package2": { + "version": "1.0.0", + "name": "package2", + "devDependencies": { + "package1": "1.0.0" + } + }, + "package3": { + "version": "1.0.0", + "name": "package3", + "private": true, + "devDependencies": { + "package1": "1.0.0" + } + }, + "package4": { + "version": "1.0.0", + "name": "package4", + "dependencies": { + "package3": "1.0.0" + } + }, + "package5": { + "version": "1.0.0", + "name": "package5", + "dependencies": { + "package1": "1.0.0" + } + }, + "package6": { + "version": "1.0.1", + "name": "package6", + "devDependencies": { + "package5": "1.0.0" + } + }, + "lock": { + "name": "test-repo", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "test-repo", + "version": "1.0.0", + "workspaces": ["packages/*"] + }, + "node_modules/package1": { + "resolved": "packages/package1", + "link": true + }, + "node_modules/package2": { + "resolved": "packages/package2", + "link": true + }, + "node_modules/package3": { + "resolved": "packages/package3", + "link": true + }, + "node_modules/package4": { + "resolved": "packages/package4", + "link": true + }, + "node_modules/package5": { + "resolved": "packages/package5", + "link": true + }, + "node_modules/package6": { + "resolved": "packages/package6", + "link": true + }, + "node_modules/package7": { + "resolved": "packages/package7", + "link": true + }, + "packages/package1": { + "version": "1.0.0" + }, + "packages/package2": { + "version": "1.0.0", + "devDependencies": { + "package1": "1.0.0" + } + }, + "packages/package3": { + "version": "1.0.0", + "devDependencies": { + "package1": "1.0.0" + } + }, + "packages/package4": { + "version": "1.0.0", + "dependencies": { + "package3": "1.0.0" + } + }, + "packages/package5": { + "version": "1.0.0", + "dependencies": { + "package1": "1.0.0" + } + }, + "packages/package6": { + "version": "1.0.1", + "devDependencies": { + "package5": "1.0.0" + } + }, + "packages/package7": { + "version": "1.0.1", + "devDependencies": { + "package6": "~1.0.1" + } + } + }, + "dependencies": { + "package1": { + "version": "file:packages/package1" + }, + "package2": { + "version": "file:packages/package2", + "requires": { + "package1": "1.0.0" + } + }, + "package3": { + "version": "file:packages/package3", + "requires": { + "package1": "1.0.0" + } + }, + "package4": { + "version": "file:packages/package4", + "requires": { + "package3": "1.0.0" + } + }, + "package5": { + "version": "file:packages/package5", + "requires": { + "package1": "1.0.0" + } + }, + "package6": { + "version": "file:packages/package6", + "requires": { + "package5": "1.0.0" + } + }, + "package7": { + "version": "file:packages/package7", + "requires": { + "package6": "~1.0.1" + } + } + } + } +} diff --git a/packages/bump-monorepo-packages/src/fixtures/skip-packages-keep-unskipped.json b/packages/bump-monorepo-packages/src/fixtures/skip-packages-keep-unskipped.json new file mode 100644 index 00000000..e7e046ab --- /dev/null +++ b/packages/bump-monorepo-packages/src/fixtures/skip-packages-keep-unskipped.json @@ -0,0 +1,147 @@ +{ + "package1": { + "version": "1.0.0", + "name": "package1" + }, + "package2": { + "version": "1.0.0", + "name": "package2", + "devDependencies": { + "package1": "1.0.0" + } + }, + "package3": { + "version": "1.0.0", + "name": "package3", + "private": true, + "devDependencies": { + "package1": "1.0.0" + } + }, + "package4": { + "version": "1.0.0", + "name": "package4", + "dependencies": { + "package3": "1.0.0" + } + }, + "package5": { + "version": "1.0.0", + "name": "package5", + "dependencies": { + "package1": "1.0.0" + } + }, + "package6": { + "version": "1.0.1", + "name": "package6", + "devDependencies": { + "package5": "1.0.0" + } + }, + "lock": { + "name": "test-repo", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "test-repo", + "version": "1.0.0", + "workspaces": ["packages/*"] + }, + "node_modules/package1": { + "resolved": "packages/package1", + "link": true + }, + "node_modules/package2": { + "resolved": "packages/package2", + "link": true + }, + "node_modules/package3": { + "resolved": "packages/package3", + "link": true + }, + "node_modules/package4": { + "resolved": "packages/package4", + "link": true + }, + "node_modules/package5": { + "resolved": "packages/package5", + "link": true + }, + "node_modules/package6": { + "resolved": "packages/package6", + "link": true + }, + "packages/package1": { + "version": "1.0.0" + }, + "packages/package2": { + "version": "1.0.0", + "devDependencies": { + "package1": "1.0.0" + } + }, + "packages/package3": { + "version": "1.0.0", + "devDependencies": { + "package1": "1.0.0" + } + }, + "packages/package4": { + "version": "1.0.0", + "dependencies": { + "package3": "1.0.0" + } + }, + "packages/package5": { + "version": "1.0.0", + "dependencies": { + "package1": "1.0.0" + } + }, + "packages/package6": { + "version": "1.0.1", + "devDependencies": { + "package5": "1.0.0" + } + } + }, + "dependencies": { + "package1": { + "version": "file:packages/package1" + }, + "package2": { + "version": "file:packages/package2", + "requires": { + "package1": "1.0.0" + } + }, + "package3": { + "version": "file:packages/package3", + "requires": { + "package1": "1.0.0" + } + }, + "package4": { + "version": "file:packages/package4", + "requires": { + "package3": "1.0.0" + } + }, + "package5": { + "version": "file:packages/package5", + "requires": { + "package1": "1.0.0" + } + }, + "package6": { + "version": "file:packages/package6", + "requires": { + "package5": "1.0.0" + } + } + } + } +} diff --git a/packages/bump-monorepo-packages/src/fixtures/skip-packages.json b/packages/bump-monorepo-packages/src/fixtures/skip-packages.json new file mode 100644 index 00000000..775b976c --- /dev/null +++ b/packages/bump-monorepo-packages/src/fixtures/skip-packages.json @@ -0,0 +1,147 @@ +{ + "package1": { + "version": "1.0.0", + "name": "package1" + }, + "package2": { + "version": "1.0.0", + "name": "package2", + "devDependencies": { + "package1": "1.0.0" + } + }, + "package3": { + "version": "1.0.0", + "name": "package3", + "private": true, + "devDependencies": { + "package1": "1.0.0" + } + }, + "package4": { + "version": "1.0.0", + "name": "package4", + "dependencies": { + "package3": "1.0.0" + } + }, + "package5": { + "version": "1.0.1", + "name": "package5", + "dependencies": { + "package1": "1.0.0" + } + }, + "package6": { + "version": "1.0.0", + "name": "package6", + "devDependencies": { + "package5": "1.0.1" + } + }, + "lock": { + "name": "test-repo", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "test-repo", + "version": "1.0.0", + "workspaces": ["packages/*"] + }, + "node_modules/package1": { + "resolved": "packages/package1", + "link": true + }, + "node_modules/package2": { + "resolved": "packages/package2", + "link": true + }, + "node_modules/package3": { + "resolved": "packages/package3", + "link": true + }, + "node_modules/package4": { + "resolved": "packages/package4", + "link": true + }, + "node_modules/package5": { + "resolved": "packages/package5", + "link": true + }, + "node_modules/package6": { + "resolved": "packages/package6", + "link": true + }, + "packages/package1": { + "version": "1.0.0" + }, + "packages/package2": { + "version": "1.0.0", + "devDependencies": { + "package1": "1.0.0" + } + }, + "packages/package3": { + "version": "1.0.0", + "devDependencies": { + "package1": "1.0.0" + } + }, + "packages/package4": { + "version": "1.0.0", + "dependencies": { + "package3": "1.0.0" + } + }, + "packages/package5": { + "version": "1.0.1", + "dependencies": { + "package1": "1.0.0" + } + }, + "packages/package6": { + "version": "1.0.0", + "devDependencies": { + "package5": "1.0.1" + } + } + }, + "dependencies": { + "package1": { + "version": "file:packages/package1" + }, + "package2": { + "version": "file:packages/package2", + "requires": { + "package1": "1.0.0" + } + }, + "package3": { + "version": "file:packages/package3", + "requires": { + "package1": "1.0.0" + } + }, + "package4": { + "version": "file:packages/package4", + "requires": { + "package3": "1.0.0" + } + }, + "package5": { + "version": "file:packages/package5", + "requires": { + "package1": "1.0.0" + } + }, + "package6": { + "version": "file:packages/package6", + "requires": { + "package5": "1.0.1" + } + } + } + } +}