Skip to content

Commit

Permalink
Packages: Introduce release types to npm publishing script (#33329)
Browse files Browse the repository at this point in the history
* Packages: Introduce release types to npm publishing script

* Select minimum version bump only for a regular publishing

* Add all the necessary changes for the bugfix release type

* Introduce a new command for bugfixes

* Include the confirmation prompt for cherry-picking commits

* Improve the initial prompt for package commands

* Include a note about `npm-bugfix` in the release docs
  • Loading branch information
gziolo authored Jul 13, 2021
1 parent 6d24854 commit c529316
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 64 deletions.
9 changes: 9 additions & 0 deletions bin/plugin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const catchException = ( command ) => {
*/
const {
publishNpmLatestDistTag,
publishNpmBugfixLatestDistTag,
publishNpmNextDistTag,
} = require( './commands/packages' );
const { getReleaseChangelog } = require( './commands/changelog' );
Expand All @@ -34,6 +35,14 @@ program
)
.action( catchException( publishNpmLatestDistTag ) );

program
.command( 'publish-npm-packages-bugfix-latest' )
.alias( 'npm-bugfix' )
.description(
'Publishes bugfixes for packages to npm (latest dist-tag, production version)'
)
.action( catchException( publishNpmBugfixLatestDistTag ) );

program
.command( 'publish-npm-packages-next' )
.alias( 'npm-next' )
Expand Down
177 changes: 117 additions & 60 deletions bin/plugin/commands/packages.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ const {
} = require( './common' );
const git = require( '../lib/git' );

/**
* Release type names.
*
* @typedef {('latest'|'bugfix'|'patch'|'next')} ReleaseType
*/

/**
* Semantic Versioning labels.
*
Expand All @@ -32,27 +38,23 @@ const git = require( '../lib/git' );
* Checks out the WordPress release branch and syncs it with the changes from
* the last plugin release.
*
* @param {string} gitWorkingDirectoryPath Git working directory path.
* @param {boolean} isPrerelease Whether the package version to publish is a prerelease.
* @param {string} abortMessage Abort Message.
* @param {string} gitWorkingDirectoryPath Git working directory path.
* @param {ReleaseType} releaseType Release type selected from CLI.
* @param {string} abortMessage Abort Message.
*
* @return {Promise<Object>} WordPress release branch.
*/
async function runWordPressReleaseBranchSyncStep(
gitWorkingDirectoryPath,
isPrerelease,
releaseType,
abortMessage
) {
const wordpressReleaseBranch = isPrerelease ? 'wp/next' : 'wp/trunk';
const wordpressReleaseBranch =
releaseType === 'next' ? 'wp/next' : 'wp/trunk';
await runStep(
'Getting into the WordPress release branch',
abortMessage,
async () => {
const packageJsonPath = gitWorkingDirectoryPath + '/package.json';
const pluginReleaseBranch = findReleaseBranchName(
packageJsonPath
);

// Creating the release branch
await git.checkoutRemoteBranch(
gitWorkingDirectoryPath,
Expand All @@ -64,27 +66,35 @@ async function runWordPressReleaseBranchSyncStep(
' has been successfully checked out.'
);

await askForConfirmation(
`The branch is ready for sync with the latest plugin release changes applied to "${ pluginReleaseBranch }". Proceed?`,
true,
abortMessage
);
if ( [ 'latest', 'next' ].includes( releaseType ) ) {
const packageJsonPath =
gitWorkingDirectoryPath + '/package.json';
const pluginReleaseBranch = findReleaseBranchName(
packageJsonPath
);

await git.replaceContentFromRemoteBranch(
gitWorkingDirectoryPath,
pluginReleaseBranch
);
await askForConfirmation(
`The branch is ready for sync with the latest plugin release changes applied to "${ pluginReleaseBranch }". Proceed?`,
true,
abortMessage
);

await git.commit(
gitWorkingDirectoryPath,
`Merge changes published in the Gutenberg plugin "${ pluginReleaseBranch }" branch`
);
await git.replaceContentFromRemoteBranch(
gitWorkingDirectoryPath,
pluginReleaseBranch
);

log(
'>> The local WordPress release branch ' +
formats.success( wordpressReleaseBranch ) +
' has been successfully synced.'
);
await git.commit(
gitWorkingDirectoryPath,
`Merge changes published in the Gutenberg plugin "${ pluginReleaseBranch }" branch`
);

log(
'>> The local WordPress release branch ' +
formats.success( wordpressReleaseBranch ) +
' has been successfully synced.'
);
}
}
);

Expand All @@ -97,15 +107,15 @@ async function runWordPressReleaseBranchSyncStep(
* Update CHANGELOG files with the new version number for those packages that
* contain new entries.
*
* @param {string} gitWorkingDirectoryPath Git working directory path.
* @param {SemVer} minimumVersionBump Minimum version bump for the packages.
* @param {boolean} isPrerelease Whether the package version to publish is a prerelease.
* @param {string} abortMessage Abort Message.
* @param {string} gitWorkingDirectoryPath Git working directory path.
* @param {SemVer} minimumVersionBump Minimum version bump for the packages.
* @param {ReleaseType} releaseType Release type selected from CLI.
* @param {string} abortMessage Abort Message.
*/
async function updatePackages(
gitWorkingDirectoryPath,
minimumVersionBump,
isPrerelease,
releaseType,
abortMessage
) {
const changelogFiles = await glob(
Expand Down Expand Up @@ -148,7 +158,7 @@ async function updatePackages(
// the stable minor or major version bump requested.
if (
! versionBump &&
! isPrerelease &&
releaseType !== 'next' &&
minimumVersionBump !== 'patch' &&
productionPackageNames.includes( packageName )
) {
Expand Down Expand Up @@ -207,7 +217,9 @@ async function updatePackages(
content.replace(
'## Unreleased',
`## Unreleased\n\n## ${
isPrerelease ? nextVersion + '-next.0' : nextVersion
releaseType === 'next'
? nextVersion + '-next.0'
: nextVersion
} (${ publishDate })`
)
);
Expand All @@ -225,7 +237,9 @@ async function updatePackages(

log(
` - ${ packageName }: ${ version } -> ${
isPrerelease ? nextVersion + '-next.0' : nextVersion
releaseType === 'next'
? nextVersion + '-next.0'
: nextVersion
}`
);
}
Expand Down Expand Up @@ -274,21 +288,21 @@ async function runPushGitChangesStep(
/**
* Publishes all changed packages to npm.
*
* @param {string} gitWorkingDirectoryPath Git working directory path.
* @param {SemVer} minimumVersionBump Minimum version bump for the packages.
* @param {boolean} isPrerelease Whether the package version to publish is a prerelease.
* @param {string} gitWorkingDirectoryPath Git working directory path.
* @param {SemVer} minimumVersionBump Minimum version bump for the packages.
* @param {ReleaseType} releaseType Release type selected from CLI.
*/
async function publishPackagesToNpm(
gitWorkingDirectoryPath,
minimumVersionBump,
isPrerelease
releaseType
) {
log( '>> Installing npm packages.' );
await command( 'npm ci', {
cwd: gitWorkingDirectoryPath,
} );

if ( isPrerelease ) {
if ( releaseType === 'next' ) {
log(
'>> Bumping version of public packages changed since the last release.'
);
Expand All @@ -306,6 +320,12 @@ async function publishPackagesToNpm(
cwd: gitWorkingDirectoryPath,
stdio: 'inherit',
} );
} else if ( releaseType === 'bugfix' ) {
log( '>> Publishing modified packages to npm.' );
await command( `npm run publish:latest`, {
cwd: gitWorkingDirectoryPath,
stdio: 'inherit',
} );
} else {
log(
'>> Bumping version of public packages changed since the last release.'
Expand All @@ -329,12 +349,18 @@ async function publishPackagesToNpm(
/**
* Prepare everything to publish WordPress packages to npm.
*
* @param {boolean} [isPrerelease] Whether the package version to publish is a prerelease.
* @param {ReleaseType} releaseType Release type selected from CLI.
* @param {SemVer} [minimumVersionBump] Minimum version bump for the packages. Default: `true`.
* @param {string} [confirmationMessage] Confirmation message to show at first.
*
* @return {Promise<Object>} Github release object.
*/
async function prepareForPackageRelease( isPrerelease ) {
await askForConfirmation( 'Ready to go?' );
async function prepareForPackageRelease(
releaseType,
minimumVersionBump = 'patch',
confirmationMessage = 'Ready to go?'
) {
await askForConfirmation( confirmationMessage );

// Cloning the Git repository.
const abortMessage = 'Aborting!';
Expand All @@ -347,24 +373,14 @@ async function prepareForPackageRelease( isPrerelease ) {
// Checking out the WordPress release branch and doing sync with the last plugin release.
const { releaseBranch } = await runWordPressReleaseBranchSyncStep(
gitWorkingDirectoryPath,
isPrerelease,
releaseType,
abortMessage
);

const { minimumVersionBump } = await prompt( [
{
type: 'list',
name: 'minimumVersionBump',
message: 'Select the minimum version bump for packages:',
default: 'patch',
choices: [ 'patch', 'minor', 'major' ],
},
] );

await updatePackages(
gitWorkingDirectoryPath,
minimumVersionBump,
isPrerelease,
releaseType,
abortMessage
);

Expand All @@ -377,7 +393,7 @@ async function prepareForPackageRelease( isPrerelease ) {
await publishPackagesToNpm(
gitWorkingDirectoryPath,
minimumVersionBump,
isPrerelease
releaseType
);

await runCleanLocalFoldersStep( temporaryFolders, 'Cleaning failed.' );
Expand All @@ -395,7 +411,44 @@ async function publishNpmLatestDistTag() {
"To perform a release you'll have to be a member of the WordPress Team on npm.\n"
);

await prepareForPackageRelease();
const minimumVersionBump = await prompt( [
{
type: 'list',
name: 'minimumVersionBump',
message: 'Select the minimum version bump for packages:',
default: 'patch',
choices: [ 'patch', 'minor', 'major' ],
},
] );

await prepareForPackageRelease( 'latest', minimumVersionBump );

log(
'\n>> 🎉 WordPress packages are now published!\n\n',
'Please remember to run `git cherry-pick` in the `trunk` branch for the newly created commits during the release with labels:\n',
' - Update changelog files (if exists)\n',
' - chore(release): publish\n\n',
'Finally, let also people know on WordPress Slack and celebrate together.'
);
}

/**
* Publishes a new latest version of WordPress packages.
*/
async function publishNpmBugfixLatestDistTag() {
log(
formats.title(
'\n💃 Time to publish WordPress packages to npm 🕺\n\n'
),
'Welcome! This tool is going to help you with publishing a new bugfix version of WordPress packages with the latest dist tag.\n',
"To perform a release you'll have to be a member of the WordPress Team on npm.\n"
);

await prepareForPackageRelease(
'bugfix',
'patch',
'Before we proceed, can you confirm that all required changes have beed already cherry-picked to the release branch?'
);

log(
'\n>> 🎉 WordPress packages are now published!\n\n',
Expand All @@ -418,12 +471,16 @@ async function publishNpmNextDistTag() {
"To perform a release you'll have to be a member of the WordPress Team on npm.\n"
);

await prepareForPackageRelease( true );
await prepareForPackageRelease( 'next' );

log(
'\n>> 🎉 WordPress packages are now published!\n',
'Let also people know on WordPress Slack.\n'
);
}

module.exports = { publishNpmLatestDistTag, publishNpmNextDistTag };
module.exports = {
publishNpmLatestDistTag,
publishNpmBugfixLatestDistTag,
publishNpmNextDistTag,
};
Loading

0 comments on commit c529316

Please sign in to comment.