internal: land #264 Bugbot fix onto docs branch (proxy workaround) #33
Workflow file for this run
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 BugBot (Self-Built) | |
| on: | |
| pull_request: | |
| types: [opened, synchronize, ready_for_review, reopened] | |
| merge_group: | |
| jobs: | |
| bugbot-review: | |
| name: BugBot PR Review | |
| if: github.event_name == 'pull_request' || github.event_name == 'merge_group' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: read | |
| id-token: write | |
| steps: | |
| - name: Merge group (no PR-scoped review) | |
| if: github.event_name == 'merge_group' | |
| run: | | |
| echo "::notice::BugBot runs on pull_request only. PR-time runs satisfy this check before merge." | |
| exit 0 | |
| - name: Checkout repository | |
| if: github.event_name == 'pull_request' | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| # ── Step 1: Check credentials ────────────────────────────────────────── | |
| # Step-level guard by necessity: the `secrets` context is not available | |
| # in job-level `if:` expressions, only at step level (via env). Do not | |
| # "simplify" this into a job-level condition — it will silently break. | |
| - name: Check credentials | |
| id: credentials | |
| if: github.event_name == 'pull_request' | |
| env: | |
| ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} | |
| CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| run: | | |
| if [ -z "$ANTHROPIC_API_KEY" ] && [ -z "$CLAUDE_CODE_OAUTH_TOKEN" ]; then | |
| echo "::notice title=BugBot skipped::No credentials set. Add ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN in repo secrets." | |
| echo "configured=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| # A present-but-invalid ANTHROPIC_API_KEY fails the whole check (KI-027): | |
| # the review action only dies after it has started, so a presence test | |
| # alone can never catch it. Probe the key and stand down on a definitive | |
| # rejection. Only 401/403 disarm the review — 200/429/5xx/timeouts all | |
| # proceed, so a transient API wobble can never silently mute BugBot and | |
| # a real action crash with a valid key still fails the check loudly. | |
| if [ -n "$ANTHROPIC_API_KEY" ] && [ -z "$CLAUDE_CODE_OAUTH_TOKEN" ]; then | |
| CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 \ | |
| -H "x-api-key: $ANTHROPIC_API_KEY" \ | |
| -H "anthropic-version: 2023-06-01" \ | |
| https://api.anthropic.com/v1/models) || CODE="000" | |
| if [ "$CODE" = "401" ] || [ "$CODE" = "403" ]; then | |
| echo "::notice title=BugBot skipped::ANTHROPIC_API_KEY is set but rejected by the API (HTTP $CODE). Replace the repo secret to re-enable BugBot." | |
| echo "configured=false" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| fi | |
| echo "configured=true" >> "$GITHUB_OUTPUT" | |
| # ── Step 2: Extract PR diff ──────────────────────────────────────────── | |
| - name: Extract PR diff | |
| id: diff | |
| if: github.event_name == 'pull_request' && steps.credentials.outputs.configured == 'true' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| DIFF=$(gh pr diff ${{ github.event.pull_request.number }} --repo ${{ github.repository }} 2>/dev/null | head -c 8000 || echo "Diff unavailable") | |
| DIFF_ENCODED=$(echo "$DIFF" | python3 -c "import sys,urllib.parse; print(urllib.parse.quote(sys.stdin.read()))") | |
| echo "diff_encoded=$DIFF_ENCODED" >> "$GITHUB_OUTPUT" | |
| # ── Step 3: Run BugBot review ────────────────────────────────────────── | |
| - name: Run BugBot Review | |
| id: bugbot | |
| if: github.event_name == 'pull_request' && steps.credentials.outputs.configured == 'true' | |
| uses: anthropics/claude-code-action@1dc994ee7a008f0ecc866d9ac23ef036b7229f84 | |
| with: | |
| anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} | |
| plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' | |
| plugins: 'code-review@claude-code-plugins' | |
| prompt: | | |
| /code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }} | |
| You are a BugBot for the Equismile platform. Review this PR with extreme focus on real bugs, not style. | |
| ## Equismile Domain Context | |
| - Equismile is a practice management platform for equine dental and veterinary practitioners | |
| - TypeScript, React, Node.js, PostgreSQL (Prisma), Vercel | |
| - Handles patient records (horses), appointment scheduling, clinical notes, invoicing | |
| - Multi-practice: data isolation between practices is CRITICAL | |
| - Financial data: invoice generation, payment processing, fee structures | |
| - Regulatory: veterinary clinical records must be accurate and auditable | |
| - DB migrations are high-risk: production migration workflow exists — schema changes must be backward compatible | |
| ## Severity Classification — USE THESE EXACTLY | |
| Rate every finding with one of: | |
| - 🔴 **[CRITICAL]** — Data loss, patient record corruption, cross-practice data leak, payment errors, broken auth | |
| - 🟠 **[HIGH]** — Logic bug causing wrong clinical/financial results, broken appointment flow, migration risk | |
| - 🟡 **[MEDIUM]** — Non-critical bug, error handling gap, performance regression risk | |
| - 🔵 **[LOW]** — Code smell, minor improvement, readability | |
| - ✅ **[PASS]** — No significant issues found | |
| ## What to look for (priority order) | |
| 1. **Cross-practice data leaks** — queries missing practice ID filters, patient records accessible across tenants | |
| 2. **Clinical record integrity** — missing validation on clinical notes, appointment data, horse/patient fields | |
| 3. **Financial accuracy** — invoice calculation bugs, fee rounding errors, payment status inconsistencies | |
| 4. **DB migration safety** — destructive schema changes without backward compatibility, missing `resolve-migration-drift` handling | |
| 5. **Auth and access control** — missing permission checks, practitioners accessing other practices' data | |
| 6. **Prisma/DB bugs** — missing transactions for multi-table writes, N+1 queries on appointment/patient lists | |
| 7. **TypeScript safety** — `any` casts hiding real type errors, unsafe non-null assertions on patient/clinical fields | |
| 8. **Vercel deploy risks** — env var mismatches, build-breaking changes in `vercel-deploy-trigger.yml` touchpoints | |
| ## Output format | |
| Start with a one-line verdict: | |
| > **BugBot verdict: [CRITICAL|HIGH|MEDIUM|LOW|PASS]** — <one sentence summary> | |
| Then list findings as: | |
| ``` | |
| 🔴 [CRITICAL] src/practices/queries.ts:87 — Missing practiceId filter on patient query | |
| Suggested fix: Add `where: { practiceId: session.practiceId }` to all patient lookups | |
| ``` | |
| End with: | |
| > **Block merge: YES/NO** (YES for CRITICAL or HIGH findings) | |
| Keep the review concise and actionable. Do not comment on formatting, linting, or things already caught by CI. |