Claude Code #99
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Claude Code | |
| on: | |
| issue_comment: | |
| types: [created] | |
| pull_request_review_comment: | |
| types: [created] | |
| pull_request_review: | |
| types: [submitted] | |
| env: | |
| # Pin the Playwright MCP server version for reproducible runs. The MCP drives | |
| # the runner's preinstalled Chrome (--browser chrome), so no browser download | |
| # is needed. Bump this to upgrade the server. | |
| PLAYWRIGHT_MCP_VERSION: '0.0.77' | |
| jobs: | |
| claude: | |
| # Skip workflow if the comment does not tag claude or the author is not a | |
| # maintainer. Having this check here ensures that this scenario does not | |
| # even start a runner. | |
| 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)) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| # Required by actions/checkout | |
| contents: read | |
| # Required by anthropics/claude-code-action to generate a short-lived | |
| # app token (contents/pull_requests/issues: write) that is revoked at the | |
| # end of the run. Thus, there should be no need to grant additional write | |
| # permissions to the workflow itself. | |
| id-token: write | |
| # Required by github_ci MCP server, which uses the workflow token instead | |
| # of the short-lived app token | |
| actions: read | |
| steps: | |
| - name: Checkout repository | |
| # Pin to the default branch: pull_request_review_comment/review events | |
| # would otherwise check out the PR merge ref (only issue_comment defaults | |
| # to the default branch). Kept as the first checkout so the trusted action | |
| # infra staged below comes from the default branch, never the PR branch. | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event.repository.default_branch }} | |
| fetch-depth: 1 | |
| persist-credentials: false | |
| - name: Stage action infra | |
| # Copy the action infra out of the repo *before* the PR branch is checked | |
| # out, so the PR-branch checkout can't remove or modify these files | |
| # (branches may predate them, and the system prompt must not come from an | |
| # untrusted PR branch). Referenced by absolute path in later steps. | |
| run: | | |
| cp .github/claude/system-prompt.md "${{ runner.temp }}/system-prompt.md" | |
| cp .github/claude/summary.js "${{ runner.temp }}/summary.js" | |
| cp .github/claude/prompt.js "${{ runner.temp }}/prompt.js" | |
| - name: Setup JDK 21 | |
| uses: actions/setup-java@v5 | |
| with: | |
| java-version: '21' | |
| distribution: 'temurin' | |
| cache: 'maven' | |
| - name: Setup Node | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '24' | |
| - name: Install TestBench license | |
| if: env.TB_LICENSE != '' | |
| env: | |
| TB_LICENSE: ${{ secrets.TB_LICENSE }} | |
| run: | | |
| mkdir -p ~/.vaadin | |
| user="${TB_LICENSE%%/*}" | |
| key="${TB_LICENSE#*/}" | |
| echo "{\"username\":\"${user}\",\"proKey\":\"${key}\"}" > ~/.vaadin/proKey | |
| - name: Clone upstream references (read-only context) | |
| run: | | |
| git clone --depth 1 https://github.com/vaadin/flow.git \ | |
| "${{ runner.temp }}/reference/flow" | |
| git clone --depth 1 https://github.com/vaadin/web-components.git \ | |
| "${{ runner.temp }}/reference/web-components" | |
| - name: Build Claude prompt | |
| id: prompt | |
| run: node "${{ runner.temp }}/prompt.js" | |
| - name: Run Claude Code | |
| id: claude | |
| uses: anthropics/claude-code-action@37b464ce72700f7b2c5ff8d2db7fa7b15df792f5 # v1.0.169 | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| # Setting a custom prompt would switch the action into agent mode | |
| # track_progress forces tag mode back | |
| track_progress: true | |
| prompt: ${{ steps.prompt.outputs.prompt }} | |
| additional_permissions: | | |
| actions: read | |
| settings: | | |
| { | |
| "permissions": { | |
| "additionalDirectories": [ | |
| "${{ runner.temp }}/reference/flow", | |
| "${{ runner.temp }}/reference/web-components" | |
| ] | |
| } | |
| } | |
| claude_args: | | |
| --append-system-prompt-file ${{ runner.temp }}/system-prompt.md | |
| --mcp-config '{"mcpServers":{"playwright":{"command":"npx","args":["@playwright/mcp@${{ env.PLAYWRIGHT_MCP_VERSION }}","--headless","--isolated","--browser","chrome"]}}}' | |
| --allowedTools "mcp__playwright,Bash(mvn:*),Bash(git status:*),Bash(git diff:*),Bash(git log:*),Bash(git show:*),Bash(git branch:*),Bash(git add:*),Bash(git commit:*),Bash(git checkout:*),Bash(git restore:*),Bash(git stash:*),Bash(cd:*),Bash(npm install),Bash(npm ci),Bash(node scripts/wtr.js:*),Bash(node scripts/computeModules.js:*),Bash(scripts/checkstyle.sh:*),Bash(./scripts/checkstyle.sh:*),Bash(ls:*),Bash(cat:*),Bash(find:*),Bash(grep:*),Bash(rg:*),Bash(head:*),Bash(tail:*),Bash(sed:*),Bash(wc:*),Bash(echo:*)" | |
| - name: Summarize Claude session | |
| if: always() && steps.claude.outputs.execution_file != '' | |
| run: node "${{ runner.temp }}/summary.js" "${{ steps.claude.outputs.execution_file }}" | |
| - name: Upload Claude execution log | |
| # The execution_file is the full stream-json trace: every tool_use with | |
| # its input and every tool_result. Off by default because on a public | |
| # repo the artifact is world-readable; set the CLAUDE_DEBUG repository | |
| # variable to 'true' to capture it when debugging a run. | |
| if: always() && vars.CLAUDE_DEBUG == 'true' && steps.claude.outputs.execution_file != '' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: claude-execution-${{ github.run_id }}-${{ github.run_attempt }} | |
| path: ${{ steps.claude.outputs.execution_file }} | |
| retention-days: 7 |