From 93d13ed13f6d3ad84f0a6be7af587461ee6f3348 Mon Sep 17 00:00:00 2001 From: Salah-Eddine Saakoun Date: Wed, 1 Jul 2026 10:55:29 +0200 Subject: [PATCH 1/6] ci: build platform-api-docs in parallel, deploy only on main Previously the docs build ran as its own job that needed lint-build-test, so on PRs it could not start until the whole matrix finished, adding several minutes in series. Now the build runs inside lint-build-test alongside lint/build/test, and the deploy workflow keeps only the get-token and deploy steps, gated to main pushes. PRs build the docs in parallel and skip deploy entirely. --- .../workflows/deploy-platform-api-docs.yml | 37 +------------------ .github/workflows/lint-build-test.yml | 32 ++++++++++++++++ .github/workflows/main.yml | 3 +- 3 files changed, 35 insertions(+), 37 deletions(-) diff --git a/.github/workflows/deploy-platform-api-docs.yml b/.github/workflows/deploy-platform-api-docs.yml index fd3daacc7fb..cd4fb28ffe0 100644 --- a/.github/workflows/deploy-platform-api-docs.yml +++ b/.github/workflows/deploy-platform-api-docs.yml @@ -4,40 +4,8 @@ on: workflow_call: jobs: - build-docs: - name: Build Platform API docs - runs-on: ubuntu-latest - permissions: - contents: read - steps: - - name: Checkout and setup environment - uses: MetaMask/action-checkout-and-setup@v3 - with: - is-high-risk-environment: true - - - name: Generate and build Platform API docs - # The site is published under the `/platform-api/` subdirectory of - # the repo's GitHub Pages site so that other doc sites (e.g. - # package API docs) can be hosted alongside under sibling paths. - env: - REPO_OWNER: ${{ github.repository_owner }} - REPO_NAME: ${{ github.event.repository.name }} - run: | - yarn docs:platform-api:build \ - --site-url "https://${REPO_OWNER}.github.io" \ - --site-base-url "/${REPO_NAME}/platform-api/" - - - name: Upload build artifact - uses: actions/upload-artifact@v7 - with: - name: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' && 'platform-api-docs-build' || 'platform-api-docs' }} - path: .platform-api-docs/build/ - retention-days: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' && 1 || 7 }} - get-token: name: Get access token - if: github.ref == 'refs/heads/main' && github.event_name == 'push' - needs: build-docs runs-on: ubuntu-latest environment: github-pages permissions: @@ -55,10 +23,7 @@ jobs: deploy: name: Deploy to GitHub Pages - if: github.ref == 'refs/heads/main' && github.event_name == 'push' - needs: - - build-docs - - get-token + needs: get-token runs-on: ubuntu-latest environment: github-pages permissions: diff --git a/.github/workflows/lint-build-test.yml b/.github/workflows/lint-build-test.yml index 5047f6a11af..c2760c31892 100644 --- a/.github/workflows/lint-build-test.yml +++ b/.github/workflows/lint-build-test.yml @@ -203,3 +203,35 @@ jobs: echo "Working tree dirty at end of job" exit 1 fi + + build-platform-api-docs: + name: Build Platform API docs + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout and setup environment + uses: MetaMask/action-checkout-and-setup@v3 + with: + is-high-risk-environment: true + + - name: Generate and build Platform API docs + # The site is published under the `/platform-api/` subdirectory of + # the repo's GitHub Pages site so that other doc sites (e.g. + # package API docs) can be hosted alongside under sibling paths. + env: + REPO_OWNER: ${{ github.repository_owner }} + REPO_NAME: ${{ github.event.repository.name }} + run: | + yarn docs:platform-api:build \ + --site-url "https://${REPO_OWNER}.github.io" \ + --site-base-url "/${REPO_NAME}/platform-api/" + + - name: Upload build artifact + # Only the `main`-branch push build is consumed by the deploy job; PR + # builds are uploaded under a different name purely for inspection. + uses: actions/upload-artifact@v7 + with: + name: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' && 'platform-api-docs-build' || 'platform-api-docs' }} + path: .platform-api-docs/build/ + retention-days: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' && 1 || 7 }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ad24587f6a0..953553b06ed 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -79,7 +79,9 @@ jobs: deploy-platform-api-docs: name: Deploy Platform API Docs + # The site is built in `lint-build-test`; only publish it on `main` pushes. needs: lint-build-test + if: github.ref == 'refs/heads/main' && github.event_name == 'push' permissions: contents: read id-token: write @@ -143,7 +145,6 @@ jobs: needs: - analyse-code - check-release - - deploy-platform-api-docs - lint-build-test outputs: passed: ${{ steps.set-output.outputs.passed }} From 509701ffd7d042e1b3b0d2a1d28cf96827073827 Mon Sep 17 00:00:00 2001 From: Salah-Eddine Saakoun Date: Wed, 1 Jul 2026 11:05:51 +0200 Subject: [PATCH 2/6] ci: use default-branch environment for docs deploy token exchange The get-token action mints a PAT via the Token Exchange Service only when the OIDC environment claim matches a registered policy. The other callers in this repo (update-changelogs, create-update-issues) use the default-branch environment, which is locked to main. Switch the docs deploy jobs to it so they align with that convention and the TES policy. --- .github/workflows/deploy-platform-api-docs.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-platform-api-docs.yml b/.github/workflows/deploy-platform-api-docs.yml index cd4fb28ffe0..149623c6b41 100644 --- a/.github/workflows/deploy-platform-api-docs.yml +++ b/.github/workflows/deploy-platform-api-docs.yml @@ -7,7 +7,10 @@ jobs: get-token: name: Get access token runs-on: ubuntu-latest - environment: github-pages + # `default-branch` is the environment the Token Exchange Service policies + # match on; it's locked to the `main` branch, so a PAT can only be minted + # from a `main` run. + environment: default-branch permissions: id-token: write outputs: @@ -25,7 +28,7 @@ jobs: name: Deploy to GitHub Pages needs: get-token runs-on: ubuntu-latest - environment: github-pages + environment: default-branch permissions: # Just for the initial `actions/checkout` — the actual push to # `gh-pages` uses the PAT from the `get-token` job, not GITHUB_TOKEN. From 0b24c2b264d6b05492feeb845db8b587a0554642 Mon Sep 17 00:00:00 2001 From: Salah-Eddine Saakoun Date: Wed, 1 Jul 2026 11:36:34 +0200 Subject: [PATCH 3/6] ci: request docs deploy token inside the deploy job The Token Exchange Service token can't be passed between jobs: GitHub drops secret job outputs, so the old get-token job handed the deploy job an empty string. Collapse into a single deploy job that checks out, downloads the build artifact, exchanges its OIDC token for a PAT, and publishes to gh-pages, all in one job with id-token: write. --- .../workflows/deploy-platform-api-docs.yml | 43 ++++++++----------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/.github/workflows/deploy-platform-api-docs.yml b/.github/workflows/deploy-platform-api-docs.yml index 7790f109610..317e43dad5a 100644 --- a/.github/workflows/deploy-platform-api-docs.yml +++ b/.github/workflows/deploy-platform-api-docs.yml @@ -4,34 +4,18 @@ on: workflow_call: jobs: - get-token: - name: Get access token - runs-on: ubuntu-latest - # `default-branch` is the environment the Token Exchange Service policies - # match on; it's locked to the `main` branch, so a PAT can only be minted - # from a `main` run. - environment: default-branch - permissions: - id-token: write - outputs: - token: ${{ steps.get-token.outputs.token }} - steps: - - name: Get access token - id: get-token - uses: MetaMask/github-tools/.github/actions/get-token@v1 - with: - token-exchange-url: ${{ vars.TOKEN_EXCHANGE_URL }} - permissions: | - contents: write - deploy: name: Deploy to GitHub Pages - needs: get-token runs-on: ubuntu-latest + # `default-branch` is the environment the Token Exchange Service policy + # matches on; it's locked to the `main` branch, so a PAT can only be minted + # from a `main` run. environment: default-branch permissions: - # Just for the initial `actions/checkout` — the actual push to - # `gh-pages` uses the PAT from the `get-token` job, not GITHUB_TOKEN. + # `id-token: write` lets the job exchange its OIDC token for a PAT via the + # Token Exchange Service; `contents: read` is for the checkout. The push + # to `gh-pages` uses the exchanged PAT, not GITHUB_TOKEN. + id-token: write contents: read steps: - name: Checkout @@ -45,6 +29,17 @@ jobs: name: platform-api-docs-build path: build/ + - name: Get access token + # The token must be requested in the same job that uses it: GitHub drops + # secret values passed between jobs, so a separate token job would hand + # back an empty string. + id: get-token + uses: MetaMask/github-tools/.github/actions/get-token@v1 + with: + token-exchange-url: ${{ vars.TOKEN_EXCHANGE_URL }} + permissions: | + contents: write + - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 with: @@ -52,7 +47,7 @@ jobs: # default `GITHUB_TOKEN`. `GITHUB_TOKEN` can't be granted branch # protections that disallow direct human pushes while still letting # this workflow publish, which is what we want for `gh-pages`. - personal_token: ${{ needs.get-token.outputs.token }} + personal_token: ${{ steps.get-token.outputs.token }} publish_dir: ./build destination_dir: platform-api # Preserve sibling subdirectories (e.g. /package-api/) so this From 79265ebd0b960f7d7211342e30de0ae395ba9d6a Mon Sep 17 00:00:00 2001 From: Salah-Eddine Saakoun Date: Wed, 1 Jul 2026 15:35:04 +0200 Subject: [PATCH 4/6] ci: build docs fresh in the deploy job instead of reusing artifact Reusing the artifact (and caches) from the lint-build-test build job for a production deploy is a supply-chain risk: that job also runs on PRs, so its output can't be trusted for publishing. The deploy job now does its own build in an isolated high-risk checkout, then exchanges a token and publishes. The lint-build-test job stays as a parallel PR build check and no longer uploads an artifact. --- .../workflows/deploy-platform-api-docs.yml | 34 +++++++++++++------ .github/workflows/lint-build-test.yml | 23 +++---------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/.github/workflows/deploy-platform-api-docs.yml b/.github/workflows/deploy-platform-api-docs.yml index 317e43dad5a..fa218e06a7b 100644 --- a/.github/workflows/deploy-platform-api-docs.yml +++ b/.github/workflows/deploy-platform-api-docs.yml @@ -5,7 +5,7 @@ on: jobs: deploy: - name: Deploy to GitHub Pages + name: Build and deploy to GitHub Pages runs-on: ubuntu-latest # `default-branch` is the environment the Token Exchange Service policy # matches on; it's locked to the `main` branch, so a PAT can only be minted @@ -18,16 +18,28 @@ jobs: id-token: write contents: read steps: - - name: Checkout - uses: actions/checkout@v7 + # Build the site fresh here rather than reusing the artifact from the + # `build-platform-api-docs` job in `lint-build-test`: that job also runs + # for PRs, so trusting its output (or the caches behind it) for a + # production deploy would risk publishing poisoned content. + # `is-high-risk-environment` isolates the build. + - name: Checkout and setup environment + uses: MetaMask/action-checkout-and-setup@v3 with: + is-high-risk-environment: true persist-credentials: false - - name: Download build artifact - uses: actions/download-artifact@v8 - with: - name: platform-api-docs-build - path: build/ + - name: Generate and build Platform API docs + # The site is published under the `/platform-api/` subdirectory of the + # repo's GitHub Pages site so that other doc sites (e.g. package API + # docs) can be hosted alongside under sibling paths. + env: + REPO_OWNER: ${{ github.repository_owner }} + REPO_NAME: ${{ github.event.repository.name }} + run: | + yarn docs:platform-api:build \ + --site-url "https://${REPO_OWNER}.github.io" \ + --site-base-url "/${REPO_NAME}/platform-api/" - name: Get access token # The token must be requested in the same job that uses it: GitHub drops @@ -48,8 +60,8 @@ jobs: # protections that disallow direct human pushes while still letting # this workflow publish, which is what we want for `gh-pages`. personal_token: ${{ steps.get-token.outputs.token }} - publish_dir: ./build + publish_dir: ./.platform-api-docs/build destination_dir: platform-api - # Preserve sibling subdirectories (e.g. /package-api/) so this - # deploy only overwrites /platform-api/. + # Preserve sibling subdirectories (e.g. /package-api/) so this deploy + # only overwrites /platform-api/. keep_files: true diff --git a/.github/workflows/lint-build-test.yml b/.github/workflows/lint-build-test.yml index 4b1a717c3d0..913e0a8b679 100644 --- a/.github/workflows/lint-build-test.yml +++ b/.github/workflows/lint-build-test.yml @@ -235,23 +235,8 @@ jobs: is-high-risk-environment: true persist-credentials: false + # Validate that the docs site builds on every PR. The deploy workflow + # rebuilds it from scratch rather than reusing an artifact from here, so + # this job only needs to prove the build succeeds — it doesn't publish. - name: Generate and build Platform API docs - # The site is published under the `/platform-api/` subdirectory of - # the repo's GitHub Pages site so that other doc sites (e.g. - # package API docs) can be hosted alongside under sibling paths. - env: - REPO_OWNER: ${{ github.repository_owner }} - REPO_NAME: ${{ github.event.repository.name }} - run: | - yarn docs:platform-api:build \ - --site-url "https://${REPO_OWNER}.github.io" \ - --site-base-url "/${REPO_NAME}/platform-api/" - - - name: Upload build artifact - # Only the `main`-branch push build is consumed by the deploy job; PR - # builds are uploaded under a different name purely for inspection. - uses: actions/upload-artifact@v7 - with: - name: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' && 'platform-api-docs-build' || 'platform-api-docs' }} - path: .platform-api-docs/build/ - retention-days: ${{ github.ref == 'refs/heads/main' && github.event_name == 'push' && 1 || 7 }} + run: yarn docs:platform-api:build From e8b5178ea1d41be109eee264d80dac974608f077 Mon Sep 17 00:00:00 2001 From: Salah-Eddine Saakoun Date: Wed, 1 Jul 2026 16:19:40 +0200 Subject: [PATCH 5/6] ci: trim verbose comments in docs workflows --- .../workflows/deploy-platform-api-docs.yml | 32 ++++++------------- .github/workflows/lint-build-test.yml | 5 ++- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/.github/workflows/deploy-platform-api-docs.yml b/.github/workflows/deploy-platform-api-docs.yml index fa218e06a7b..c4138419b7e 100644 --- a/.github/workflows/deploy-platform-api-docs.yml +++ b/.github/workflows/deploy-platform-api-docs.yml @@ -7,22 +7,16 @@ jobs: deploy: name: Build and deploy to GitHub Pages runs-on: ubuntu-latest - # `default-branch` is the environment the Token Exchange Service policy - # matches on; it's locked to the `main` branch, so a PAT can only be minted - # from a `main` run. + # Locked to `main`, matching the Token Exchange Service policy that lets + # this job mint a `contents: write` token. environment: default-branch permissions: - # `id-token: write` lets the job exchange its OIDC token for a PAT via the - # Token Exchange Service; `contents: read` is for the checkout. The push - # to `gh-pages` uses the exchanged PAT, not GITHUB_TOKEN. id-token: write contents: read steps: - # Build the site fresh here rather than reusing the artifact from the - # `build-platform-api-docs` job in `lint-build-test`: that job also runs - # for PRs, so trusting its output (or the caches behind it) for a - # production deploy would risk publishing poisoned content. - # `is-high-risk-environment` isolates the build. + # Build fresh rather than reusing the artifact from `lint-build-test`, + # which also builds untrusted PR code — publishing its output would be a + # supply-chain risk. - name: Checkout and setup environment uses: MetaMask/action-checkout-and-setup@v3 with: @@ -30,9 +24,6 @@ jobs: persist-credentials: false - name: Generate and build Platform API docs - # The site is published under the `/platform-api/` subdirectory of the - # repo's GitHub Pages site so that other doc sites (e.g. package API - # docs) can be hosted alongside under sibling paths. env: REPO_OWNER: ${{ github.repository_owner }} REPO_NAME: ${{ github.event.repository.name }} @@ -42,9 +33,7 @@ jobs: --site-base-url "/${REPO_NAME}/platform-api/" - name: Get access token - # The token must be requested in the same job that uses it: GitHub drops - # secret values passed between jobs, so a separate token job would hand - # back an empty string. + # Requested here because GitHub drops secret outputs passed between jobs. id: get-token uses: MetaMask/github-tools/.github/actions/get-token@v1 with: @@ -55,13 +44,10 @@ jobs: - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 with: - # Use a PAT obtained via Token Exchange Service rather than the - # default `GITHUB_TOKEN`. `GITHUB_TOKEN` can't be granted branch - # protections that disallow direct human pushes while still letting - # this workflow publish, which is what we want for `gh-pages`. + # Push with the exchanged PAT so `gh-pages` can keep protections that + # block direct human pushes. personal_token: ${{ steps.get-token.outputs.token }} publish_dir: ./.platform-api-docs/build destination_dir: platform-api - # Preserve sibling subdirectories (e.g. /package-api/) so this deploy - # only overwrites /platform-api/. + # Only overwrite `/platform-api/`, leaving sibling doc sites intact. keep_files: true diff --git a/.github/workflows/lint-build-test.yml b/.github/workflows/lint-build-test.yml index 913e0a8b679..2f36e190094 100644 --- a/.github/workflows/lint-build-test.yml +++ b/.github/workflows/lint-build-test.yml @@ -235,8 +235,7 @@ jobs: is-high-risk-environment: true persist-credentials: false - # Validate that the docs site builds on every PR. The deploy workflow - # rebuilds it from scratch rather than reusing an artifact from here, so - # this job only needs to prove the build succeeds — it doesn't publish. + # PR build check only; the deploy workflow rebuilds from scratch, so this + # doesn't publish an artifact. - name: Generate and build Platform API docs run: yarn docs:platform-api:build From e7a2d74883ae59e712d63fc0b5a534071b2d9b66 Mon Sep 17 00:00:00 2001 From: Salah-Eddine Saakoun Date: Wed, 1 Jul 2026 16:21:39 +0200 Subject: [PATCH 6/6] ci: drop explanatory comments from docs workflows --- .github/workflows/deploy-platform-api-docs.yml | 9 --------- .github/workflows/lint-build-test.yml | 2 -- 2 files changed, 11 deletions(-) diff --git a/.github/workflows/deploy-platform-api-docs.yml b/.github/workflows/deploy-platform-api-docs.yml index c4138419b7e..d01eb55ac1f 100644 --- a/.github/workflows/deploy-platform-api-docs.yml +++ b/.github/workflows/deploy-platform-api-docs.yml @@ -7,16 +7,11 @@ jobs: deploy: name: Build and deploy to GitHub Pages runs-on: ubuntu-latest - # Locked to `main`, matching the Token Exchange Service policy that lets - # this job mint a `contents: write` token. environment: default-branch permissions: id-token: write contents: read steps: - # Build fresh rather than reusing the artifact from `lint-build-test`, - # which also builds untrusted PR code — publishing its output would be a - # supply-chain risk. - name: Checkout and setup environment uses: MetaMask/action-checkout-and-setup@v3 with: @@ -33,7 +28,6 @@ jobs: --site-base-url "/${REPO_NAME}/platform-api/" - name: Get access token - # Requested here because GitHub drops secret outputs passed between jobs. id: get-token uses: MetaMask/github-tools/.github/actions/get-token@v1 with: @@ -44,10 +38,7 @@ jobs: - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0 with: - # Push with the exchanged PAT so `gh-pages` can keep protections that - # block direct human pushes. personal_token: ${{ steps.get-token.outputs.token }} publish_dir: ./.platform-api-docs/build destination_dir: platform-api - # Only overwrite `/platform-api/`, leaving sibling doc sites intact. keep_files: true diff --git a/.github/workflows/lint-build-test.yml b/.github/workflows/lint-build-test.yml index 2f36e190094..bc0f9d711d9 100644 --- a/.github/workflows/lint-build-test.yml +++ b/.github/workflows/lint-build-test.yml @@ -235,7 +235,5 @@ jobs: is-high-risk-environment: true persist-credentials: false - # PR build check only; the deploy workflow rebuilds from scratch, so this - # doesn't publish an artifact. - name: Generate and build Platform API docs run: yarn docs:platform-api:build