The labelling approach introduced in 6089075265
means contributors can now trigger the workflow on their own when the label
is added by a maintainer and they update the PR. Hence we need to allow all
users to access the claude code action. This is safe because we already gate
the workflow ourselves to only the contributors that we want to allow.
Additionally, the claude code job has no permissions anymore except read access
to the repository and can execute very limited tools, so this should be safe.
The name doesn't actually matter, it gets replaced with the name
of the file when not archiving. So stop passing a name and pass in
the filename as the name when downloading the artifact.
Rather than have claude fetch the context itself, let's fetch the
context for it in the setup job. This has the following advantages:
- We can reduce the permissions granted to the claude job
- claude has less opportunity to mess up trying to fetch the context
itself. Specifically, it keeps spawsning a background task to fetch
the PR branch which messes up the structured output at the end, causing
the review job to fail. By pre-fetching the context it won't have to
spawn the background task. Additionally, we limit the git commands it
can execute to local ones to ensure it doesn't try to fetch the PR branch.
Finally, we fetch the branch ourselves as pr-review so claude can look at it
to review the PR.
- If a pr is labeled with claude-review, review it immediately
- If a pr labeled with claude-review is updated, review it regardless
of the author
- If a pr is opened by a maintainer, review it and add the claude-review
label. If the claude-review label is later removed, the pr won't be
auto-reviewed anymore.
Bash(gh:api *) wasn't actually working. Turns out the colon syntax
is deprecated and unnecessary. Let's stop using it which also fixes
the bug so that gh api calls are allowed now.
Claude now identifies which existing review comment threads should be
resolved (because the issue was addressed or someone disagreed) and
returns their REST API IDs in a new `resolve` array in the structured
output. The post job uses GraphQL to map comment IDs to threads and
resolve them.
Also switches all GitHub data fetching from MCP tools to `gh api` calls,
since the MCP tool strips comment IDs during its GraphQL-to-minimal
conversion and cannot be used for thread resolution.
The thread resolution GraphQL pagination is wrapped in a try/catch so
that a failure to fetch threads degrades gracefully instead of aborting
the entire post job. Unmatched comment IDs are logged for debuggability.
Adds explicit instructions to complete all data fetching before starting
review and to cancel background tasks before returning structured output,
working around a claude-code-action issue where a late-completing
background task triggers a new conversation turn that overwrites the
structured JSON result.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Switch claude-review from reviewing the entire PR diff at once to
reviewing each commit individually via subagents. Each commit review
subagent receives the PR context, preceding commit diffs, and its own
commit diff, then returns comments tagged with the commit SHA. This
ensures review comments are attached to the correct commit via the
GitHub API rather than all pointing at HEAD.
Also add Bash(gh:*) to allowed tools so subagents can fetch per-commit
diffs via `gh api` without needing local git objects, and remove CI
analysis (needs to be delayed until CI finishes to be useful).
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
Address feedback from facebook/bpfilter#472:
- Fix setFailed error message counting file-level comments (without
line numbers) that are intentionally skipped, use inlineComments.length
instead of comments.length
- Fix double severity prefix in inline comments: the prompt told Claude
to prefix body with **must-fix**/etc but the post job also prepended
"Claude: ", producing "Claude: **must-fix**: ...". Now the prompt says
not to prefix and the post job adds "Claude **severity**: " using the
structured severity field
- Move error tracking instructions to a top-level section after all phases
so they apply to all runs, not just the first run
- Clarify that line is optional: use "should be" instead of "must be"
and document that omitting line still surfaces the comment in the
tracking comment summary
- Distinguish cancelled vs failed in tracking comment message
- Add side: "RIGHT" and subject_type: "line" to createReviewComment
per GitHub API recommendations
- Downgrade partial inline comment posting failures to warnings; only
fail the job when no comments at all could be posted
Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
- Use github.paginate() for listComments to handle PRs with 100+ comments
- Make line optional in review schema to allow file-level comments
- Skip createReviewComment for comments without a line number
- Fix failed count to exclude skipped file-level comments
- Pass review result via env var instead of expression injection
- Use core.warning() instead of console.log() for JSON parse failures
- Fix MARKER insertion for single-line summaries that have no newline
- Require "@claude review" instead of just "@claude" to trigger
Co-developed-by: Claude <claude@anthropic.com>
This workflow runs on any comment to a github PR. 99% of the time the
workflow will be skipped yet it will still cancel any previous ongoing
workflows. Let's not cancel in progress workflow but instead queue the
workflow so we don't cancel in progress reviews any time a comment is
posted on a PR that is being reviewed.
The workflow is split into two jobs for least-privilege:
1. 'review' job — runs Claude with read-only permissions (contents: read,
id-token: write for AWS OIDC, actions: read). Claude produces a structured
JSON review via --json-schema with a 'comments' array and a 'summary'
string. Its tools are restricted to read-only operations (Read, LS, Grep,
Glob, Task, and various Bash prefixes for common read-only commands).
Claude also has access to CI MCP tools to analyze failed workflow runs.
2. 'post' job — only has pull-requests: write. Reads the structured JSON
output from the review job and posts inline comments individually (so
re-runs only add new comments). Maintains a tracking comment with a
<!-- claude-pr-review --> marker that is created on first run and updated
in-place on subsequent runs, preserving existing item order, wording,
and checkbox state. Posts a notification comment when the tracking
comment is updated or left unchanged.
Comment deduplication is handled by Claude in the prompt rather than in
the posting script, allowing for better semantic understanding of whether
two comments address the same issue.
The PR number is resolved via github.event.pull_request.number with a
fallback to github.event.issue.number for issue_comment events where
github.event.pull_request is not populated. The concurrency group uses
the same fallback.
Co-developed-by: Claude <claude@anthropic.com>
This will allow maintainers to mention claude in comments on issues
and prs to do stuff like review something or try to reproduce a bug
or other stuff. Let's give it a try and see whether we like it or
not.
Set `persist-credentials: false` for actions/checkout.
By default, using `actions/checkout` causes a credential to be persisted on
disk. Subsequent steps may accidentally publicly persist the credential, e.g.
by including it in a publicly accessible artifact via actions/upload-artifact.
However, even without this, persisting the credential on disk is non-ideal
unless actually needed.
Link: https://docs.zizmor.sh/audits/#artipacked
* 66d51024b7 man: Update caching section
* 4eac60f168 Remove all cached images if repository metadata will be synced
* 025c6c0150 Move Incremental= to inherited settings in docs
* 427970d8fd Make MakeScriptsExecutable= a multiversal setting
* 53bd2da6fe Look at all CacheOnly= settings to determine if we need to sync metadata
* 114ae558ef config / qemu: add Console=headless
* d6ddc66acb Use python3.12 as interpreter in CentOS Stream 9 zipapp
* 89d876c86f tests: fix running pytest on undetected distro
* 61a47eeb1c centos: Fix EPEL repositories for RHEL 10
* e5aa19e2bc oci: allow user defined labels and annotations
* 1680fc5789 man: be more precise that the tools tree distribution is decided by the host distribution
* 7025b8e67d Support resizing output image
* 14d2d37a19 sandbox: Make sure we're dumpable before writing uidmap files
* 215a9497cc fedora: Use N-1 key as well when querying rawhide GPG key
* 842a37ed6c Add MakeScriptsExecutable= setting to optionally try to make scripts executable before bailing out
* 814f2004bb build(deps): bump github/codeql-action from 4.31.9 to 4.32.0
* d8f4f628bf build(deps): bump actions/checkout from 6.0.1 to 6.0.2
* 3e55361142 docs: remove superfluous definition colon
* 5901524c48 mkosi-tools: add libarchive-tools package.
* 968392f1b9 docs: Add information about gui mkosi-tools profile
* 0e2960c245 Add missing call to run_locale_gen()
* 41cd2067bc rpm: Set pkgverify_level to digest
* 86fe0f448a dnf: Give advanced users some control over plugins
* 50a1feee52 run: Improve sandbox command logging
* b1dffe1c3c Fix environment variable name for systemd-repart
* 07726068d9 Allow specifying "default" value for Initrds=
* 704f163ec0 Allow setting PORTABLE_PREFIXES= via Environment=
* e6588afb45 opensuse: More GPG key handling fixes
* c367f993dd opensuse: Fetch remote keys as well if RepositoryKeyFetch= is enabled
* 31852c9314 ci: Use mkosi box for unit test CI as well
* e4229f5bf5 Make sure we pass the right context to finalize_default_initrd()
* 9b431b783a tools: don't pull in virtiofsd in bookworm tools trees
* ae2d88d463 build(deps): bump github/codeql-action from 4.31.6 to 4.31.9
* 933401a8b6 build(deps): bump actions/checkout from 6.0.0 to 6.0.1
* 6bfeb4ac86 opensuse: Import GPG keys for all repositories
* 9829b9136f Add support for locale-gen
* 63ae86ec04 nixos: Use repository key fetching by default on nixos
* f01ca9904b docs: Reword dependencies vs tools tree requirement a bit
* ab47ba25ef docs: Minor correction on enabling unprivileged namespaces
* 7bd46a417e docs: Update unprivileged user namespace docs
Since super-linter 8.4.0, it is enabled by default and requires GITHUB_TOKEN.
We do not provide GITHUB_TOKEN for the action, then it fails with the following:
```
Failed to get [GITHUB_TOKEN]. Terminating because status reports were explicitly enabled,
but GITHUB_TOKEN was not provided.
```
Also, even if GITHUB_TOKEN is set, the feature provides annoying
messages in each PR. See https://github.com/super-linter/super-linter/issues/7458
So, let's disable the feature.