Skip to content

Add Claude Code GitHub Workflow - #4537

Merged
Hmbown merged 4 commits into
mainfrom
add-claude-github-actions-1784415751828
Jul 18, 2026
Merged

Add Claude Code GitHub Workflow#4537
Hmbown merged 4 commits into
mainfrom
add-claude-github-actions-1784415751828

Conversation

@Hmbown

@Hmbown Hmbown commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Claude issue worker

This PR adds a deliberately bounded @claude path for maintainers to start work from a GitHub issue.

What it enables after merge

A repository owner, member, or collaborator can add an exact @claude <request> comment to an issue. Claude then works from main, creates a signed branch named claude/issue-…, runs focused verification, and updates the triggering comment with the branch and a PR-creation link.

Guardrails

  • Issue comments only; PR comments and issue titles/bodies cannot trigger it.
  • Only OWNER, MEMBER, and COLLABORATOR comments qualify; bots and look-alike mentions do not.
  • One run per issue at a time, capped at 20 minutes.
  • No untrusted PR checkout, no workflow/auth/billing/deploy/release changes, no merge/rebase/force-push, and no automatic PR creation.
  • Commits use the Claude GitHub App signing path.
  • The existing claude-review.yml remains the single advisory PR reviewer; this PR removes the redundant generated reviewer.

Verification

  • actionlint .github/workflows/claude.yml
  • git diff --check
  • Local command-gate cases, including rejection of @claude-bot, @claudeish, and embedded mentions.

First post-merge test

On a maintainer-owned small issue, comment:

@claude
Reply with a short implementation plan only. Do not edit files.

Then use a small documentation-only issue to verify signed-branch creation and the PR-creation link before requesting substantive changes.

Copilot AI review requested due to automatic review settings July 18, 2026 23:02
@cursor

cursor Bot commented Jul 18, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 2m 10s —— View job


Review complete

Todo list

  • Gather context (PR diff, changed files)
  • Read .github/workflows/claude.yml
  • Read .github/workflows/claude-code-review.yml
  • Review for correctness, security, and CodeWhale-specific conventions
  • Post review

Summary

This PR is workflow-only (no product/Rust code touched), so the provider/model-route safety invariant doesn't apply here, and there's nothing for cargo test to cover.

Main finding — duplicate automated review (see inline comment on claude-code-review.yml):

