From 3259e6f39cba99bd18f96076085ec923a62ad444 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Thu, 13 Aug 2026 08:58:35 +0000 Subject: [PATCH] ci: scan the live base...head compare in comment-cop, cap posts per run comment-cop took its file list from pulls.listFiles. Right after a rebase or a merge from main, that list can still be relative to the base the PR was opened against, so it contains every file main has touched since then and the workflow flags comments the PR never added. It posted one review comment per group with no bound, so each such run kept posting until the 5 minute job timeout cancelled it (about 120 comments per push). Take the diff from repos.compareCommitsWithBasehead(base.ref...head.sha), which GitHub computes from the current merge base at request time, and post at most 25 new comments per run, logging a warning when capped. --- .github/workflows/comment-cop.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/comment-cop.yml b/.github/workflows/comment-cop.yml index f6cf8005a8d2..aae553e8a444 100644 --- a/.github/workflows/comment-cop.yml +++ b/.github/workflows/comment-cop.yml @@ -34,9 +34,11 @@ jobs: const repo = context.repo.repo; const pull_number = context.payload.pull_request.number; const headSha = context.payload.pull_request.head.sha; + const baseRef = context.payload.pull_request.base.ref; const SRC_EXT = /\.(rs|c|cc|cpp|h|hpp|m|mm|ts|tsx|mts|cts|js|jsx|mjs|cjs)$/; const MIN_LINES = 2; + const MAX_COMMENTS_PER_RUN = 25; function isCommentLine(line) { const t = line.trimStart(); @@ -89,9 +91,15 @@ jobs: return out; } - const files = await github.paginate(github.rest.pulls.listFiles, { - owner, repo, pull_number, per_page: 100, + // Not pulls.listFiles: right after a rebase or a merge from main, the PR's + // cached diff can still be relative to the old base and list every file + // main touched since the PR was opened. The compare is computed live; its + // files (at most 300) all come on the first page, per_page only pages commits. + const { data: compare } = await github.rest.repos.compareCommitsWithBasehead({ + owner, repo, basehead: `${baseRef}...${headSha}`, per_page: 1, }); + const files = compare.files ?? []; + core.info(`${files.length} file(s) in ${baseRef}...${headSha.slice(0, 10)} (merge base ${compare.merge_base_commit.sha.slice(0, 10)}).`); const groups = []; for (const f of files) { @@ -167,8 +175,12 @@ jobs: `\n` + `If you need a paragraph-long comment to justify why the workaround is OK, the code is wrong — fix the code\n\n`; + if (fresh.length > MAX_COMMENTS_PER_RUN) { + core.warning(`${fresh.length} new comment groups; posting the first ${MAX_COMMENTS_PER_RUN} only.`); + } + let posted = 0; - for (const g of fresh) { + for (const g of fresh.slice(0, MAX_COMMENTS_PER_RUN)) { const params = { owner, repo, pull_number, commit_id: headSha,