name: Claude Code on: # Responds to @claude mentions in comments. issue_comment: types: [created] pull_request_review_comment: types: [created] issues: types: [opened] pull_request_review: types: [submitted] jobs: claude: # Only run when @claude is mentioned by a trusted user (OWNER, MEMBER, or COLLABORATOR) # Note: the claude-code-action can only be triggered by users with write access to the repository so this is extra # see https://github.com/anthropics/claude-code-action/blob/main/docs/security.md if: | (github.event_name == 'issue_comment' && 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 == 'pull_request_review' && contains(github.event.review.body, '@claude') && contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.review.author_association)) || (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')) && contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), github.event.issue.author_association)) runs-on: ubuntu-latest permissions: contents: write pull-requests: write issues: write id-token: write actions: read steps: - env: ESC_ACTION_ENVIRONMENT: github-secrets/${{ github.repository_owner }}-${{ github.event.repository.name }} ESC_ACTION_EXPORT_ENVIRONMENT_VARIABLES: "false" ESC_ACTION_OIDC_AUTH: "true" ESC_ACTION_OIDC_ORGANIZATION: pulumi ESC_ACTION_OIDC_REQUESTED_TOKEN_TYPE: urn:pulumi:token-type:access_token:organization id: esc-secrets name: Fetch secrets from ESC uses: pulumi/esc-action@9840934db12128a33f6afb60b17d9de8f7ec5519 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 0 - name: Checkout PR head (if applicable) if: ${{ github.event.pull_request.number || (github.event.issue.pull_request && github.event.issue.number) }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} PR_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} run: gh pr checkout "$PR_NUMBER" - name: Setup mise uses: jdx/mise-action@8d3b0ba20a9cea7b883d922ea958553c941ab082 env: MISE_FETCH_REMOTE_VERSIONS_TIMEOUT: 30s with: version: 2026.3.7 github_token: ${{ secrets.GITHUB_TOKEN }} # only saving the cache in the prerequisites job cache_save: false - name: Set git identity run: |- git config --global user.name "claude[bot]" git config --global user.email "bot@pulumi.com" shell: bash - name: Prepare local workspace # this runs install_plugins and upstream run: make prepare_local_workspace - name: Run Claude Code Review # Comment must contain '@claude review' if: | (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude review')) || (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude review')) || (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude review')) id: claude-review uses: anthropics/claude-code-action@f4fb5c6cdccc1ee7af63692f5d08d56efaa64cc8 # v1 with: anthropic_api_key: ${{ steps.esc-secrets.outputs.ANTHROPIC_API_KEY }} prompt: | REPO: ${{ github.repository }} PR NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }} Review this pull request using the provider-code-review skill for guidelines. The PR branch is already checked out in the current working directory. Use `gh pr comment` for top-level feedback. Use `mcp__github_inline_comment__create_inline_comment` to highlight specific code issues. Only post GitHub comments - don't submit review text as messages. # Taken from https://github.com/anthropics/claude-code/blob/main/plugins/code-review/commands/code-review.md claude_args: | --allowedTools "Skill,Bash(gh issue view *),Bash(gh search *),Bash(gh issue list *),Bash(gh pr comment *),Bash(gh pr diff *),Bash(gh pr view *),Bash(gh pr list *),mcp__github_inline_comment__create_inline_comment" - name: Run Claude Code # Comment must contain '@claude', but not '@claude review' if: | !contains(github.event.comment.body, '@claude review') && !contains(github.event.review.body, '@claude review') id: claude-action uses: anthropics/claude-code-action@f4fb5c6cdccc1ee7af63692f5d08d56efaa64cc8 # v1 with: anthropic_api_key: ${{ steps.esc-secrets.outputs.ANTHROPIC_API_KEY }} # This allows claude to read github action logs additional_permissions: | actions: read # Sandbox settings: --allowedTools controls which tools Claude can invoke, # but the sandbox also enforces OS-level filesystem restrictions. Edit() # rules in permissions.allow control all bash filesystem writes (mkdir, # output redirection, etc.), not just the Edit tool. Without these, commands # like `mkdir .pulumi` or `cmd > file.txt` would be blocked by the sandbox. settings: | { "permissions": { "allow": ["Edit(./**)", "Edit(/tmp/**)"] } } claude_args: | --max-turns 50 --allowedTools "Skill,Edit,MultiEdit,Write,Read,Glob,Grep,LS,Bash(upgrade-provider *),Bash(./scripts/upstream.sh *),Bash(git *),Bash(GIT_EDITOR=* git *),Bash(make *),Bash(gh *),Bash(mkdir *),Bash(go mod tidy *),Bash(ls *),Bash(test *),Bash(cat *),Bash(pwd),Bash(head *),Bash(tail *),Bash(tee *),Bash(rg *),Bash(grep *),Bash(sed *),Bash(awk *),Bash(find *)" # If the claude action fails you don't get any logs on what claude was doing # Uploading the artifact allows you to download the artifact from the UI - name: Upload Claude review output on failure if: failure() && steps.claude-review.outputs.execution_file uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: claude-review-execution-log path: ${{ steps.claude-review.outputs.execution_file }} retention-days: 7 - name: Upload Claude output on failure if: failure() && steps.claude-action.outputs.execution_file uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: claude-execution-log path: ${{ steps.claude-action.outputs.execution_file }} retention-days: 7