The repo already has .github/workflows/claude-review.yml, which triggers on the exact same PR events (opened, synchronize, reopened, ready_for_review) and runs a CodeWhale-tailored Claude review (the same prompt embedded in this bot's own instructions — correctness, provider/model-route safety, reuse, tests, security). The new claude-code-review.yml in this PR does the same job but with the generic code-review@claude-code-plugins plugin, and is missing three safeguards the existing workflow has:

  • No concurrency group → concurrent pushes queue duplicate paid runs instead of cancelling stale ones.
  • No if: github.event.pull_request.draft == false gate → draft PRs get a full review immediately.
  • No graceful skip when CLAUDE_CODE_OAUTH_TOKEN is unset → hard failure instead of a clean notice.

Once merged, every future PR to main would get two separate automated Claude reviews. Recommend dropping claude-code-review.yml and keeping claude-review.yml as the PR-review workflow, unless the plugin-based review is intentionally meant to run alongside it — in which case it should pick up the same concurrency/draft/secret guards.

claude.yml (the interactive @claude-mention workflow): this is net-new functionality, not currently duplicated elsewhere in .github/workflows/. Looks correct — permissions: contents: read is sufficient because writes (comments, commits, pushes) go through the claude_code_oauth_token's own GitHub App scope rather than the workflow's GITHUB_TOKEN (this is empirically confirmed: this very comment is being posted through that path). No security issues found; trigger gating (contains(..., '@claude')) and secret handling follow the standard upstream claude-code-action template.

No other correctness, security, or reuse issues found in the two files.

Comment on lines +3 to +5
on:
pull_request:
types: [opened, synchronize, ready_for_review, reopened]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This duplicates the existing .github/workflows/claude-review.yml, which already runs an automated Claude review on the same pull_request: [opened, synchronize, reopened, ready_for_review] events (restricted to branches: [master, main]). Once this merges, every PR against main will get two separate automated Claude reviews, doubling API spend and posting redundant/conflicting comments.

The existing workflow is also more defensive than this one:

  • concurrency: { group: claude-review-${{ pr.number }}, cancel-in-progress: true } — this new workflow has none, so rapid pushes queue multiple concurrent paid runs on the same PR.
  • if: github.event.pull_request.draft == false — this new workflow has no draft gate, so opening a draft PR triggers a full review immediately.
  • Graceful no-op (HAS_OAUTH check) when CLAUDE_CODE_OAUTH_TOKEN is unset, so the job stays green instead of hard-failing.
  • A CodeWhale-specific review prompt (correctness, the v0.8.65 provider/model-route safety invariant, reuse, tests, security) vs. this workflow's generic upstream code-review@claude-code-plugins plugin, which has no context on this repo's conventions.

Suggest either dropping this file (keep the existing claude-review.yml as the PR-review workflow) or, if the plugin-based review is intentionally additive, porting over the concurrency group, draft gate, and secret-presence guard so it doesn't duplicate cost/noise.

Replace the generated broad Claude workflows with a maintainer-only issue command. The worker checks out main, serializes runs by issue, creates signed branches, and does not create or merge pull requests automatically.

Retain the existing advisory Claude PR reviewer rather than adding a duplicate.

Verification: actionlint .github/workflows/claude.yml; git diff --check; local command-gate regex cases.

Agent assistance: Codex.
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 1m 30s —— View job


Review complete

Todo list

  • Gather context (PR diff, changed files, new push)
  • Read .github/workflows/claude.yml
  • Confirm status of duplicate claude-code-review.yml flagged in earlier review
  • Review for correctness, provider/model safety, reuse, tests, security
  • Post review

Summary

This push replaced the original generic templates with a purpose-built, tightly-scoped workflow (claude.yml, now "Claude issue worker") and removed claude-code-review.yml, resolving the duplicate-review issue flagged in the prior round — claude-review.yml remains the sole PR-review workflow, and the new claude.yml only triggers on issue_comment, so there's no overlap.

The new design is a meaningful security improvement over a typical @claude-mention template:

  • Avoids the classic pwn-request pattern: always checks out ref: main (line 61), never an untrusted PR head, and explicitly excludes PR comments (!issue.pull_request, line 36) so a comment on an attacker-controlled PR can't reach this job.
  • Explicit allowlist authorization: requires author_association in {OWNER, MEMBER, COLLABORATOR} plus an exact @claude mention regex (line 34) and a bot-sender check (line 35), computed server-side by GitHub at delivery time.
  • Constrained tool policy: --allowedTools (line 94) is scoped to cargo/npm/pnpm fmt/test/check/clippy subcommands only — no arbitrary shell, network, or git-destructive commands.
  • Defense-in-depth in the prompt (lines 80-91): forbids editing workflow/credentials/permissions/release config and forbids merging/force-pushing even though the GitHub App's own permissions already block workflow-file edits.
  • Serialized per-issue via concurrency (lines 11-13, cancel-in-progress: false — sensible since a mid-flight commit shouldn't be cancelled), and commits are signed (use_commit_signing: true, line 71), consistent with this repo's scratch/release-branch stewardship conventions.
  • actions/checkout@v7 matches the version pinned everywhere else in .github/workflows/.

Minor (non-blocking) — permission scope: pull-requests: write is granted at line 55, but this job only ever touches issues (PRs are excluded at the authorization gate) and the prompt explicitly forbids creating/merging a PR. Unless claude-code-action needs this permission internally for the "create PR" link it leaves in the issue comment, it looks unused here and could likely be dropped to tighten least-privilege — worth a quick check against the action's docs rather than a hard blocker.

No correctness bugs, provider/model-route safety issues (none of this logic touches model/provider selection), reuse problems, or missing-test concerns — this is a CI/workflow-only change with no product code path to unit test.

The issue worker's GitHub operations (signed branch, commits, issue
comments) run on the app token from the OIDC exchange, whose permission
set is fixed in the exchange request — not on the workflow GITHUB_TOKEN.
The job never creates or edits pull requests by design, so the
workflow-level pull-requests: write grant was inert. Remove it per
least-privilege review.

Signed-off-by: Hunter B <hmbown@gmail.com>
@claude

claude Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Claude finished @Hmbown's task in 1m 17s —— View job


Review complete

Todo list

  • Gather context (new commits since last review)
  • Read updated .github/workflows/claude.yml
  • Confirm the pull-requests: write permission change addresses prior minor finding
  • Post review

Summary

This push (b55099b gate the issue worker, 763450c drop unused permission) resolves the minor finding from the last round: pull-requests: write (previously present but unused, since PR creation is intentionally never automated here) has been removed from the claude job's permissions: block (line 52-55). Remaining permissions (contents: write, issues: write, id-token: write) are all exercised — signed commits to the issue branch, updating the triggering issue comment, and OIDC for commit signing respectively.

I cross-checked the action inputs against the vendored anthropics/claude-code-action@v1 source (src/utils/branch-template.ts, action.yml) since actionlint/find aren't in my allowed tool list in this run:

  • branch_name_template: '{{prefix}}issue-{{entityNumber}}-{{timestamp}}' (line 69) — prefix, entityNumber, and timestamp are all valid template variables (branch-template.ts:45-53). Hardcoding issue- instead of {{entityType}} is fine since this workflow only ever fires on issue comments (issue.pull_request is excluded at the gate, line 36), so entityType is always "issue" anyway.
  • base_branch, use_commit_signing, show_full_output, display_report, claude_args all match documented action.yml inputs.

No correctness bugs, no provider/model-route safety concerns (workflow-only diff, no model/provider selection logic), and no duplication (claude-review.yml is untouched and remains the sole PR reviewer; this file only reacts to issue_comment). Nothing new needed in tests — this is CI configuration, verified via the gate logic's own inline comment plus the template cross-check above rather than a test suite.

Nice tightening from the last round — this addresses every actionable item raised in the two prior reviews. No new issues found.

@Hmbown
Hmbown merged commit 77a6649 into main Jul 18, 2026
22 checks passed
@Hmbown
Hmbown deleted the add-claude-github-actions-1784415751828 branch July 24, 2026 21:10
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