summaryrefslogtreecommitdiffstats
path: root/.github/workflows/review.yml
blob: 9e5d32e81315ee1f25a38e422a5aa3420129d83c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
name: Review

on:
  workflow_run:
    workflows:
      - Reviewed
    types: [completed]

# This is used as fallback without app only.
# This happens when testing in forks without setting up that app.
permissions:
  pull-requests: write # minimizing dismissed reviews and adding reactions

defaults:
  run:
    shell: bash

jobs:
  process:
    runs-on: ubuntu-slim
    timeout-minutes: 2
    steps:
      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
        with:
          persist-credentials: false
          sparse-checkout: |
            ci/github-script

      # Use the GitHub App to make sure the reaction happens with the same user who will later merge.
      - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
        if: github.event_name != 'pull_request' && vars.NIXPKGS_CI_CLIENT_ID
        id: app-token
        with:
          client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }}
          private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
          permission-pull-requests: write

      - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
        with:
          github-token: ${{ steps.app-token.outputs.token || github.token }}
          retries: 3
          script: |
            const { handleMergeComment } = await import('${{ github.workspace }}/ci/github-script/merge.js')

            // PRs from forks don't have any PRs associated by default.
            // Thus, we request the PR number with an API call *to* the fork's repo.
            // Multiple pull requests can be open from the same head commit, either via
            // different base branches or head branches.
            const { head_repository, head_sha, repository } = context.payload.workflow_run
            await Promise.all(
              (await github.paginate(github.rest.repos.listPullRequestsAssociatedWithCommit, {
                owner: head_repository.owner.login,
                repo: head_repository.name,
                commit_sha: head_sha
              }))
              .filter(pull_request => pull_request.base.repo.id == repository.id)
              .map(async (pull_request) =>
                Promise.all(
                  (await github.paginate(github.rest.pulls.listReviews, {
                    owner: context.repo.owner,
                    repo: context.repo.repo,
                    pull_number: pull_request.number
                  })).map(review => {
                    // The `check` workflow creates review comments which reviewers
                    // are encouraged to manually dismiss if they're not relevant.
                    // When a CI-generated review is dismissed, this job automatically minimizes
                    // it, preventing it from cluttering the PR.
                    if (review.user?.login == 'github-actions[bot]' && review.state == 'DISMISSED')
                      return github.graphql(`
                        mutation($node_id:ID!) {
                          minimizeComment(input: {
                            classifier: RESOLVED,
                            subjectId: $node_id
                          })
                          { clientMutationId }
                        }`,
                        { node_id: review.node_id }
                      )

                    // The `bot` workflow reacts to comments with @NixOS/nixpkgs-merge-bot references, but might only
                    // pick up a comment after up to 10 minutes. To give the user instant feedback, this job adds
                    // a reaction to these comments.
                    return handleMergeComment({
                      github,
                      body: review.body,
                      node_id: review.node_id,
                      reaction: 'EYES',
                    })
                  })
                )
              )
            )