From 8572e60f9c5f279ee503c9739b0f17ff3b781039 Mon Sep 17 00:00:00 2001 From: Christian Gunderman Date: Tue, 5 May 2026 08:43:16 -0700 Subject: [PATCH] fix(bot): implement pagination for metric scripts to avoid GraphQL limit --- .../metrics/scripts/bottlenecks.ts | 49 ++++++++++++------- .../metrics/scripts/priority_distribution.ts | 49 ++++++++++++------- 2 files changed, 64 insertions(+), 34 deletions(-) diff --git a/tools/gemini-cli-bot/metrics/scripts/bottlenecks.ts b/tools/gemini-cli-bot/metrics/scripts/bottlenecks.ts index 715173dc27..241f95ca55 100644 --- a/tools/gemini-cli-bot/metrics/scripts/bottlenecks.ts +++ b/tools/gemini-cli-bot/metrics/scripts/bottlenecks.ts @@ -20,28 +20,43 @@ interface IssueNode { */ function run() { try { - // Fetch 1000 open issues, sorted by least recently updated. - const query = ` - query($owner: String!, $repo: String!) { - repository(owner: $owner, name: $repo) { - issues(first: 1000, states: OPEN, orderBy: {field: UPDATED_AT, direction: ASC}) { - nodes { - number - updatedAt - comments { - totalCount + const issues: IssueNode[] = []; + let hasNextPage = true; + let endCursor: string | null = null; + const MAX_ISSUES = 1000; + + // Fetch up to 1000 open issues, sorted by least recently updated, using pagination. + while (hasNextPage && issues.length < MAX_ISSUES) { + const query = ` + query($owner: String!, $repo: String!, $after: String) { + repository(owner: $owner, name: $repo) { + issues(first: 100, states: OPEN, orderBy: {field: UPDATED_AT, direction: ASC}, after: $after) { + nodes { + number + updatedAt + comments { + totalCount + } + } + pageInfo { + hasNextPage + endCursor } } } } + `; + const variables = endCursor ? `-F after=${endCursor}` : ''; + const output = execSync( + `gh api graphql -F owner=${GITHUB_OWNER} -F repo=${GITHUB_REPO} ${variables} -f query='${query}'`, + { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] }, + ).trim(); + + const data = JSON.parse(output).data.repository.issues; + issues.push(...data.nodes); + hasNextPage = data.pageInfo.hasNextPage; + endCursor = data.pageInfo.endCursor; } - `; - const output = execSync( - `gh api graphql -F owner=${GITHUB_OWNER} -F repo=${GITHUB_REPO} -f query='${query}'`, - { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] }, - ).trim(); - const data = JSON.parse(output).data.repository; - const issues: IssueNode[] = data.issues.nodes; if (issues.length === 0) { process.stdout.write('bottleneck_zombie_issues_count,0\n'); diff --git a/tools/gemini-cli-bot/metrics/scripts/priority_distribution.ts b/tools/gemini-cli-bot/metrics/scripts/priority_distribution.ts index 1191554de1..7fc6349def 100644 --- a/tools/gemini-cli-bot/metrics/scripts/priority_distribution.ts +++ b/tools/gemini-cli-bot/metrics/scripts/priority_distribution.ts @@ -18,29 +18,44 @@ interface IssueNode { */ function run() { try { - // Fetch last 1000 open issues and their labels. - // Using 'last' to get more recent context, but distribution is better from a larger sample. - const query = ` - query($owner: String!, $repo: String!) { - repository(owner: $owner, name: $repo) { - issues(last: 1000, states: OPEN) { - nodes { - labels(first: 20) { - nodes { - name + const issues: IssueNode[] = []; + let hasPreviousPage = true; + let startCursor: string | null = null; + const MAX_ISSUES = 1000; + + // Fetch up to 1000 open issues and their labels using pagination. + // Using 'last' to get more recent context. + while (hasPreviousPage && issues.length < MAX_ISSUES) { + const query = ` + query($owner: String!, $repo: String!, $before: String) { + repository(owner: $owner, name: $repo) { + issues(last: 100, states: OPEN, before: $before) { + nodes { + labels(first: 20) { + nodes { + name + } } } + pageInfo { + hasPreviousPage + startCursor + } } } } + `; + const variables = startCursor ? `-F before=${startCursor}` : ''; + const output = execSync( + `gh api graphql -F owner=${GITHUB_OWNER} -F repo=${GITHUB_REPO} ${variables} -f query='${query}'`, + { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] }, + ).trim(); + + const data = JSON.parse(output).data.repository.issues; + issues.push(...data.nodes); + hasPreviousPage = data.pageInfo.hasPreviousPage; + startCursor = data.pageInfo.startCursor; } - `; - const output = execSync( - `gh api graphql -F owner=${GITHUB_OWNER} -F repo=${GITHUB_REPO} -f query='${query}'`, - { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] }, - ).trim(); - const data = JSON.parse(output).data.repository; - const issues: IssueNode[] = data.issues.nodes; const distribution: Record = { p0: 0,