From 51146cee8c9d42969a8d7918256583efe58206dd Mon Sep 17 00:00:00 2001 From: John Blackbourn Date: Wed, 13 May 2026 15:49:19 +0100 Subject: [PATCH 1/4] Grant minimally-scoped permissions. --- .github/workflows/auto-label-prs.yml | 11 +++- .github/workflows/ci.yml | 55 ++++++++++++++++++- .github/workflows/dependabot-lockfile.yml | 8 ++- .github/workflows/deploy-cors-proxy.yml | 7 +++ .github/workflows/deploy-my-wordpress-net.yml | 7 +++ .github/workflows/deploy-website.yml | 7 +++ .../workflows/publish-devtools-extension.yml | 6 +- .github/workflows/publish-github-release.yml | 7 ++- .github/workflows/publish-npm-packages.yml | 9 ++- .../publish-self-hosted-package-release.yml | 6 ++ .../workflows/refresh-sqlite-integration.yml | 7 +++ .../refresh-wordpress-major-and-beta.yml | 7 +++ .../workflows/refresh-wordpress-nightly.yml | 6 ++ .github/workflows/update-changelog.yml | 6 ++ 14 files changed, 135 insertions(+), 14 deletions(-) diff --git a/.github/workflows/auto-label-prs.yml b/.github/workflows/auto-label-prs.yml index d9f2136e1f2..6283598673c 100644 --- a/.github/workflows/auto-label-prs.yml +++ b/.github/workflows/auto-label-prs.yml @@ -30,14 +30,17 @@ on: pull_request_target: types: [opened, synchronize, reopened, ready_for_review] -permissions: - contents: read - pull-requests: write +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} jobs: paths: if: github.repository == 'WordPress/wordpress-playground' runs-on: ubuntu-latest + permissions: + contents: read # Required for actions/labeler to read the configuration file. + pull-requests: write # Required to apply labels to pull requests. steps: # Pinned to a commit SHA, not a tag: this job runs with # pull-requests:write, so a moved tag would be a supply-chain @@ -50,6 +53,8 @@ jobs: package-and-type: if: github.repository == 'WordPress/wordpress-playground' runs-on: ubuntu-latest + permissions: + pull-requests: write # Required to apply labels to pull requests. steps: - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fb54a1b3dd4..c4abd3e099b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,6 +5,10 @@ on: - trunk pull_request: +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} + jobs: # This step: # * Warms up the node_modules cache @@ -18,6 +22,8 @@ jobs: name: 'Lint and typecheck' if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. steps: - uses: actions/checkout@v4 with: @@ -30,6 +36,8 @@ jobs: test-unit-asyncify: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. strategy: fail-fast: false matrix: @@ -79,6 +87,8 @@ jobs: test-unit-jspi: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. strategy: fail-fast: false matrix: @@ -130,6 +140,8 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] continue-on-error: true runs-on: ${{ matrix.os }} + permissions: + contents: read # Required to clone the repo. name: 'test-playground-cli (${{ matrix.os }})' steps: - uses: actions/checkout@v4 @@ -148,6 +160,8 @@ jobs: async-strategy: [asyncify, jspi] continue-on-error: true runs-on: ${{ matrix.os }} + permissions: + contents: read # Required to clone the repo. name: 'test-file-locking-${{ matrix.async-strategy }} (${{ matrix.os }})' steps: - uses: actions/checkout@v4 @@ -161,6 +175,8 @@ jobs: test-e2e-php-wasm-web-jspi: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. steps: - uses: actions/checkout@v4 with: @@ -171,6 +187,8 @@ jobs: test-e2e-php-wasm-web-asyncify: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. steps: - uses: actions/checkout@v4 with: @@ -181,6 +199,8 @@ jobs: test-e2e: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. # Run as root to allow node to bind to port 80 steps: - uses: actions/checkout@v4 @@ -201,6 +221,8 @@ jobs: test-e2e-playwright: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. strategy: fail-fast: false matrix: @@ -282,6 +304,8 @@ jobs: test-e2e-personal-wp: runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. steps: - uses: actions/checkout@v4 with: @@ -301,6 +325,8 @@ jobs: test-e2e-components: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. steps: - uses: actions/checkout@v4 with: @@ -320,6 +346,8 @@ jobs: # Run MCP e2e tests independently from other tests because running a local version of the MCP server from TypeScript files requires Node 22+ test-e2e-mcp: runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. steps: - uses: actions/checkout@v4 with: @@ -341,6 +369,8 @@ jobs: test-docs-api-reference: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. steps: - uses: actions/checkout@v4 with: @@ -360,6 +390,8 @@ jobs: test-built-npm-packages: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. steps: - uses: actions/checkout@v4 with: @@ -373,6 +405,8 @@ jobs: test-playground-client-types-rollup: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. steps: - uses: actions/checkout@v4 with: @@ -388,6 +422,8 @@ jobs: test-running-unbuilt-playground-cli: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. steps: - uses: actions/checkout@v4 with: @@ -400,6 +436,8 @@ jobs: test-php-wasm-cli-smoke: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. steps: - uses: actions/checkout@v4 with: @@ -412,6 +450,8 @@ jobs: detect-compile-extension-helper-changes: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo and fetch commit history. outputs: changed: ${{ steps.changed.outputs.changed }} steps: @@ -447,6 +487,8 @@ jobs: needs: detect-compile-extension-helper-changes if: (github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request') && needs.detect-compile-extension-helper-changes.outputs.changed == 'true' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. steps: - name: Free up runner disk space shell: bash @@ -481,6 +523,8 @@ jobs: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest timeout-minutes: 30 + permissions: + contents: read # Required to clone the repo. steps: - uses: actions/checkout@v4 with: @@ -511,6 +555,8 @@ jobs: test-redis-extension: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. services: redis: image: redis:7-alpine @@ -539,6 +585,8 @@ jobs: test-memcached-extension: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. services: memcached: image: memcached:1.6-alpine @@ -562,6 +610,8 @@ jobs: build: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. steps: - uses: actions/checkout@v4 with: @@ -592,8 +642,9 @@ jobs: # Grant GITHUB_TOKEN the permissions required to make a Pages deployment permissions: - pages: write # to deploy to Pages - id-token: write # to verify the deployment originates from an appropriate source + contents: read # Required to clone the repo. + pages: write # Required to deploy to GitHub Pages. + id-token: write # Required to verify the deployment originates from an appropriate source. # Deploy to the github-pages environment environment: diff --git a/.github/workflows/dependabot-lockfile.yml b/.github/workflows/dependabot-lockfile.yml index f7f2b4a3585..d960b12b1bd 100644 --- a/.github/workflows/dependabot-lockfile.yml +++ b/.github/workflows/dependabot-lockfile.yml @@ -4,14 +4,16 @@ on: pull_request: types: [opened, synchronize] -permissions: - contents: write - pull-requests: write +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} jobs: fix-lock: if: github.actor == 'dependabot[bot]' runs-on: ubuntu-latest + permissions: + contents: write # Required to push the updated lockfile commit back to the branch. steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/deploy-cors-proxy.yml b/.github/workflows/deploy-cors-proxy.yml index 297d51beedb..ae59e1a3894 100644 --- a/.github/workflows/deploy-cors-proxy.yml +++ b/.github/workflows/deploy-cors-proxy.yml @@ -6,6 +6,10 @@ on: concurrency: group: cors-proxy-deployment +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} + jobs: # Check preconditions in a separate job because secrets aren't # available in job-level `if` conditions. @@ -27,6 +31,7 @@ jobs: github.actor == 'ashfame' ) runs-on: ubuntu-latest + permissions: {} environment: name: cors-proxy-wp-cloud outputs: @@ -56,6 +61,8 @@ jobs: # Specify runner + deployment step runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. environment: name: cors-proxy-wp-cloud steps: diff --git a/.github/workflows/deploy-my-wordpress-net.yml b/.github/workflows/deploy-my-wordpress-net.yml index 7905fb9d8f1..8a270578338 100644 --- a/.github/workflows/deploy-my-wordpress-net.yml +++ b/.github/workflows/deploy-my-wordpress-net.yml @@ -9,6 +9,10 @@ on: concurrency: group: my-wordpress-net-deployment +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} + jobs: # Check preconditions in a separate job because secrets aren't # available in job-level `if` conditions. @@ -29,6 +33,7 @@ jobs: github.actor == 'ashfame' ) runs-on: ubuntu-latest + permissions: {} environment: name: my-wordpress-net-wp-cloud outputs: @@ -57,6 +62,8 @@ jobs: if: needs.check_preconditions.outputs.meets_deploy_preconditions == 'true' runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. environment: name: my-wordpress-net-wp-cloud steps: diff --git a/.github/workflows/deploy-website.yml b/.github/workflows/deploy-website.yml index ffdab8245c9..d1aa11116cd 100644 --- a/.github/workflows/deploy-website.yml +++ b/.github/workflows/deploy-website.yml @@ -9,6 +9,10 @@ on: concurrency: group: website-deployment +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} + jobs: # Check preconditions in a separate job because secrets aren't # available in job-level `if` conditions. @@ -29,6 +33,7 @@ jobs: github.actor == 'ashfame' ) runs-on: ubuntu-latest + permissions: {} environment: name: playground-wordpress-net-wp-cloud outputs: @@ -58,6 +63,8 @@ jobs: # Specify runner + deployment step runs-on: ubuntu-latest + permissions: + contents: read # Required to clone the repo. environment: name: playground-wordpress-net-wp-cloud steps: diff --git a/.github/workflows/publish-devtools-extension.yml b/.github/workflows/publish-devtools-extension.yml index 7cf7f1274ea..cfd70a267df 100644 --- a/.github/workflows/publish-devtools-extension.yml +++ b/.github/workflows/publish-devtools-extension.yml @@ -13,6 +13,10 @@ on: - minor - major +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} + jobs: publish: # Only run this workflow on the playground repo, from the trunk branch, and when triggered by a Playground maintainer @@ -32,7 +36,7 @@ jobs: runs-on: ubuntu-latest permissions: - contents: write + contents: write # Required to push the new tag and create the GitHub release. steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/publish-github-release.yml b/.github/workflows/publish-github-release.yml index 8baee007120..ff5fdb15f07 100644 --- a/.github/workflows/publish-github-release.yml +++ b/.github/workflows/publish-github-release.yml @@ -7,8 +7,9 @@ on: types: - completed -permissions: - contents: write +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} jobs: create-release: @@ -25,6 +26,8 @@ jobs: ) runs-on: ubuntu-latest + permissions: + contents: write # Required to clone the repo, create the GitHub release, and push the tag. steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/publish-npm-packages.yml b/.github/workflows/publish-npm-packages.yml index f881c99d9dc..266ef285545 100644 --- a/.github/workflows/publish-npm-packages.yml +++ b/.github/workflows/publish-npm-packages.yml @@ -15,9 +15,9 @@ on: # Auto-publish every Monday - cron: '0 9 * * 1' -permissions: - id-token: write - contents: write +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} concurrency: group: npm-release @@ -40,6 +40,9 @@ jobs: ) runs-on: ubuntu-latest + permissions: + id-token: write # Required for OIDC-based npm trusted publishing. + contents: write # Required to push the version bump commit and tags. environment: name: npm diff --git a/.github/workflows/publish-self-hosted-package-release.yml b/.github/workflows/publish-self-hosted-package-release.yml index 97822750438..ee4decf77a0 100644 --- a/.github/workflows/publish-self-hosted-package-release.yml +++ b/.github/workflows/publish-self-hosted-package-release.yml @@ -14,6 +14,10 @@ on: required: true default: 'patch' +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} + jobs: publish: # Only run this workflow on the playground repo, from the trunk branch, and when triggered by a Playground maintainer @@ -33,6 +37,8 @@ jobs: # Specify runner + deployment step runs-on: ubuntu-latest + permissions: + contents: write # Required to clone the repo, push version bump commits, and create tags. environment: name: self-hosted-packages steps: diff --git a/.github/workflows/refresh-sqlite-integration.yml b/.github/workflows/refresh-sqlite-integration.yml index ec6c37eb7a4..34fc490c7d7 100644 --- a/.github/workflows/refresh-sqlite-integration.yml +++ b/.github/workflows/refresh-sqlite-integration.yml @@ -5,6 +5,10 @@ on: schedule: - cron: '0 10 * * *' +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} + jobs: build_and_deploy: # Only run this workflow on the playground repo, from the trunk branch, and when triggered by a Playground maintainer @@ -22,6 +26,9 @@ jobs: ) runs-on: ubuntu-latest + permissions: + contents: write # Required to clone the repo and push the updated SQLite bundle commit. + actions: write # Required to trigger the deploy-website workflow via workflow_dispatch. environment: name: wordpress-assets concurrency: diff --git a/.github/workflows/refresh-wordpress-major-and-beta.yml b/.github/workflows/refresh-wordpress-major-and-beta.yml index f8afdda7889..7caceb7c81a 100644 --- a/.github/workflows/refresh-wordpress-major-and-beta.yml +++ b/.github/workflows/refresh-wordpress-major-and-beta.yml @@ -14,6 +14,10 @@ on: concurrency: group: refresh-wordpress-major-and-beta +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} + jobs: build_wordpress_major_and_beta_push_to_github_and_deploy_website: # Only run this workflow on the playground repo, from the trunk branch, and when triggered by a Playground maintainer @@ -36,6 +40,9 @@ jobs: # Be conservative and set _some_ timeout to prevent a hanging # job from blocking the queue of scheduled runs. timeout-minutes: 120 + permissions: + contents: write # Required to clone the repo and push the rebuilt WordPress commit. + actions: write # Required to trigger the deploy-website workflow via workflow_dispatch. steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/refresh-wordpress-nightly.yml b/.github/workflows/refresh-wordpress-nightly.yml index fc07ba6bd04..a3c98187661 100644 --- a/.github/workflows/refresh-wordpress-nightly.yml +++ b/.github/workflows/refresh-wordpress-nightly.yml @@ -6,6 +6,10 @@ on: schedule: - cron: '0 8 * * *' +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} + jobs: build_and_deploy: # Only run this workflow on the playground repo, from the trunk branch, and when triggered by a Playground maintainer @@ -23,6 +27,8 @@ jobs: ) runs-on: ubuntu-latest + permissions: + contents: write # Required to clone the repo and push the refreshed WordPress nightly commit. environment: name: wordpress-assets steps: diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml index 31c49a3c32b..6eb1f18a1a0 100644 --- a/.github/workflows/update-changelog.yml +++ b/.github/workflows/update-changelog.yml @@ -12,6 +12,10 @@ on: types: - completed +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} + jobs: release: # Only run this workflow on the playground repo, from the trunk branch, and when triggered by a Playground maintainer @@ -31,6 +35,8 @@ jobs: # Specify runner + deployment step runs-on: ubuntu-latest + permissions: + contents: write # Required to clone the repo, commit, and push the updated changelog. environment: name: wordpress-assets env: From cda15b8f224a7a975e315c8fc447762daad87e17 Mon Sep 17 00:00:00 2001 From: John Blackbourn Date: Wed, 13 May 2026 15:56:48 +0100 Subject: [PATCH 2/4] Set timeouts on all jobs. --- .github/workflows/auto-label-prs.yml | 2 ++ .github/workflows/ci.yml | 23 +++++++++++++++++++ .github/workflows/dependabot-lockfile.yml | 1 + .github/workflows/deploy-cors-proxy.yml | 2 ++ .github/workflows/deploy-my-wordpress-net.yml | 2 ++ .github/workflows/deploy-website.yml | 2 ++ .../workflows/publish-devtools-extension.yml | 1 + .github/workflows/publish-github-release.yml | 1 + .github/workflows/publish-npm-packages.yml | 3 +++ .../publish-self-hosted-package-release.yml | 3 +++ .../workflows/refresh-sqlite-integration.yml | 1 + .../workflows/refresh-wordpress-nightly.yml | 1 + .github/workflows/update-changelog.yml | 1 + 13 files changed, 43 insertions(+) diff --git a/.github/workflows/auto-label-prs.yml b/.github/workflows/auto-label-prs.yml index 6283598673c..db7a3d3ddba 100644 --- a/.github/workflows/auto-label-prs.yml +++ b/.github/workflows/auto-label-prs.yml @@ -38,6 +38,7 @@ jobs: paths: if: github.repository == 'WordPress/wordpress-playground' runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: read # Required for actions/labeler to read the configuration file. pull-requests: write # Required to apply labels to pull requests. @@ -53,6 +54,7 @@ jobs: package-and-type: if: github.repository == 'WordPress/wordpress-playground' runs-on: ubuntu-latest + timeout-minutes: 10 permissions: pull-requests: write # Required to apply labels to pull requests. steps: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c4abd3e099b..97d6d2e329f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,7 @@ jobs: name: 'Lint and typecheck' if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. steps: @@ -36,6 +37,7 @@ jobs: test-unit-asyncify: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. strategy: @@ -87,6 +89,7 @@ jobs: test-unit-jspi: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. strategy: @@ -140,6 +143,7 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] continue-on-error: true runs-on: ${{ matrix.os }} + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. name: 'test-playground-cli (${{ matrix.os }})' @@ -160,6 +164,7 @@ jobs: async-strategy: [asyncify, jspi] continue-on-error: true runs-on: ${{ matrix.os }} + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. name: 'test-file-locking-${{ matrix.async-strategy }} (${{ matrix.os }})' @@ -175,6 +180,7 @@ jobs: test-e2e-php-wasm-web-jspi: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. steps: @@ -187,6 +193,7 @@ jobs: test-e2e-php-wasm-web-asyncify: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. steps: @@ -199,6 +206,7 @@ jobs: test-e2e: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. # Run as root to allow node to bind to port 80 @@ -221,6 +229,7 @@ jobs: test-e2e-playwright: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. strategy: @@ -304,6 +313,7 @@ jobs: test-e2e-personal-wp: runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. steps: @@ -325,6 +335,7 @@ jobs: test-e2e-components: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. steps: @@ -346,6 +357,7 @@ jobs: # Run MCP e2e tests independently from other tests because running a local version of the MCP server from TypeScript files requires Node 22+ test-e2e-mcp: runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. steps: @@ -369,6 +381,7 @@ jobs: test-docs-api-reference: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. steps: @@ -390,6 +403,7 @@ jobs: test-built-npm-packages: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. steps: @@ -405,6 +419,7 @@ jobs: test-playground-client-types-rollup: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. steps: @@ -422,6 +437,7 @@ jobs: test-running-unbuilt-playground-cli: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. steps: @@ -436,6 +452,7 @@ jobs: test-php-wasm-cli-smoke: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. steps: @@ -450,6 +467,7 @@ jobs: detect-compile-extension-helper-changes: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo and fetch commit history. outputs: @@ -487,6 +505,7 @@ jobs: needs: detect-compile-extension-helper-changes if: (github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request') && needs.detect-compile-extension-helper-changes.outputs.changed == 'true' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. steps: @@ -555,6 +574,7 @@ jobs: test-redis-extension: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. services: @@ -585,6 +605,7 @@ jobs: test-memcached-extension: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. services: @@ -610,6 +631,7 @@ jobs: build: if: github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request' runs-on: ubuntu-latest + timeout-minutes: 30 permissions: contents: read # Required to clone the repo. steps: @@ -653,6 +675,7 @@ jobs: # Specify runner + deployment step runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/dependabot-lockfile.yml b/.github/workflows/dependabot-lockfile.yml index d960b12b1bd..1eae1136352 100644 --- a/.github/workflows/dependabot-lockfile.yml +++ b/.github/workflows/dependabot-lockfile.yml @@ -12,6 +12,7 @@ jobs: fix-lock: if: github.actor == 'dependabot[bot]' runs-on: ubuntu-latest + timeout-minutes: 10 permissions: contents: write # Required to push the updated lockfile commit back to the branch. steps: diff --git a/.github/workflows/deploy-cors-proxy.yml b/.github/workflows/deploy-cors-proxy.yml index ae59e1a3894..4a6384db960 100644 --- a/.github/workflows/deploy-cors-proxy.yml +++ b/.github/workflows/deploy-cors-proxy.yml @@ -31,6 +31,7 @@ jobs: github.actor == 'ashfame' ) runs-on: ubuntu-latest + timeout-minutes: 20 permissions: {} environment: name: cors-proxy-wp-cloud @@ -61,6 +62,7 @@ jobs: # Specify runner + deployment step runs-on: ubuntu-latest + timeout-minutes: 20 permissions: contents: read # Required to clone the repo. environment: diff --git a/.github/workflows/deploy-my-wordpress-net.yml b/.github/workflows/deploy-my-wordpress-net.yml index 8a270578338..73f841f8992 100644 --- a/.github/workflows/deploy-my-wordpress-net.yml +++ b/.github/workflows/deploy-my-wordpress-net.yml @@ -33,6 +33,7 @@ jobs: github.actor == 'ashfame' ) runs-on: ubuntu-latest + timeout-minutes: 20 permissions: {} environment: name: my-wordpress-net-wp-cloud @@ -62,6 +63,7 @@ jobs: if: needs.check_preconditions.outputs.meets_deploy_preconditions == 'true' runs-on: ubuntu-latest + timeout-minutes: 20 permissions: contents: read # Required to clone the repo. environment: diff --git a/.github/workflows/deploy-website.yml b/.github/workflows/deploy-website.yml index d1aa11116cd..070b7883855 100644 --- a/.github/workflows/deploy-website.yml +++ b/.github/workflows/deploy-website.yml @@ -33,6 +33,7 @@ jobs: github.actor == 'ashfame' ) runs-on: ubuntu-latest + timeout-minutes: 20 permissions: {} environment: name: playground-wordpress-net-wp-cloud @@ -63,6 +64,7 @@ jobs: # Specify runner + deployment step runs-on: ubuntu-latest + timeout-minutes: 20 permissions: contents: read # Required to clone the repo. environment: diff --git a/.github/workflows/publish-devtools-extension.yml b/.github/workflows/publish-devtools-extension.yml index cfd70a267df..53c8c7e3af0 100644 --- a/.github/workflows/publish-devtools-extension.yml +++ b/.github/workflows/publish-devtools-extension.yml @@ -35,6 +35,7 @@ jobs: ) runs-on: ubuntu-latest + timeout-minutes: 20 permissions: contents: write # Required to push the new tag and create the GitHub release. diff --git a/.github/workflows/publish-github-release.yml b/.github/workflows/publish-github-release.yml index ff5fdb15f07..1e89e3be223 100644 --- a/.github/workflows/publish-github-release.yml +++ b/.github/workflows/publish-github-release.yml @@ -26,6 +26,7 @@ jobs: ) runs-on: ubuntu-latest + timeout-minutes: 20 permissions: contents: write # Required to clone the repo, create the GitHub release, and push the tag. diff --git a/.github/workflows/publish-npm-packages.yml b/.github/workflows/publish-npm-packages.yml index 266ef285545..4408883d059 100644 --- a/.github/workflows/publish-npm-packages.yml +++ b/.github/workflows/publish-npm-packages.yml @@ -40,6 +40,9 @@ jobs: ) runs-on: ubuntu-latest + # Timeout is set to an hour as Lerna sequentially publishes a large number of packages + # and the workflow regularly takes more than 30 minutes to complete. + timeout-minutes: 60 permissions: id-token: write # Required for OIDC-based npm trusted publishing. contents: write # Required to push the version bump commit and tags. diff --git a/.github/workflows/publish-self-hosted-package-release.yml b/.github/workflows/publish-self-hosted-package-release.yml index ee4decf77a0..65e662d0f56 100644 --- a/.github/workflows/publish-self-hosted-package-release.yml +++ b/.github/workflows/publish-self-hosted-package-release.yml @@ -37,6 +37,9 @@ jobs: # Specify runner + deployment step runs-on: ubuntu-latest + # This workflow is current disabled. This timeout is set to a high value in anticipation of the workflow + # being re-enabled and needing to run through the full deployment process. + timeout-minutes: 60 permissions: contents: write # Required to clone the repo, push version bump commits, and create tags. environment: diff --git a/.github/workflows/refresh-sqlite-integration.yml b/.github/workflows/refresh-sqlite-integration.yml index 34fc490c7d7..4969fb520f8 100644 --- a/.github/workflows/refresh-sqlite-integration.yml +++ b/.github/workflows/refresh-sqlite-integration.yml @@ -26,6 +26,7 @@ jobs: ) runs-on: ubuntu-latest + timeout-minutes: 60 permissions: contents: write # Required to clone the repo and push the updated SQLite bundle commit. actions: write # Required to trigger the deploy-website workflow via workflow_dispatch. diff --git a/.github/workflows/refresh-wordpress-nightly.yml b/.github/workflows/refresh-wordpress-nightly.yml index a3c98187661..f0142eda31b 100644 --- a/.github/workflows/refresh-wordpress-nightly.yml +++ b/.github/workflows/refresh-wordpress-nightly.yml @@ -27,6 +27,7 @@ jobs: ) runs-on: ubuntu-latest + timeout-minutes: 60 permissions: contents: write # Required to clone the repo and push the refreshed WordPress nightly commit. environment: diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml index 6eb1f18a1a0..2e9a4f3cca0 100644 --- a/.github/workflows/update-changelog.yml +++ b/.github/workflows/update-changelog.yml @@ -35,6 +35,7 @@ jobs: # Specify runner + deployment step runs-on: ubuntu-latest + timeout-minutes: 20 permissions: contents: write # Required to clone the repo, commit, and push the updated changelog. environment: From 211cf44d8dada446b8d5a509bd9a93c0d06f35af Mon Sep 17 00:00:00 2001 From: John Blackbourn Date: Thu, 14 May 2026 00:02:57 +0100 Subject: [PATCH 3/4] Typo Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- .github/workflows/publish-self-hosted-package-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-self-hosted-package-release.yml b/.github/workflows/publish-self-hosted-package-release.yml index 65e662d0f56..c94ca063335 100644 --- a/.github/workflows/publish-self-hosted-package-release.yml +++ b/.github/workflows/publish-self-hosted-package-release.yml @@ -37,7 +37,7 @@ jobs: # Specify runner + deployment step runs-on: ubuntu-latest - # This workflow is current disabled. This timeout is set to a high value in anticipation of the workflow + # This workflow is currently disabled. This timeout is set to a high value in anticipation of the workflow # being re-enabled and needing to run through the full deployment process. timeout-minutes: 60 permissions: From e62869e81633aae1d1e1c82cdf2b23c14541a656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20Zieli=C5=84ski?= Date: Tue, 19 May 2026 22:09:45 +0200 Subject: [PATCH 4/4] Tune workflow permissions and timeouts --- .github/workflows/ci.yml | 2 +- .github/workflows/update-changelog.yml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97d6d2e329f..7615565b3a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -505,7 +505,7 @@ jobs: needs: detect-compile-extension-helper-changes if: (github.repository == 'WordPress/wordpress-playground' || github.event_name == 'pull_request') && needs.detect-compile-extension-helper-changes.outputs.changed == 'true' runs-on: ubuntu-latest - timeout-minutes: 30 + timeout-minutes: 60 permissions: contents: read # Required to clone the repo. steps: diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml index 2e9a4f3cca0..24a00d3698d 100644 --- a/.github/workflows/update-changelog.yml +++ b/.github/workflows/update-changelog.yml @@ -38,6 +38,7 @@ jobs: timeout-minutes: 20 permissions: contents: write # Required to clone the repo, commit, and push the updated changelog. + issues: read # Required to query merged pull requests for changelog generation. environment: name: wordpress-assets env: