Skip to content

claude.yml: grant actions:write so @claude can dispatch code review#911

Merged
d-morrison merged 1 commit into
mainfrom
fix/claude-review-dispatch-perm
Jun 17, 2026
Merged

claude.yml: grant actions:write so @claude can dispatch code review#911
d-morrison merged 1 commit into
mainfrom
fix/claude-review-dispatch-perm

Conversation

@d-morrison

Copy link
Copy Markdown
Owner

What

Grant the claude.yml job actions: write (was actions: read) so the post-Claude steps can actually dispatch the dedicated code-review workflow.

Root cause

claude.yml fires the reviewer via gh workflow run claude-code-review.yml (the workflow_dispatch REST endpoint POST /actions/workflows/{id}/dispatches) in three steps. That endpoint requires actions: write for GITHUB_TOKEN, but the job only granted actions: read. So every dispatch returned:

could not create workflow dispatch event: HTTP 403: Resource not accessible by integration
  (.../actions/workflows/273583888/dispatches)

…and the error was swallowed by the || echo "::warning::…" fallback on each call. Net effect: @claude review (and the post-commit auto-dispatch) silently never triggered a review.

Evidence

  • Directly observed in claude.yml run 27598978484, step "Dispatch claude-code-review.yml on @claude review comment": the 403 above, immediately followed by the swallowed warning.
  • On PR claude-code-review: run on Claude-bot pushes #900, two @claude review requests produced only the "👀 Picked up…" ack and no review — and get_reviews/get_comments show no review content was ever posted there.
  • No workflow_dispatch run of claude-code-review.yml has fired from claude.yml. (The handful of workflow_dispatch runs in the history are from May and predate the affected PRs — most likely manual dispatches.)
  • git blame puts actions: read on this job since 2026-05-08, so this has been broken since at least then.

Change

  • actions: readactions: write in the claude job's permissions: (one line; write is a superset of read, so Claude's CI-result reads are unaffected).
  • Corrected the inline comment that claimed GITHUB_TOKEN "is permitted to trigger workflow_dispatch" without noting the actions: write requirement, and added a note at the permissions: block so a future edit doesn't silently re-break it.

Verification

  • python3 -c "import yaml; ..." parses claude.yml and confirms permissions.actions == 'write'.
  • The fix can only be fully confirmed once merged (a real @claude review should then produce a dispatched claude-code-review.yml run instead of a swallowed 403).

Context / related

This is the real fix for the gap that PR #900 was trying (ineffectively) to address. Investigation on #900 showed its actor-filter approach is a no-op — Claude's PR pushes arrive as actor d-morrison (already reviewed) and claude[bot] only ever fires issue_comment, never pull_request — so the actual reason Claude-authored commits weren't getting reviewed is this broken dispatch, not the if: filter. #900 is being closed in favor of this PR.

Per CLAUDE.md, this is a .github/CI-only change kept in its own dedicated PR.

https://claude.ai/code/session_01ER1dFrUPTjaHeL3n7Yy7qG


Generated by Claude Code

The post-Claude steps call `gh workflow run claude-code-review.yml` to
fire the dedicated reviewer via workflow_dispatch, but the job granted
only `actions: read`. The workflow_dispatch REST endpoint
(POST /actions/workflows/{id}/dispatches) requires `actions: write` for
GITHUB_TOKEN, so every dispatch returned

  HTTP 403: Resource not accessible by integration

and was swallowed by the `|| echo "::warning::"` fallback — the
code-review never auto-ran. Directly observed on PR #900 run
27598978484 (the @claude-review dispatch 403'd silently); no dispatched
claude-code-review.yml run has succeeded from claude.yml as a result.

Bump `actions: read` -> `actions: write` (a superset, so Claude's
CI-result reads still work) and correct the now-inaccurate dispatch
comment to note the write requirement.

Workflow/infra-only change, kept in its own PR per CLAUDE.md.
@claude

claude Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Claude finished @d-morrison's task in 1m 30s —— View job


Code Review: PR #911actions: write permission fix

  • Gathering context
  • Reading changed file
  • Reviewing changes

Verdict: LGTM. The fix is correct and the diagnosis is accurate. One non-blocking observation below.


Permission change (.github/workflows/claude.yml, line 70)

The one-line fix is right. The workflow_dispatch REST endpoint (POST /repos/{owner}/{repo}/actions/workflows/{id}/dispatches) requires actions: write on the GITHUB_TOKEN; actions: read is insufficient and produces an HTTP 403 that the || echo "::warning::" fallback silently consumed. The change from read to write is the minimal available fix — GitHub Actions doesn't offer a more granular scope between the two for this endpoint.

additional_permissions: actions: read at line 338 (unchanged — correct)

additional_permissions: |
  actions: read

This is passed to the anthropics/claude-code-action@v1 action to configure what the action itself can do (reading CI results inside its session). It's separate from the job-level permissions block that governs the GITHUB_TOKEN used by the post-Claude gh workflow run steps. Leaving this at read is correct.

Non-blocking: swallowed warnings remain after the fix

All three dispatch call-sites keep their || echo "::warning::" fallback:

  • Line 835–836 (@claude review comment dispatch)
  • Lines 867–868 (post-commit dispatch)
  • Lines 986–987 (issue-trigger dispatch)

With actions: write in place the 403s should stop, so this shouldn't matter in practice. But if a different failure mode arises (e.g. the review workflow is disabled, renamed, or the runner has no network), the warning will again be easy to overlook. Not a blocker for this PR — the pattern is pre-existing and out of scope here — but worth keeping in mind if the dispatch ever goes silent again.

Comment updates

The updated inline comments accurately explain the permission requirement, reference the observed failure evidence, and cross-link the two affected blocks. This is exactly the kind of explanatory comment that prevents the same regression from creeping back in.


The PR is correctly scoped (CI-only, no book content mixed in — per CLAUDE.md), the root cause analysis checks out against the evidence cited (run 27598978484, PR #900), and the change is backward-compatible (writeread for CI result access). Ready to merge.

@d-morrison d-morrison marked this pull request as ready for review June 17, 2026 19:37
@d-morrison d-morrison merged commit e1aa515 into main Jun 17, 2026
3 checks passed
@d-morrison d-morrison deleted the fix/claude-review-dispatch-perm branch June 17, 2026 19:37
@claude

claude Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Claude finished @d-morrison's task in 1m 35s —— View job


Code Review: PR #911actions: write permission fix

  • Gathering context
  • Reading changed file
  • Reviewing changes

Verdict: LGTM. The fix is correct, the diagnosis is accurate, and the added comments prevent silent re-regression. Two non-blocking observations below.


Permission change (line 70)

actions: write   # was: actions: read

This is the right fix. The workflow_dispatch REST endpoint (POST /repos/{owner}/{repo}/actions/workflows/{id}/dispatches) requires actions: write on the calling GITHUB_TOKEN. GitHub Actions does not expose a more granular scope between read and write for this endpoint, so write is the minimal correct value.

The change is backward-compatible: write is a strict superset of read, so the existing CI-result reads (via additional_permissions: actions: read passed to claude-code-action@v1 at line 338) are unaffected — that field controls what the action itself can do inside its own session, not what the job-level GITHUB_TOKEN used by the surrounding shell steps can do.

Comment block (lines 60–69)

# `write` (not `read`) is required: besides letting Claude read CI
# results on PRs, the post-Claude steps below call `gh workflow run
# claude-code-review.yml` (the workflow_dispatch REST endpoint
# `POST /actions/workflows/{id}/dispatches`), which GITHUB_TOKEN can
# only reach with `actions: write`. With `actions: read` every
# dispatch 403s ("Resource not accessible by integration") and is
# swallowed by the `|| echo "::warning::"` fallback, so the
# code-review never auto-runs (observed on PR #900, run
# 27598978484: the @claude-review dispatch 403'd silently). `write`
# is a superset of `read`, so CI reads still work.

This is exactly the kind of comment worth keeping — it names the REST endpoint, explains why write is required (not obvious from the setting name alone), cites the observable failure mode, references the specific run where it was caught, and clarifies that the change is backward-compatible. Future readers (and future automated edits) won't silently re-break this.

The cross-references at lines 862–866 (inside the post-Claude dispatch step) also correctly point back to this block.


Non-blocking: swallowed fallbacks remain

All three dispatch call-sites retain || echo "::warning::":

  • Line 836 (@claude review comment dispatch)
  • Line 868 (post-commit dispatch)
  • Line 987 (issue-trigger dispatch)

With actions: write in place the 403s stop, so this is moot for the current failure. But if a different failure mode arises — review workflow disabled, renamed, or rate-limited — the warning will again be easy to overlook. Pre-existing behavior; out of scope for this PR.

Non-blocking: asymmetric error handling on reviewer re-request (line 859)

gh api -X POST ... -f "reviewers[]=d-morrison" || true

The reviewer re-request at line 859 uses || true (completely silent on failure), while the dispatch immediately after uses || echo "::warning::". A failure here — e.g., the reviewer is no longer a collaborator — produces no output at all. This is pre-existing behavior unchanged by this PR, but worth noting alongside the dispatch comment update in case this step ever goes mysteriously quiet.


The PR is correctly scoped to CI-only changes per CLAUDE.md ("Workflow / .github/ / CI / infra changes go in their own dedicated PRs"), the root-cause analysis is sound, and the change is backward-compatible. The inline evidence (run 27598978484, PR #900) makes the diagnosis independently verifiable.

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.

2 participants