llvm/.github/workflows/issue-write.yml

name: Comment on an issue

on:
  workflow_run:
    workflows:
      - "Check code formatting"
      - "Check for private emails used in PRs"
      - "PR Request Release Note"
    types:
      - completed

permissions:
  contents: read

jobs:
  pr-comment:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
    if: >
      github.event.workflow_run.event == 'pull_request' &&
      (
        github.event.workflow_run.conclusion == 'success' ||
        github.event.workflow_run.conclusion == 'failure'
      )
    steps:
      - name: Fetch Sources
        uses: actions/checkout@v4
        with:
          sparse-checkout: |
            .github/workflows/unprivileged-download-artifact/action.yml
          sparse-checkout-cone-mode: false
      - name: 'Download artifact'
        uses: ./.github/workflows/unprivileged-download-artifact
        id: download-artifact
        with:
          run-id: ${{ github.event.workflow_run.id }}
          artifact-name: workflow-args

      - name: 'Comment on PR'
        if: steps.download-artifact.outputs.artifact-id != ''
        uses: actions/github-script@v3
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            var fs = require('fs');
            const comments = JSON.parse(fs.readFileSync('./comments'));
            if (!comments || comments.length == 0) {
              return;
            }

            let runInfo = await github.actions.getWorkflowRun({
              owner: context.repo.owner,
              repo: context.repo.repo,
              run_id: context.payload.workflow_run.id
            });

            console.log(runInfo);


            // Query to find the number of the pull request that triggered this job.
            // The associated pull requests are based off of the branch name, so if
            // you create a pull request for a branch, close it, and then create
            // another pull request with the same branch, then this query will return
            // two associated pull requests.  This is why we have to fetch all the
            // associated pull requests and then iterate through them to find the
            // one that is open.
            const gql_query = `
              query($repo_owner : String!, $repo_name : String!, $branch: String!) {
                repository(owner: $repo_owner, name: $repo_name) {
                  ref (qualifiedName: $branch) {
                    associatedPullRequests(first: 100) {
                      nodes {
                        baseRepository {
                          owner {
                            login
                          }
                        }
                        number
                        state
                      }
                    }
                  }
                }
              }
            `
            const gql_variables = {
              repo_owner: runInfo.data.head_repository.owner.login,
              repo_name: runInfo.data.head_repository.name,
              branch: runInfo.data.head_branch
            }
            const gql_result = await github.graphql(gql_query, gql_variables);
            console.log(gql_result);
            // If the branch for the PR was deleted before this job has a chance
            // to run, then the ref will be null.  This can happen if someone:
            // 1. Rebase the PR, which triggers some workflow.
            // 2. Immediately merges the PR and deletes the branch.
            // 3. The workflow finishes and triggers this job.
            if (!gql_result.repository.ref) {
              console.log("Ref has been deleted");
              return;
            }
            console.log(gql_result.repository.ref.associatedPullRequests.nodes);

            var pr_number = 0;
            gql_result.repository.ref.associatedPullRequests.nodes.forEach((pr) => {

              // The largest PR number is the one we care about.  The only way
              // to have more than one associated pull requests is if all the
              // old pull requests are in the closed state.
              if (pr.baseRepository.owner.login = context.repo.owner && pr.number > pr_number) {
                pr_number = pr.number;
              }
            });
            if (pr_number == 0) {
              console.log("Error retrieving pull request number");
              return;
            }
            
            await comments.forEach(function (comment) {
              if (comment.id) {
                // Security check: Ensure that this comment was created by
                // the github-actions bot, so a malicious input won't overwrite
                // a user's comment.
                github.issues.getComment({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  comment_id: comment.id
                }).then((old_comment) => {
                  console.log(old_comment);
                  if (old_comment.data.user.login != "github-actions[bot]") {
                    console.log("Invalid comment id: " + comment.id);
                    return;
                  }
                  github.issues.updateComment({
                    owner: context.repo.owner,
                    repo: context.repo.repo,
                    issue_number: pr_number,
                    comment_id: comment.id,
                    body: comment.body
                  });
                });
              } else {
                github.issues.createComment({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  issue_number: pr_number,
                  body: comment.body
                });
              }
            });

      - name: Dump comments file
        if: >-
          always() &&
          steps.download-artifact.outputs.artifact-id != ''
        run: cat comments