Gutenberg Release Process

This Repository is used to perform several types of releases. This document serves as a checklist for each one of these. It is helpful if you’d like to understand the different workflows.

To release Gutenberg, you need commit access to the plugin repository as well as being part of the WordPress organization at npm. 🙂

Plugin Releases


We release a new major version approximately every two weeks. The current and next versions are tracked in GitHub milestones, along with each version’s tagging date (the day when the release candidate is to be tagged).

  • On the date of the current milestone, we publish a release candidate and make it available for plugin authors and users to test. If any regressions are found with a release candidate, a new one can be published. On this date, all remaining PRs on the milestone are moved automatically to the next release. Release candidates should be versioned incrementally, starting with -rc.1, then -rc.2, and so on.
  • Two days after the first release candidate, the stable version is created based on the last release candidate and any necessary regression fixes. Once the stable version is released, a post like this describing the changes and performing a performance audit is published.

If critical bugs are discovered on stable versions of the plugin, patch versions can be released at any time.

Release Tool

Note that at the time of writing, the tool doesn’t support releasing consecutive RC releases. However, it is possible to use the tool for patch releases following the first stable release.

The plugin release process is entirely automated. To release the RC version of the plugin, run the following command and follow the instructions:

./bin/plugin/cli.js rc

To release a stable version, run:

./bin/plugin/cli.js stable

During the release process, you’ll be asked to provide:

  • A changelog: prepare one beforehand by following the instructions below.
  • personal access token: have one ready beforehand by visiting this page, if you haven’t got one yet.
  • User and password for your GitHub account: if 2FA is enabled for your account (it should), you need to provide a personal access token instead of password (you can use the one necessary for the release).

Manual Release Process

Creating the first Release Candidate

Releasing the first release candidate for this milestone (x.x) involves:

  1. writing a release blog post and changelog
  2. creating the release branch
  3. bumping the version and tagging the release
  4. building the plugin
  5. publishing the release to GitHub
  6. publishing the call for testing
Writing the Release Post and Changelog

To generate a changelog for a release, use the changelog generator tool:

npm run changelog

By default, this will search for and organize all pull requests associated with the milestone for the next version of the project.

To override the default behavior, you can pass one or both of the following options. Remember to use -- to let NPM pass the options to the script.

  • --milestone <milestone>: Provide the title of the milestone for which the changelog should be generated. This should exactly match the title as shown on the milestones page.
    • Example: npm run changelog -- --milestone="Gutenberg 8.1"
  • --token <token>: Provide a GitHub personal access token for authenticating requests. This should only be necessary if you run the script frequently enough to been blocked by rate limiting.
    • Example: npm run changelog -- --token="..."

The script will output a generated changelog, grouped by pull request label. Note that this is intended to be a starting point for release notes. You will still want to manually review and curate the changelog entries.

Guidelines for proof-reading include:

  • Fix spelling errors or clarify wording. Phrasing should be easy to understand where the intended audience are those who use the plugin or are keeping up with ongoing development.
  • Create new groupings as applicable, and move pull requests between.
  • When multiple pull requests relate to the same task (such as a follow-up pull request), try to combine them to a single entry.
  • If subtasks of a related set of pull requests are substantial, consider organizing as entries in a nested list.
  • Remove mobile app pull request entries.

Once you have cleaned up the changelog, choose a few features to highlight in the release post and record an animation of them in use.

You should also include a performance audit at the end of the release post. You can use bin/plugin/cli.js perf to automatically do this.

Compile this to a draft post on; this post should be published after the actual release.

Creating the Release Branch

For each milestone (let’s assume it’s x.x here), a release branch is used to release all RCs and minor releases. For the first RC of the milestone, a release branch is created from master.

git checkout master
git checkout -b release/x.x
git push origin release/x.x
Bumping the Version and Tagging the Release
  1. Checkout the release/x.x branch.
  2. Create a commit like this, bumping the version number in gutenberg.phppackage.json, and package-lock.json to x.x.0-rc.1.
  3. Create a Pull Request from the release branch into master using the changelog as a description and ensure the tests pass properly.
  4. Tag the RC version. git tag vx.x.0-rc.1 from the release branch.
  5. Push the tag git push --tags.
  6. Merge the version bump pull request and avoid removing the release branch.
Build the Plugin
  1. Run git fetch --tags.
  2. Check out the tag for this release, you should run git checkout vx.x.0-rc.1.
  3. Run npm run build:plugin-zip from the root of project. This packages a zip file with a release build of
Publish the Release on GitHub
  1. Create a new release on GitHub.
  2. If you were releasing the x.x.0-rc.1 release candidate, label it x.x.0-rc.1 and use the vx.x.x-rc.1 as a tag.
  3. Upload the file into the release.
  4. Use the changelog as a description of the release.
  5. Publish the release.

