GitHub API Authentication - GitHub Actions
Tags: github, javascript, octokit
Published: 2020-01-17 21:26:12

In this post, I will explain how to create a GitHub Action workflow that adds a comment to every new pull request using

1. A [GitHub Action workflow](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions) file (`.github/workflows/pr-comment.yml`)
2. A single JavaScript file (`.github/actions/pr-comment.js`)

Both files live in the same repository where the comments will be added. If you get stuck at any point, [here is my repository](https://github.com/gr2m/create-pull-request-comment-action-example) with all the code described in this post.

## Prerequisites

1. Install [git](https://git-scm.com/) and [Node.js](https://nodejs.org/en/)
2. [Create a repository on GitHub](https://github.com/new)
3. [Clone the repository to your local machine](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository).

## Passing the `GITHUB_TOKEN` secret to a JavaScript file

GitHub Actions come with their own special token that must be passed to each workflow step explicitly: [`secrets.GITHUB_TOKEN`](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/authenticating-with-the-github_token). Unlike [Personal Access Tokens](https://dev.to/gr2m/github-api-authentication-personal-access-tokens-53kd) that I explained in the previous post of this series, you don't have to manually create them. A unique `GITHUB_TOKEN` is created each time your GitHub Action is run.

Let's start out by creating a new workflow file at `.github/workflows/pr-comment.yml`

```yml
name: PR Comment
on:
  # Run this workflow only when a new pull request is opened
  # compare: https://git.io/JvTyV
  pull_request:
    types: [opened]

jobs:
  pr_comment:
    runs-on: ubuntu-latest

    steps:
      # Make files accessible to actions
      # https://github.com/actions/checkout#readme
      - uses: actions/checkout@v2
      # Install Node
      # https://github.com/actions/setup-node#readme
      - uses: actions/setup-node@v1
        with:
          node-version: 12
      # Install dependencies
      - run: npm ci
      # Run pr-comment.js with Node and pass the authentication token 
      - run: node .github/actions/pr-comment.js
        with:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

Next, we need to create a `package.json` file and install a few dependencies, and create the `.github/actions/pr-comment.js`.

## Creating a comment using JavaScript

We will use GitHub's [Create a comment](https://developer.github.com/v3/issues/comments/#create-a-comment) REST API endpoint to create the comment on every new pull request. A GraphQL query would work just the same, using `octokit.graphql` instead of `octokit.request`.

Create a `package.json` file in the folder you cloned your repository into:

```shell
npm init
```

After that, install [`@octokit/action`](https://github.com/octokit/action.js)

```shell
npm install @octokit/action
```

Next, create the `.github/actions/pr-comment.js` file

```js
// GITHUB_EVENT_PATH always exists when run by an Action,
// see https://git.io/JvUf7 for a full list
const eventPayload = require(process.env.GITHUB_EVENT_PATH);
const { Octokit } = require("@octokit/action");

createPrComment();

async function createPrComment() {
  // No need to pass process.env.GITHUB_TOKEN, `@octokit/action`
  // is using it directly and throws an error if it is not present.
  const octokit = new Octokit();

  // See https://developer.github.com/v3/issues/comments/#create-a-comment
  const { data } = await octokit.request(
    "POST /repos/:repository/issues/:pr_number/comments",
    {
      repository: process.env.GITHUB_REPOSITORY,
      pr_number: eventPayload.pull_request.number,
      body: "Thank you for your pull request!"
    }
  );

  console.log("Comment created: %d", data.html_url);
}
```

Commit and push your changes

```
git add .
git commit -m 'add GitHub Action workflow to comment on new PRs'
git push origin master
```

Now create a new pull request on your repository. After a short delay, the Action will show up in the list of checks as pending

![Screenshot of new pull request](https://thepracticaldev.s3.amazonaws.com/i/ordv02m8ybwrexdgdepn.png)

If all goes as expected, the action will add the new comment

![Screenshot of new comment](https://thepracticaldev.s3.amazonaws.com/i/wri0tub497howpsfj0c7.png)

Congratulations 👏 Now that you know how to send authenticated requests against GitHub's APIs with Actions and JavaScript, sky is the limit 🚀

![With great power comes great responsibility](https://media.giphy.com/media/EybtniuGPjSdG/giphy.gif)

# Secrets and pull requests from forks

Creating the comment will not work when someone creates a pull request from a fork. The `GITHUB_TOKEN` secret is still passed, but has only read permissions, it cannot create or update anything. If that was not the case, anyone could create a pull request changing the code of the `pr-comment.js` script to do something malicious with your repository.

For now, I you can prevent the action from running altogether if the pull request comes from a fork by adding an [`if` statement](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#jobsjob_idif)

```yml
# ...

jobs:
  pr_comment:
    runs-on: ubuntu-latest
    if: eventPayload.pull_request.head.repo.fork == false
    steps:
      # ...
```

Another alternative is to use GitHub Apps instead, which I will cover in my next blog post 😇