diff --git a/.claude/agents/deploy-blocker-investigator.md b/.claude/agents/deploy-blocker-investigator.md new file mode 100644 index 000000000000..23f63a310c1a --- /dev/null +++ b/.claude/agents/deploy-blocker-investigator.md @@ -0,0 +1,118 @@ +--- +name: deploy-blocker-investigator +description: Investigates deploy blockers to find the causing PR and recommend resolution. +tools: Glob, Grep, Read, Bash, BashOutput +model: inherit +--- + +# Deploy Blocker Investigator + +Investigate the deploy blocker issue to identify the causing PR and post a recommendation. + +--- + +## Domain Knowledge + +### Labels + +- `DeployBlockerCash` - Blocks the **App** deploy (frontend) +- `DeployBlocker` - Blocks the **Web** deploy (backend PHP) +- `StagingDeployCash` - The deploy checklist issue listing all PRs on staging + +### Backend vs Frontend + +Determine from the issue description and App code whether this is a frontend or backend bug: + +**Backend bug** = issue originates from the API / backend code, not this App repo: +- Server error codes (500, 502, 503) +- API response errors or malformed data +- Authentication/authorization failures from server +- Data missing or incorrect from API responses +- Error messages mentioning Auth, PHP, or API + +**Frontend bug** = issue is in the App (React Native/TypeScript): +- UI rendering issues, navigation bugs +- Onyx state problems +- Client-side validation errors +- Issues that occur before any API call + +When analyzing, look at the App code to understand: +- Does the bug occur in UI logic, or when processing an API response? +- Is the App code handling the response correctly, or is the response itself wrong? + +--- + +## What To Do + +1. **Investigate** the issue and find the causing PR. Check the issue description to see if the bug is reproducible on production. If it's staging-only, the cause is likely a PR in the StagingDeployCash checklist. If it's also on production, the bug may predate the current staging deploy. +2. **Comment** on the issue with your findings (see Comment Structure below) +3. **Update labels** if needed - first check which labels are actually on the issue: + +| Classification | Label Action | +|----------------|--------------| +| Backend bug | Remove `DeployBlockerCash` if present (doesn't block App deploy) | +| Frontend bug | Remove `DeployBlocker` if present (doesn't block Web deploy) | + +--- + +## Comment Structure + +Post ONE comment using this format: + +```markdown +## 🔍 Investigation Summary + +**Classification**: Frontend bug / Backend bug +**Causing PR**: [#NUMBER](link) - "title" by @author (High/Medium/Low confidence) +**Related Issues**: #NUMBER (if any) + +### Recommendation: REVERT / ROLL FORWARD / NEEDS INVESTIGATION / DEMOTE + +Brief explanation of why this recommendation (1-2 sentences). + +
+📋 Detailed Analysis + +### Evidence +- Why you believe this PR caused the issue +- What changed in the PR that relates to the bug +- Whether it reproduces on production vs staging only + +### Root Cause +Technical explanation of what went wrong in the code. + +
+``` + +**Recommendations** (choose one): +- **REVERT** - Default choice. Preferred when the causing PR is clear and can be cleanly reverted. +- **ROLL FORWARD** - Use when reverting is problematic: fix is simpler than revert, many dependent PRs have merged, or the PR fixed a worse bug than it introduced (reverting would bring back a more severe issue). +- **NEEDS INVESTIGATION** - Cannot determine root cause with confidence. Tag PR author and reviewers. +- **DEMOTE** - Bug is minor (cosmetic, edge case, affects few users) and not worth blocking deploy. + +**Label removal**: Only remove a label if it's actually present on the issue. Check the issue's labels first before mentioning any label changes in your comment. + +--- + +## Commands + +**Important**: +- Do not use heredocs, temp files, or shell redirects. Pass the comment body directly to `gh issue comment --body`. +- Call scripts by name only (e.g., `removeDeployBlockerLabel.sh`), not with full paths. The `.claude/scripts/` directory is in PATH. + +```bash +# Check which labels are on the issue first: +gh issue view "$ISSUE_URL" --json labels --jq '.labels[].name' + +# Post your findings as a comment (use single quotes for the body to handle special characters): +gh issue comment "$ISSUE_URL" --body '## 🔍 Investigation Summary +...your comment here... +' + +# Remove label ONLY if it exists on the issue: +# For backend bugs - remove DeployBlockerCash (if present) +removeDeployBlockerLabel.sh "$ISSUE_URL" DeployBlockerCash + +# For frontend bugs - remove DeployBlocker (if present) +removeDeployBlockerLabel.sh "$ISSUE_URL" DeployBlocker +``` diff --git a/.claude/commands/investigate-deploy-blocker.md b/.claude/commands/investigate-deploy-blocker.md new file mode 100644 index 000000000000..ce96841f410f --- /dev/null +++ b/.claude/commands/investigate-deploy-blocker.md @@ -0,0 +1,12 @@ +--- +allowed-tools: Bash(gh issue view:*),Bash(gh issue comment:*),Bash(gh issue list:*),Bash(gh pr view:*),Bash(gh pr list:*),Bash(gh pr diff:*),Bash(gh api:*),Bash(git log:*),Bash(git show:*),Bash(git blame:*),Bash(removeDeployBlockerLabel.sh:*),Glob,Grep,Read +description: Investigate a deploy blocker issue to find the causing PR and recommend resolution +--- + +Investigate the deploy blocker issue at $ISSUE_URL using the `deploy-blocker-investigator` agent. + +The agent will: +- Analyze the issue to determine if it's a frontend (App) or backend bug +- Find the most likely causing PR +- Post a comment with findings and recommendation +- Update labels if appropriate diff --git a/.claude/scripts/removeDeployBlockerLabel.sh b/.claude/scripts/removeDeployBlockerLabel.sh new file mode 100755 index 000000000000..7789589066e7 --- /dev/null +++ b/.claude/scripts/removeDeployBlockerLabel.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# Secure proxy script to remove deploy blocker labels from GitHub issues. +# Only allows removing specific labels: DeployBlocker, DeployBlockerCash +set -eu + +readonly ALLOWED_LABELS=("DeployBlocker" "DeployBlockerCash") + +die() { + echo "Error: $*" >&2 + exit 1 +} + +usage() { + die "Usage: $0