Search code examples
githubyamlgithub-actions

GitHub Actions checks-action unable to comment contents on PR main page


I am new to GitHub Action programming trying to write a workflow with "checks-action" that can initiate a check on the main page of the PR. The plan runs successfully and can output to script variable but seems "actions/github-script" facing permission issue posting the plan output to the PR. I tried different permission but still getting below error. Requesting help and advise.

If deploying without checks-action on a normal workflow, its able to post content with existing permission. Seems I am missing something with this process.

Run actions/github-script@v6
RequestError [HttpError]: Not Found
    at /home/runner/work/_actions/actions/github-script/v6/dist/index.js:6803:21
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at async eval (eval at callAsyncFunction (/home/runner/work/_actions/actions/github-script/v6/dist/index.js:15099:16), <anonymous>:4:28)
    at async main (/home/runner/work/_actions/actions/github-script/v6/dist/index.js:15198:20) {
  status: 404,
  response: {
    url: 'https://api.github.com/repos/My-Apps/devops-master/issues//comments',
    status: 404,
    headers: {
      'access-control-allow-origin': '*',
      'access-control-expose-headers': 'ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset',
      connection: 'close',
      'content-encoding': 'gzip',
      'content-security-policy': "default-src 'none'",
      'content-type': 'application/json; charset=utf-8',
      date: 'Tue, 04 Apr 2023 22:41:26 GMT',
      'referrer-policy': 'origin-when-cross-origin, strict-origin-when-cross-origin',
      server: 'GitHub.com',
      'strict-transport-security': 'max-age=31536000; includeSubdomains; preload',
      'transfer-encoding': 'chunked',
      vary: 'Accept-Encoding, Accept, X-Requested-With',
      'x-content-type-options': 'nosniff',
      'x-frame-options': 'deny',
      'x-github-api-version-selected': '2022-11-28',
      'x-github-media-type': 'github.v3',
      'x-github-request-id': 'B740:1FCE:86030:113BD4:642CA796',
      'x-ratelimit-limit': '15000',
      'x-ratelimit-remaining': '14993',
      'x-ratelimit-reset': '1680649234',
      'x-ratelimit-resource': 'core',
      'x-ratelimit-used': '7',
      'x-xss-protection': '0'
    },
    data: {
      message: 'Not Found',
      documentation_url: 'https://docs.github.com/rest'
    }
  },
  request: {
    method: 'GET',
    url: 'https://api.github.com/repos/My-Apps/devops-master/issues//comments',
    headers: {
      accept: 'application/vnd.github.-preview+json',
      'user-agent': 'actions/github-script octokit-core.js/3.6.0 Node.js/16.16.0 (linux; x64)',
      authorization: 'token [REDACTED]'
    },
    request: { agent: [Agent], hook: [Function: bound bound register] }
  }
}
Error: Unhandled error: HttpError: Not Found

.github/workflows/tf_main.yml

name: Terraform WF

on:
  pull_request:
    types: [opened, edited, synchronize, reopened]
    paths:
      - 'accounts/global/**'
  workflow_dispatch:

env:
  action_assume_role: ${{ vars.ASSUME_ROLE }}

  tf_version: 'latest'
  tf_actions_working_dir: './accounts/global'

  backend_s3_bucket: ${{ vars.BACKEND_BUCKET }}
  backend_s3_region: ${{ vars.BACKEND_REGION }}
  backend_encrypt_key: ${{ vars.BACKEND_KMS_KEY_ID }}
  backend_tfstate_key: "${{ github.repository }}/accounts/global/global_state.tfstate"

permissions:
  id-token: write
  contents: read
  pull-requests: write
  actions: write

jobs:
  terraform-fmt:
    runs-on: ubuntu-latest

    defaults:
      run:
        working-directory: ${{ env.tf_actions_working_dir }}

    steps:
    - uses: actions/checkout@v3
    - uses: hashicorp/setup-terraform@v2
      with:
        terraform_version: ${{ env.tf_version }}

    - name: terraform fmt
      id: fmt
      run: terraform fmt -check
      continue-on-error: true
    
    - name: Generate token
      uses: tibdex/github-app-token@v1
      id: get_installation_token
      with: 
        app_id: ${{ secrets.APP_ID }}
        private_key: ${{ secrets.PRIVATE_KEY }}

    - uses: LouisBrunner/[email protected]
      id: check
      with:
        sha: ${{ github.sha }}
        token: ${{ steps.get_installation_token.outputs.token }}
        name: terraform plan
        status: in_progress

    - name: Trigger Workflow
      uses: actions/github-script@v6
      with:
        script: |
          github.rest.actions.createWorkflowDispatch({
            owner: context.repo.owner,
            repo: context.repo.repo,
            workflow_id: 'tf_deployment_plan.yml',
            ref: '${{ github.head_ref }}',
            inputs: {
              "tf_actions_working_dir": "${{ env.tf_actions_working_dir }}",
              "get_installation_token": "${{ steps.get_installation_token.outputs.token }}",
              "action_assume_role": "${{ env.action_assume_role }}",
              "backend_s3_bucket": "${{ env.backend_s3_bucket }}",
              "backend_s3_region": "${{ env.backend_s3_region }}",
              "backend_tfstate_key": "${{ env.backend_tfstate_key }}",
              "backend_encrypt_key": "${{ env.backend_encrypt_key }}"
            }
          })

    - uses: LouisBrunner/[email protected]
      if: failure()
      with:
        sha: ${{ github.sha }}
        token: ${{ steps.get_installation_token.outputs.token }}
        name: terraform plan
        conclusion: ${{ job.status }}
        output: |
          {"summary":"${{ steps.plan.outputs.summary }}"}
          
          
          
          

