ci: split clang-tidy-bazel into pull_request + workflow_run stages#10521
Conversation
Fork PRs on the public repo (where external contributors land) get a read-only GITHUB_TOKEN, so the single-stage pull_request workflow couldn't post reviewdog review comments — POST /pulls/N/reviews returned 403 and reviewdog exited 1. Stage A (clang-tidy-bazel) keeps the bazel --config=lint build but now only uploads clang-tidy.txt and pr-meta.txt as an artifact. It needs no write permissions, so it stays safe on fork code. Stage B (clang-tidy-bazel-post) runs on workflow_run in the base repo's context with a writable token. It downloads the artifact, validates pr-meta fields against a strict allowlist, synthesizes a pull_request event payload (workflow_run.pull_requests[] is empty for fork PRs), and runs reviewdog with -reporter=github-pr-review. It never checks out the fork's code or runs any fork scripts. Signed-off-by: Joao Luis Sombrio <sombrio@sombrasoft.dev>
|
Note Gemini is unable to generate a review for this pull request due to the file types involved not being currently supported. |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2d79066ddb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Reviewdog's github-pr-review reporter resolves the local git root before flushing comments. On a fresh runner containing only the downloaded artifact, reviewdog logs "reviewdog: .git not found" and silently no-ops (exit 0, no review posted). Confirmed locally by running reviewdog from a scratch dir against the same synthesized event + artifact: zero comments posted; running the same command from inside a checkout works. Add a shallow actions/checkout step before the artifact download. The default ref in workflow_run context is the base repo's default branch, which is safe (no fork code) and sufficient — reviewdog fetches the actual PR diff via the GitHub API, so the local SHA need not match. Signed-off-by: Joao Luis Sombrio <sombrio@sombrasoft.dev>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 24d544ace0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| echo "base_repo=${{ github.event.pull_request.base.repo.full_name }}" | ||
| } > pr-meta.txt | ||
|
|
||
| - name: Upload clang-tidy artifact |
There was a problem hiding this comment.
Restore failing the PR check on lint findings
When a PR produces clang-tidy diagnostics, this pull_request workflow now finishes successfully after uploading clang-tidy.txt; the only remaining -fail-level=any is in the workflow_run companion, and GitHub documents workflow_run as running at the default-branch GITHUB_SHA, not the PR head. That means branch protection on the original clang-tidy-bazel PR check can pass even though the previous inline reviewdog step would have failed the PR check for the same diagnostics.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Confirmed and fixed in fcb0180.
Stage A now re-runs reviewdog with -reporter=local -filter-mode=added -fail-level=any after the artifact upload. Local mode only needs the filesystem and an explicit -diff command, so it works fine under the fork-PR read-only token. Step is positioned after upload-artifact so the post workflow still has the findings to comment on even when this check exits non-zero.
Stage B's guard relaxes from conclusion == 'success' to conclusion != 'cancelled' so it still runs and posts review comments when Stage A's check step failed. Net behaviour: same as the original single-stage workflow — clang-tidy findings in the PR diff fail the clang-tidy-bazel check (branch protection blocks merge) AND the post workflow posts inline review comments. Fork PRs still benefit from the split because the posting half runs in base-repo context with a writable token.
Summary
clang-tidy-bazelinto two stages so reviewdog can post review comments on fork PRs on the public repo, where thepull_requesttoken is read-only.clang-tidy-bazel) keeps the bazel--config=lintbuild and uploadsclang-tidy.txt+pr-meta.txtas an artifact. No write permissions.clang-tidy-bazel-post) runs onworkflow_runin base-repo context with a writable token. Downloads the artifact, validatespr-meta.txtfields against a strict regex allowlist, synthesizes apull_requestevent JSON (becauseworkflow_run.pull_requests[]is empty for fork PRs), then runs reviewdog with-reporter=github-pr-review.Why
Single-stage
pull_requestworkflow can't post reviewdog reviews on fork PRs — GitHub gives those runs a read-onlyGITHUB_TOKENregardless ofpermissions:, soPOST /pulls/N/reviewsreturned 403 and reviewdog exited 1 (see failed run on public tier). This mirrors the legacy two-stageclang-tidy-review/clang-tidy-review-postsetup that solved the same problem before the bazel-based rewrite landed.Security
pr-meta.txtis parsed with a strict allowlist (pr_numbernumeric, SHAs hex-40, repo slugs^[A-Za-z0-9._-]+/[A-Za-z0-9._-]+$).BAZEL_CACHE_PASSWORDis not available there (consistent with prior behaviour).Test plan
workflow_run completedand posts a review on the in-org PR.conclusion != 'success'.