From aaa9b21d5aff05617f49baf2cfd20f4c060d22d4 Mon Sep 17 00:00:00 2001 From: "gemini-cli[bot]" Date: Tue, 12 May 2026 20:56:36 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20Gemini=20Bot=20Maintenance=20Upd?= =?UTF-8?q?ate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../metrics/scripts/backlog_age.ts | 4 +- .../gemini-cli-bot/metrics/scripts/latency.ts | 65 ++++++++++--------- .../metrics/scripts/throughput.ts | 41 ++++++------ .../metrics/scripts/user_touches.ts | 25 ++++--- 4 files changed, 71 insertions(+), 64 deletions(-) diff --git a/tools/gemini-cli-bot/metrics/scripts/backlog_age.ts b/tools/gemini-cli-bot/metrics/scripts/backlog_age.ts index 816dfbdf59..5993ec4a54 100644 --- a/tools/gemini-cli-bot/metrics/scripts/backlog_age.ts +++ b/tools/gemini-cli-bot/metrics/scripts/backlog_age.ts @@ -15,7 +15,7 @@ function run() { const query = ` query($owner: String!, $repo: String!) { repository(owner: $owner, name: $repo) { - issues(first: 100, states: OPEN, orderBy: {field: CREATED_AT, direction: ASC}) { + issues(first: 500, states: OPEN, orderBy: {field: CREATED_AT, direction: ASC}) { nodes { createdAt } @@ -28,7 +28,7 @@ function run() { { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] }, ).trim(); const data = JSON.parse(output).data.repository; - const issues = data.issues.nodes; + const issues = data.issues.nodes.filter((n: any) => n && n.createdAt); if (issues.length === 0) { process.stdout.write('backlog_age_days,0\n'); diff --git a/tools/gemini-cli-bot/metrics/scripts/latency.ts b/tools/gemini-cli-bot/metrics/scripts/latency.ts index 7dd5dcd1f6..2be98d01b3 100644 --- a/tools/gemini-cli-bot/metrics/scripts/latency.ts +++ b/tools/gemini-cli-bot/metrics/scripts/latency.ts @@ -10,18 +10,21 @@ import { GITHUB_OWNER, GITHUB_REPO } from '../types.js'; import { execSync } from 'node:child_process'; try { + const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0]; const query = ` - query($owner: String!, $repo: String!) { - repository(owner: $owner, name: $repo) { - pullRequests(last: 100, states: MERGED) { - nodes { + query($prQuery: String!, $issueQuery: String!) { + prs: search(query: $prQuery, type: ISSUE, last: 100) { + nodes { + ... on PullRequest { authorAssociation createdAt mergedAt } } - issues(last: 100, states: CLOSED) { - nodes { + } + issues: search(query: $issueQuery, type: ISSUE, last: 100) { + nodes { + ... on Issue { authorAssociation createdAt closedAt @@ -30,36 +33,34 @@ try { } } `; + const prSearchQuery = `repo:${GITHUB_OWNER}/${GITHUB_REPO} is:pr is:merged merged:>${sevenDaysAgo}`; + const issueSearchQuery = `repo:${GITHUB_OWNER}/${GITHUB_REPO} is:issue is:closed closed:>${sevenDaysAgo}`; const output = execSync( - `gh api graphql -F owner=${GITHUB_OWNER} -F repo=${GITHUB_REPO} -f query='${query}'`, + `gh api graphql -F prQuery='${prSearchQuery}' -F issueQuery='${issueSearchQuery}' -f query='${query}'`, { encoding: 'utf-8' }, ); - const data = JSON.parse(output).data.repository; + const data = JSON.parse(output).data; - const prs = data.pullRequests.nodes.map( - (p: { - authorAssociation: string; - mergedAt: string; - createdAt: string; - }) => ({ - association: p.authorAssociation, - latencyHours: - (new Date(p.mergedAt).getTime() - new Date(p.createdAt).getTime()) / - (1000 * 60 * 60), - }), - ); - const issues = data.issues.nodes.map( - (i: { - authorAssociation: string; - closedAt: string; - createdAt: string; - }) => ({ - association: i.authorAssociation, - latencyHours: - (new Date(i.closedAt).getTime() - new Date(i.createdAt).getTime()) / - (1000 * 60 * 60), - }), - ); + const prs = data.prs.nodes + .filter((p: any) => p && p.mergedAt && p.createdAt) + .map( + (p: any) => ({ + association: p.authorAssociation, + latencyHours: + (new Date(p.mergedAt).getTime() - new Date(p.createdAt).getTime()) / + (1000 * 60 * 60), + }), + ); + const issues = data.issues.nodes + .filter((i: any) => i && i.closedAt && i.createdAt) + .map( + (i: any) => ({ + association: i.authorAssociation, + latencyHours: + (new Date(i.closedAt).getTime() - new Date(i.createdAt).getTime()) / + (1000 * 60 * 60), + }), + ); const isMaintainer = (assoc: string) => ['MEMBER', 'OWNER', 'COLLABORATOR'].includes(assoc); diff --git a/tools/gemini-cli-bot/metrics/scripts/throughput.ts b/tools/gemini-cli-bot/metrics/scripts/throughput.ts index 3806dd407a..6bc78f43bc 100644 --- a/tools/gemini-cli-bot/metrics/scripts/throughput.ts +++ b/tools/gemini-cli-bot/metrics/scripts/throughput.ts @@ -10,17 +10,20 @@ import { GITHUB_OWNER, GITHUB_REPO } from '../types.js'; import { execSync } from 'node:child_process'; try { + const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0]; const query = ` - query($owner: String!, $repo: String!) { - repository(owner: $owner, name: $repo) { - pullRequests(last: 100, states: MERGED) { - nodes { + query($prQuery: String!, $issueQuery: String!) { + prs: search(query: $prQuery, type: ISSUE, last: 100) { + nodes { + ... on PullRequest { authorAssociation mergedAt } } - issues(last: 100, states: CLOSED) { - nodes { + } + issues: search(query: $issueQuery, type: ISSUE, last: 100) { + nodes { + ... on Issue { authorAssociation closedAt } @@ -28,25 +31,27 @@ try { } } `; + const prSearchQuery = `repo:${GITHUB_OWNER}/${GITHUB_REPO} is:pr is:merged merged:>${sevenDaysAgo}`; + const issueSearchQuery = `repo:${GITHUB_OWNER}/${GITHUB_REPO} is:issue is:closed closed:>${sevenDaysAgo}`; const output = execSync( - `gh api graphql -F owner=${GITHUB_OWNER} -F repo=${GITHUB_REPO} -f query='${query}'`, + `gh api graphql -F prQuery='${prSearchQuery}' -F issueQuery='${issueSearchQuery}' -f query='${query}'`, { encoding: 'utf-8' }, ); - const data = JSON.parse(output).data.repository; + const data = JSON.parse(output).data; - const prs = data.pullRequests.nodes - .map((p: { authorAssociation: string; mergedAt: string }) => ({ + const prs = data.prs.nodes + .filter((p: any) => p && p.mergedAt) + .map((p: any) => ({ association: p.authorAssociation, date: new Date(p.mergedAt).getTime(), - })) - .sort((a: { date: number }, b: { date: number }) => a.date - b.date); + })); const issues = data.issues.nodes - .map((i: { authorAssociation: string; closedAt: string }) => ({ + .filter((i: any) => i && i.closedAt) + .map((i: any) => ({ association: i.authorAssociation, date: new Date(i.closedAt).getTime(), - })) - .sort((a: { date: number }, b: { date: number }) => a.date - b.date); + })); const isMaintainer = (assoc: string) => ['MEMBER', 'OWNER', 'COLLABORATOR'].includes(assoc); @@ -54,11 +59,7 @@ try { const calculateThroughput = ( items: { association: string; date: number }[], ) => { - if (items.length < 2) return 0; - const first = items[0].date; - const last = items[items.length - 1].date; - const days = (last - first) / (1000 * 60 * 60 * 24); - return days > 0 ? items.length / days : items.length; // items per day + return items.length / 7; // items per day over 7 day window }; const prOverall = calculateThroughput(prs); diff --git a/tools/gemini-cli-bot/metrics/scripts/user_touches.ts b/tools/gemini-cli-bot/metrics/scripts/user_touches.ts index 5ccffa94fc..79062439af 100644 --- a/tools/gemini-cli-bot/metrics/scripts/user_touches.ts +++ b/tools/gemini-cli-bot/metrics/scripts/user_touches.ts @@ -10,18 +10,21 @@ import { GITHUB_OWNER, GITHUB_REPO } from '../types.js'; import { execSync } from 'node:child_process'; try { + const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0]; const query = ` - query($owner: String!, $repo: String!) { - repository(owner: $owner, name: $repo) { - pullRequests(last: 100, states: MERGED) { - nodes { + query($prQuery: String!, $issueQuery: String!) { + prs: search(query: $prQuery, type: ISSUE, last: 100) { + nodes { + ... on PullRequest { authorAssociation comments { totalCount } reviews { totalCount } } } - issues(last: 100, states: CLOSED) { - nodes { + } + issues: search(query: $issueQuery, type: ISSUE, last: 100) { + nodes { + ... on Issue { authorAssociation comments { totalCount } } @@ -29,14 +32,16 @@ try { } } `; + const prSearchQuery = `repo:${GITHUB_OWNER}/${GITHUB_REPO} is:pr is:merged merged:>${sevenDaysAgo}`; + const issueSearchQuery = `repo:${GITHUB_OWNER}/${GITHUB_REPO} is:issue is:closed closed:>${sevenDaysAgo}`; const output = execSync( - `gh api graphql -F owner=${GITHUB_OWNER} -F repo=${GITHUB_REPO} -f query='${query}'`, + `gh api graphql -F prQuery='${prSearchQuery}' -F issueQuery='${issueSearchQuery}' -f query='${query}'`, { encoding: 'utf-8' }, ); - const data = JSON.parse(output).data.repository; + const data = JSON.parse(output).data; - const prs = data.pullRequests.nodes; - const issues = data.issues.nodes; + const prs = data.prs.nodes.filter((p: any) => p && p.comments); + const issues = data.issues.nodes.filter((i: any) => i && i.comments); const allItems = [ ...prs.map(