spacehub

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

Fix lock-closed-issues workflow: use search API instead of offset pagination (#69470)Browse files
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
Ashwin Bhat authored on Jun 19, 2026 · GitHub committed on Jun 19, 2026 parent 4fa369b · commit baf38ddaaa03
1 changed file+24 -39compared with 4fa369b
M.github/workflows/lock-closed-issues.yml
@@ -22,71 +22,56 @@
2222 script: |
2323 const sevenDaysAgo = new Date();
2424 sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
25+ const cutoff = sevenDaysAgo.toISOString().split('T')[0];
2526
2627 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.`;
2728
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();
3035 let totalLocked = 0;
3136
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,
3840 sort: 'updated',
39- direction: 'asc',
41+ order: 'asc',
4042 per_page: 100,
41- page: page
4243 });
43-
44- if (issues.length === 0) {
45- hasMore = false;
46- break;
44+
45+ if (totalLocked === 0) {
46+ console.log(`Total candidates: ${data.total_count}`);
4747 }
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);
6555 try {
66- // Add comment before locking
6756 await github.rest.issues.createComment({
6857 owner: context.repo.owner,
6958 repo: context.repo.repo,
7059 issue_number: issue.number,
71- body: lockComment
60+ body: lockComment,
7261 });
73-
74- // Lock the issue
7562 await github.rest.issues.lock({
7663 owner: context.repo.owner,
7764 repo: context.repo.repo,
7865 issue_number: issue.number,
79- lock_reason: 'resolved'
66+ lock_reason: 'resolved',
8067 });
81-
8268 totalLocked++;
8369 console.log(`Locked issue #${issue.number}: ${issue.title}`);
70+ await sleep(1000);
8471 } catch (error) {
8572 console.error(`Failed to lock issue #${issue.number}: ${error.message}`);
8673 }
8774 }
88-
89- page++;
9075 }
9176
9277 console.log(`Total issues locked: ${totalLocked}`);