Skip to content

fix: post dogfood PR review comments on fork PRs#556

Open
michael-denyer wants to merge 1 commit into
tirth8205:mainfrom
michael-denyer:fix/pr-review-fork-comments
Open

fix: post dogfood PR review comments on fork PRs#556
michael-denyer wants to merge 1 commit into
tirth8205:mainfrom
michael-denyer:fix/pr-review-fork-comments

Conversation

@michael-denyer

Copy link
Copy Markdown
Contributor

Linked issue

No linked issue — fixes a CI failure observed live on #555 and #552 (details below). Happy to file a bug report via the issue form if you'd prefer one for tracking.

What & why

The pr-review.yml dogfood workflow fails on every fork-originated PR: the graph build and risk analysis complete, but the sticky-comment upsert dies with gh: Resource not accessible by integration (HTTP 403), because GITHUB_TOKEN in pull_request runs from public forks is capped at read access — the workflow's permissions: pull-requests: write can't raise it. Same-repo PRs (e.g. #548, #545) are unaffected, which is why this never showed up before external fork PRs started arriving: #555 and #552 both fail with the identical 403 at the identical step. docs/GITHUB_ACTION.md already documents this exact limitation for external consumers ("Fork PRs" security note); this PR applies the mitigation to the dogfood workflow itself.

The fix is the standard unprivileged-analysis / privileged-comment split:

  • pr-review.yml now runs fully unprivileged (contents: read only — pull-requests: write dropped). It runs the action with comment: "false" and uploads the rendered report plus the PR number as an artifact.
  • pr-review-comment.yml (new) triggers on workflow_run with pull-requests: write, downloads the artifact, and upserts the same sticky comment. It never checks out or executes PR code, and treats the artifact as untrusted input: the PR number must be digits-only, and the named PR's head must match the triggering run's head_sha, otherwise it refuses to post. All event values reach run: blocks via env:; the comment body is passed as -F body=@file, never shell-interpolated.
  • action.yml gains a comment-file output (path to the rendered markdown) so any consumer can implement the same pattern. Existing consumers are unaffected — comment still defaults to true and posts exactly as before.
  • docs/GITHUB_ACTION.md: documents the new output, updates the "Fork PRs" security note to recommend this pattern (replacing the pull_request_target suggestion, which runs untrusted code with a privileged token), and updates the Dogfooding section.

Note for review: workflow_run workflows execute from the default branch, so pr-review-comment.yml only activates after this PR merges. On this PR you'll see the unprivileged half work (report artifact uploaded) but no comment — that's expected, not a failure. The first fork PR after merge will exercise the full path.

How it was tested

No Python changed, so no new pytest tests — the comment-rendering logic is untouched and remains covered by tests/test_action_render.py. Both workflows validated with actionlint (no findings) and action.yml checked to parse cleanly.

uv run pytest tests/ --tb=short -q
# 1384 passed, 1 skipped, 2 xpassed

uv run ruff check code_review_graph/
# All checks passed!

actionlint
# no findings

Checklist

  • Tests added for new functionality — N/A (workflow YAML + one composite-action output; validated with actionlint, render logic still covered by tests/test_action_render.py)
  • All tests pass: uv run pytest tests/ --tb=short -q
  • Linting passes: uv run ruff check code_review_graph/
  • Type checking passes: uv run mypy code_review_graph/ --ignore-missing-imports --no-strict-optional
  • Lines are at most 100 characters
  • Docs updated where behavior changed (README, docs/, docstrings)

The pr-review.yml dogfood workflow failed on every fork-originated PR:
GITHUB_TOKEN is read-only in pull_request runs from forks, so the
sticky-comment upsert died with HTTP 403 (observed on tirth8205#555). The
analysis ran fine — only the comment write failed.

Split into the standard two-workflow pattern:
- pr-review.yml runs unprivileged (contents: read only) with
  comment: false, and uploads the rendered report plus PR number as an
  artifact.
- pr-review-comment.yml (workflow_run, pull-requests: write) downloads
  the artifact and upserts the sticky comment. It never checks out PR
  code and treats the artifact as untrusted: the PR number must be
  numeric and the named PR's head must match the triggering run's
  head_sha before anything is posted.

action.yml gains a comment-file output (path to the rendered markdown)
so any caller can implement the same pattern; existing consumers are
unaffected (comment defaults to true and posts exactly as before).
docs/GITHUB_ACTION.md documents the output and replaces the
pull_request_target suggestion in the fork-PRs note with this safer
pattern.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant