From 09ac3ee36d60f8f6e468d7cceb6ac2c6a98575b4 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Mon, 6 Apr 2020 11:44:47 +0200 Subject: [PATCH 1/7] Release tool: bumping version works for monorepo now. --- .../lib/release-tools/tasks/bumpversions.js | 157 ++++++++++-------- .../utils/getpackagestorelease.js | 36 +++- .../utils/getsubpackagespaths.js | 17 +- .../utils/getsubrepositoriespaths.js | 14 +- .../utils/getsubpackagespaths.js | 91 +++++++++- 5 files changed, 216 insertions(+), 99 deletions(-) diff --git a/packages/ckeditor5-dev-env/lib/release-tools/tasks/bumpversions.js b/packages/ckeditor5-dev-env/lib/release-tools/tasks/bumpversions.js index a6f3780a6..6626d1488 100644 --- a/packages/ckeditor5-dev-env/lib/release-tools/tasks/bumpversions.js +++ b/packages/ckeditor5-dev-env/lib/release-tools/tasks/bumpversions.js @@ -9,28 +9,28 @@ const path = require( 'path' ); const chalk = require( 'chalk' ); const { tools, logger } = require( '@ckeditor/ckeditor5-dev-utils' ); const cli = require( '../utils/cli' ); +const versions = require( '../utils/versions' ); +const changelog = require( '../utils/changelog' ); const displaySkippedPackages = require( '../utils/displayskippedpackages' ); const executeOnPackages = require( '../utils/executeonpackages' ); -const { getChangesForVersion } = require( '../utils/changelog' ); const getPackageJson = require( '../utils/getpackagejson' ); const getPackagesToRelease = require( '../utils/getpackagestorelease' ); -const getSubRepositoriesPaths = require( '../utils/getsubrepositoriespaths' ); +const getSubPackagesPaths = require( '../utils/getsubpackagespaths' ); const updateDependenciesVersions = require( '../utils/updatedependenciesversions' ); const validatePackageToRelease = require( '../utils/validatepackagetorelease' ); const BREAK_RELEASE_MESSAGE = 'You aborted updating versions. Why? Oh why?!'; /** - * Updates version of all sub-repositories found in specified path. + * Updates version of all subpackages found in specified path. * * This task does: - * - finds paths to sub repositories, - * - filters packages which versions should be updated, + * - finds paths to subpackages, * - updates versions of all dependencies (even if some packages will not be released, its version will be updated in released packages), * - bumps version of all packages. * * @param {String} options.cwd Current working directory (packages) from which all paths will be resolved. - @param {String|null} options.packages Where to look for other packages (dependencies). If `null`, only repository specified under + * @param {String|null} options.packages Where to look for other packages (dependencies). If `null`, only repository specified under * `options.cwd` will be used in the task. * @param {Array.} [options.skipPackages=[]] Name of packages which won't be touched. * @param {Boolean} [options.dryRun=false] If set on true, all changes will be printed on the screen. Changes produced by commands like @@ -44,27 +44,30 @@ module.exports = function bumpVersions( options ) { const dryRun = Boolean( options.dryRun ); - const pathsCollection = getSubRepositoriesPaths( { + const pathsCollection = getSubPackagesPaths( { cwd: options.cwd, packages: options.packages, skipPackages: options.skipPackages || [], skipMainRepository: options.skipMainRepository } ); + const mainRepositoryVersion = versions.getLastFromChangelog( options.cwd ); + const mainChangelog = changelog.getChangesForVersion( mainRepositoryVersion ); + logDryRun( '⚠️ DRY RUN mode ⚠️' ); logDryRun( 'All changes made by this script will be reverted automatically.' ); logProcess( 'Collecting packages which versions should be updated...' ); // In order to avoid setting global variables, every function passes `packages` variable to another function. - return getPackagesToRelease( pathsCollection.matched ) + return getPackagesToRelease( pathsCollection.matched, { changes: mainChangelog, version: mainRepositoryVersion } ) .then( packages => isAnythingForRelease( packages ) ) .then( packages => confirmUpdate( packages ) ) .then( packages => prepareDependenciesVersions( packages ) ) .then( ( { packages, dependencies } ) => filterPackagesThatWillNotBeReleased( packages, dependencies ) ) .then( ( { packages, dependencies } ) => updateDependenciesOfPackages( packages, dependencies ) ) - .then( packages => getLatestChangesForPackagesThatWillBeReleased( packages ) ) - .then( packages => validateRepositories( packages ) ) + .then( packages => updateLatestChangesForMainRepository( packages, mainRepositoryVersion ) ) + .then( packages => validateRepository( packages ) ) .then( packages => bumpVersion( packages ) ) .then( () => { process.chdir( cwd ); @@ -185,6 +188,7 @@ module.exports = function bumpVersions( options ) { // @returns {Promise.>} function updateDependenciesOfPackages( packages, dependencies ) { logProcess( 'Updating dependencies for packages that will be released...' ); + let hasUpdatedAnyPackage = false; return executeOnPackages( pathsCollection.matched, repositoryPath => { process.chdir( repositoryPath ); @@ -202,71 +206,64 @@ module.exports = function bumpVersions( options ) { log.info( chalk.grey( exec( 'git diff --word-diff package.json' ) ) ); exec( 'git checkout package.json' ); } else { + hasUpdatedAnyPackage = true; + exec( 'git add package.json' ); - exec( 'git commit -m "Internal: Updated dependencies. [skip ci]"' ); } } return Promise.resolve(); - } ).then( () => packages ); + } ).then( () => { + process.chdir( cwd ); + + if ( hasUpdatedAnyPackage ) { + exec( 'git commit -m "Internal: Updated dependencies. [skip ci]"' ); + } + + return packages; + } ); } // Gather descriptions of the release for all packages. // // @params {Map.} packages - // @returns {Promise.>} - function getLatestChangesForPackagesThatWillBeReleased( packages ) { - logProcess( 'Gathering changes from changelog for specified versions...' ); + // @returns {} + function updateLatestChangesForMainRepository( packages, changes ) { + logProcess( 'Updating changes for the main repossitory...' ); - return executeOnPackages( pathsCollection.matched, repositoryPath => { - process.chdir( repositoryPath ); + const packageJson = getPackageJson( cwd ); + const releaseDetails = packages.get( packageJson.name ); - const packageJson = getPackageJson( repositoryPath ); - const releaseDetails = packages.get( packageJson.name ); + releaseDetails.changes = changes; - releaseDetails.changes = getChangesForVersion( releaseDetails.version, repositoryPath ); - - return Promise.resolve(); - } ).then( () => packages ); + return packages; } - // Validate the repositories. + // Validate the main repository. // // @params {Map.} packages - // @returns {Promise.>} - function validateRepositories( packages ) { - logProcess( 'Validating the repositories...' ); - - const errors = []; - - return executeOnPackages( pathsCollection.matched, validateSingleRepository ) - .then( () => { - if ( errors.length ) { - errors.forEach( log.error.bind( log ) ); - - throw new Error( 'Updating has been aborted due to errors.' ); - } + // @returns {Map.} + function validateRepository( packages ) { + logProcess( 'Validating the main repository...' ); - return packages; - } ); + const mainPackageJson = getPackageJson( options.cwd ); + const releaseDetails = packages.get( mainPackageJson.name ); - function validateSingleRepository( repositoryPath ) { - process.chdir( repositoryPath ); + const errors = validatePackageToRelease( { + changes: releaseDetails.changes, + version: releaseDetails.version + } ); - const packageJson = getPackageJson( repositoryPath ); - const releaseDetails = packages.get( packageJson.name ); - const errorsForPackage = validatePackageToRelease( { - changes: releaseDetails.changes, - version: releaseDetails.version + if ( errors.length ) { + log.error( `‼️ ${ chalk.underline( mainPackageJson.name ) }` ); + errors.forEach( err => { + log.error( '* ' + err ); } ); - if ( errorsForPackage.length ) { - errors.push( `‼️ ${ chalk.underline( packageJson.name ) }` ); - errors.push( ...errorsForPackage.map( err => '* ' + err ) ); - } - - return Promise.resolve(); + throw new Error( 'Updating has been aborted due to errors.' ); } + + return packages; } // Updates versions of packages. @@ -276,35 +273,49 @@ module.exports = function bumpVersions( options ) { function bumpVersion( packages ) { logProcess( 'Tagging new versions of packages...' ); - return executeOnPackages( pathsCollection.matched, repositoryPath => { - process.chdir( repositoryPath ); + let numberOfCommitsBeforeVersioning; - const packageJson = getPackageJson( repositoryPath ); - const releaseDetails = packages.get( packageJson.name ); + // Based on number of commits before and after executing `npm version`, we will be able to revert all changes + // that have been done. It allows reverting changes done by npm `preversion` and/or `postversion` hooks. + if ( dryRun ) { + numberOfCommitsBeforeVersioning = Number( exec( 'git rev-list --count HEAD' ) ); + } - log.info( `\nBumping version for "${ chalk.underline( packageJson.name ) }"...` ); + return executeOnPackages( pathsCollection.matched, bumpVersionForSinglePackage ) + .then( () => { + process.chdir( cwd ); - let numberOfCommitsBeforeVersioning; + const packageJson = getPackageJson( cwd ); + const releaseDetails = packages.get( packageJson.name ); - // Based on number of commits before and after executing `npm version`, we will be able to revert all changes - // that have been done. It allows reverting changes done by `npm preversion` or `npm postversion` hooks. - if ( dryRun ) { - numberOfCommitsBeforeVersioning = Number( exec( 'git rev-list --count HEAD' ) ); - } + log.info( '\nCommitting and tagging changes...' ); + + exec( `git commit --message "Release: v${ releaseDetails.version }. [skip ci]"` ); + exec( `git tag v${ releaseDetails.version }` ); - exec( `npm version ${ releaseDetails.version } --message "Release: v${ releaseDetails.version }. [skip ci]"` ); + if ( dryRun ) { + const numberOfCommitsAfterVersioning = Number( exec( 'git rev-list --count HEAD' ) ); + const commitsToRevert = numberOfCommitsAfterVersioning - numberOfCommitsBeforeVersioning; - if ( dryRun ) { - const numberOfCommitsAfterVersioning = Number( exec( 'git rev-list --count HEAD' ) ); - const commitsToRevert = numberOfCommitsAfterVersioning - numberOfCommitsBeforeVersioning; + logDryRun( `Reverting changes made by "npm version". Removing a tag and ${ commitsToRevert } commit(s).` ); + exec( `git reset --hard HEAD~${ commitsToRevert }` ); + exec( `git tag -d v${ releaseDetails.version }` ); + } - logDryRun( `Reverting changes made by "npm version". Removing a tag and ${ commitsToRevert } commit(s).` ); - exec( `git reset --hard HEAD~${ commitsToRevert }` ); - exec( `git tag -d v${ releaseDetails.version }` ); - } + return packages; + } ); - return Promise.resolve(); - } ).then( () => packages ); + function bumpVersionForSinglePackage( repositoryPath ) { + process.chdir( repositoryPath ); + + const packageJson = getPackageJson( repositoryPath ); + const releaseDetails = packages.get( packageJson.name ); + + log.info( `\nBumping version for "${ chalk.underline( packageJson.name ) }"...` ); + + exec( `npm version ${ releaseDetails.version } --no-git-tag-version` ); + exec( 'git add .' ); + } } function exec( command ) { diff --git a/packages/ckeditor5-dev-env/lib/release-tools/utils/getpackagestorelease.js b/packages/ckeditor5-dev-env/lib/release-tools/utils/getpackagestorelease.js index 77526deab..7b98dbb11 100644 --- a/packages/ckeditor5-dev-env/lib/release-tools/utils/getpackagestorelease.js +++ b/packages/ckeditor5-dev-env/lib/release-tools/utils/getpackagestorelease.js @@ -7,15 +7,18 @@ const executeOnPackages = require( './executeonpackages' ); const getPackageJson = require( './getpackagejson' ); -const versionUtils = require( './versions' ); /** * Returns a list of packages which should be releases based on changes in a changelog file and tags created in Git repository. * * @param {Set} pathsToPackages A collection of paths to packages that should be checked. + * @param {Object} options + * @param {String} options.changes A description of changes for the main repository. It should contain a script-friendly list that provides + * new versions for parsed packages. If didn't find, `options.version` will be used instead. + * @param {String} options.version New version for the main repository. * @returns {Promise.>} */ -module.exports = function getPackagesToRelease( pathsToPackages ) { +module.exports = function getPackagesToRelease( pathsToPackages, options ) { const cwd = process.cwd(); const packagesToRelease = new Map(); @@ -29,17 +32,17 @@ module.exports = function getPackagesToRelease( pathsToPackages ) { function filterPackagesToRelease( repositoryPath ) { process.chdir( repositoryPath ); - const gitVersion = versionUtils.getLastTagFromGit(); - const changelogVersion = versionUtils.getLastFromChangelog(); const packageJson = getPackageJson(); const repositoryName = packageJson.name; + const newVersion = findVersionInChangelog( options.changes, repositoryName ) || options.version; + // If these versions aren't equal, it means that the package is ready to release - // because we assume that a version from changelog is the latest. - if ( gitVersion !== changelogVersion ) { + // because we assume that a version from `package.json` is the latest. + if ( packageJson.version !== newVersion ) { packagesToRelease.set( repositoryName, { previousVersion: packageJson.version, - version: changelogVersion + version: newVersion } ); } @@ -47,6 +50,25 @@ module.exports = function getPackagesToRelease( pathsToPackages ) { } }; +// Search for a new version for specified package in the main changelog description. +// It must be defined as following: +// +// [packageName](https://www.npmjs.com/package/packageName): v0.0.1 => [v1.0.0](https://github.com/.../releases/tag/v1.0.0) +// +// where: +// `v0.0.1` is the current version (already published), +// `v1.0.0` is the new version what we're looking for. +// +// @param {String} changelog Changes. +// @param {String} packageName Package to look. +// @returns {String|null} `null` if the version was not found. +function findVersionInChangelog( changelog, packageName ) { + const versionRegexp = new RegExp( `\\[${ packageName.replace( '/', '\\/' ) }\\].*\\[v([\\d.]+)\\]` ); + const match = changelog.match( versionRegexp ); + + return match ? match[ 1 ] : null; +} + /** * @typedef {Object} ReleaseDetails * diff --git a/packages/ckeditor5-dev-env/lib/release-tools/utils/getsubpackagespaths.js b/packages/ckeditor5-dev-env/lib/release-tools/utils/getsubpackagespaths.js index 10771e770..37def06dd 100644 --- a/packages/ckeditor5-dev-env/lib/release-tools/utils/getsubpackagespaths.js +++ b/packages/ckeditor5-dev-env/lib/release-tools/utils/getsubpackagespaths.js @@ -25,17 +25,28 @@ const minimatch = require( 'minimatch' ); * @param {String} options.packages Name of directory where to look for packages. * @param {String|Array.} options.skipPackages Glob pattern(s) which describes which packages should be skipped. * @param {String} [options.scope] Package names have to match to specified glob pattern. + * @param {Boolean} [options.skipMainRepository=false] If set on true, package found in `options.cwd` will be skipped. * @returns {PathsCollection} */ module.exports = function getSubPackagesPaths( options ) { - const packagesPath = path.join( options.cwd, options.packages ); - const skipPackages = Array.isArray( options.skipPackages ) ? options.skipPackages : [ options.skipPackages ]; - const pathsCollection = { matched: new Set(), skipped: new Set() }; + if ( options.skipMainRepository ) { + pathsCollection.skipped.add( options.cwd ); + } else { + pathsCollection.matched.add( options.cwd ); + } + + if ( !options.packages ) { + return pathsCollection; + } + + const packagesPath = path.join( options.cwd, options.packages ); + const skipPackages = Array.isArray( options.skipPackages ) ? options.skipPackages : [ options.skipPackages ]; + for ( const directory of tools.getDirectories( packagesPath ) ) { const dependencyPath = path.join( packagesPath, directory ); const dependencyName = getPackageJson( dependencyPath ).name; diff --git a/packages/ckeditor5-dev-env/lib/release-tools/utils/getsubrepositoriespaths.js b/packages/ckeditor5-dev-env/lib/release-tools/utils/getsubrepositoriespaths.js index 95da2a976..541a38357 100644 --- a/packages/ckeditor5-dev-env/lib/release-tools/utils/getsubrepositoriespaths.js +++ b/packages/ckeditor5-dev-env/lib/release-tools/utils/getsubrepositoriespaths.js @@ -32,19 +32,19 @@ const getPackageJson = require( './getpackagejson' ); * @returns {PathsCollection} */ module.exports = function getSubRepositoriesPaths( options ) { - const collection = { + const pathsCollection = { matched: new Set(), skipped: new Set() }; if ( options.skipMainRepository ) { - collection.skipped.add( options.cwd ); + pathsCollection.skipped.add( options.cwd ); } else { - collection.matched.add( options.cwd ); + pathsCollection.matched.add( options.cwd ); } if ( !options.packages ) { - return collection; + return pathsCollection; } const packagesPath = path.join( options.cwd, options.packages ); @@ -60,16 +60,16 @@ module.exports = function getSubRepositoriesPaths( options ) { const dependencyName = getPackageJson( dependencyPath ).name; if ( isValidPackage( dependencyName ) ) { - collection.matched.add( dependencyPath ); + pathsCollection.matched.add( dependencyPath ); } else { - collection.skipped.add( dependencyPath ); + pathsCollection.skipped.add( dependencyPath ); } } catch ( err ) { console.warn( `Missing "package.json file in "${ dependencyPath }". Skipping.` ); } } - return collection; + return pathsCollection; function isValidPackage( packageName ) { if ( !dependencies.includes( packageName ) ) { diff --git a/packages/ckeditor5-dev-env/tests/release-tools/utils/getsubpackagespaths.js b/packages/ckeditor5-dev-env/tests/release-tools/utils/getsubpackagespaths.js index d50ce2020..aee6381f5 100644 --- a/packages/ckeditor5-dev-env/tests/release-tools/utils/getsubpackagespaths.js +++ b/packages/ckeditor5-dev-env/tests/release-tools/utils/getsubpackagespaths.js @@ -47,7 +47,8 @@ describe( 'dev-env/release-tools/utils', () => { const options = { cwd: '/tmp', packages: 'packages', - skipPackages: [] + skipPackages: [], + skipMainRepository: true }; getPackageJsonStub.onFirstCall().returns( { name: '@ckeditor/ckeditor5-core' } ); @@ -61,6 +62,9 @@ describe( 'dev-env/release-tools/utils', () => { expect( pathsCollection.matched.has( '/tmp/packages/ckeditor5-core' ) ).to.equal( true ); expect( pathsCollection.matched.has( '/tmp/packages/ckeditor5-engine' ) ).to.equal( true ); expect( pathsCollection.matched.has( '/tmp/packages/ckeditor5-utils' ) ).to.equal( true ); + + expect( pathsCollection.skipped.size ).to.equal( 1 ); + expect( pathsCollection.skipped.has( '/tmp' ) ).to.equal( true ); } ); it( 'allows ignoring specified packages', () => { @@ -75,7 +79,8 @@ describe( 'dev-env/release-tools/utils', () => { packages: 'packages', skipPackages: [ '@ckeditor/ckeditor5-utils' - ] + ], + skipMainRepository: true }; getPackageJsonStub.onFirstCall().returns( { name: '@ckeditor/ckeditor5-core' } ); @@ -88,7 +93,8 @@ describe( 'dev-env/release-tools/utils', () => { expect( pathsCollection.matched.size ).to.equal( 2 ); expect( pathsCollection.skipped ).to.be.instanceof( Set ); - expect( pathsCollection.skipped.size ).to.equal( 1 ); + expect( pathsCollection.skipped.size ).to.equal( 2 ); + expect( pathsCollection.skipped.has( '/tmp' ) ).to.equal( true ); expect( pathsCollection.skipped.has( '/tmp/packages/ckeditor5-utils' ) ).to.equal( true ); } ); @@ -102,7 +108,8 @@ describe( 'dev-env/release-tools/utils', () => { const options = { cwd: '/tmp', packages: 'packages', - skipPackages: '@ckeditor/ckeditor5-u*' + skipPackages: '@ckeditor/ckeditor5-u*', + skipMainRepository: true }; getPackageJsonStub.onFirstCall().returns( { name: '@ckeditor/ckeditor5-core' } ); @@ -115,7 +122,8 @@ describe( 'dev-env/release-tools/utils', () => { expect( pathsCollection.matched.size ).to.equal( 2 ); expect( pathsCollection.skipped ).to.be.instanceof( Set ); - expect( pathsCollection.skipped.size ).to.equal( 1 ); + expect( pathsCollection.skipped.size ).to.equal( 2 ); + expect( pathsCollection.skipped.has( '/tmp' ) ).to.equal( true ); expect( pathsCollection.skipped.has( '/tmp/packages/ckeditor5-utils' ) ).to.equal( true ); } ); @@ -132,7 +140,8 @@ describe( 'dev-env/release-tools/utils', () => { cwd: '/tmp', packages: 'packages', scope: '@ckeditor/ckeditor5-build-*', - skipPackages: [] + skipPackages: [], + skipMainRepository: true }; getPackageJsonStub.onCall( 0 ).returns( { name: '@ckeditor/ckeditor5-core' } ); @@ -149,7 +158,8 @@ describe( 'dev-env/release-tools/utils', () => { expect( pathsCollection.matched.has( '/tmp/packages/ckeditor5-build-inline' ) ).to.equal( true ); expect( pathsCollection.skipped ).to.be.instanceof( Set ); - expect( pathsCollection.skipped.size ).to.equal( 3 ); + expect( pathsCollection.skipped.size ).to.equal( 4 ); + expect( pathsCollection.skipped.has( '/tmp' ) ).to.equal( true ); expect( pathsCollection.skipped.has( '/tmp/packages/ckeditor5-core' ) ).to.equal( true ); expect( pathsCollection.skipped.has( '/tmp/packages/ckeditor5-engine' ) ).to.equal( true ); expect( pathsCollection.skipped.has( '/tmp/packages/ckeditor5-utils' ) ).to.equal( true ); @@ -170,7 +180,8 @@ describe( 'dev-env/release-tools/utils', () => { scope: '@ckeditor/ckeditor5-build-*', skipPackages: [ '@ckeditor/ckeditor5-build-inline' - ] + ], + skipMainRepository: true }; getPackageJsonStub.onCall( 0 ).returns( { name: '@ckeditor/ckeditor5-core' } ); @@ -186,11 +197,73 @@ describe( 'dev-env/release-tools/utils', () => { expect( pathsCollection.matched.has( '/tmp/packages/ckeditor5-build-classic' ) ).to.equal( true ); expect( pathsCollection.skipped ).to.be.instanceof( Set ); - expect( pathsCollection.skipped.size ).to.equal( 4 ); + expect( pathsCollection.skipped.size ).to.equal( 5 ); + expect( pathsCollection.skipped.has( '/tmp' ) ).to.equal( true ); expect( pathsCollection.skipped.has( '/tmp/packages/ckeditor5-core' ) ).to.equal( true ); expect( pathsCollection.skipped.has( '/tmp/packages/ckeditor5-engine' ) ).to.equal( true ); expect( pathsCollection.skipped.has( '/tmp/packages/ckeditor5-utils' ) ).to.equal( true ); expect( pathsCollection.skipped.has( '/tmp/packages/ckeditor5-build-inline' ) ).to.equal( true ); } ); + + it( 'allows returning the main repository', () => { + getDirectoriesStub.returns( [ + 'ckeditor5-core', + 'ckeditor5-engine', + 'ckeditor5-utils' + ] ); + + const options = { + cwd: '/tmp', + packages: 'packages', + skipPackages: [], + skipMainRepository: false + }; + + getPackageJsonStub.onFirstCall().returns( { name: '@ckeditor/ckeditor5-core' } ); + getPackageJsonStub.onSecondCall().returns( { name: '@ckeditor/ckeditor5-engine' } ); + getPackageJsonStub.onThirdCall().returns( { name: '@ckeditor/ckeditor5-utils' } ); + + const pathsCollection = getSubPackagesPaths( options ); + + expect( pathsCollection.matched ).to.be.instanceof( Set ); + expect( pathsCollection.matched.size ).to.equal( 4 ); + expect( pathsCollection.matched.has( '/tmp' ) ).to.equal( true ); + expect( pathsCollection.matched.has( '/tmp/packages/ckeditor5-core' ) ).to.equal( true ); + expect( pathsCollection.matched.has( '/tmp/packages/ckeditor5-engine' ) ).to.equal( true ); + expect( pathsCollection.matched.has( '/tmp/packages/ckeditor5-utils' ) ).to.equal( true ); + } ); + + it( 'allows returning the main repository only (skipMainRepository=false)', () => { + const options = { + cwd: '/tmp', + packages: null + }; + + const pathsCollection = getSubPackagesPaths( options ); + + expect( pathsCollection.matched ).to.be.instanceof( Set ); + expect( pathsCollection.matched.size ).to.equal( 1 ); + expect( pathsCollection.matched.has( '/tmp' ) ).to.equal( true ); + + expect( pathsCollection.skipped ).to.be.instanceof( Set ); + expect( pathsCollection.skipped.size ).to.equal( 0 ); + } ); + + it( 'allows returning the main repository only (skipMainRepository=true)', () => { + const options = { + cwd: '/tmp', + packages: null, + skipMainRepository: true + }; + + const pathsCollection = getSubPackagesPaths( options ); + + expect( pathsCollection.matched ).to.be.instanceof( Set ); + expect( pathsCollection.matched.size ).to.equal( 0 ); + + expect( pathsCollection.skipped ).to.be.instanceof( Set ); + expect( pathsCollection.skipped.size ).to.equal( 1 ); + expect( pathsCollection.skipped.has( '/tmp' ) ).to.equal( true ); + } ); } ); } ); From 1361740080b66bb335753515bb41a9be86982166 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Mon, 6 Apr 2020 14:22:28 +0200 Subject: [PATCH 2/7] Release tool: Publisher works with monorepo. --- .../lib/release-tools/tasks/bumpversions.js | 6 +- .../tasks/releasesubrepositories.js | 191 +++++++++--------- 2 files changed, 103 insertions(+), 94 deletions(-) diff --git a/packages/ckeditor5-dev-env/lib/release-tools/tasks/bumpversions.js b/packages/ckeditor5-dev-env/lib/release-tools/tasks/bumpversions.js index 6626d1488..9b3ff7913 100644 --- a/packages/ckeditor5-dev-env/lib/release-tools/tasks/bumpversions.js +++ b/packages/ckeditor5-dev-env/lib/release-tools/tasks/bumpversions.js @@ -231,7 +231,7 @@ module.exports = function bumpVersions( options ) { function updateLatestChangesForMainRepository( packages, changes ) { logProcess( 'Updating changes for the main repossitory...' ); - const packageJson = getPackageJson( cwd ); + const packageJson = getPackageJson( options.cwd ); const releaseDetails = packages.get( packageJson.name ); releaseDetails.changes = changes; @@ -283,9 +283,9 @@ module.exports = function bumpVersions( options ) { return executeOnPackages( pathsCollection.matched, bumpVersionForSinglePackage ) .then( () => { - process.chdir( cwd ); + process.chdir( options.cwd ); - const packageJson = getPackageJson( cwd ); + const packageJson = getPackageJson( options.cwd ); const releaseDetails = packages.get( packageJson.name ); log.info( '\nCommitting and tagging changes...' ); diff --git a/packages/ckeditor5-dev-env/lib/release-tools/tasks/releasesubrepositories.js b/packages/ckeditor5-dev-env/lib/release-tools/tasks/releasesubrepositories.js index 3c7c3fd95..e6c29b5b1 100644 --- a/packages/ckeditor5-dev-env/lib/release-tools/tasks/releasesubrepositories.js +++ b/packages/ckeditor5-dev-env/lib/release-tools/tasks/releasesubrepositories.js @@ -16,7 +16,7 @@ const displaySkippedPackages = require( '../utils/displayskippedpackages' ); const executeOnPackages = require( '../utils/executeonpackages' ); const { getChangesForVersion } = require( '../utils/changelog' ); const getPackageJson = require( '../utils/getpackagejson' ); -const getSubRepositoriesPaths = require( '../utils/getsubrepositoriespaths' ); +const getSubPackagesPaths = require( '../utils/getsubpackagespaths' ); const GitHubApi = require( '@octokit/rest' ); const PACKAGE_JSON_TEMPLATE_PATH = require.resolve( '../templates/release-package.json' ); @@ -96,7 +96,7 @@ module.exports = function releaseSubRepositories( options ) { const dryRun = Boolean( options.dryRun ); const emptyReleases = Array.isArray( options.emptyReleases ) ? options.emptyReleases : [ options.emptyReleases ].filter( Boolean ); - const pathsCollection = getSubRepositoriesPaths( { + const pathsCollection = getSubPackagesPaths( { cwd: options.cwd, packages: options.packages, skipPackages: options.skipPackages || [], @@ -243,28 +243,44 @@ module.exports = function releaseSubRepositories( options ) { displaySkippedPackages( pathsCollection.skipped ); - return executeOnPackages( pathsCollection.matched, repositoryPath => { - process.chdir( repositoryPath ); + return Promise.resolve() + .then( () => { + // Prepare the main repository release details. + const packageJson = getPackageJson( options.cwd ); + const releaseDetails = { + version: packageJson.version, + changes: getChangesForVersion( packageJson.version, options.cwd ) + }; + + if ( releaseOptions.github ) { + const repositoryInfo = parseGithubUrl( + exec( 'git remote get-url origin --push' ).trim() + ); - const packageJson = getPackageJson( repositoryPath ); - const releaseDetails = { - version: packageJson.version, - changes: getChangesForVersion( packageJson.version, repositoryPath ) - }; + releaseDetails.repositoryOwner = repositoryInfo.owner; + releaseDetails.repositoryName = repositoryInfo.name; + } - packages.set( packageJson.name, releaseDetails ); + packages.set( packageJson.name, releaseDetails ); - if ( releaseOptions.github ) { - const repositoryInfo = parseGithubUrl( - exec( 'git remote get-url origin --push' ).trim() - ); + return executeOnPackages( pathsCollection.matched, repositoryPath => { + // The main repository is handled before calling the `executeOnPackages()` function. + if ( repositoryPath === options.cwd ) { + return; + } - releaseDetails.repositoryOwner = repositoryInfo.owner; - releaseDetails.repositoryName = repositoryInfo.name; - } + const packageJson = getPackageJson( repositoryPath ); - return Promise.resolve(); - } ); + packages.set( packageJson.name, { + version: packageJson.version + } ); + + return Promise.resolve(); + } ); + } ) + .then( () => { + process.chdir( cwd ); + } ); } // Checks which packages should be published on NPM. It compares version defined in `package.json` @@ -336,42 +352,40 @@ module.exports = function releaseSubRepositories( options ) { logProcess( 'Collecting the latest releases published on GitHub...' ); - return executeOnPackages( pathsCollection.matched, repositoryPath => { - process.chdir( repositoryPath ); + process.chdir( options.cwd ); - const packageJson = getPackageJson( repositoryPath ); - const releaseDetails = packages.get( packageJson.name ); + const packageJson = getPackageJson( options.cwd ); + const releaseDetails = packages.get( packageJson.name ); - log.info( `\nChecking "${ chalk.underline( packageJson.name ) }"...` ); + log.info( `\nChecking "${ chalk.underline( packageJson.name ) }"...` ); - return getLastRelease( releaseDetails.repositoryOwner, releaseDetails.repositoryName ) - .then( ( { data } ) => { - // It can be `null` if there is no releases on GitHub. - let githubVersion = data.tag_name; + return getLastRelease( releaseDetails.repositoryOwner, releaseDetails.repositoryName ) + .then( ( { data } ) => { + // It can be `null` if there is no releases on GitHub. + let githubVersion = data.tag_name; - if ( githubVersion ) { - githubVersion = data.tag_name.replace( /^v/, '' ); - } + if ( githubVersion ) { + githubVersion = data.tag_name.replace( /^v/, '' ); + } - logDryRun( - `Versions: package.json: "${ releaseDetails.version }", GitHub: "${ githubVersion || 'initial release' }".` - ); + logDryRun( + `Versions: package.json: "${ releaseDetails.version }", GitHub: "${ githubVersion || 'initial release' }".` + ); - releaseDetails.githubVersion = githubVersion; - releaseDetails.shouldReleaseOnGithub = githubVersion !== releaseDetails.version; + releaseDetails.githubVersion = githubVersion; + releaseDetails.shouldReleaseOnGithub = githubVersion !== releaseDetails.version; - if ( releaseDetails.shouldReleaseOnGithub ) { - log.info( '✅ Added to release.' ); + if ( releaseDetails.shouldReleaseOnGithub ) { + log.info( '✅ Added to release.' ); - releasesOnGithub.add( repositoryPath ); - } else { - log.info( '❌ Nothing to release.' ); - } - } ) - .catch( err => { - log.warning( err ); - } ); - } ); + releasesOnGithub.add( options.cwd ); + } else { + log.info( '❌ Nothing to release.' ); + } + } ) + .catch( err => { + log.warning( err ); + } ); function getLastRelease( repositoryOwner, repositoryName ) { const requestParams = { @@ -533,22 +547,20 @@ module.exports = function releaseSubRepositories( options ) { function pushPackages() { logProcess( 'Pushing packages to the remote...' ); - return executeOnPackages( releasesOnGithub, repositoryPath => { - process.chdir( repositoryPath ); + process.chdir( options.cwd ); - const packageJson = getPackageJson( repositoryPath ); - const releaseDetails = packages.get( packageJson.name ); + const packageJson = getPackageJson( options.cwd ); + const releaseDetails = packages.get( packageJson.name ); - log.info( `\nPushing "${ chalk.underline( packageJson.name ) }" package...` ); + log.info( `\nPushing "${ chalk.underline( packageJson.name ) }" package...` ); - if ( dryRun ) { - logDryRun( `Command: "git push origin master v${ releaseDetails.version }" would be executed.` ); - } else { - exec( `git push origin master v${ releaseDetails.version }` ); - } + if ( dryRun ) { + logDryRun( `Command: "git push origin master v${ releaseDetails.version }" would be executed.` ); + } else { + exec( `git push origin master v${ releaseDetails.version }` ); + } - return Promise.resolve(); - } ); + return Promise.resolve(); } // Creates the releases on GitHub. In `dry run` mode it will just print a URL to release. @@ -561,47 +573,45 @@ module.exports = function releaseSubRepositories( options ) { logProcess( 'Creating releases on GitHub...' ); - return executeOnPackages( releasesOnGithub, repositoryPath => { - process.chdir( repositoryPath ); + process.chdir( options.cwd ); - const packageJson = getPackageJson( repositoryPath ); - const releaseDetails = packages.get( packageJson.name ); + const packageJson = getPackageJson( options.cwd ); + const releaseDetails = packages.get( packageJson.name ); - log.info( `\nCreating a GitHub release for "${ packageJson.name }"...` ); + log.info( `\nCreating a GitHub release for "${ packageJson.name }"...` ); - // eslint-disable-next-line max-len - const url = `https://github.com/${ releaseDetails.repositoryOwner }/${ releaseDetails.repositoryName }/releases/tag/v${ releaseDetails.version }`; + // eslint-disable-next-line max-len + const url = `https://github.com/${ releaseDetails.repositoryOwner }/${ releaseDetails.repositoryName }/releases/tag/v${ releaseDetails.version }`; - logDryRun( `Created release will be available under: ${ chalk.underline( url ) }` ); + logDryRun( `Created release will be available under: ${ chalk.underline( url ) }` ); - if ( dryRun ) { - return Promise.resolve(); - } + if ( dryRun ) { + return Promise.resolve(); + } - const githubReleaseOptions = { - repositoryOwner: releaseDetails.repositoryOwner, - repositoryName: releaseDetails.repositoryName, - version: `v${ releaseDetails.version }`, - description: releaseDetails.changes - }; + const githubReleaseOptions = { + repositoryOwner: releaseDetails.repositoryOwner, + repositoryName: releaseDetails.repositoryName, + version: `v${ releaseDetails.version }`, + description: releaseDetails.changes + }; - return createGithubRelease( releaseOptions.token, githubReleaseOptions ) - .then( - () => { - releasedPackages.add( repositoryPath ); + return createGithubRelease( releaseOptions.token, githubReleaseOptions ) + .then( + () => { + releasedPackages.add( options.cwd ); - log.info( `Created the release: ${ chalk.green( url ) }` ); + log.info( `Created the release: ${ chalk.green( url ) }` ); - return Promise.resolve(); - }, - err => { - log.info( 'Cannot create a release on GitHub. Skipping that package.' ); - log.error( err ); + return Promise.resolve(); + }, + err => { + log.info( 'Cannot create a release on GitHub. Skipping that package.' ); + log.error( err ); - return Promise.resolve(); - } - ); - } ); + return Promise.resolve(); + } + ); } // Removes all temporary directories that were created for publishing an empty repository. @@ -638,7 +648,6 @@ module.exports = function releaseSubRepositories( options ) { if ( !shouldRemove ) { logDryRun( 'You can remove these files manually by calling `git clean -f` command.' ); - logDryRun( 'It will also work using mrgit: `mrgit exec "git clean -f"`' ); return; } From aa86e8683d1a5089e7343dbfeb5c0bcc5e27c7ee Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Tue, 7 Apr 2020 09:56:01 +0200 Subject: [PATCH 3/7] Fixed failing tests. --- .../utils/getpackagestorelease.js | 50 ++++++++++++------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/packages/ckeditor5-dev-env/tests/release-tools/utils/getpackagestorelease.js b/packages/ckeditor5-dev-env/tests/release-tools/utils/getpackagestorelease.js index f9c5f90d7..67cae5763 100644 --- a/packages/ckeditor5-dev-env/tests/release-tools/utils/getpackagestorelease.js +++ b/packages/ckeditor5-dev-env/tests/release-tools/utils/getpackagestorelease.js @@ -53,16 +53,12 @@ describe( 'dev-env/release-tools/utils', () => { ] ); // @ckeditor/ckeditor5-core - stubs.versions.getLastFromChangelog.onFirstCall().returns( '0.6.0' ); - stubs.versions.getLastTagFromGit.onFirstCall().returns( '0.5.0' ); stubs.getPackageJson.onFirstCall().returns( { name: '@ckeditor/ckeditor5-core', version: '0.5.0' } ); // @ckeditor/ckeditor5-engine - stubs.versions.getLastFromChangelog.onSecondCall().returns( '1.0.1' ); - stubs.versions.getLastTagFromGit.onSecondCall().returns( '1.0.0' ); stubs.getPackageJson.onSecondCall().returns( { name: '@ckeditor/ckeditor5-engine', version: '1.0.0' @@ -70,7 +66,12 @@ describe( 'dev-env/release-tools/utils', () => { sandbox.stub( process, 'cwd' ).returns( '/cwd' ); - return getPackagesToRelease( packagesToCheck ) + const changes = [ + '[@ckeditor/ckeditor5-core](npm link): v0.5.0 => [v1.0.0](GitHub link)', + '[@ckeditor/ckeditor5-engine](npm link): v1.0.0 => [v1.0.1](GitHub link)' + ].join( '\n' ); + + return getPackagesToRelease( packagesToCheck, { changes, version: '2.0.0' } ) .then( packages => { expect( packages.size ).to.equal( 2 ); @@ -80,36 +81,51 @@ describe( 'dev-env/release-tools/utils', () => { expect( stubs.chdir.thirdCall.args[ 0 ] ).to.equal( '/cwd' ); const corePackageDetails = packages.get( '@ckeditor/ckeditor5-core' ); - expect( corePackageDetails.version ).to.equal( '0.6.0' ); + expect( corePackageDetails.version ).to.equal( '1.0.0' ); const enginePackageDetails = packages.get( '@ckeditor/ckeditor5-engine' ); expect( enginePackageDetails.version ).to.equal( '1.0.1' ); } ); } ); - it( 'ignores package if its dependencies have not changed', () => { + it( 'uses passed version if changes miss some package', () => { const packagesToCheck = new Set( [ '/packages/ckeditor5-core', - '/packages/ckeditor5-utils' + '/packages/ckeditor5-engine' ] ); // @ckeditor/ckeditor5-core - stubs.versions.getLastFromChangelog.onFirstCall().returns( '0.6.0' ); - stubs.versions.getLastTagFromGit.onFirstCall().returns( '0.5.0' ); stubs.getPackageJson.onFirstCall().returns( { + name: '@ckeditor/ckeditor5-core', version: '0.5.0' } ); - // @ckeditor/ckeditor5-utils - stubs.versions.getLastFromChangelog.onSecondCall().returns( '1.0.0' ); - stubs.versions.getLastTagFromGit.onSecondCall().returns( '1.0.0' ); - stubs.getPackageJson.onSecondCall().returns( {} ); + // @ckeditor/ckeditor5-engine + stubs.getPackageJson.onSecondCall().returns( { + name: '@ckeditor/ckeditor5-engine', + version: '1.0.0' + } ); + + sandbox.stub( process, 'cwd' ).returns( '/cwd' ); + + const changes = [ + '[@ckeditor/ckeditor5-core](npm link): v0.5.0 => [v1.0.0](GitHub link)' + ].join( '\n' ); - return getPackagesToRelease( packagesToCheck ) + return getPackagesToRelease( packagesToCheck, { changes, version: '2.0.0' } ) .then( packages => { - expect( packages.size ).to.equal( 1 ); + expect( packages.size ).to.equal( 2 ); + + expect( stubs.chdir.calledThrice ).to.equal( true ); + expect( stubs.chdir.firstCall.args[ 0 ] ).to.match( /^\/packages\/ckeditor5-core$/ ); + expect( stubs.chdir.secondCall.args[ 0 ] ).to.match( /^\/packages\/ckeditor5-engine$/ ); + expect( stubs.chdir.thirdCall.args[ 0 ] ).to.equal( '/cwd' ); - expect( packages.get( '@ckeditor/ckeditor5-utils' ) ).to.equal( undefined ); + const corePackageDetails = packages.get( '@ckeditor/ckeditor5-core' ); + expect( corePackageDetails.version ).to.equal( '1.0.0' ); + + const enginePackageDetails = packages.get( '@ckeditor/ckeditor5-engine' ); + expect( enginePackageDetails.version ).to.equal( '2.0.0' ); } ); } ); } ); From 0f876ec9610fd5626f03106f5c6e973a7b393070 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Thu, 14 May 2020 12:01:51 +0200 Subject: [PATCH 4/7] Fixed regexp for receiving new version. Now it includes new packages. --- .../utils/getpackagestorelease.js | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/packages/ckeditor5-dev-env/lib/release-tools/utils/getpackagestorelease.js b/packages/ckeditor5-dev-env/lib/release-tools/utils/getpackagestorelease.js index 7b98dbb11..2e39ac4ad 100644 --- a/packages/ckeditor5-dev-env/lib/release-tools/utils/getpackagestorelease.js +++ b/packages/ckeditor5-dev-env/lib/release-tools/utils/getpackagestorelease.js @@ -53,18 +53,32 @@ module.exports = function getPackagesToRelease( pathsToPackages, options ) { // Search for a new version for specified package in the main changelog description. // It must be defined as following: // -// [packageName](https://www.npmjs.com/package/packageName): v0.0.1 => [v1.0.0](https://github.com/.../releases/tag/v1.0.0) +// [packageName](https://www.npmjs.com/package/packageName): v0.0.1 => v1.0.0 // // where: // `v0.0.1` is the current version (already published), // `v1.0.0` is the new version what we're looking for. // +// or: +// +// [packageName](https://www.npmjs.com/package/packageName): v0.0.1 +// +// where: +// `v0.0.1` is the current version (not published yet), +// // @param {String} changelog Changes. // @param {String} packageName Package to look. // @returns {String|null} `null` if the version was not found. function findVersionInChangelog( changelog, packageName ) { - const versionRegexp = new RegExp( `\\[${ packageName.replace( '/', '\\/' ) }\\].*\\[v([\\d.]+)\\]` ); - const match = changelog.match( versionRegexp ); + const existingPackageRegExp = new RegExp( `\\[${ packageName.replace( '/', '\\/' ) }\\].*v[\\d.]+\\ => v([\\d.]+)` ); + let match = changelog.match( existingPackageRegExp ); + + if ( match ) { + return match[ 1 ]; + } + + const newPackageRegExp = new RegExp( `\\[${ packageName.replace( '/', '\\/' ) }\\].*v([\\d.]+)` ); + match = changelog.match( newPackageRegExp ); return match ? match[ 1 ] : null; } From 06a6e57c0823ea6b4019515e636a97b01241b314 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Thu, 14 May 2020 12:27:44 +0200 Subject: [PATCH 5/7] Fixed a deprecated warning. --- .../lib/release-tools/tasks/releasesubrepositories.js | 4 ++-- .../lib/release-tools/utils/creategithubrelease.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/ckeditor5-dev-env/lib/release-tools/tasks/releasesubrepositories.js b/packages/ckeditor5-dev-env/lib/release-tools/tasks/releasesubrepositories.js index e6c29b5b1..a07b7bef1 100644 --- a/packages/ckeditor5-dev-env/lib/release-tools/tasks/releasesubrepositories.js +++ b/packages/ckeditor5-dev-env/lib/release-tools/tasks/releasesubrepositories.js @@ -17,7 +17,7 @@ const executeOnPackages = require( '../utils/executeonpackages' ); const { getChangesForVersion } = require( '../utils/changelog' ); const getPackageJson = require( '../utils/getpackagejson' ); const getSubPackagesPaths = require( '../utils/getsubpackagespaths' ); -const GitHubApi = require( '@octokit/rest' ); +const { Octokit } = require( '@octokit/rest' ); const PACKAGE_JSON_TEMPLATE_PATH = require.resolve( '../templates/release-package.json' ); const BREAK_RELEASE_MESSAGE = 'You aborted publishing the release. Why? Oh why?!'; @@ -199,7 +199,7 @@ module.exports = function releaseSubRepositories( options ) { if ( releaseOptions.github ) { // Because `octokit.authenticate()` is deprecated, the entire API object is created here. - github = new GitHubApi( { + github = new Octokit( { version: '3.0.0', auth: `token ${ releaseOptions.token }` } ); diff --git a/packages/ckeditor5-dev-env/lib/release-tools/utils/creategithubrelease.js b/packages/ckeditor5-dev-env/lib/release-tools/utils/creategithubrelease.js index 69731d648..b714b35ed 100644 --- a/packages/ckeditor5-dev-env/lib/release-tools/utils/creategithubrelease.js +++ b/packages/ckeditor5-dev-env/lib/release-tools/utils/creategithubrelease.js @@ -5,7 +5,7 @@ 'use strict'; -const GitHubApi = require( '@octokit/rest' ); +const { Octokit } = require( '@octokit/rest' ); /** * Create a Github release. @@ -19,7 +19,7 @@ const GitHubApi = require( '@octokit/rest' ); * @returns {Promise} */ module.exports = function createGithubRelease( token, options ) { - const github = new GitHubApi( { + const github = new Octokit( { version: '3.0.0', auth: `token ${ token }` } ); From c456a0e70f95a46741bdf0d3b0e9473f9e15ab37 Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Thu, 14 May 2020 12:28:07 +0200 Subject: [PATCH 6/7] Introduced an option to skip releasing packages on NPM. --- .../tasks/releasesubrepositories.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/ckeditor5-dev-env/lib/release-tools/tasks/releasesubrepositories.js b/packages/ckeditor5-dev-env/lib/release-tools/tasks/releasesubrepositories.js index a07b7bef1..0b829d850 100644 --- a/packages/ckeditor5-dev-env/lib/release-tools/tasks/releasesubrepositories.js +++ b/packages/ckeditor5-dev-env/lib/release-tools/tasks/releasesubrepositories.js @@ -87,7 +87,7 @@ const additionalFiles = [ * @param {Object} [options.packageJsonForEmptyReleases={}] Additional fields that will be added to `package.json` for packages which * will publish an empty directory. All properties copied from original package's "package.json" file will be overwritten by fields * specified in this option. - * @param {Boolean} [options.skipMainRepository=false] If set on true, package found in "cwd" will be skipped. + * @param {Array.} [options.skipNpmPublish=[]] Name of packages that should not be published on NPM. * @returns {Promise} */ module.exports = function releaseSubRepositories( options ) { @@ -118,6 +118,9 @@ module.exports = function releaseSubRepositories( options ) { const releasesOnGithub = new Set(); const emptyReleasesOnNpm = new Map(); + // A list of packages that should not be published on NPM. + const skipNpmPublish = new Set( options.skipNpmPublish || [] ); + // List of packages that were released on NPM or/and GitHub. const releasedPackages = new Set(); @@ -310,9 +313,16 @@ module.exports = function releaseSubRepositories( options ) { releaseDetails.shouldReleaseOnNpm = npmVersion !== releaseDetails.version; if ( releaseDetails.shouldReleaseOnNpm ) { - log.info( '✅ Added to release.' ); + if ( skipNpmPublish.has( packageJson.name ) ) { + releaseDetails.shouldReleaseOnNpm = false; + log.warning( '⚠️ Skipping because the package was listed as `options.skipNpmPublish`.' ); - releasesOnNpm.add( repositoryPath ); + return Promise.resolve(); + } else { + log.info( '✅ Added to release.' ); + + releasesOnNpm.add( repositoryPath ); + } } else { log.info( '❌ Nothing to release.' ); } From 1835a7e6da6ab588defbbc97e046bbb2a651483a Mon Sep 17 00:00:00 2001 From: Kamil Piechaczek Date: Thu, 14 May 2020 12:40:00 +0200 Subject: [PATCH 7/7] Fixed a test. --- .../release-tools/utils/creategithubrelease.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/ckeditor5-dev-env/tests/release-tools/utils/creategithubrelease.js b/packages/ckeditor5-dev-env/tests/release-tools/utils/creategithubrelease.js index 75cd6782b..bde19bb34 100644 --- a/packages/ckeditor5-dev-env/tests/release-tools/utils/creategithubrelease.js +++ b/packages/ckeditor5-dev-env/tests/release-tools/utils/creategithubrelease.js @@ -28,13 +28,15 @@ describe( 'dev-env/release-tools/tasks', () => { warnOnUnregistered: false } ); - mockery.registerMock( '@octokit/rest', function GitHubApi( options ) { - octokitOptions = options; - - this.authenticate = stubs.authenticate; - this.repos = { - createRelease: stubs.createRelease - }; + mockery.registerMock( '@octokit/rest', { + Octokit: function GitHubApi( options ) { + octokitOptions = options; + + this.authenticate = stubs.authenticate; + this.repos = { + createRelease: stubs.createRelease + }; + } } ); createGithubRelease = require( '../../../lib/release-tools/utils/creategithubrelease' );