|
| 1 | +name: Claude Code |
| 2 | + |
| 3 | +# Reactive: does nothing until someone writes @claude. Pairs with claude-pr-review.yml. |
| 4 | +# |
| 5 | +# >>> DO NOT MERGE THESE TWO INTO ONE JOB. <<< |
| 6 | +# They look redundant and are not. The shared action for THIS file supplies no `prompt`, |
| 7 | +# which is what keeps claude-code-action in TAG mode. Supplying one -- as the review |
| 8 | +# action does -- puts it in AGENT mode for every event it sees, where an @claude comment |
| 9 | +# gets no PR context, no tracking comment, and nothing posted back. |
| 10 | +# |
| 11 | +# NOTE: `issue_comment` workflows always run from the default branch, so edits to this |
| 12 | +# file do nothing until they are merged. |
| 13 | + |
| 14 | +on: |
| 15 | + issue_comment: |
| 16 | + types: [created] |
| 17 | + pull_request_review_comment: |
| 18 | + types: [created] |
| 19 | + issues: |
| 20 | + types: [opened, assigned] |
| 21 | + pull_request_review: |
| 22 | + types: [submitted] |
| 23 | + |
| 24 | +jobs: |
| 25 | + claude: |
| 26 | + # >>> THIS GUARD IS LOAD-BEARING ON A PUBLIC REPOSITORY. <<< |
| 27 | + # Two conditions, both required, both checked per-event. |
| 28 | + # |
| 29 | + # 1. author_association of the person who ACTUALLY TRIGGERED IT. This job has |
| 30 | + # `contents: write` and blanket `Bash`, so without this check any passer-by who |
| 31 | + # types @claude gets an arbitrary-code-execution agent run on the maintainer's |
| 32 | + # OAuth token. The pairing matters: on `issue_comment`, |
| 33 | + # `github.event.issue.author_association` is the issue's *opener*, not the |
| 34 | + # commenter, so checking that field here would let a stranger trigger a run |
| 35 | + # merely by commenting on a maintainer's own issue. OWNER covers the repository |
| 36 | + # owner; COLLABORATOR/MEMBER cover anyone later given push access. |
| 37 | + # 2. the @claude mention itself. |
| 38 | + # |
| 39 | + # The guard cannot live in the shared action: by the time a composite action runs, |
| 40 | + # the runner is already up and the token already minted. |
| 41 | + if: | |
| 42 | + (github.event_name == 'issue_comment' && |
| 43 | + contains(github.event.comment.body, '@claude') && |
| 44 | + contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)) || |
| 45 | + (github.event_name == 'pull_request_review_comment' && |
| 46 | + contains(github.event.comment.body, '@claude') && |
| 47 | + contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)) || |
| 48 | + (github.event_name == 'pull_request_review' && |
| 49 | + contains(github.event.review.body, '@claude') && |
| 50 | + contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.review.author_association)) || |
| 51 | + (github.event_name == 'issues' && |
| 52 | + (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')) && |
| 53 | + contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.issue.author_association)) |
| 54 | + runs-on: ubuntu-latest |
| 55 | + permissions: |
| 56 | + contents: write |
| 57 | + pull-requests: write |
| 58 | + issues: write |
| 59 | + id-token: write |
| 60 | + actions: read # Required for Claude to read CI results on PRs |
| 61 | + |
| 62 | + steps: |
| 63 | + - name: Checkout repository |
| 64 | + uses: actions/checkout@v7 |
| 65 | + with: |
| 66 | + fetch-depth: 1 |
| 67 | + |
| 68 | + - uses: jantman/github-actions-workflows/claude-mention@v1 |
| 69 | + with: |
| 70 | + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} |
0 commit comments