From 6764e6bb958c9cf481d683658444b08802b7b70f Mon Sep 17 00:00:00 2001 From: Brandon Payton Date: Fri, 1 May 2026 14:15:44 -0400 Subject: [PATCH 1/2] ci: gate release cascade on success and stream build output Two related fixes for the npm publish workflow chain: 1. Don't create a GitHub Release on a failed publish. update-changelog.yml was OR'ing the workflow_run success check with the maintainer allowlist, so a maintainer-dispatched run that failed still triggered the changelog workflow, which then cascade-triggered publish-github-release.yml. The condition now requires conclusion == 'success' for workflow_run triggers and gates the maintainer allowlist to workflow_dispatch only. 2. Surface build failures during release. Run npm run build as a separate step before lerna publish, with --output-style=stream and NX_TUI=false, so nx writes output as tasks run instead of buffering. lerna's prepublishOnly still re-runs the build but should hit the nx cache. Without this, a build failure inside lerna shows up only as "lifecycle 'prepublishOnly' errored" with no diagnostics. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/publish-npm-packages.yml | 12 ++++++++ .github/workflows/update-changelog.yml | 32 +++++++++++++++------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/.github/workflows/publish-npm-packages.yml b/.github/workflows/publish-npm-packages.yml index f881c99d9dc..5b6d3ff623d 100644 --- a/.github/workflows/publish-npm-packages.yml +++ b/.github/workflows/publish-npm-packages.yml @@ -88,6 +88,18 @@ jobs: - uses: ./.github/actions/prepare-playground + # Run the build standalone before lerna publish so any failure + # produces clear, streamed output. lerna's prepublishOnly will + # re-run this build, but it should hit the nx cache and finish + # quickly. Without this step, build output gets swallowed by + # lerna's lifecycle handling and a failure shows up only as + # "lifecycle 'prepublishOnly' errored" with no diagnostics. + - name: Build all packages (verbose) + run: npm run build -- --output-style=stream --verbose + env: + NX_TUI: 'false' + NX_VERBOSE_LOGGING: 'true' + - name: Publish NPM packages # Version bump, release, tag a new version on GitHub. # On non-trunk branches, --no-push avoids pushing the version diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml index 31c49a3c32b..633963a51dd 100644 --- a/.github/workflows/update-changelog.yml +++ b/.github/workflows/update-changelog.yml @@ -14,19 +14,31 @@ on: jobs: release: - # Only run this workflow on the playground repo, from the trunk branch, and when triggered by a Playground maintainer + # Only run this workflow on the playground repo, from the trunk branch. + # For workflow_run triggers, require the parent workflow to have succeeded + # so we don't update the changelog (and cascade-trigger the GitHub Release + # workflow) when an npm publish actually failed. For workflow_dispatch, + # restrict to Playground maintainers. if: > github.repository == 'WordPress/wordpress-playground' && github.ref == 'refs/heads/trunk' && ( - github.event.workflow_run.conclusion == 'success' || - github.actor == 'adamziel' || - github.actor == 'dmsnell' || - github.actor == 'bgrgicak' || - github.actor == 'brandonpayton' || - github.actor == 'zaerl' || - github.actor == 'janjakes' || - github.actor == 'mho22' || - github.actor == 'ashfame' + ( + github.event_name == 'workflow_run' && + github.event.workflow_run.conclusion == 'success' + ) || + ( + github.event_name == 'workflow_dispatch' && + ( + github.actor == 'adamziel' || + github.actor == 'dmsnell' || + github.actor == 'bgrgicak' || + github.actor == 'brandonpayton' || + github.actor == 'zaerl' || + github.actor == 'janjakes' || + github.actor == 'mho22' || + github.actor == 'ashfame' + ) + ) ) # Specify runner + deployment step From 2bb4692b6dc30b81a7a1b83ebae5fcfc8a1c2004 Mon Sep 17 00:00:00 2001 From: Brandon Payton Date: Fri, 1 May 2026 15:46:18 -0400 Subject: [PATCH 2/2] ci: address Copilot review feedback - update-changelog.yml: gate the workflow_run path on workflow_run.head_branch == 'trunk' instead of github.ref. For workflow_run events github.ref is always the default branch where the workflow file lives (i.e. always trunk), so the previous check did not actually verify the parent run's branch. - publish-npm-packages.yml: drop the standalone "Build all packages (verbose)" step and instead set NX_TUI=false on the lerna publish step. This prevents nx from buffering all task output until the end (which is what swallowed diagnostics in the failed v3.1.23 publish) without running the build twice. The earlier double-build approach would not have benefited from the nx cache anyway, since lerna mutates every package.json before re-running prepublishOnly, invalidating the build cache for every project. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/publish-npm-packages.yml | 21 +++++++++------------ .github/workflows/update-changelog.yml | 20 ++++++++++++-------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/.github/workflows/publish-npm-packages.yml b/.github/workflows/publish-npm-packages.yml index 5b6d3ff623d..55c69f13e2b 100644 --- a/.github/workflows/publish-npm-packages.yml +++ b/.github/workflows/publish-npm-packages.yml @@ -88,23 +88,20 @@ jobs: - uses: ./.github/actions/prepare-playground - # Run the build standalone before lerna publish so any failure - # produces clear, streamed output. lerna's prepublishOnly will - # re-run this build, but it should hit the nx cache and finish - # quickly. Without this step, build output gets swallowed by - # lerna's lifecycle handling and a failure shows up only as - # "lifecycle 'prepublishOnly' errored" with no diagnostics. - - name: Build all packages (verbose) - run: npm run build -- --output-style=stream --verbose - env: - NX_TUI: 'false' - NX_VERBOSE_LOGGING: 'true' - - name: Publish NPM packages # Version bump, release, tag a new version on GitHub. # On non-trunk branches, --no-push avoids pushing the version # bump commit back to the branch. The published packages still # get the version bump in their package.json on npm. + # + # NX_TUI=false disables Nx's terminal UI mode, which otherwise + # buffers all task output until the run ends. lerna runs the + # build via the prepublishOnly lifecycle script; without this, + # if the build crashes mid-run (e.g. an OOM kill), the entire + # buffer is lost and the only signal in the log is + # "lifecycle 'prepublishOnly' errored" with no diagnostics. + env: + NX_TUI: 'false' run: > lerna publish ${{ inputs.version_bump || 'patch' }} --yes --no-private --loglevel=verbose diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml index 633963a51dd..3cb85d8320b 100644 --- a/.github/workflows/update-changelog.yml +++ b/.github/workflows/update-changelog.yml @@ -14,20 +14,24 @@ on: jobs: release: - # Only run this workflow on the playground repo, from the trunk branch. - # For workflow_run triggers, require the parent workflow to have succeeded - # so we don't update the changelog (and cascade-trigger the GitHub Release - # workflow) when an npm publish actually failed. For workflow_dispatch, - # restrict to Playground maintainers. + # Only run this workflow on the playground repo. For workflow_run triggers, + # require the parent workflow to have succeeded on trunk so we don't update + # the changelog (and cascade-trigger the GitHub Release workflow) when an + # npm publish actually failed or ran on a non-trunk branch. Note: for + # workflow_run events, github.ref is always the default branch where this + # file lives, so we must use workflow_run.head_branch to gate on the + # parent's actual branch. For workflow_dispatch, restrict to Playground + # maintainers running on trunk. if: > - github.repository == 'WordPress/wordpress-playground' && - github.ref == 'refs/heads/trunk' && ( + github.repository == 'WordPress/wordpress-playground' && ( ( github.event_name == 'workflow_run' && - github.event.workflow_run.conclusion == 'success' + github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.head_branch == 'trunk' ) || ( github.event_name == 'workflow_dispatch' && + github.ref == 'refs/heads/trunk' && ( github.actor == 'adamziel' || github.actor == 'dmsnell' ||