|
| 1 | +name: Org Issue Checkup |
| 2 | + |
| 3 | +on: |
| 4 | + workflow_call: |
| 5 | + inputs: |
| 6 | + max_issues: |
| 7 | + description: 'Maximum number of issues to process' |
| 8 | + required: false |
| 9 | + type: number |
| 10 | + default: 20 |
| 11 | + stale_days: |
| 12 | + description: 'Days before an untriaged issue is considered stale' |
| 13 | + required: false |
| 14 | + type: number |
| 15 | + default: 7 |
| 16 | + project_id: |
| 17 | + description: 'GitHub Projects board ID' |
| 18 | + required: false |
| 19 | + type: string |
| 20 | + default: '' |
| 21 | + secrets: |
| 22 | + CLAUDE_CODE_OAUTH_TOKEN: |
| 23 | + description: 'Claude Code OAuth token' |
| 24 | + required: true |
| 25 | + GH_TOKEN: |
| 26 | + description: 'GitHub token for API access' |
| 27 | + required: true |
| 28 | + |
| 29 | +permissions: |
| 30 | + contents: read |
| 31 | + issues: write |
| 32 | + actions: read |
| 33 | + id-token: write |
| 34 | + |
| 35 | +jobs: |
| 36 | + find-issues: |
| 37 | + runs-on: arc-happyvertical |
| 38 | + timeout-minutes: 5 |
| 39 | + outputs: |
| 40 | + issues: ${{ steps.scan.outputs.issues }} |
| 41 | + count: ${{ steps.scan.outputs.count }} |
| 42 | + steps: |
| 43 | + - name: Scan for Issues Needing Attention |
| 44 | + id: scan |
| 45 | + env: |
| 46 | + GH_TOKEN: ${{ secrets.GH_TOKEN }} |
| 47 | + run: | |
| 48 | + echo "Scanning for issues needing attention..." |
| 49 | +
|
| 50 | + # Get all open issues |
| 51 | + ISSUES=$(gh issue list --state open --limit 100 --json number,title,labels,createdAt,body) |
| 52 | +
|
| 53 | + # Find issues missing required labels or with short descriptions |
| 54 | + NEEDS_ATTENTION=$(echo "$ISSUES" | jq -c '[.[] | select( |
| 55 | + # Missing type label |
| 56 | + ([.labels[].name | select(startswith("type:"))] | length) == 0 or |
| 57 | + # Missing priority label |
| 58 | + ([.labels[].name | select(startswith("priority:"))] | length) == 0 or |
| 59 | + # Missing size label |
| 60 | + ([.labels[].name | select(startswith("size:"))] | length) == 0 or |
| 61 | + # Short description (less than 50 chars) |
| 62 | + ((.body // "") | length) < 50 |
| 63 | + )] | .[0:${{ inputs.max_issues }}]') |
| 64 | +
|
| 65 | + COUNT=$(echo "$NEEDS_ATTENTION" | jq 'length') |
| 66 | +
|
| 67 | + echo "Found $COUNT issues needing attention" |
| 68 | + echo "issues=$(echo $NEEDS_ATTENTION | jq -c '.')" >> $GITHUB_OUTPUT |
| 69 | + echo "count=$COUNT" >> $GITHUB_OUTPUT |
| 70 | +
|
| 71 | + checkup: |
| 72 | + needs: find-issues |
| 73 | + if: needs.find-issues.outputs.count != '0' |
| 74 | + runs-on: arc-happyvertical |
| 75 | + timeout-minutes: 30 |
| 76 | + steps: |
| 77 | + - name: Checkout repository |
| 78 | + uses: actions/checkout@v4 |
| 79 | + with: |
| 80 | + fetch-depth: 1 |
| 81 | + |
| 82 | + - name: Post Checkup Summary |
| 83 | + env: |
| 84 | + GH_TOKEN: ${{ secrets.GH_TOKEN }} |
| 85 | + run: | |
| 86 | + echo "## Issue Checkup Report" >> $GITHUB_STEP_SUMMARY |
| 87 | + echo "" >> $GITHUB_STEP_SUMMARY |
| 88 | + echo "Found **${{ needs.find-issues.outputs.count }}** issues needing attention." >> $GITHUB_STEP_SUMMARY |
| 89 | + echo "" >> $GITHUB_STEP_SUMMARY |
| 90 | + echo "Processing with Claude..." >> $GITHUB_STEP_SUMMARY |
| 91 | +
|
| 92 | + - name: Run Claude Issue Checkup |
| 93 | + uses: anthropics/claude-code-action@v1 |
| 94 | + with: |
| 95 | + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} |
| 96 | + timeout_minutes: 25 |
| 97 | + prompt: | |
| 98 | + REPO: ${{ github.repository }} |
| 99 | + STALE_DAYS: ${{ inputs.stale_days }} |
| 100 | +
|
| 101 | + You are performing a scheduled issue checkup/hygiene scan. |
| 102 | +
|
| 103 | + ## Issues Needing Attention |
| 104 | +
|
| 105 | + The following issues need review: |
| 106 | + ```json |
| 107 | + ${{ needs.find-issues.outputs.issues }} |
| 108 | + ``` |
| 109 | +
|
| 110 | + ## Your Tasks |
| 111 | +
|
| 112 | + For EACH issue above: |
| 113 | +
|
| 114 | + ### 1. Read the Issue |
| 115 | + ```bash |
| 116 | + gh issue view <number> |
| 117 | + ``` |
| 118 | +
|
| 119 | + ### 2. Analyze What's Missing |
| 120 | +
|
| 121 | + Check for: |
| 122 | + - **Type label**: bug, feature, docs, maintenance, research, question |
| 123 | + - **Priority label**: critical, high, medium, low, icebox |
| 124 | + - **Size label**: xs, s, m, l, xl |
| 125 | + - **Description quality**: Is it clear what needs to be done? |
| 126 | +
|
| 127 | + ### 3. Add Missing Labels |
| 128 | +
|
| 129 | + If you can determine the appropriate labels from the issue content, add them: |
| 130 | + ```bash |
| 131 | + gh issue edit <number> --add-label "type: X,priority: Y,size: Z" |
| 132 | + ``` |
| 133 | +
|
| 134 | + ### 4. Add "needs-info" Label If Unclear |
| 135 | +
|
| 136 | + If the issue lacks enough information to determine labels or next steps: |
| 137 | + ```bash |
| 138 | + gh issue edit <number> --add-label "needs-info" |
| 139 | + ``` |
| 140 | +
|
| 141 | + ### 5. Post a Helpful Comment |
| 142 | +
|
| 143 | + For issues that need human input, post a comment like: |
| 144 | + ``` |
| 145 | + ## Issue Checkup |
| 146 | +
|
| 147 | + This issue was flagged during our scheduled review. |
| 148 | +
|
| 149 | + **Status**: [what's missing or unclear] |
| 150 | +
|
| 151 | + **To move forward**, please: |
| 152 | + - [specific ask 1] |
| 153 | + - [specific ask 2] |
| 154 | +
|
| 155 | + Once updated, remove the `needs-info` label and the issue will be ready for work. |
| 156 | +
|
| 157 | + --- |
| 158 | + *Automated checkup by Claude* |
| 159 | + ``` |
| 160 | +
|
| 161 | + ## Important Rules |
| 162 | +
|
| 163 | + - DO NOT implement anything - this is checkup only |
| 164 | + - DO NOT add `agent: claude` label |
| 165 | + - DO NOT create branches or PRs |
| 166 | + - Be helpful and specific in comments |
| 167 | + - Skip issues that already have all required labels AND adequate description |
| 168 | + - If an issue is fine, don't comment on it |
| 169 | +
|
| 170 | + ## Summary |
| 171 | +
|
| 172 | + After processing all issues, output a summary: |
| 173 | + - How many issues were updated |
| 174 | + - How many need human attention (needs-info) |
| 175 | + - How many were already fine |
| 176 | +
|
| 177 | + allowed_tools: | |
| 178 | + Bash(gh issue:*),Bash(gh search:*),Read,Grep,Glob |
| 179 | +
|
| 180 | + report: |
| 181 | + needs: [find-issues, checkup] |
| 182 | + if: always() && needs.find-issues.outputs.count != '0' |
| 183 | + runs-on: arc-happyvertical |
| 184 | + timeout-minutes: 5 |
| 185 | + steps: |
| 186 | + - name: Generate Report |
| 187 | + env: |
| 188 | + GH_TOKEN: ${{ secrets.GH_TOKEN }} |
| 189 | + run: | |
| 190 | + echo "## Issue Checkup Complete" >> $GITHUB_STEP_SUMMARY |
| 191 | + echo "" >> $GITHUB_STEP_SUMMARY |
| 192 | + echo "Processed ${{ needs.find-issues.outputs.count }} issues." >> $GITHUB_STEP_SUMMARY |
| 193 | + echo "" >> $GITHUB_STEP_SUMMARY |
| 194 | + echo "View the checkup job logs for details." >> $GITHUB_STEP_SUMMARY |
| 195 | +
|
| 196 | + no-issues: |
| 197 | + needs: find-issues |
| 198 | + if: needs.find-issues.outputs.count == '0' |
| 199 | + runs-on: arc-happyvertical |
| 200 | + timeout-minutes: 1 |
| 201 | + steps: |
| 202 | + - name: Report Clean State |
| 203 | + run: | |
| 204 | + echo "## Issue Checkup Complete" >> $GITHUB_STEP_SUMMARY |
| 205 | + echo "" >> $GITHUB_STEP_SUMMARY |
| 206 | + echo "All issues are properly triaged. No action needed." >> $GITHUB_STEP_SUMMARY |
0 commit comments