Skip to content

Commit d9d99cf

Browse files
committed
refactor(eng): update contributor report generator output
- Modify generateMarkdownReport to include per-user sections with PR details - Remove total PR count and simplify PR link format Commit-generated-by: GitHub Copilot <[email protected]> Signed-off-by: Ashley Childress <[email protected]>
1 parent 1322aa2 commit d9d99cf

File tree

1 file changed

+58
-47
lines changed

1 file changed

+58
-47
lines changed

eng/contributor-report.mjs

Lines changed: 58 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -423,58 +423,74 @@ export const generateContributorReport = (username, { includeAllFiles = false }
423423
* @returns {string}
424424
*/
425425
export const generateMarkdownReport = (reports, missingCount = 0) => {
426-
// The report is intentionally minimal: a single list of affected PRs and
427-
// a single copy/paste command maintainers can run locally.
428-
// No timestamps, per-file breakdowns, or duplicated metadata.
429-
430426
if (!missingCount) {
431427
return 'No missing contributors detected.\n';
432428
}
433429

434-
// 1) Single list of affected PRs (deduped).
435-
const prEntries = new Map(); // key=prNumber or url, value={number,url,mergedAt}
436-
for (const report of reports) {
437-
for (const pr of report.prs) {
438-
const key = pr.prUrl || String(pr.prNumber);
439-
if (!prEntries.has(key)) {
440-
prEntries.set(key, {
441-
number: pr.prNumber,
442-
url: pr.prUrl,
443-
mergedAt: pr.mergedAt
444-
});
445-
}
446-
}
447-
}
430+
const nowIso = new Date().toISOString();
448431

449-
const prList = Array.from(prEntries.values()).sort((a, b) => {
450-
// Prefer chronological sort for stable “what happened” review.
451-
const aTime = a.mergedAt ? Date.parse(a.mergedAt) : 0;
452-
const bTime = b.mergedAt ? Date.parse(b.mergedAt) : 0;
453-
if (aTime !== bTime) return aTime - bTime;
454-
return (a.number ?? 0) - (b.number ?? 0);
455-
});
456432

457-
// 2) One command (one line). If multiple users are missing, chain them.
458-
const commandParts = [];
459-
for (const report of reports) {
433+
const computeTypesArg = (report) => {
460434
const typeSet = new Set();
461-
for (const pr of report.prs) {
435+
for (const pr of report.prs || []) {
462436
for (const type of pr.contributionTypes || []) {
463-
typeSet.add(type);
437+
if (type) {
438+
typeSet.add(type);
439+
}
464440
}
465441
}
466442

467-
const types = Array.from(typeSet).filter(Boolean).sort((a, b) => a.localeCompare(b));
468-
const typesArg = types.length > 0 ? types.join(',') : 'code';
469-
commandParts.push(`npx all-contributors add ${report.username} ${typesArg}`);
443+
const types = Array.from(typeSet).sort((a, b) => a.localeCompare(b));
444+
return types.length > 0 ? types.join(',') : 'code';
445+
};
446+
447+
const lines = [];
448+
449+
lines.push('# Missing Contributors Report');
450+
lines.push('');
451+
lines.push(`Generated (ISO): ${nowIso}`);
452+
lines.push('');
453+
lines.push(`Missing contributors: ${missingCount}`);
454+
lines.push('');
455+
456+
for (const report of reports) {
457+
lines.push(`## @${report.username}`);
458+
lines.push('');
459+
460+
const prs = Array.from(report.prs || []).sort((a, b) => {
461+
// Prefer most recent PRs first.
462+
const aTime = a.mergedAt ? Date.parse(a.mergedAt) : 0;
463+
const bTime = b.mergedAt ? Date.parse(b.mergedAt) : 0;
464+
if (aTime !== bTime) return bTime - aTime;
465+
return (b.prNumber ?? 0) - (a.prNumber ?? 0);
466+
});
467+
468+
for (const pr of prs) {
469+
lines.push(`### PR #${pr.prNumber}: ${pr.prTitle}`);
470+
lines.push('');
471+
lines.push(`Add this comment on PR: ${pr.prUrl}`);
472+
lines.push('');
473+
474+
const prTypes = (pr.contributionTypes || []).filter(Boolean);
475+
const prTypesArg = prTypes.length > 0 ? prTypes.join(', ') : 'code';
476+
477+
lines.push('```text');
478+
lines.push(`@all-contributors please add @${report.username} for ${prTypesArg}`);
479+
lines.push('```');
480+
lines.push('');
481+
}
482+
483+
lines.push('### CLI command (all-contributors-cli)');
484+
lines.push('');
485+
lines.push('```bash');
486+
lines.push(`npx all-contributors add ${report.username} ${computeTypesArg(report)}`);
487+
lines.push('```');
488+
lines.push('');
489+
lines.push('---');
490+
lines.push('');
470491
}
471492

472-
let markdown = '';
473-
markdown += prList.map((pr) => `- #${pr.number} ${pr.url}`).join('\n');
474-
markdown += '\n\n';
475-
markdown += commandParts.join(' && ');
476-
markdown += '\n';
477-
return markdown;
493+
return `${lines.join('\n')}\n`;
478494
};
479495

480496
/**
@@ -552,14 +568,9 @@ export const autoAddCommentsToReports = (reports) => {
552568

553569
const main = () => {
554570
try {
555-
const ghToken = process.env.GITHUB_TOKEN || process.env.PRIVATE_TOKEN;
556-
if (!ghToken) {
557-
console.error('❌ GITHUB_TOKEN or PRIVATE_TOKEN environment variable is required for GitHub CLI operations');
558-
process.exit(1);
559-
}
560-
561-
// gh CLI only reads GITHUB_TOKEN or GH_TOKEN, so ensure it's set
562-
if (process.env.PRIVATE_TOKEN && !process.env.GITHUB_TOKEN) {
571+
// gh CLI can use either its own authenticated session or token env vars.
572+
// In CI, we commonly receive a token via PRIVATE_TOKEN.
573+
if (process.env.PRIVATE_TOKEN && !process.env.GITHUB_TOKEN && !process.env.GH_TOKEN) {
563574
process.env.GITHUB_TOKEN = process.env.PRIVATE_TOKEN;
564575
}
565576

0 commit comments

Comments
 (0)