vcluster config restructure #494
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 PR Review | |
| on: | |
| pull_request_target: | |
| types: [opened, synchronize] | |
| paths-ignore: | |
| - 'vendor/**' | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| id-token: write | |
| jobs: | |
| review: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| if: github.repository_owner == 'loft-sh' | |
| steps: | |
| - name: Check for existing review | |
| id: check-review | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const comments = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| per_page: 100 | |
| }); | |
| // Check if Claude already reviewed this PR (look for loft-bot comments with review content) | |
| const claudeReview = comments.data.find(c => | |
| c.user.login === 'loft-bot' && | |
| c.body.includes('Claude finished') && | |
| !c.body.includes('encountered an error') | |
| ); | |
| if (claudeReview && context.payload.action === 'synchronize') { | |
| console.log('Claude already reviewed this PR. Skipping duplicate review.'); | |
| return { skip: true, reason: 'existing_review' }; | |
| } | |
| return { skip: false }; | |
| result-encoding: json | |
| - name: Checkout repository | |
| if: ${{ !fromJson(steps.check-review.outputs.result).skip }} | |
| uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup fork as origin for Claude | |
| if: ${{ !fromJson(steps.check-review.outputs.result).skip && github.event.pull_request.head.repo.fork == true }} | |
| run: | | |
| git remote rename origin upstream | |
| git remote add origin ${{ github.event.pull_request.head.repo.clone_url }} | |
| git fetch origin ${{ github.event.pull_request.head.ref }} | |
| git checkout -B ${{ github.event.pull_request.head.ref }} origin/${{ github.event.pull_request.head.ref }} | |
| - name: Claude Review | |
| id: claude-review | |
| if: ${{ !fromJson(steps.check-review.outputs.result).skip }} | |
| continue-on-error: true | |
| uses: anthropics/claude-code-action@v1 | |
| env: | |
| GH_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }} | |
| GITHUB_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }} | |
| with: | |
| github_token: ${{ secrets.GH_ACCESS_TOKEN }} | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| track_progress: true | |
| prompt: | | |
| REPO: ${{ github.repository }} | |
| PR NUMBER: ${{ github.event.pull_request.number }} | |
| Review this PR. Focus on finding issues, not praise. | |
| ## Output Rules (CRITICAL) | |
| - NO todo lists or checklists in comments | |
| - NO "What's Good" sections - skip praise entirely | |
| - NO verbose explanations of what you checked | |
| - ONLY comment on actual issues found | |
| - If no issues: single line "No issues found." as top-level comment | |
| - Be terse. One issue = one inline comment with fix suggestion | |
| ## Documentation files (.mdx, .md) | |
| Read CONTRIBUTING.md for style guide. Flag violations of: | |
| - Broken links (must use relative .mdx paths) | |
| - Wrong YAML indentation in code blocks | |
| - Admonitions inside JSX components (illegal) | |
| - Title Case headings (should be Sentence case) | |
| - Future tense or passive voice | |
| - Forbidden words: easy, simple, obvious, just | |
| - "vClusters" (wrong) vs "vCluster" (correct) | |
| ## Code/CI files (.js, .ts, .yml) | |
| - Hardcoded secrets | |
| - Syntax errors | |
| - Logic bugs | |
| ## vCluster YAML configs | |
| Use mcp__vcluster-yaml__validate-config to validate. | |
| ## Comment Format | |
| - Inline comments: point to exact line, suggest fix | |
| - Top-level: brief summary only if issues found | |
| ## PR Description Summary | |
| 1. Get current body: `gh pr view ${{ github.event.pull_request.number }} --json body -q .body` | |
| 2. ONLY replace content between <!-- CLAUDE_SUMMARY --> and <!-- /CLAUDE_SUMMARY --> markers | |
| 3. Keep ALL other PR description content unchanged | |
| 4. Update with: `gh pr edit ${{ github.event.pull_request.number }} --body "$UPDATED_BODY"` | |
| Summary format (insert between markers): | |
| > [!NOTE] | |
| > Brief summary of changes. | |
| > | |
| > <sup>Generated by Claude for ${{ github.event.pull_request.head.sha }}</sup> | |
| claude_args: | | |
| --model claude-sonnet-4-20250514 --mcp-config '{"mcpServers":{"vcluster-yaml":{"command":"npx","args":["-y","vcluster-yaml-mcp-server@latest"]}}}' --allowedTools "Read,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr edit:*),mcp__github_inline_comment__create_inline_comment,mcp__vcluster-yaml__*" | |
| - name: Comment on failure | |
| if: ${{ !fromJson(steps.check-review.outputs.result).skip && steps.claude-review.outcome == 'failure' }} | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: 'Claude Code review failed to complete. This may be due to API rate limits or network issues. The PR can still be reviewed manually.' | |
| }) |