name: Build Gutenberg Plugin Zip on: pull_request: push: branches: - trunk - 'release/**' - 'wp/**' workflow_dispatch: inputs: version: description: 'rc or stable?' required: true # Cancels all previous workflow runs for pull requests that have not completed. concurrency: # The concurrency group contains the workflow name and the branch name for pull requests # or the commit hash for any other events. group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }} cancel-in-progress: true jobs: compute-stable-branches: name: Compute current and next stable release branches runs-on: ubuntu-latest if: ${{ github.event_name == 'workflow_dispatch' }} outputs: current_stable_branch: ${{ steps.get_branches.outputs.current_stable_branch }} next_stable_branch: ${{ steps.get_branches.outputs.next_stable_branch }} steps: - name: Get current and next stable release branches id: get_branches run: | curl \ -H "Accept: application/vnd.github.v3+json" \ -o latest.json \ "https://api.github.com/repos/${{ github.repository }}/releases/latest" LATEST_STABLE_TAG=$(jq --raw-output '.tag_name' latest.json) IFS='.' read LATEST_STABLE_MAJOR LATEST_STABLE_MINOR LATEST_STABLE_PATCH <<< "${LATEST_STABLE_TAG#v}" echo "current_stable_branch=release/${LATEST_STABLE_MAJOR}.${LATEST_STABLE_MINOR}" >> $GITHUB_OUTPUT if [[ ${LATEST_STABLE_MINOR} == "9" ]]; then echo "next_stable_branch=release/$((LATEST_STABLE_MAJOR + 1)).0" >> $GITHUB_OUTPUT else echo "next_stable_branch=release/${LATEST_STABLE_MAJOR}.$((LATEST_STABLE_MINOR + 1))" >> $GITHUB_OUTPUT fi bump-version: name: Bump version runs-on: ubuntu-latest needs: compute-stable-branches if: | github.event_name == 'workflow_dispatch' && ( ( github.ref == 'refs/heads/trunk' || endsWith( github.ref, needs.compute-stable-branches.outputs.next_stable_branch ) ) && ( github.event.inputs.version == 'rc' || github.event.inputs.version == 'stable' ) || ( startsWith( github.ref, 'refs/heads/release/' ) && github.event.inputs.version == 'stable' ) ) outputs: old_version: ${{ steps.get_version.outputs.old_version }} new_version: ${{ steps.get_version.outputs.new_version }} release_branch: ${{ steps.get_version.outputs.release_branch }} release_branch_commit: ${{ steps.commit_version_bump_to_release_branch.outputs.version_bump_commit }} trunk_commit: ${{ steps.commit_version_bump_to_trunk.outputs.version_bump_commit }} steps: - name: Checkout code uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: token: ${{ secrets.GUTENBERG_TOKEN }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Compute old and new version id: get_version run: | OLD_VERSION=$(jq --raw-output '.version' package.json) echo "old_version=${OLD_VERSION}" >> $GITHUB_OUTPUT if [[ ${{ github.event.inputs.version }} == 'stable' ]]; then NEW_VERSION=$(npx semver $OLD_VERSION -i patch) else if [[ $OLD_VERSION == *"rc"* ]]; then NEW_VERSION=$(npx semver $OLD_VERSION -i prerelease) else # WordPress version guidelines: If minor is 9, bump major instead. IFS='.' read -r -a OLD_VERSION_ARRAY <<< "$OLD_VERSION" if [[ ${OLD_VERSION_ARRAY[1]} == "9" ]]; then NEW_VERSION="$(npx semver $OLD_VERSION -i major)-rc.1" else NEW_VERSION="$(npx semver $OLD_VERSION -i minor)-rc.1" fi fi fi echo "new_version=${NEW_VERSION}" >> $GITHUB_OUTPUT IFS='.' read -r -a NEW_VERSION_ARRAY <<< "$NEW_VERSION" RELEASE_BRANCH="release/${NEW_VERSION_ARRAY[0]}.${NEW_VERSION_ARRAY[1]}" echo "release_branch=${RELEASE_BRANCH}" >> $GITHUB_OUTPUT - name: Configure git user name and email run: | git config user.name "Gutenberg Repository Automation" git config user.email gutenberg@wordpress.org - name: Create and switch to release branch if: | github.event.inputs.version == 'rc' && ! contains( steps.get_version.outputs.old_version, 'rc' ) run: git checkout -b "${{ steps.get_version.outputs.release_branch }}" - name: Switch to release branch if: | github.event.inputs.version == 'stable' || contains( steps.get_version.outputs.old_version, 'rc' ) run: | git fetch --depth=1 origin "${{ steps.get_version.outputs.release_branch }}" git checkout "${{ steps.get_version.outputs.release_branch }}" - name: Update plugin version env: VERSION: ${{ steps.get_version.outputs.new_version }} run: | cat <<< $(jq --tab --arg version "${VERSION}" '.version = $version' package.json) > package.json cat <<< $(jq --tab --arg version "${VERSION}" '.version = $version | .packages[""].version = $version' package-lock.json) > package-lock.json sed -i "s/${{ steps.get_version.outputs.old_version }}/${VERSION}/g" gutenberg.php - name: Commit the version bump to the release branch id: commit_version_bump_to_release_branch run: | git add gutenberg.php package.json package-lock.json git commit -m "Bump plugin version to ${{ steps.get_version.outputs.new_version }}" git push --set-upstream origin "${{ steps.get_version.outputs.release_branch }}" echo "version_bump_commit=$(git rev-parse --verify --short HEAD)" >> $GITHUB_OUTPUT - name: Fetch trunk if: ${{ github.ref != 'refs/heads/trunk' }} run: git fetch --depth=1 origin trunk - name: Cherry-pick the version bump commit to trunk id: commit_version_bump_to_trunk run: | git checkout trunk git pull TRUNK_VERSION=$(jq --raw-output '.version' package.json) if [[ ${{ steps.get_version.outputs.old_version }} == "$TRUNK_VERSION" ]]; then git cherry-pick "${{ steps.get_version.outputs.release_branch }}" git push echo "version_bump_commit=$(git rev-parse --verify --short HEAD)" >> $GITHUB_OUTPUT fi build: name: Build Release Artifact runs-on: ubuntu-latest needs: bump-version if: | always() && ( github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' || github.repository == 'WordPress/gutenberg' ) outputs: job_status: ${{ job.status }} steps: - name: Checkout code uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: ref: ${{ needs.bump-version.outputs.release_branch || github.ref }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Use desired version of Node.js uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version-file: '.nvmrc' check-latest: true cache: npm - name: Build Gutenberg plugin ZIP file run: ./bin/build-plugin-zip.sh env: NO_CHECKS: 'true' - name: Upload artifact uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: gutenberg-plugin path: ./gutenberg.zip - name: Build release notes draft if: ${{ needs.bump-version.outputs.new_version }} env: VERSION: ${{ needs.bump-version.outputs.new_version }} run: | IFS='.' read -r -a VERSION_ARRAY <<< "${VERSION}" MILESTONE="Gutenberg ${VERSION_ARRAY[0]}.${VERSION_ARRAY[1]}" npm run other:changelog -- --milestone="$MILESTONE" --unreleased > release-notes.txt sed -ie '1,6d' release-notes.txt if [[ ${{ needs.bump-version.outputs.new_version }} != *"rc"* ]]; then # Include previous RCs' release notes, if any CHANGELOG_REGEX="=\s[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?\s=" RC_REGEX="=\s${VERSION}(-rc\.[0-9]+)?\s=" awk "/${RC_REGEX}/ {found=1;print;next} /${CHANGELOG_REGEX}/ {found=0} found" changelog.txt >> release-notes.txt fi - name: Upload release notes artifact if: ${{ needs.bump-version.outputs.new_version }} uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 with: name: release-notes path: ./release-notes.txt revert-version-bump: name: Revert version bump if build failed needs: [bump-version, build] runs-on: ubuntu-latest if: | always() && ( needs.build.outputs.job_status == 'failure' ) && needs.bump-version.outputs.release_branch_commit steps: - name: Checkout code uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: fetch-depth: 2 ref: ${{ needs.bump-version.outputs.release_branch }} token: ${{ secrets.GUTENBERG_TOKEN }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Configure git user name and email run: | git config user.name "Gutenberg Repository Automation" git config user.email gutenberg@wordpress.org - name: Revert version bump commit on release branch if: | github.event.inputs.version == 'stable' || contains( needs.bump-version.outputs.old_version, 'rc' ) run: | git revert --no-edit ${{ needs.bump-version.outputs.release_branch_commit }} git push --set-upstream origin "${{ needs.bump-version.outputs.release_branch }}" - name: Delete release branch if it was only just created for the RC if: | github.event.inputs.version == 'rc' && ! contains( needs.bump-version.outputs.old_version, 'rc' ) run: | git push origin :"${{ needs.bump-version.outputs.release_branch }}" - name: Revert version bump on trunk if: ${{ needs.bump-version.outputs.trunk_commit }} run: | git fetch --depth=2 origin trunk git checkout trunk git revert --no-edit ${{ needs.bump-version.outputs.trunk_commit }} git push --set-upstream origin trunk create-release: name: Create Release Draft and Attach Asset needs: [bump-version, build] runs-on: ubuntu-latest steps: - name: Set Release Version id: get_release_version env: VERSION: ${{ needs.bump-version.outputs.new_version }} run: echo "version=$(echo $VERSION | cut -d / -f 3 | sed 's/-rc./ RC/' )" >> $GITHUB_OUTPUT - name: Download Plugin Zip Artifact uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: gutenberg-plugin - name: Download Release Notes Artifact uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: release-notes - name: Create Release Draft id: create_release uses: actions/create-release@0cb9c9b65d5d1901c1f53e5e66eaf4afd303e70e # v1.1.4 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: 'v${{ needs.bump-version.outputs.new_version }}' release_name: ${{ steps.get_release_version.outputs.version }} commitish: ${{ needs.bump-version.outputs.release_branch || github.ref }} draft: true prerelease: ${{ contains(needs.bump-version.outputs.new_version, 'rc') }} body_path: release-notes.txt - name: Upload Release Asset id: upload-release-asset uses: actions/upload-release-asset@e8f9f06c4b078e705bd2ea027f0926603fc9b4d5 # v1.0.2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ./gutenberg.zip asset_name: gutenberg.zip asset_content_type: application/zip npm-publish: name: Publish WordPress packages to npm runs-on: ubuntu-latest environment: WordPress packages needs: [bump-version, build] if: ${{ endsWith( needs.bump-version.outputs.new_version, '-rc.1' ) }} steps: - name: Checkout (for CLI) uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: path: main ref: trunk show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Checkout (for publishing) uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 with: path: publish # Later, we switch this branch in the script that publishes packages. ref: trunk token: ${{ secrets.GUTENBERG_TOKEN }} show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} - name: Configure git user name and email (for publishing) run: | cd publish git config user.name "Gutenberg Repository Automation" git config user.email gutenberg@wordpress.org - name: Setup Node.js uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 with: node-version-file: 'main/.nvmrc' registry-url: 'https://registry.npmjs.org' check-latest: true - name: Publish packages to npm ("latest" dist-tag) run: | cd main npm ci ./bin/plugin/cli.js npm-latest --semver minor --ci --repository-path ../publish env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}