.github/workflows/tf_deployment_plan.yml

name: terraform plan

on:
  workflow_dispatch:
    inputs:
      tf_actions_working_dir:
        ...

permissions:
  id-token: write
  contents: read
  pull-requests: write
  actions: write
  issues: write

  #checks: write
  #contents: write
  #deployments: write
  #packages: write
  #repository-projects: write
  #security-events: write
  #statuses: write

jobs:
  terraform-plan:
    runs-on: ubuntu-latest

    defaults:
      run:
        working-directory: ${{ github.event.inputs.tf_actions_working_dir }}

    steps:
    - uses: actions/checkout@v3
    - uses: hashicorp/setup-terraform@v2
      with:
        terraform_version: ${{ env.tf_version }}
    - uses: aws-actions/configure-aws-credentials@v2
      with:
        aws-region: ${{ github.event.inputs.backend_s3_region }}
        role-to-assume: ${{ github.event.inputs.action_assume_role }}
        mask-aws-account-id: false

    - name: terraform init
      id: init
      run: terraform init

    - name: terraform validate
      id: validate
      run: terraform validate -no-color

    - name: terraform plan
      id: plan
      run: terraform plan -no-color
      continue-on-error: true
    
    - uses: actions/github-script@v6
      # if: github.event_name == 'pull_request'
      env:
        PLAN: "terraform\n${{ steps.plan.outputs.stdout }}"
      with:
        # github-token: ${{ secrets.GITHUB_TOKEN }}
        # github-token: ${{ github.event.inputs.get_installation_token }}
        script: |
            ...

            #### Terraform Plan Output📖\`${{ steps.plan.outcome }}\`

            <details><summary>Plan </summary>

            \`\`\`\n
            ${process.env.PLAN}
            \`\`\`

            </details>

            // 3. If we have a comment, update it, otherwise create a new one
            if (botComment) {
              github.rest.issues.updateComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                comment_id: botComment.id,
                body: output
              })
            } else {
              github.rest.issues.createComment({
                issue_number: context.issue.number,
                owner: context.repo.owner,
                repo: context.repo.repo,
                body: output
              })
            }

    - name: terraform plan status
      if: steps.plan.outcome == 'failure'
      run: exit 1

    - uses: LouisBrunner/[email protected]
      if: always()
      with:
        sha: ${{ github.sha }}
        token: ${{ github.event.inputs.get_installation_token }}

        name: terraform plan
        conclusion: ${{ job.status }}
        output: |
          {"summary":"${{ steps.plan.outcome }}"}

Solution

  • Your issue is misuse of the context in your script, as best as I can tell.

    tf_deployment_plan is running under the workflow_dispatch context because that is the event that triggered it. Trying to access context.issue.number will not provide a valid value, thus your 404 error trying to create the comment.

    Give your provided workflows, what you need to do is add another input to tf_deployment_plan that is the issue number, and pass that during your dispatch.

    tf_main.yml

    ...
        - name: Trigger Workflow
          uses: actions/github-script@v6
          with:
            script: |
              github.rest.actions.createWorkflowDispatch({
    ...
                  "backend_en crypt_key": "${{ env.backend_encrypt_key }}",
                  "issue": "${{ context.pull_request.number }}"
                }
              })
    ...
    

    What will complicate the solution for tf_main is that you also have workflow_dispatch as an event. For this to work for that case also, you will need to have an input under workflow_dispatch and then add some additional code to check where you should get the issue number from.

    tf_deployment_plan.yml

    on:
      workflow_dispatch:
        inputs:
          issue:
            required: true
    ...
                  github.rest.issues.createComment({
                    issue_number: ${{ inputs.issue }},
                    owner: context.repo.owner,
                    repo: context.repo.repo,
                    body: output
                  })
    ...