From ecd54a001e6a7c13fa2562859ec4703b9520977f Mon Sep 17 00:00:00 2001 From: Brooklyn Nicholson Date: Sat, 18 Jul 2026 01:06:36 -0400 Subject: [PATCH] fix(ci): make timings report fork-safe (missed by #66577) #66373 swapped GITHUB_TOKEN -> AUTOFIX_BOT_PAT across the workflows and #66577 restored the `|| github.token` fork fallback for detect-changes and the label gates -- but it missed the ci-timings "Collect timings and generate report" step, which still passes a bare AUTOFIX_BOT_PAT. On fork PRs that PAT is empty, so timings_report.py hard-fails at expect_env("GITHUB_TOKEN") before it can reach its own "degraded run must never redden the PR" soft-fail path. Every fork PR gets a red run from this advisory job (e.g. #66573). - ci.yml: apply the same `secrets.AUTOFIX_BOT_PAT || github.token` fallback to the timings step. github.token has `actions: read`, enough to read the run's job/step durations on forks. - timings_report.py: treat a missing/empty GITHUB_TOKEN as a degraded run (TimingsUnavailable) instead of a hard ValueError, so this whole class of failure can never redden a PR again even if a future workflow drops the token. Still writes no JSON, so no empty baseline is ever cached. --- .github/workflows/ci.yml | 5 ++++- scripts/ci/timings_report.py | 8 +++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 72e34a06d64c..faae3b6f2704 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -226,7 +226,10 @@ jobs: - name: Collect timings and generate report env: - GITHUB_TOKEN: ${{ secrets.AUTOFIX_BOT_PAT }} + # Forks get no repo secrets (AUTOFIX_BOT_PAT is empty); fall back to + # the built-in read-only token so the timings API read still works + # there instead of hard-failing this advisory job on every fork PR. + GITHUB_TOKEN: ${{ secrets.AUTOFIX_BOT_PAT || github.token }} run: | python3 scripts/ci/timings_report.py \ --baseline ci-timings-baseline.json \ diff --git a/scripts/ci/timings_report.py b/scripts/ci/timings_report.py index 9df3fc519aac..0e19e539c63a 100644 --- a/scripts/ci/timings_report.py +++ b/scripts/ci/timings_report.py @@ -923,11 +923,17 @@ def main(): with open(args.from_json, encoding="utf-8") as f: timings = json.load(f) else: - token = expect_env("GITHUB_TOKEN") repo = expect_env("GITHUB_REPOSITORY") run_id = expect_env("GITHUB_RUN_ID") head_sha = expect_env("GITHUB_SHA") try: + # A missing token (e.g. an empty PAT on a fork PR, where repo + # secrets are unavailable) is a degraded run, not a hard error: + # route it through the same soft-fail path so this advisory job + # never reddens the PR. + token = os.environ.get("GITHUB_TOKEN") + if not token: + raise TimingsUnavailable("GITHUB_TOKEN is empty") timings = collect_timings(token, repo, run_id, head_sha) except TimingsUnavailable as e: # Observability job: a missing report must never redden the PR.