feat: switch to org-level reusable Claude Code workflow#134
Conversation
📝 WalkthroughWalkthroughThe Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
There was a problem hiding this comment.
Pull request overview
This PR refactors the repository’s Claude Code GitHub Actions workflow to delegate execution to an organization-level reusable workflow, aiming to centralize maintenance while keeping the same triggers/behavior.
Changes:
- Replaces the prior inline
claude.ymlimplementation (multiple jobs + steps) with a single reusable-workflow caller. - Updates workflow header comments to describe the delegation model.
- Keeps a job-level permissions block in the caller workflow.
| contains(fromJson('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)) | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 60 | ||
| claude-code: |
There was a problem hiding this comment.
Job now delegates to a reusable workflow without any of the previous job-level if: guards (same-repo PR check + @claude author_association allowlist). If the reusable workflow doesn’t replicate those checks, this becomes a security regression (external users could trigger the automation via comments/PR review comments). Consider keeping the if: conditions here in the caller (or add an explicit note + link to where the checks live in the reusable workflow).
| claude-code: | |
| claude-code: | |
| if: >- | |
| ${{ | |
| (github.event_name == 'pull_request' && | |
| github.event.pull_request.head.repo.full_name == github.repository) || | |
| (github.event_name == 'issue_comment' && | |
| github.event.issue.pull_request && | |
| contains(github.event.comment.body, '@claude') && | |
| contains(fromJson('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)) || | |
| (github.event_name == 'pull_request_review_comment' && | |
| contains(github.event.comment.body, '@claude') && | |
| contains(fromJson('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)) || | |
| (github.event_name == 'issues' && | |
| github.event.issue.pull_request && | |
| github.event.label.name == '@claude' && | |
| contains(fromJson('["OWNER","MEMBER","COLLABORATOR"]'), github.event.sender.author_association)) | |
| }} |
| timeout-minutes: 60 | ||
| claude-code: | ||
| uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@main | ||
| secrets: inherit |
There was a problem hiding this comment.
secrets: inherit passes all repository/environment secrets to the called workflow. Even if the org workflow is trusted, this is broader than necessary and increases blast radius if the reusable workflow is ever modified or misconfigured. Prefer passing only the required secrets (e.g., CLAUDE_CODE_OAUTH_TOKEN / GH_PAT_WORKFLOWS) explicitly.
| secrets: inherit | |
| secrets: | |
| CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| GH_PAT_WORKFLOWS: ${{ secrets.GH_PAT_WORKFLOWS }} |
| permissions: | ||
| contents: write | ||
| id-token: write | ||
| pull-requests: write | ||
| issues: write | ||
| actions: read | ||
| checks: read |
There was a problem hiding this comment.
PR description says this adds a token with workflows write scope so Claude can push .github/workflows/*, but this job’s permissions don’t include workflows: write. Because reusable workflows can’t elevate permissions beyond the caller, Claude still won’t be able to modify workflow files via GITHUB_TOKEN unless workflows: write is granted here (or you rely solely on a PAT).
| runs-on: ubuntu-latest | ||
| timeout-minutes: 60 | ||
| claude-code: | ||
| uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@main |
There was a problem hiding this comment.
uses: ...@main means the workflow behavior can change without any change in this repository (and can break builds or alter automation unexpectedly). Prefer pinning the reusable workflow to an immutable ref (tag or commit SHA) and updating intentionally when you want new behavior.
| uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@main | |
| uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@<PINNED_COMMIT_SHA> |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
.github/workflows/claude.yml (2)
21-21: Security: Pin the reusable workflow to a specific SHA or tag instead of@main.Referencing
@mainmeans any commit pushed to the org's reusable workflow immediately affects all caller repos without local review. An attacker with write access topetry-projects/.githubcould inject malicious steps that run with this workflow's elevated permissions.Consider pinning to a commit SHA (e.g.,
@abc1234...) or a versioned tag, updating deliberately when changes are reviewed.Example pinned reference
- uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@main + uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@v1.0.0 # or SHA🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/claude.yml at line 21, The workflow call is pinned to `@main` which is unsafe; replace the `uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@main` reference with a specific immutable ref (a commit SHA or a versioned tag) so the reusable workflow is fixed to a reviewed revision; update the `uses:` value to the chosen SHA or tag and document the chosen ref in the PR so future changes require an explicit update.
22-22:secrets: inheritforwards all repository secrets to the reusable workflow.This is valid and convenient, but be aware it grants the external workflow access to every secret defined in this repository. If the reusable workflow is compromised or modified maliciously (especially given the
@mainref), secrets could be exfiltrated.Ensure this is intentional and that the org workflow is trusted and access-controlled.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/claude.yml at line 22, The workflow currently uses "secrets: inherit", which forwards all repo secrets to the reusable workflow; replace this with an explicit secrets block listing only the secrets the reusable workflow needs (e.g., secrets: { REQUIRED_SECRET: ${{ secrets.REQUIRED_SECRET }}, OTHER_SECRET: ${{ secrets.OTHER_SECRET }} }) and/or remove inheritance, and also avoid calling the reusable workflow with an unpinned ref like "@main" (pin to a specific tag or commit) so only intended secrets are exposed to a trusted, fixed workflow; update the call site where "secrets: inherit" is set and the reusable workflow ref to explicit secret mappings and a pinned ref.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/claude.yml:
- Around line 23-29: The permissions block in the workflow is missing the
required workflows: write permission described in the PR; update the permissions
map (the permissions: block in .github/workflows/claude.yml) to include
workflows: write alongside contents: write, id-token: write, pull-requests:
write, issues: write, actions: read, checks: read so the generated github_token
can push to .github/workflows/, and ensure this permission is declared in this
reusable workflow (callers cannot elevate permissions for it).
---
Nitpick comments:
In @.github/workflows/claude.yml:
- Line 21: The workflow call is pinned to `@main` which is unsafe; replace the
`uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@main`
reference with a specific immutable ref (a commit SHA or a versioned tag) so the
reusable workflow is fixed to a reviewed revision; update the `uses:` value to
the chosen SHA or tag and document the chosen ref in the PR so future changes
require an explicit update.
- Line 22: The workflow currently uses "secrets: inherit", which forwards all
repo secrets to the reusable workflow; replace this with an explicit secrets
block listing only the secrets the reusable workflow needs (e.g., secrets: {
REQUIRED_SECRET: ${{ secrets.REQUIRED_SECRET }}, OTHER_SECRET: ${{
secrets.OTHER_SECRET }} }) and/or remove inheritance, and also avoid calling the
reusable workflow with an unpinned ref like "@main" (pin to a specific tag or
commit) so only intended secrets are exposed to a trusted, fixed workflow;
update the call site where "secrets: inherit" is set and the reusable workflow
ref to explicit secret mappings and a pinned ref.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 3248253c-2c56-4f41-a663-cf86b307f007
📒 Files selected for processing (1)
.github/workflows/claude.yml
| permissions: | ||
| contents: write | ||
| id-token: write | ||
| pull-requests: write | ||
| issues: write | ||
| actions: read | ||
| checks: read |
There was a problem hiding this comment.
Missing workflows: write permission contradicts PR objectives.
The PR description states this change "Adds a github_token with workflows write scope enabling Claude to push files into .github/workflows/". However, the permissions block does not include workflows: write. Without this permission, Claude will still be blocked from modifying workflow files.
If the intent is to grant this permission from within the reusable workflow, note that callers cannot grant more permissions than they themselves possess—the permission must be declared here.
Proposed fix to add the missing permission
permissions:
contents: write
id-token: write
pull-requests: write
issues: write
actions: read
checks: read
+ workflows: write📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| permissions: | |
| contents: write | |
| id-token: write | |
| pull-requests: write | |
| issues: write | |
| actions: read | |
| checks: read | |
| permissions: | |
| contents: write | |
| id-token: write | |
| pull-requests: write | |
| issues: write | |
| actions: read | |
| checks: read | |
| workflows: write |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.github/workflows/claude.yml around lines 23 - 29, The permissions block in
the workflow is missing the required workflows: write permission described in
the PR; update the permissions map (the permissions: block in
.github/workflows/claude.yml) to include workflows: write alongside contents:
write, id-token: write, pull-requests: write, issues: write, actions: read,
checks: read so the generated github_token can push to .github/workflows/, and
ensure this permission is declared in this reusable workflow (callers cannot
elevate permissions for it).


Summary
claude.ymlwith a thin caller that delegates topetry-projects/.github/.github/workflows/claude-code-reusable.yml@mainGH_PAT_WORKFLOWSsupport are now maintained centrally in the org repoWhy
Centralizes maintenance so prompt/config updates only need one change instead of 7. Also adds
github_tokenwithworkflowswrite scope so Claude can push.github/workflows/files (previously blocked).Test plan
claudeand verify Claude creates a PR🤖 Generated with Claude Code
Summary by CodeRabbit