Files
gemini-cli/tools/gemini-cli-bot/metrics/scripts/priority_distribution.ts
T
gemini-cli[bot] f8e99e3afa ## Description
Fixes the throughput metrics script and introduces new visibility into backlog bottlenecks and priority distribution.

### Changes
- **Throughput Fixes**: Resolved a `ReferenceError` where `isMaintainer` was not correctly scoped, fixed a malformed license header, and added a new metric for `issue_arrival_rate_per_day` to enable growth-vs-closure analysis.
- **Backlog Bottlenecks**: Introduced `bottlenecks.ts` to identify "Zombie" issues (no activity > 30 days) and "Hot" issues (high activity).
- **Priority Distribution**: Introduced `priority_distribution.ts` to track the count of open issues by priority level (P0-P3).

### Impact
These metrics will provide the necessary data to confirm if the repository is experiencing systemic backlog growth (Arrival Rate > Throughput) and help identify which segments of the backlog require urgent triage.
2026-05-01 20:10:24 +00:00

91 lines
2.3 KiB
TypeScript

/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { GITHUB_OWNER, GITHUB_REPO } from '../types.js';
import { execSync } from 'node:child_process';
interface IssueNode {
labels: {
nodes: Array<{ name: string }>;
};
}
/**
* Calculates the distribution of open issues across priority labels.
*/
function run() {
try {
// Fetch last 100 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: 100, states: OPEN) {
nodes {
labels(first: 20) {
nodes {
name
}
}
}
}
}
}
`;
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<string, number> = {
p0: 0,
p1: 0,
p2: 0,
p3: 0,
other: 0,
};
issues.forEach((issue) => {
let found = false;
issue.labels.nodes.forEach((label) => {
const name = label.name.toLowerCase();
if (name.includes('p0')) {
distribution.p0++;
found = true;
} else if (name.includes('p1')) {
distribution.p1++;
found = true;
} else if (name.includes('p2')) {
distribution.p2++;
found = true;
} else if (name.includes('p3')) {
distribution.p3++;
found = true;
}
});
if (!found) {
distribution.other++;
}
});
process.stdout.write(`priority_p0_count,${distribution.p0}\n`);
process.stdout.write(`priority_p1_count,${distribution.p1}\n`);
process.stdout.write(`priority_p2_count,${distribution.p2}\n`);
process.stdout.write(`priority_p3_count,${distribution.p3}\n`);
process.stdout.write(`priority_none_count,${distribution.other}\n`);
} catch (error) {
process.stderr.write(
error instanceof Error ? error.message : String(error),
);
process.exit(1);
}
}
run();