From 3a712cc5027b0e08216882af83ef4096efc0627a Mon Sep 17 00:00:00 2001 From: R script Date: Thu, 20 Aug 2026 11:59:19 +0100 Subject: [PATCH] Collapse superseded benchmark comments rather than prefixing them The step already tracked which of its own comments were stale; it just had no way to act on it beyond prepending a warning banner, which left every old result at full height. GitHub's `minimizeComment` mutation with `classifier: OUTDATED` is the real thing -- the comment folds into the collapsed "marked as outdated" state. Listing moves to GraphQL out of necessity, not taste: REST's comment payload omits `isMinimized`, and since minimizing no longer touches the body, that flag is the only remaining idempotency guard. Without it every run would re-minimize the whole history. Neither half may throw. The step exists to post the new result, and losing that to a hiccup in tidying up the old ones would be a poor trade -- so a failed listing or a failed collapse warns and the comment still lands. The likeliest such failure is a token without the scope `minimizeComment` needs. This job declares no `permissions:` block, so it runs on the repository default; if the warning fires, that is where to look. Comments already carrying the old banner keep it, and will be collapsed banner-and-all on the next run. Co-Authored-By: Claude Opus 5 --- .github/workflows/R-CMD-check.yml | 63 ++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/.github/workflows/R-CMD-check.yml b/.github/workflows/R-CMD-check.yml index 27a059f8..d31c33b1 100644 --- a/.github/workflows/R-CMD-check.yml +++ b/.github/workflows/R-CMD-check.yml @@ -330,29 +330,58 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} script: | const benchmarkIdentifier = ''; - const outdatedPrefix = '> **⚠️ This benchmark result is outdated. See the latest comment below.**\n\n'; - const comments = await github.rest.issues.listComments({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: context.issue.number - }); - - const previousBenchmarkComments = comments.data.filter(comment => - comment.user.type === 'Bot' && - comment.body.includes(benchmarkIdentifier) && - !comment.body.startsWith('> **⚠️ This benchmark result is outdated.') - ); - - for (const comment of previousBenchmarkComments) { - await github.rest.issues.updateComment({ + // Nothing below may throw: this step exists to post the new result, + // and losing that to a hiccup in the tidy-up of the old ones would + // be a poor trade. Both halves warn instead. + let previousBenchmarkComments = []; + try { + // The listing has to come from GraphQL: REST's comment payload + // omits isMinimized, so it cannot tell a comment this step has + // already collapsed from a live one, and each run would re- + // minimize the whole history. + const { repository } = await github.graphql(` + query($owner: String!, $repo: String!, $number: Int!) { + repository(owner: $owner, name: $repo) { + pullRequest(number: $number) { + comments(last: 100) { + nodes { id body isMinimized author { __typename } } + } + } + } + }`, { owner: context.repo.owner, repo: context.repo.repo, - comment_id: comment.id, - body: outdatedPrefix + comment.body + number: context.issue.number }); + previousBenchmarkComments = + repository.pullRequest.comments.nodes.filter(comment => + comment.author?.__typename === 'Bot' && + comment.body.includes(benchmarkIdentifier) && + !comment.isMinimized + ); + } catch (error) { + core.warning(`Could not list benchmark comments: ${error.message}`); + } + + // Collapse each as outdated. The likeliest failure is a token + // without the scope minimizeComment needs. + for (const comment of previousBenchmarkComments) { + try { + await github.graphql(` + mutation($id: ID!) { + minimizeComment(input: { subjectId: $id, classifier: OUTDATED }) { + minimizedComment { isMinimized } + } + }`, { id: comment.id }); + } catch (error) { + core.warning( + `Could not collapse benchmark comment ${comment.id}: ${error.message}` + ); + } } + // Create new comment with identifier const newCommentBody = benchmarkIdentifier + '\n' + process.env.BENCHMARK_MESSAGE; await github.rest.issues.createComment({