surshar / claude-code
Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.
Built by Anthropic · github.com/anthropics
The workflow has been failing daily since 2026-04-27 with HTTP 422 "Pagination with the page parameter is not supported for large datasets" at page=100. The repo now has ~58k closed issues and the script was paging past ~10k already-locked ones every run before reaching any candidates. Replace listForRepo + page=N with the search API (is:issue is:closed is:unlocked updated:<cutoff), which returns only the issues that actually need locking. Cap at 250/run with a 1s sleep between locks to stay under secondary rate limits. Claude-Session: https://claude.ai/code/session_016EWY3FKCJyfUdCAZkXfi7i
| @@ -22,71 +22,56 @@ | ||
| 22 | 22 | script: | |
| 23 | 23 | const sevenDaysAgo = new Date(); |
| 24 | 24 | sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7); |
| 25 | + const cutoff = sevenDaysAgo.toISOString().split('T')[0]; | |
| 25 | 26 | |
| 26 | 27 | const lockComment = `This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.`; |
| 27 | 28 | |
| 28 | - let page = 1; | |
| 29 | - let hasMore = true; | |
| 29 | + const query = `repo:${context.repo.owner}/${context.repo.repo} is:issue is:closed is:unlocked updated:<${cutoff}`; | |
| 30 | + console.log(`Search query: ${query}`); | |
| 31 | + | |
| 32 | + const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); | |
| 33 | + const MAX_PER_RUN = 250; | |
| 34 | + const processed = new Set(); | |
| 30 | 35 | let totalLocked = 0; |
| 31 | 36 | |
| 32 | - while (hasMore) { | |
| 33 | - // Get closed issues (pagination) | |
| 34 | - const { data: issues } = await github.rest.issues.listForRepo({ | |
| 35 | - owner: context.repo.owner, | |
| 36 | - repo: context.repo.repo, | |
| 37 | - state: 'closed', | |
| 37 | + while (totalLocked < MAX_PER_RUN) { | |
| 38 | + const { data } = await github.rest.search.issuesAndPullRequests({ | |
| 39 | + q: query, | |
| 38 | 40 | sort: 'updated', |
| 39 | - direction: 'asc', | |
| 41 | + order: 'asc', | |
| 40 | 42 | per_page: 100, |
| 41 | - page: page | |
| 42 | 43 | }); |
| 43 | - | |
| 44 | - if (issues.length === 0) { | |
| 45 | - hasMore = false; | |
| 46 | - break; | |
| 44 | + | |
| 45 | + if (totalLocked === 0) { | |
| 46 | + console.log(`Total candidates: ${data.total_count}`); | |
| 47 | 47 | } |
| 48 | - | |
| 49 | - for (const issue of issues) { | |
| 50 | - // Skip if already locked | |
| 51 | - if (issue.locked) continue; | |
| 52 | - | |
| 53 | - // Skip pull requests | |
| 54 | - if (issue.pull_request) continue; | |
| 55 | - | |
| 56 | - // Check if updated more than 7 days ago | |
| 57 | - const updatedAt = new Date(issue.updated_at); | |
| 58 | - if (updatedAt > sevenDaysAgo) { | |
| 59 | - // Since issues are sorted by updated_at ascending, | |
| 60 | - // once we hit a recent issue, all remaining will be recent too | |
| 61 | - hasMore = false; | |
| 62 | - break; | |
| 63 | - } | |
| 64 | - | |
| 48 | + | |
| 49 | + const fresh = data.items.filter((i) => !processed.has(i.number)); | |
| 50 | + if (fresh.length === 0) break; | |
| 51 | + | |
| 52 | + for (const issue of fresh) { | |
| 53 | + if (totalLocked >= MAX_PER_RUN) break; | |
| 54 | + processed.add(issue.number); | |
| 65 | 55 | try { |
| 66 | - // Add comment before locking | |
| 67 | 56 | await github.rest.issues.createComment({ |
| 68 | 57 | owner: context.repo.owner, |
| 69 | 58 | repo: context.repo.repo, |
| 70 | 59 | issue_number: issue.number, |
| 71 | - body: lockComment | |
| 60 | + body: lockComment, | |
| 72 | 61 | }); |
| 73 | - | |
| 74 | - // Lock the issue | |
| 75 | 62 | await github.rest.issues.lock({ |
| 76 | 63 | owner: context.repo.owner, |
| 77 | 64 | repo: context.repo.repo, |
| 78 | 65 | issue_number: issue.number, |
| 79 | - lock_reason: 'resolved' | |
| 66 | + lock_reason: 'resolved', | |
| 80 | 67 | }); |
| 81 | - | |
| 82 | 68 | totalLocked++; |
| 83 | 69 | console.log(`Locked issue #${issue.number}: ${issue.title}`); |
| 70 | + await sleep(1000); | |
| 84 | 71 | } catch (error) { |
| 85 | 72 | console.error(`Failed to lock issue #${issue.number}: ${error.message}`); |
| 86 | 73 | } |
| 87 | 74 | } |
| 88 | - | |
| 89 | - page++; | |
| 90 | 75 | } |
| 91 | 76 | |
| 92 | 77 | console.log(`Total issues locked: ${totalLocked}`); |