diff --git a/.gitignore b/.gitignore index 8e1653fe..8d4a4246 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ coverage/ node_modules/ yarn.lock .idea +/release/ diff --git a/README.md b/README.md index ddf96be3..f63f974b 100644 --- a/README.md +++ b/README.md @@ -125,19 +125,15 @@ After generating the changelog, you are ready for publishing packages. First, you need to bump their versions: ```bash -npm run release:bump-version +npm run release:prepare-packages ``` -You can also use the `--dry-run` option to see what this task does. - After bumping versions, you can publish changes: ```bash -npm run release:publish +npm run release:publish-packages ``` -As in the previous task, the `--dry-run` option is also available. - ## License The `ckeditor5-package-generator` tool is available under [MIT license](https://opensource.org/licenses/MIT). diff --git a/package.json b/package.json index 5199177e..ce7961df 100644 --- a/package.json +++ b/package.json @@ -17,18 +17,20 @@ "license": "MIT", "homepage": "https://ckeditor.com/ckeditor-5", "devDependencies": { - "@ckeditor/ckeditor5-dev-bump-year": "^35.0.0", - "@ckeditor/ckeditor5-dev-ci": "^35.0.0", - "@ckeditor/ckeditor5-dev-release-tools": "^35.0.0", - "@ckeditor/ckeditor5-dev-web-crawler": "^35.0.0", + "@ckeditor/ckeditor5-dev-bump-year": "^38.0.0", + "@ckeditor/ckeditor5-dev-ci": "^38.0.0", + "@ckeditor/ckeditor5-dev-release-tools": "^38.0.0", + "@ckeditor/ckeditor5-dev-web-crawler": "^38.0.0", "chalk": "^4.1.2", "eslint": "^7.32.0", "eslint-config-ckeditor5": "^4.0.0", + "glob": "^10.2.5", "husky": "^8.0.2", "lint-staged": "^10.5.4", "mocha": "^9.1.1", "nyc": "^15.1.0", - "strip-ansi": "^6.0.1" + "strip-ansi": "^6.0.1", + "upath": "^2.0.1" }, "engines": { "node": ">=16.0.0", @@ -40,8 +42,8 @@ "coverage": "nyc npm run test", "lint": "eslint --quiet \"**/*.js\"", "precommit": "lint-staged", - "release:bump-version": "node scripts/release/bump-versions.js", - "release:publish": "node scripts/release/publish.js", + "release:prepare-packages": "node scripts/release/preparepackages.js", + "release:publish-packages": "node scripts/release/publishpackages.js", "test": "mocha 'packages/*/tests/**/*.js'", "clean": "npx rimraf package-lock.json yarn.lock ./**/node_modules", "reinstall": "yarn run clean && yarn install" diff --git a/packages/ckeditor5-package-generator/package.json b/packages/ckeditor5-package-generator/package.json index b429f0a6..56281c0f 100644 --- a/packages/ckeditor5-package-generator/package.json +++ b/packages/ckeditor5-package-generator/package.json @@ -10,7 +10,7 @@ "node": ">=16.0.0" }, "dependencies": { - "@ckeditor/ckeditor5-dev-utils": "^35.0.0", + "@ckeditor/ckeditor5-dev-utils": "^38.0.0", "chalk": "^4.1.2", "commander": "^8.1.0", "glob": "^7.1.7", @@ -20,6 +20,7 @@ "webpack": "^5.67.0" }, "files": [ + "bin", "lib" ], "bin": { diff --git a/packages/ckeditor5-package-tools/package.json b/packages/ckeditor5-package-tools/package.json index d46a6501..105f3c22 100644 --- a/packages/ckeditor5-package-tools/package.json +++ b/packages/ckeditor5-package-tools/package.json @@ -11,9 +11,9 @@ ], "main": "lib/index.js", "dependencies": { - "@ckeditor/ckeditor5-dev-transifex": "^35.0.0", - "@ckeditor/ckeditor5-dev-translations": "^35.0.0", - "@ckeditor/ckeditor5-dev-utils": "^35.0.0", + "@ckeditor/ckeditor5-dev-transifex": "^38.0.0", + "@ckeditor/ckeditor5-dev-translations": "^38.0.0", + "@ckeditor/ckeditor5-dev-utils": "^38.0.0", "buffer": "^6.0.3", "chai": "^4.3.4", "css-loader": "^5.2.7", diff --git a/scripts/release/bump-versions.js b/scripts/release/bump-versions.js deleted file mode 100755 index 93c3bc94..00000000 --- a/scripts/release/bump-versions.js +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env node - -/** - * @license Copyright (c) 2020-2023, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -/* eslint-env node */ - -'use strict'; - -// This scripts preparing all packages to release: -// - checking what should be released, -// - updates version of all dependencies for all packages, -// - validates the whole process (whether the changes could be published), -// - tagging new versions. -// -// You can test the whole process using `dry-run` mode. It won't change anything in the project -// and any repository. -// -// This task must be called before: `yarn run release:publish`. -// -// Use: -// yarn run release:bump-version --dry-run - -require( '@ckeditor/ckeditor5-dev-release-tools' ) - .bumpVersions( { - cwd: process.cwd(), - packages: 'packages', - dryRun: process.argv.includes( '--dry-run' ) - } ); diff --git a/scripts/release/preparepackages.js b/scripts/release/preparepackages.js new file mode 100644 index 00000000..0c6941e0 --- /dev/null +++ b/scripts/release/preparepackages.js @@ -0,0 +1,106 @@ +#!/usr/bin/env node + +/** + * @license Copyright (c) 2020-2023, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +/* eslint-env node */ + +'use strict'; + +const { Listr } = require( 'listr2' ); +const releaseTools = require( '@ckeditor/ckeditor5-dev-release-tools' ); +const parseArguments = require( './utils/parsearguments' ); +const { PACKAGE_GENERATOR_ROOT, PACKAGES_DIRECTORY, RELEASE_DIRECTORY } = require( './utils/constants' ); +const upath = require( 'upath' ); +const { globSync } = require( 'glob' ); + +const cliArguments = parseArguments( process.argv.slice( 2 ) ); +const latestVersion = releaseTools.getLastFromChangelog(); +const versionChangelog = releaseTools.getChangesForVersion( latestVersion ); + +const PACKAGE_GENERATOR_PACKAGES_NAMES = globSync( '*/', { + cwd: upath.join( PACKAGE_GENERATOR_ROOT, PACKAGES_DIRECTORY ), + absolute: true +} ).map( packagePath => { + return require( upath.join( packagePath, 'package.json' ) ).name; +} ); + +const tasks = new Listr( [ + { + title: 'Verifying the repository.', + task: async () => { + const errors = await releaseTools.validateRepositoryToRelease( { + version: latestVersion, + changes: versionChangelog, + branch: 'master' + } ); + + if ( !errors.length ) { + return; + } + + return Promise.reject( 'Aborted due to errors.\n' + errors.map( message => `* ${ message }` ).join( '\n' ) ); + } + }, + { + title: 'Updating the `#version` field.', + task: () => { + return releaseTools.updateVersions( { + packagesDirectory: PACKAGES_DIRECTORY, + version: latestVersion + } ); + } + }, + { + title: 'Updating dependencies.', + task: () => { + return releaseTools.updateDependencies( { + version: '^' + latestVersion, + packagesDirectory: PACKAGES_DIRECTORY, + shouldUpdateVersionCallback: packageName => { + return PACKAGE_GENERATOR_PACKAGES_NAMES.includes( packageName ); + } + } ); + } + }, + { + title: 'Copying `package-generator` packages to the release directory.', + task: () => { + return releaseTools.prepareRepository( { + outputDirectory: RELEASE_DIRECTORY, + packagesDirectory: PACKAGES_DIRECTORY, + packagesToCopy: cliArguments.packages + } ); + } + }, + { + title: 'Cleaning-up.', + task: () => { + return releaseTools.cleanUpPackages( { + packagesDirectory: RELEASE_DIRECTORY + } ); + } + }, + { + title: 'Commit & tag.', + task: () => { + return releaseTools.commitAndTag( { + version: latestVersion, + files: [ + 'package.json', + `${ PACKAGES_DIRECTORY }/*/package.json` + ] + } ); + } + } +] ); + +tasks.run() + .catch( err => { + process.exitCode = 1; + + console.log( '' ); + console.error( err ); + } ); diff --git a/scripts/release/publish.js b/scripts/release/publish.js deleted file mode 100755 index bf004b7c..00000000 --- a/scripts/release/publish.js +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env node - -/** - * @license Copyright (c) 2020-2023, CKSource Holding sp. z o.o. All rights reserved. - * For licensing, see LICENSE.md. - */ - -/* eslint-env node */ - -'use strict'; - -const rootPackageJson = require( '../../package.json' ); - -// This scripts publish changes. -// -// You can test the whole process using `dry-run` mode. It won't change anything in the project -// and any repository. Nothing will be pushed. Instead of `npm publish`, the `npm pack` command will be called. -// -// Note: This task based on versions published on NPM and GitHub. If something went wrong, you can call this script one more time. -// -// This task should be executed after: `yarn run release:bump-version`. -// -// Use: -// yarn run release:publish --dry-run - -require( '@ckeditor/ckeditor5-dev-release-tools' ) - .releaseSubRepositories( { - cwd: process.cwd(), - packages: 'packages', - skipNpmPublish: [ - rootPackageJson.name - ], - dryRun: process.argv.includes( '--dry-run' ) - } ); diff --git a/scripts/release/publishpackages.js b/scripts/release/publishpackages.js new file mode 100644 index 00000000..d083fef2 --- /dev/null +++ b/scripts/release/publishpackages.js @@ -0,0 +1,71 @@ +#!/usr/bin/env node + +/** + * @license Copyright (c) 2020-2023, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +/* eslint-env node */ + +'use strict'; + +const { Listr } = require( 'listr2' ); +const releaseTools = require( '@ckeditor/ckeditor5-dev-release-tools' ); +const { provideToken } = require( '@ckeditor/ckeditor5-dev-release-tools/lib/utils/cli' ); +const parseArguments = require( './utils/parsearguments' ); +const { RELEASE_DIRECTORY } = require( './utils/constants' ); + +const cliArguments = parseArguments( process.argv.slice( 2 ) ); +const latestVersion = releaseTools.getLastFromChangelog(); +const versionChangelog = releaseTools.getChangesForVersion( latestVersion ); + +let githubToken; + +const tasks = new Listr( [ + { + title: 'Publishing packages.', + task: async ( _, task ) => { + return releaseTools.publishPackages( { + packagesDirectory: RELEASE_DIRECTORY, + npmOwner: 'ckeditor', + npmTag: cliArguments.npmTag, + listrTask: task, + confirmationCallback: () => { + return task.prompt( { type: 'Confirm', message: 'Do you want to continue?' } ); + } + } ); + }, + retry: 3 + }, + { + title: 'Pushing changes.', + task: () => { + return releaseTools.push( { + releaseBranch: 'master', + version: latestVersion + } ); + } + }, + { + title: 'Creating the release page.', + task: async ( _, task ) => { + const releaseUrl = await releaseTools.createGithubRelease( { + token: githubToken, + version: latestVersion, + description: versionChangelog + } ); + + task.output = `Release page: ${ releaseUrl }`; + } + } +] ); + +( async () => { + try { + githubToken = await provideToken(); + + await tasks.run(); + } catch ( err ) { + console.error( err ); + } +} )(); diff --git a/scripts/release/utils/constants.js b/scripts/release/utils/constants.js new file mode 100644 index 00000000..66f5402d --- /dev/null +++ b/scripts/release/utils/constants.js @@ -0,0 +1,12 @@ +/** + * @license Copyright (c) 2020-2023, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +const upath = require( 'upath' ); + +module.exports = { + PACKAGES_DIRECTORY: 'packages', + RELEASE_DIRECTORY: 'release', + PACKAGE_GENERATOR_ROOT: upath.join( __dirname, '..', '..', '..' ) +}; diff --git a/scripts/release/utils/parsearguments.js b/scripts/release/utils/parsearguments.js new file mode 100644 index 00000000..75f3c06e --- /dev/null +++ b/scripts/release/utils/parsearguments.js @@ -0,0 +1,47 @@ +/** + * @license Copyright (c) 2020-2023, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +/* eslint-env node */ + +'use strict'; + +const minimist = require( 'minimist' ); + +/** + * @param {Array.} cliArguments + * @returns {ReleaseOptions} options + */ +module.exports = function parseArguments( cliArguments ) { + const config = { + string: [ + 'packages', + 'npm-tag' + ], + + default: { + packages: null, + 'npm-tag': 'latest' + } + }; + + const options = minimist( cliArguments, config ); + + if ( typeof options.packages === 'string' ) { + options.packages = options.packages.split( ',' ); + } + + options.npmTag = options[ 'npm-tag' ]; + delete options[ 'npm-tag' ]; + + return options; +}; + +/** + * @typedef {Object} ReleaseOptions + * + * @property {String} [npmTag='latest'] + * + * @property {Array.|null} packages + */