feat: switch to org-level reusable Claude Code workflow - #40
Conversation
📝 WalkthroughWalkthroughThe workflow consolidates two separate inline jobs for Claude Code automation into a single job that delegates to an organization-level reusable workflow. This reduces code duplication by centralizing workflow execution logic and configuration management at the org level. Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~5 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
Switches the repository’s Claude automation workflow to a thin “caller” that delegates execution to an org-level reusable GitHub Actions workflow, aiming to centralize maintenance of prompts/config and permissions.
Changes:
- Replaces the inline Claude Code workflow implementation with a
uses:reference topetry-projects/.github/.github/workflows/claude-code-reusable.yml. - Inherits secrets and defines job permissions in the caller workflow.
- Updates workflow header comments to reflect the new delegation model.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| 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.
The caller job no longer has the event/author gating that previously prevented runs unless (a) the PR head repo is this repo, or (b) an org member/collaborator mentions @claude on a PR/PR review comment. Without an equivalent if: in this workflow, every issue_comment / pull_request_review_comment create event will invoke the reusable workflow, which can unintentionally increase runs and may expose secrets to untrusted triggers. Consider re-adding the if: conditions at the caller level so the security boundary is enforced even if the reusable workflow changes.
| 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') && | |
| (github.event.comment.author_association == 'OWNER' || | |
| github.event.comment.author_association == 'MEMBER' || | |
| github.event.comment.author_association == 'COLLABORATOR')) || | |
| (github.event_name == 'pull_request_review_comment' && | |
| contains(github.event.comment.body, '@claude') && | |
| (github.event.comment.author_association == 'OWNER' || | |
| github.event.comment.author_association == 'MEMBER' || | |
| github.event.comment.author_association == 'COLLABORATOR')) || | |
| github.event_name == 'issues' |
| 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. The previous inline workflow only consumed specific secrets (e.g., CLAUDE_CODE_OAUTH_TOKEN), so this is an expansion of secret exposure if the reusable workflow is ever changed/compromised. Prefer explicitly passing only the required secrets to the reusable workflow (or using a dedicated environment with tightly scoped secrets).
| secrets: inherit | |
| secrets: | |
| CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} |
| 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.
The reusable workflow reference is pinned to @main. Elsewhere in this repo, GitHub Actions are pinned to immutable SHAs, which reduces supply-chain risk and avoids unexpected behavior changes. Consider pinning the reusable workflow to a specific commit SHA (or an immutable, versioned tag) instead of a moving branch.
| uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@main | |
| uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@0123456789abcdef0123456789abcdef01234567 |
| jobs: | ||
| # Interactive mode: PR reviews and @claude mentions | ||
| claude: | ||
| 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)) | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 60 | ||
| claude-code: | ||
| uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@main | ||
| secrets: inherit | ||
| permissions: | ||
| contents: write |
There was a problem hiding this comment.
The previous workflow had issue-label automation concurrency (group: claude-issue-${{ github.event.issue.number }} with cancel-in-progress: true) to prevent overlapping runs per issue. That concurrency control is not present in the caller job, so unless the reusable workflow enforces it internally, repeated label events can run in parallel and race. Consider adding the concurrency block back at the caller level (or confirming it exists in the reusable workflow).
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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:
- Line 21: The reusable workflow reference currently uses the mutable ref
"petry-projects/.github/.github/workflows/claude-code-reusable.yml@main";
replace the "@main" ref with an immutable commit SHA for that reusable workflow
to prevent downstream changes (update the uses: entry to point to the specific
commit SHA of petry-projects/.github that you trust). Locate the uses: line in
this file (the line containing
petry-projects/.github/.github/workflows/claude-code-reusable.yml@main) and
substitute the branch name with the exact commit SHA, then commit the change.
- Line 22: The workflow currently forwards all secrets via "secrets: inherit"
when calling the reusable workflow (uses:
petry-projects/.github/.github/workflows/claude-code-reusable.yml@main); replace
that with an explicit list of only the secrets that reusable workflow actually
needs by opening that reusable workflow file and copying its required secret
names, then change the caller to map each required secret explicitly (e.g.,
SECRET_NAME: ${{ secrets.SECRET_NAME }}) instead of inheriting everything;
remove "secrets: inherit" and only pass the minimal set discovered in the
reusable workflow.
🪄 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: 17227aa7-6754-44a5-9a53-0b9bfc4dd7c7
📒 Files selected for processing (1)
.github/workflows/claude.yml
| 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.
🧩 Analysis chain
🏁 Script executed:
cat -n .github/workflows/claude.yml | head -30Repository: petry-projects/ContentTwin
Length of output: 1055
🏁 Script executed:
# Check if there are other workflow references in the repository
find .github -name "*.yml" -o -name "*.yaml" | head -20Repository: petry-projects/ContentTwin
Length of output: 266
🏁 Script executed:
# Search for other uses of reusable workflows to see if there's a pattern
rg "uses:.*/.github/workflows" .githubRepository: petry-projects/ContentTwin
Length of output: 179
Pin the reusable workflow to an immutable ref.
Line 21 uses @main, which allows behavior/security to change without a PR in this repo. Since this workflow has write permissions (contents, pull-requests, issues), pin to a commit SHA instead.
🔒 Suggested fix
- uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@main
+ uses: petry-projects/.github/.github/workflows/claude-code-reusable.yml@<commit-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 reusable workflow reference
currently uses the mutable ref
"petry-projects/.github/.github/workflows/claude-code-reusable.yml@main";
replace the "@main" ref with an immutable commit SHA for that reusable workflow
to prevent downstream changes (update the uses: entry to point to the specific
commit SHA of petry-projects/.github that you trust). Locate the uses: line in
this file (the line containing
petry-projects/.github/.github/workflows/claude-code-reusable.yml@main) and
substitute the branch name with the exact commit SHA, then commit the change.
| 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.
🧩 Analysis chain
🏁 Script executed:
# Check if the file exists and read the workflow
cat -n .github/workflows/claude.yml | head -40Repository: petry-projects/ContentTwin
Length of output: 1055
🏁 Script executed:
# Search for any references to secrets in the repo and in this workflow file
rg -i "CLAUDE_CODE_OAUTH_TOKEN|GH_PAT_WORKFLOWS" --type yml
# Also check if the reusable workflow file exists locally
find . -name "claude-code-reusable.yml" -o -name "*reusable*" | head -20Repository: petry-projects/ContentTwin
Length of output: 97
🏁 Script executed:
# Search for secrets without file type specification
rg "CLAUDE_CODE_OAUTH_TOKEN|GH_PAT_WORKFLOWS|secrets:" --max-count 20
# Check if the reusable workflow exists locally
find . -type f -name "*reusable*"
# List all workflow files
find .github/workflows -type fRepository: petry-projects/ContentTwin
Length of output: 243
🏁 Script executed:
# Search for all secret references across workflow files
rg "\$\{\{.*secrets\." .github/
# Also check the main workflow for any secret usage
cat -n .github/workflows/claude.yml
# Check other workflow files for secret patterns
for file in .github/workflows/*.yml; do
echo "=== $file ==="
grep -i "secret" "$file" || echo "no secrets found"
doneRepository: petry-projects/ContentTwin
Length of output: 1626
🏁 Script executed:
# Check for secret definitions in the repository
rg -i "CLAUDE_CODE_OAUTH_TOKEN|GH_PAT_WORKFLOWS" .
# Check for any .github/workflows configuration files
find .github -type f
# Look for any environment or secret configuration files
find . -name "*.env*" -o -name "*secret*" | grep -v ".git"Repository: petry-projects/ContentTwin
Length of output: 266
🏁 Script executed:
# Check if there are any comments or documentation about required secrets
rg -i "secret|oauth|pat" .github/
# Check if there are any setup files or documentation
cat .github/dependabot.yml
# Look for any references to the org standards or reusable workflow
rg "claude-code|petry-projects" .Repository: petry-projects/ContentTwin
Length of output: 1555
🏁 Script executed:
# Final confirmation: check if these exact secrets are defined anywhere
rg "CLAUDE_CODE_OAUTH_TOKEN|GH_PAT_WORKFLOWS" --no-heading
echo "Exit code: $?"Repository: petry-projects/ContentTwin
Length of output: 82
Pass only the required secrets instead of inheriting all.
Line 22 forwards all available secrets to the called workflow, which violates least-privilege security controls. However, the specific secrets suggested in the fix (CLAUDE_CODE_OAUTH_TOKEN, GH_PAT_WORKFLOWS) do not exist in this repository. Determine which secrets the reusable workflow (petry-projects/.github/.github/workflows/claude-code-reusable.yml@main) actually requires and pass only those explicitly.
🤖 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 forwards all
secrets via "secrets: inherit" when calling the reusable workflow (uses:
petry-projects/.github/.github/workflows/claude-code-reusable.yml@main); replace
that with an explicit list of only the secrets that reusable workflow actually
needs by opening that reusable workflow file and copying its required secret
names, then change the caller to map each required secret explicitly (e.g.,
SECRET_NAME: ${{ secrets.SECRET_NAME }}) instead of inheriting everything;
remove "secrets: inherit" and only pass the minimal set discovered in the
reusable workflow.


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