1name: Comment on an issue 2 3on: 4 workflow_run: 5 workflows: 6 - "Check code formatting" 7 - "Check for private emails used in PRs" 8 - "PR Request Release Note" 9 types: 10 - completed 11 12permissions: 13 contents: read 14 15jobs: 16 pr-comment: 17 runs-on: ubuntu-latest 18 permissions: 19 pull-requests: write 20 if: > 21 github.event.workflow_run.event == 'pull_request' && 22 ( 23 github.event.workflow_run.conclusion == 'success' || 24 github.event.workflow_run.conclusion == 'failure' 25 ) 26 steps: 27 - name: Fetch Sources 28 uses: actions/checkout@v4 29 with: 30 sparse-checkout: | 31 .github/workflows/unprivileged-download-artifact/action.yml 32 sparse-checkout-cone-mode: false 33 - name: 'Download artifact' 34 uses: ./.github/workflows/unprivileged-download-artifact 35 id: download-artifact 36 with: 37 run-id: ${{ github.event.workflow_run.id }} 38 artifact-name: workflow-args 39 40 - name: 'Comment on PR' 41 if: steps.download-artifact.outputs.artifact-id != '' 42 uses: actions/github-script@v3 43 with: 44 github-token: ${{ secrets.GITHUB_TOKEN }} 45 script: | 46 var fs = require('fs'); 47 const comments = JSON.parse(fs.readFileSync('./comments')); 48 if (!comments || comments.length == 0) { 49 return; 50 } 51 52 let runInfo = await github.actions.getWorkflowRun({ 53 owner: context.repo.owner, 54 repo: context.repo.repo, 55 run_id: context.payload.workflow_run.id 56 }); 57 58 console.log(runInfo); 59 60 61 // Query to find the number of the pull request that triggered this job. 62 // The associated pull requests are based off of the branch name, so if 63 // you create a pull request for a branch, close it, and then create 64 // another pull request with the same branch, then this query will return 65 // two associated pull requests. This is why we have to fetch all the 66 // associated pull requests and then iterate through them to find the 67 // one that is open. 68 const gql_query = ` 69 query($repo_owner : String!, $repo_name : String!, $branch: String!) { 70 repository(owner: $repo_owner, name: $repo_name) { 71 ref (qualifiedName: $branch) { 72 associatedPullRequests(first: 100) { 73 nodes { 74 baseRepository { 75 owner { 76 login 77 } 78 } 79 number 80 state 81 } 82 } 83 } 84 } 85 } 86 ` 87 const gql_variables = { 88 repo_owner: runInfo.data.head_repository.owner.login, 89 repo_name: runInfo.data.head_repository.name, 90 branch: runInfo.data.head_branch 91 } 92 const gql_result = await github.graphql(gql_query, gql_variables); 93 console.log(gql_result); 94 // If the branch for the PR was deleted before this job has a chance 95 // to run, then the ref will be null. This can happen if someone: 96 // 1. Rebase the PR, which triggers some workflow. 97 // 2. Immediately merges the PR and deletes the branch. 98 // 3. The workflow finishes and triggers this job. 99 if (!gql_result.repository.ref) { 100 console.log("Ref has been deleted"); 101 return; 102 } 103 console.log(gql_result.repository.ref.associatedPullRequests.nodes); 104 105 var pr_number = 0; 106 gql_result.repository.ref.associatedPullRequests.nodes.forEach((pr) => { 107 108 // The largest PR number is the one we care about. The only way 109 // to have more than one associated pull requests is if all the 110 // old pull requests are in the closed state. 111 if (pr.baseRepository.owner.login = context.repo.owner && pr.number > pr_number) { 112 pr_number = pr.number; 113 } 114 }); 115 if (pr_number == 0) { 116 console.log("Error retrieving pull request number"); 117 return; 118 } 119 120 await comments.forEach(function (comment) { 121 if (comment.id) { 122 // Security check: Ensure that this comment was created by 123 // the github-actions bot, so a malicious input won't overwrite 124 // a user's comment. 125 github.issues.getComment({ 126 owner: context.repo.owner, 127 repo: context.repo.repo, 128 comment_id: comment.id 129 }).then((old_comment) => { 130 console.log(old_comment); 131 if (old_comment.data.user.login != "github-actions[bot]") { 132 console.log("Invalid comment id: " + comment.id); 133 return; 134 } 135 github.issues.updateComment({ 136 owner: context.repo.owner, 137 repo: context.repo.repo, 138 issue_number: pr_number, 139 comment_id: comment.id, 140 body: comment.body 141 }); 142 }); 143 } else { 144 github.issues.createComment({ 145 owner: context.repo.owner, 146 repo: context.repo.repo, 147 issue_number: pr_number, 148 body: comment.body 149 }); 150 } 151 }); 152 153 - name: Dump comments file 154 if: >- 155 always() && 156 steps.download-artifact.outputs.artifact-id != '' 157 run: cat comments 158