|
9 | 9 | ci_conclusion: |
10 | 10 | type: string |
11 | 11 | required: true |
| 12 | + ci_run_id: |
| 13 | + type: string |
| 14 | + required: false |
| 15 | + default: '' |
12 | 16 | secrets: |
13 | 17 | ANTHROPIC_API_KEY: |
14 | 18 | required: true |
|
34 | 38 | --description "Auto-approved by Claude" \ |
35 | 39 | --repo "$GH_REPO" \ |
36 | 40 | --force |
37 | | - gh label create "ai-skipped-major" \ |
| 41 | + gh label create "ai-skipped-needs-review" \ |
38 | 42 | --color "e4e669" \ |
39 | | - --description "Major bump — needs manual review" \ |
| 43 | + --description "Needs manual review (major bump or high risk)" \ |
40 | 44 | --repo "$GH_REPO" \ |
41 | 45 | --force |
42 | 46 | gh label create "ai-skipped-ci-failed" \ |
@@ -126,58 +130,173 @@ jobs: |
126 | 130 | echo "EOF_ANALYSIS" |
127 | 131 | } >> "$GITHUB_OUTPUT" |
128 | 132 |
|
| 133 | + - name: Write comment templates |
| 134 | + if: steps.already-processed.outputs.skip == 'false' |
| 135 | + run: | |
| 136 | + mkdir -p /tmp/dependabot-templates |
| 137 | +
|
| 138 | + cat > /tmp/dependabot-templates/approved.md << 'TEMPLATE' |
| 139 | + ## What Changed |
| 140 | + | Field | Value | |
| 141 | + |-------|-------| |
| 142 | + | Package | {package name(s)} | |
| 143 | + | From | {from version} | |
| 144 | + | To | {to version} | |
| 145 | + | Type | {MINOR or PATCH} | |
| 146 | +
|
| 147 | + {1–2 sentences summarising what this release contains, from the changelog} |
| 148 | +
|
| 149 | + ## Usage In This Repo |
| 150 | + {For each file where this package is used, one line per call site:} |
| 151 | + - `{filepath}` — `{MethodOrClass()}`: {one sentence on what it does in this codebase} |
| 152 | +
|
| 153 | + ## Risk Assessment |
| 154 | + {LOW — for patch with no notable changes | MEDIUM — for minor with new APIs} |
| 155 | +
|
| 156 | + ## Positive Signals |
| 157 | + {List only signals that actually apply, e.g.:} |
| 158 | + - Patch release |
| 159 | + - No breaking changes reported in changelog |
| 160 | + - CI passed |
| 161 | + - Changed APIs not used in this repo |
| 162 | +
|
| 163 | + ## Decision |
| 164 | + ✅ Auto-approved and merged by Claude |
| 165 | + TEMPLATE |
| 166 | +
|
| 167 | + cat > /tmp/dependabot-templates/needs-review.md << 'TEMPLATE' |
| 168 | + ## What Changed |
| 169 | + | Field | Value | |
| 170 | + |-------|-------| |
| 171 | + | Package | {package name(s)} | |
| 172 | + | From | {from version} | |
| 173 | + | To | {to version} | |
| 174 | + | Type | {MAJOR or MINOR or PATCH} | |
| 175 | +
|
| 176 | + {2–4 sentences summarising the most important changes from the changelog, focusing on breaking changes, removed APIs, and migration notes} |
| 177 | +
|
| 178 | + ## Usage In This Repo |
| 179 | + {For each file where this package is used, one line per call site:} |
| 180 | + - `{filepath}` — `{MethodOrClass()}`: {one sentence on what it does in this codebase} |
| 181 | +
|
| 182 | + ## Risk Signals |
| 183 | + {For each breaking change or high-risk signal matched to a call site above:} |
| 184 | + - `{filepath}` — `{method()}`: {concise explanation of why this call site may be affected} |
| 185 | +
|
| 186 | + ## Risk Assessment |
| 187 | + HIGH |
| 188 | +
|
| 189 | + ## Why This Needs A Human |
| 190 | + {1–3 sentences explaining the specific reason: major version bump / breaking API change in use / security vulnerability / etc.} |
| 191 | +
|
| 192 | + ## How To Fix |
| 193 | + - {step 1, e.g. "Read the migration guide at {URL from changelog}"} |
| 194 | + - {step 2, e.g. "Check `{filepath}` — the `{method}` signature changed"} |
| 195 | + {add more steps only if clearly identified from the changelog} |
| 196 | +
|
| 197 | + ## Decision |
| 198 | + 🟡 SKIPPED — Manual review required |
| 199 | + TEMPLATE |
| 200 | +
|
| 201 | + cat > /tmp/dependabot-templates/ci-failed.md << 'TEMPLATE' |
| 202 | + ## What Changed |
| 203 | + | Field | Value | |
| 204 | + |-------|-------| |
| 205 | + | Package | {package name(s)} | |
| 206 | + | From | {from version} | |
| 207 | + | To | {to version} | |
| 208 | + | Type | {MAJOR or MINOR or PATCH} | |
| 209 | +
|
| 210 | + {one sentence summarising what this release contains, from the changelog} |
| 211 | +
|
| 212 | + ## CI Failure |
| 213 | + **Failed job:** {job name} |
| 214 | + **Step:** {step name} |
| 215 | + **Error:** {concise error message, max 3 lines} |
| 216 | +
|
| 217 | + ## How To Fix |
| 218 | + - {actionable step 1 derived from the error} |
| 219 | + - {actionable step 2} |
| 220 | + {add more steps only if clearly needed} |
| 221 | +
|
| 222 | + ## Decision |
| 223 | + ❌ SKIPPED — CI failed, manual review required |
| 224 | + TEMPLATE |
| 225 | +
|
129 | 226 | - name: Claude merge decision |
130 | 227 | if: steps.already-processed.outputs.skip == 'false' |
131 | 228 | uses: anthropics/claude-code-action@9dd8b95a392eb34b6f5fb56cf5a64cb735912d4b # v1 |
132 | 229 | with: |
133 | 230 | anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} |
134 | 231 | github_token: ${{ secrets.GH_AUTO_MERGE_TOKEN }} |
135 | 232 | allowed_bots: 'dependabot[bot]' |
136 | | - claude_args: '--allowedTools "Bash(gh:*)" "Bash(grep:*)"' |
| 233 | + claude_args: '--allowedTools "Bash(gh:*)" "Bash(grep:*)" Read Write' |
137 | 234 | prompt: | |
138 | 235 | You are reviewing a Dependabot PR in repository ${{ github.repository }}. |
139 | 236 |
|
140 | 237 | PR number: ${{ inputs.pr_number }} |
141 | 238 | CI result: ${{ inputs.ci_conclusion }} |
| 239 | + CI run ID: ${{ inputs.ci_run_id }} |
142 | 240 | Bump analysis (pre-parsed by script — do not re-derive version numbers): |
143 | 241 | ${{ steps.parse-bump.outputs.analysis }} |
144 | 242 |
|
145 | | - Follow these steps before making a decision: |
| 243 | + == PHASE 1: GATHER DATA == |
146 | 244 |
|
147 | | - **Step 1 — Changelog analysis** |
148 | | - Fetch the full PR description: |
149 | | - gh pr view ${{ inputs.pr_number }} --json body --jq '.body' --repo ${{ github.repository }} |
150 | | - Read the changelog. For each package identify: |
151 | | - - Security fixes or CVE patches |
152 | | - - API changes, deprecations, or removals |
153 | | - - Breaking changes even if the bump type is minor or patch |
| 245 | + Step 1 — Fetch changelog (always run) |
| 246 | + Run: gh pr view ${{ inputs.pr_number }} --json body --jq '.body' --repo ${{ github.repository }} |
| 247 | + Identify: security fixes, API changes, deprecations, breaking changes. |
154 | 248 |
|
155 | | - **Step 2 — Codebase usage check** |
156 | | - For each updated package, find how it is used in this repository: |
| 249 | + Step 2 — Fetch CI failure details (only if ci_conclusion is not "success" OR ci_run_id is empty) |
| 250 | + 2a. Get failed job and step names: |
| 251 | + gh api repos/${{ github.repository }}/actions/runs/${{ inputs.ci_run_id }}/jobs \ |
| 252 | + --jq '.jobs[] | select(.conclusion == "failure") | {job: .name, failed_steps: [.steps[] | select(.conclusion == "failure") | .name]}' |
| 253 | + 2b. Get error messages from the failed log: |
| 254 | + gh run view ${{ inputs.ci_run_id }} --log-failed --repo ${{ github.repository }} \ |
| 255 | + | grep -E "ERROR:|##\[error\]" | head -5 |
| 256 | +
|
| 257 | + Step 3 — Check codebase usage (only if ci_conclusion is "success" AND ci_run_id is non-empty) |
| 258 | + For each updated package run: |
157 | 259 | grep -r "<package-name>" . --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" -l 2>/dev/null |
158 | | - If the changelog mentions specific changed APIs (functions, methods, config options), |
159 | | - search for those names in the codebase as well. |
| 260 | + For each changed API or method mentioned in changelog, also run: |
| 261 | + grep -r "<method-or-api-name>" . --include="*.ts" --include="*.js" --include="*.tsx" --include="*.jsx" -n 2>/dev/null |
| 262 | +
|
| 263 | + == PHASE 2: DECIDE == |
| 264 | +
|
| 265 | + Apply these rules in order and stop at the first match: |
160 | 266 |
|
161 | | - **Step 3 — Make the merge decision** |
162 | | - Apply these rules in order: |
| 267 | + Rule 1 — CI failed or CI run ID unavailable |
| 268 | + Condition: ci_conclusion is not "success" OR ci_run_id is empty |
| 269 | + Action: |
| 270 | + - gh pr edit ${{ inputs.pr_number }} --add-label "ai-skipped-ci-failed" --repo ${{ github.repository }} |
| 271 | + - Template: /tmp/dependabot-templates/ci-failed.md |
| 272 | + - If ci_run_id was empty, set Failed job and Step to "N/A — CI run ID unavailable, check the Actions tab manually" |
163 | 273 |
|
164 | | - 1. If ci_conclusion is not "success": |
165 | | - - gh pr edit ${{ inputs.pr_number }} --add-label "ai-skipped-ci-failed" --repo ${{ github.repository }} |
166 | | - - Post a comment explaining that CI failed and manual review is needed. |
| 274 | + Rule 2 — Major or unknown bump |
| 275 | + Condition: worst_bump is "major" or "unknown" |
| 276 | + Action: |
| 277 | + - gh pr edit ${{ inputs.pr_number }} --add-label "ai-skipped-needs-review" --repo ${{ github.repository }} |
| 278 | + - Template: /tmp/dependabot-templates/needs-review.md |
167 | 279 |
|
168 | | - 2. Else if worst_bump is "major" or "unknown": |
169 | | - - gh pr edit ${{ inputs.pr_number }} --add-label "ai-skipped-major" --repo ${{ github.repository }} |
170 | | - - Post a comment listing which packages have major bumps and that manual review is needed for breaking changes. |
| 280 | + Rule 3 — High risk signal detected |
| 281 | + Condition: Step 1 or Step 3 reveals a breaking API change actively used in this repo, |
| 282 | + or a security vulnerability in a code path we depend on |
| 283 | + Action: |
| 284 | + - gh pr edit ${{ inputs.pr_number }} --add-label "ai-skipped-needs-review" --repo ${{ github.repository }} |
| 285 | + - Template: /tmp/dependabot-templates/needs-review.md |
171 | 286 |
|
172 | | - 3. Else if Step 1 or Step 2 reveals a HIGH RISK signal |
173 | | - (a breaking API change that is actively used in this repo, or a security vulnerability in a code path we depend on): |
174 | | - - gh pr edit ${{ inputs.pr_number }} --add-label "ai-skipped-major" --repo ${{ github.repository }} |
175 | | - - Post a comment explaining the specific risk found, which files are affected, and what to verify manually. |
| 287 | + Rule 4 — Safe to merge |
| 288 | + Condition: patch or minor, CI green, no high-risk signals |
| 289 | + Action: |
| 290 | + - gh pr edit ${{ inputs.pr_number }} --add-label "ai-approved" --repo ${{ github.repository }} |
| 291 | + - gh pr review ${{ inputs.pr_number }} --approve --repo ${{ github.repository }} |
| 292 | + - gh pr merge ${{ inputs.pr_number }} --auto --squash --repo ${{ github.repository }} |
| 293 | + - Template: /tmp/dependabot-templates/approved.md |
176 | 294 |
|
177 | | - 4. Else (patch or minor, CI green, no high-risk signals): |
178 | | - - gh pr edit ${{ inputs.pr_number }} --add-label "ai-approved" --repo ${{ github.repository }} |
179 | | - - gh pr review ${{ inputs.pr_number }} --approve --repo ${{ github.repository }} |
180 | | - - gh pr merge ${{ inputs.pr_number }} --auto --squash --repo ${{ github.repository }} |
181 | | - - Post a comment with a risk summary: what changed in the package, how it is used in this repo, and why it is safe to auto-merge. |
| 295 | + == PHASE 3: WRITE COMMENT == |
182 | 296 |
|
183 | | - Write all comments in English. Be concise but informative. |
| 297 | + 1. Read the template file for your matched rule using the Read tool. |
| 298 | + 2. Fill in every {placeholder} with the actual data gathered in Phase 1. |
| 299 | + Do not add or remove sections. Write all content in English. |
| 300 | + 3. Write the filled comment to /tmp/comment-output.md using the Write tool. |
| 301 | + 4. Post the comment: |
| 302 | + gh pr comment ${{ inputs.pr_number }} --body-file /tmp/comment-output.md --repo ${{ github.repository }} |
0 commit comments