Here’s an example release candidate page; yours should look like that when you’re finished.

Creating Release Candidate Patches (done via git cherry-pick)

If a bug is found in a release candidate and a fix is committed to master, we should include that fix in a new release candidate. To do this you’ll need to use git cherry-pick to add these changes to the milestone’s release branch. This way only fixes are added to the release candidate and not all the new code that has landed on master since tagging:

  1. Checkout the corresponding release branch with: git checkout release/x.x.
  2. Cherry-pick fix commits (in chronological order) with git cherry-pick [SHA].
  3. Create a commit like this, bumping the version number in gutenberg.phppackage.json, and package-lock.json to x.x.0-rc.2.
  4. Create a Pull Request from the release branch into master using the changelog as a description and ensure the tests pass properly. Note that if there there are merge conflicts, Travis CI will not run on the PR. Run tests locally using npm run test and npm run test-e2e if this happens.
  5. Tag the RC version. git tag vx.x.0-rc.2 from the release branch.
  6. Push the tag git push --tags.
  7. Create a branch for bumping the version number. git checkout -b bump/x.x.
  8. Create a Pull Request from the bump/x.x branch into master using the changelog as a description.
  9. Merge the version bump pull request.
  10. Follow the steps in build the plugin and publish the release on GitHub.

You can copy the existing changelog from the previous release candidate. Let other contributors know that a new release candidate has been released in the #core-editor channel and the call for testing post.

Official Gutenberg Releases™

The process of releasing Gutenberg is similar to creating a release candidate, except we don’t use the -rc.X in the git tag and we publish a new branch in the subversion repository. This updates the version available in the WordPress plugin repository and will cause WordPress sites around the world to prompt users to update to this new version.

Creating a Release

Creating a release involves:

  1. verifying the release blog post and changelog
  2. bumping the version
  3. building the plugin
  4. publishing the new release to GitHub
  5. committing to the plugin repository
  6. publishing the release blog post
Verifying the Release Post and Changelog
  1. Check the draft post on; make sure the changelog reflects what’s shipping in the release.
Bumping the Version
  1. Checkout the release branch git checkout release/x.x.

Note: This branch should never be removed or rebased. When we want to merge something from it to master and conflicts exist/may exist we use a temporary branch bump/x.x.

  1. Create a commit like this, removing the -rc.X from the version number in gutenberg.phppackage.json, and package-lock.json.
  2. Create a new branch called bump/x.x from release/x.x and switch to it: git checkout -b bump/x.x.
  3. Create a pull request from bump/x.x to master. Verify the continuous integrations tests pass, before continuing to the next step even if conflicts exist.
  4. Rebase bump/x.x against origin/master using git fetch origin && git rebase origin/master.
  5. Force push the branch bump/x.x using git push --force-with-lease.
  6. Switch to the release/x.x branch. Tag the version from the release branch git tag vx.x.0.
  7. Push the tag git push --tags.
  8. Merge the version bump pull request.
Build the Plugin
  1. Run git fetch --tags.
  2. Check out the tag for this release, you should run git checkout vx.x.0.
  3. Run npm run build:plugin-zip from the root of project. This packages a zip file with a release build of
Publish the Release on GitHub
  1. Create a new release on GitHub.
  2. If you were releasing the x.x.0 release candidate, label it x.x.0 and use the vx.x.x as a tag.
  3. Upload the a file into the release.
  4. Use the changelog as a description of the release.
  5. Publish the release.
Commit to the Plugin Repository

You’ll need to use Subversion to publish the plugin to

  1. Do an SVN checkout of
  • If this is your first checkout, run: svn checkout
  • If you already have a copy, run: svn up
  1. Delete the contents except for the readme.txt and changelog.txt files (these files don’t exist in the git repo, only in Subversion).
  2. Extract the contents of the zip file.
  3. Edit readme.txt, replacing the changelog for the previous version with the current release’s changelog.
  4. Add the changelog for the current release to changelog.txt.
  5. Add new files/remove deleted files from the repository:
# Add new files:
svn st | grep '^\?' | awk '{print $2}' | xargs svn add # add the -r option to xargs if you use a linux-based OS
# Delete old files:
svn st | grep '^!' | awk '{print $2}' | xargs svn rm # add the -r option to xargs if you use a linux-based OS
  1. Commit the new version:
# Replace X.X.X with your version:
svn ci -m "Committing Gutenberg version X.X.X"
  1. Tag the new version:
svn cp -m "Tagging Gutenberg version X.X.X"
  1. Edit readme.txt to point to the new tag. The Stable version header in readme.txt should be updated to match the new release version number. After updating and committing that, the new version should be released:
svn ci -m "Releasing Gutenberg version X.X.X"

This will cause the new version to be available to users of WordPress all over the globe! 💃

You should check that folks are able to install the new version from their Dashboard.

Publish the Release Blog Post

  1. Publish the make/core release blog post drafted earlier.
  2. Pat yourself on the back! 👍

If you don’t have access to, ping someone on the Gutenberg Core team in the WordPress #core-editor Slack channel to publish the post.

Packages Releases and WordPress Core Updates

The Gutenberg repository mirrors the WordPress SVN repository in terms of branching for each SVN branch, a corresponding Gutenberg wp/* branch is created:

  • The wp/trunk branch contains all the packages that are published and used in the trunk branch of WordPress.
  • A Gutenberg branch targeting a specific WordPress major release (including its further minor increments) is created (example wp/5.2) based on the wp/trunk Gutenberg branch when the corresponding WordPress release branch is created. (This usually happens when the first RC of the next WordPress major version is released).

Synchronizing WordPress Trunk

For each Gutenberg plugin release, WordPress trunk should be synchronized. Note that the WordPress trunk branch can be closed or in “feature-freeze” mode. Usually, this happens between the first beta and the first RC of the WordPress release cycle. During this period, the Gutenberg plugin releases should not be synchronized with WordPress Core.

The process has three steps: 1) update the wp/trunk branch within the Gutenberg repo 2) publish the new package versions to npm 3) update the WordPress trunk branch.

The first step is automated via ./bin/plugin/cli.js npm-stable command. You only have to run the command, but, for the record, the manual process would look like this:

  1. Ensure the WordPress trunk branch is open for enhancements.
  2. Get the last published Gutenberg release branch with git fetch.
  3. Check out the wp/trunk branch.
  4. Remove all files from the current branch: git rm -r ..
  5. Check out all the files from the release branch: git checkout release/x.x -- ..
  6. Commit all changes to the wp/trunk branch with git commit -m "Merge changes published in the Gutenberg plugin vX.X release" and push to the repository.
  7. Update the files of the packages with the new publish version calculated and commit to the wp/trunk branch. Assuming the package versions are written using this format major.minor.patch, make sure to bump at least the minor version number. For example, if the CHANGELOG of the package to be released indicates that the next unreleased version is 5.6.1, choose 5.7.0 as a version in case of minor version. This is important as the patch version numbers should be reserved in case bug fixes are needed for a minor WordPress release (see below).

Once the command is finished, you can start the second part: publishing the npm packages.

  1. Update your local wp/trunk branch with the latest changes pushed to GitHub.
  2. Log-in to npm via the console: npm login. Note that you should have 2FA enabled.
  3. From the wp/trunk branch, run the script npm run publish:prod.
    • When asked for the version numbers to choose for each package pick the values of the updated CHANGELOG files.
    • You’ll be asked for your One-Time Password (OTP) a couple of times. This is the code from the 2FA authenticator app you use. Depending on how many packages are to be released you may be asked for more than one OTP, as they tend to expire before all packages are released.
    • If the publishing process ends up incomplete (perhaps because it timed-out or an bad OTP was introduce) you can resume it via lerna publish from-package.
  4. Cherry-pick the commits created by lerna (“Publish” and the CHANGELOG update) into the master branch of Gutenberg.

Finally, now that the npm packages are ready, a patch can be created and committed into WordPress trunk.

Minor WordPress Releases

The following workflow is needed when bug fixes or security releases need to be backported into WordPress Core. This can happen in a few use-cases:

  • During the beta and the RC period of the WordPress release cycle.
  • For WordPress minor releases and WordPress security releases (example 5.1.1).
  1. Check out the relevant WordPress major branch (If the minor release is 5.2.1, check out wp/5.2).
  2. Create a feature branch from that branch, and cherry-pick the merge commits for the needed bug fixes onto it.
  3. Create a Pull Request from this branch targeting the WordPress major branch used above.
  4. Merge the Pull Request using the “Rebase and Merge” button to keep the history of the commits.

Now, the branch is ready to be used to publish the npm packages.

  1. Check out the WordPress branch used before (Example wp/5.2).
  2. git pull.
  3. Run the package release process but when asked for the version numbers to choose for each package, (assuming the package versions are written using this format major.minor.patch) make sure to bump only the patch version number. For example, if the last published package version for this WordPress branch was 5.6.0, choose 5.6.1 as a version.

Note: For WordPress 5.0 and WordPress 5.1, a different release process was used. This means that when choosing npm package versions targeting these two releases, you won’t be able to use the next patch version number as it may have been already used. You should use the “metadata” modifier for these. For example, if the last published package version for this WordPress branch was 5.6.1, choose 5.6.1+patch.1 as a version.

  1. Update the files of the published packages with the new released versions and commit to the corresponding branch (Example wp/5.2).
  2. Cherry-pick the CHANGELOG update commits into the master branch of Gutenberg.

Now, the npm packages should be ready and a patch can be created and committed into the corresponding WordPress SVN branch.

Standalone Package Releases

The following workflow is needed when packages require bug fixes or security releases to be published to npm outside of a WordPress release cycle.

Note: Both the master and wp/trunk branches are restricted and can only be pushed to by the Gutenberg Core team.

Identify the commit hashes from the pull requests that need to be ported from the repo master branch to wp/trunk

The wp/trunk branch now needs to be prepared to release and publish the packages to npm.

Open a terminal and perform the following steps:

  1. git checkout master
  2. git pull
  3. git checkout wp/trunk
  4. git pull

Before porting commits check that the wp/trunk branch does not have any outstanding packages waiting to be published:

  1. git checkout wp/trunk
  2. npm run publish:check

Now cherry-pick the commits from master to wp/trunk, use -m 1 commithash if the commit was a pull request merge commit:

  1. git cherry-pick -m 1 cb150a2
  2. git push

Whilst waiting for the GitHub actions build for wp/trunkbranch to pass, identify and begin updating the files:

  1. git checkout wp/trunk
  2. npm run publish:check


npm run publish:check
lerna success found 3 packages ready to publish

Check the versions listed in the current file, looking through the commit history of a package e.g @wordpress/scripts and look out for “chore(release): publish” and “Update changelogs” commits to determine recent version bumps, then looking at the commits since the most recent release should aid with discovering what changes have occurred since the last release.

Note: You may discover the current version of each package is not up to date, if so updating the previous released versions would be appreciated.

Begin updating the changelogs based on the Maintaining Changelogs documentation and commit the changes:

  1. git checkout wp/trunk
  2. Update each of the files
  3. Stage the changelog changes git add packages/
  4. git commit -m "Update changelogs"
  5. Make a note of the commit hash of this commit


[master 278f524f16] Update changelogs` 278f524
  1. git push

Now that the changes have been committed to the wp/trunk branch and the Travis CI builds for the wp/trunk branch are passing it’s time to publish the packages to npm:

  1. Once again run npm run publish:check to confirm there are no unexpected packages ready to be published:


npm run publish:check
lerna success found 3 packages ready to publish
  1. Run the package release process but when asked for the version numbers to choose for each package use the versions you made note of above when updating each packages file.

Truncated example of publishing process output

npm run publish:prod

Build Progress: [==============================] 100%
lerna notice cli v3.18.2
lerna info versioning independent
? Select a new version for @wordpress/e2e-tests (currently 1.9.0) Patch (1.9.1)
? Select a new version for @wordpress/jest-preset-default (currently 5.3.0) Patch (5.3.1)
? Select a new version for @wordpress/scripts (currently 6.1.0) Patch (6.1.1)

 - @wordpress/e2e-tests: 1.9.0 => 1.9.1
 - @wordpress/jest-preset-default: 5.3.0 => 5.3.1
 - @wordpress/scripts: 6.1.0 => 6.1.1

? Are you sure you want to publish these packages? Yes
lerna info execute Skipping releases
lerna info git Pushing tags...
lerna info publish Publishing packages to npm...
lerna info Verifying npm credentials
lerna info Checking two-factor auth mode
? Enter OTP: 753566
lerna success published @wordpress/jest-preset-default 5.3.1
lerna success published @wordpress/scripts 6.1.1
lerna success published @wordpress/e2e-tests 1.9.1
Successfully published:
 - @wordpress/e2e-tests@1.9.1
 - @wordpress/jest-preset-default@5.3.1
 - @wordpress/scripts@6.1.1
lerna success published 3 packages

Now that the packages have been published the “chore(release): publish” and “Update changelogs” commits to wp/trunk need to be ported to the master branch:

  1. git checkout master
  2. git pull
  3. Cherry-pick the 278f524hash you noted above from the “Update changelogs” commit made to wp/trunk
  4. git cherry-pick 278f524
  5. Get the commit hash from the the lerna publish commit either from the terminal or wp/trunk commits
  6. Cherry-pick the fe6ae0d “chore(release): publish”_ commit made to wp/trunk
  7. git cherry-pick fe6ae0d
  8. git push

Confirm the packages dependencies do not contain file:// links in the dependencies or devdependencies section of the packages released, e.g:

Time to announce the published changes in the #core-js and #core-editor Slack channels

📣 Successfully published:
• @wordpress/e2e-tests@1.9.1
• @wordpress/jest-preset-default@5.3.1
• @wordpress/scripts@6.1.1
Lerna success published 3 packages

Ta-da! 🎉