Script updates.

This commit is contained in:
Christian Gunderman
2026-04-23 07:57:37 -07:00
parent 9109505145
commit 87485c87a4
8 changed files with 367 additions and 93 deletions
+47 -6
View File
@@ -36,14 +36,17 @@ export async function getMaintainers(): Promise<string[]> {
const lines = content.split('\n');
for (const line of lines) {
if (line.startsWith('#') || !line.trim()) continue;
const cleanLine = line.split('#')[0].trim();
if (!cleanLine) continue;
// Match @user or @org/team
const matches = line.match(/@[\w-]+\/[\w-]+|@[\w-]+/g);
const matches = cleanLine.match(/@[\w-]+\/[\w-]+|@[\w-]+/g);
if (matches) {
for (const match of matches) {
if (match.includes('/')) {
// For team mentions, we might want to expand them,
// but for now let's just skip them or handle them if needed.
// For teams, we should ideally expand them via gh api,
// but for simulation/simple use, we'll just log it.
console.log(`[INFO] Found team ownership: ${match}. Skipping team expansion for now.`);
continue;
}
maintainers.add(match.replace('@', ''));
@@ -52,6 +55,7 @@ export async function getMaintainers(): Promise<string[]> {
}
if (maintainers.size === 0) {
console.warn('No maintainers found in CODEOWNERS, using fallbacks.');
return ['gundermanc', 'jackwotherspoon', 'DavidAPierce'];
}
@@ -126,7 +130,14 @@ export async function updateSimulationCsv(
for (const [colName, newValue] of Object.entries(update)) {
const colIndex = header.indexOf(colName);
if (colIndex !== -1) {
columns[colIndex] = newValue;
if (colName === 'labels') {
const existingLabels = columns[colIndex].replace(/"/g, '').split(',').map(s => s.trim()).filter(Boolean);
const newLabels = newValue.split(',').map(s => s.trim()).filter(Boolean);
const combined = Array.from(new Set([...existingLabels, ...newLabels]));
columns[colIndex] = `"${combined.join(', ')}"`;
} else {
columns[colIndex] = newValue.includes(',') ? `"${newValue}"` : newValue;
}
}
}
}
@@ -136,10 +147,37 @@ export async function updateSimulationCsv(
await fs.writeFile(filePath, newLines.join('\n'));
}
/**
* Reads maintainer workload from maintainer_workload.csv.
*/
export async function getMaintainerWorkload(): Promise<Record<string, number>> {
try {
const filePath = path.join(process.cwd(), 'maintainer_workload.csv');
const content = await fs.readFile(filePath, 'utf8');
const workload: Record<string, number> = {};
const lines = content.split('\n');
for (let i = 1; i < lines.length; i++) {
const line = lines[i].trim();
if (!line || line.startsWith('TOTAL') || line.startsWith('RATIO')) continue;
const columns = line.split(',');
const maintainer = columns[0];
const assignedIssues = parseInt(columns[1] || '0', 10);
const assignedPrs = parseInt(columns[2] || '0', 10);
workload[maintainer] = assignedIssues + assignedPrs;
}
return workload;
} catch (err) {
console.warn('maintainer_workload.csv not found or unreadable, returning empty workload.');
return {};
}
}
/**
* Executes a gh command with logging and dry-run support.
*/
export function execGh(command: string, execute: boolean) {
export async function execGh(command: string, execute: boolean) {
if (!execute) {
console.log(`[DRY RUN] Would execute: gh ${command}`);
return;
@@ -147,8 +185,11 @@ export function execGh(command: string, execute: boolean) {
console.log(`Executing: gh ${command}`);
try {
// Small delay to be nicer to the API and avoid race conditions if run concurrently
await new Promise(resolve => setTimeout(resolve, 100));
execSync(`gh ${command}`, { stdio: 'inherit' });
} catch (err) {
console.error(`Failed to execute gh ${command}:`, err);
}
}