1
0
Fork 1
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-06-09 09:36:20 +09:00

workflows/check-cherry-picks: post review comments

Instead of failing the job, the workflow will now post review comments
as "Request Changes". This makes the feedback more readily visible and
avoids having to merge despite a failing CI job. It is also a
pre-requisite to enable required status checks / required workflows in
the future.

Committers are asked to confirm the differences by explicitly dismissing
the generated review. After dismissal, the related review comment will
automatically be marked as "resolved".

The comments only report warnings and errors. Reviews are automatically
dismissed when they have been addressed by the author and no problems
remain. If problems remain, existing, still pending, review comments
will be updated. If the same problems had already been dismissed
earlier, no new review comment will be created either.
This commit is contained in:
Wolfgang Walther 2025-05-28 21:16:01 +02:00
parent 3dff9c34c0
commit 515b174c42
No known key found for this signature in database
GPG key ID: B39893FA5F65CAE1
4 changed files with 165 additions and 11 deletions

View file

@ -10,7 +10,8 @@ on:
- 'staging-**'
- '!staging-next'
permissions: {}
permissions:
pull-requests: write
jobs:
check:
@ -24,8 +25,105 @@ jobs:
path: trusted
- name: Check cherry-picks
id: check
continue-on-error: true
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
./trusted/ci/check-cherry-picks.sh "$BASE_SHA" "$HEAD_SHA"
./trusted/ci/check-cherry-picks.sh "$BASE_SHA" "$HEAD_SHA" checked-cherry-picks.md
- name: Prepare review
if: steps.check.outcome == 'failure'
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const { readFile, writeFile } = require('node:fs/promises')
const job_url = (await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.runId
})).data.jobs[0].html_url + '?pr=' + context.payload.pull_request.number
const header = await readFile('trusted/ci/check-cherry-picks.md')
const body = await readFile('checked-cherry-picks.md')
const footer =
`\n_Hint: The diffs are also available in the [runner logs](${job_url}) with slightly better highlighting._`
const review = header + body + footer
await writeFile('review.md', review)
core.summary.addRaw(review)
core.summary.write()
- name: Request changes
if: ${{ github.event_name == 'pull_request_target' && steps.check.outcome == 'failure' }}
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const { readFile } = require('node:fs/promises')
const body = await readFile('review.md', 'utf-8')
const pendingReview = (await github.paginate(github.rest.pulls.listReviews, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number
})).find(review =>
review.user.login == 'github-actions[bot]' && (
// If a review is still pending, we can just update this instead
// of posting a new one.
review.state == 'CHANGES_REQUESTED' ||
// No need to post a new review, if an older one with the exact
// same content had already been dismissed.
review.body == body
)
)
if (pendingReview) {
await github.rest.pulls.updateReview({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
review_id: pendingReview.id,
body
})
} else {
await github.rest.pulls.createReview({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
event: 'REQUEST_CHANGES',
body
})
}
- name: Dismiss old reviews
if: ${{ github.event_name == 'pull_request_target' && steps.check.outcome == 'success' }}
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
await Promise.all(
(await github.paginate(github.rest.pulls.listReviews, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number
})).filter(review =>
review.user.login == 'github-actions[bot]' &&
review.state == 'CHANGES_REQUESTED'
).map(async (review) => {
await github.rest.pulls.dismissReview({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
review_id: review.id,
message: 'All cherry-picks are good now, thank you!'
})
await github.graphql(`mutation($node_id:ID!) {
minimizeComment(input: {
classifier: RESOLVED,
subjectId: $node_id
})
{ clientMutationId }
}`, { node_id: review.node_id })
})
)

30
.github/workflows/dismissed-review.yml vendored Normal file
View file

@ -0,0 +1,30 @@
name: Dismissed Review
on:
pull_request_review:
types: [dismissed]
permissions:
pull-requests: write
jobs:
# The check-cherry-picks workflow creates review comments,
# that should sometimes be manually dismissed.
# When a CI-generated review is dismissed, this job automatically
# minimizes it, to prevent it from cluttering the PR.
minimize:
name: Minimize as resolved
if: github.event.review.user.login == 'github-actions[bot]'
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
await github.graphql(`mutation($node_id:ID!) {
minimizeComment(input: {
classifier: RESOLVED,
subjectId: $node_id
})
{ clientMutationId }
}`, { node_id: context.payload.review.node_id })