Checking out the branch from a fork in GitHub Actions, when using pull_request_target

Featured image for sharing metadata for article

This week, I've setting up a GitHub Actions Workflow which will:

  • Look at modified file(s) on the PR
  • Look up the owner of the files (based on an external HTTP API, using a GitHub Actions Secret)
  • Comment back onto the PR to indicate that ownership
  • On a private repo (that will never need to run on a public repo)

This looked something like:

on:
  pull_request:
    branches: [main]
    paths:
      - configuration/tools/*

jobs:
  list-changed-files:
    # omitted for brevity

  annotate-tool-changes:
    runs-on: ubuntu-latest
    needs: list-changed-files

    permissions:
      contents: read
      pull-requests: write

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Determine PR comments + make them
        env:
          ALL_CHANGED_FILES: ${{ needs.list-changed-files.outputs.changed-files }}
        run: |
          set -o pipefail
          echo "Checking if there are changes in $ALL_CHANGED_FILES"

          # note that we don't glob on purpose
          .scripts/do-the-thing $ALL_CHANGED_FILES          

I had it all working when pushing branches, but as soon as folks started trying to push PRs from forks, the Workflow could no longer access the base repo's secrets - for very good secure defaults!

In particular this meant that the HTTP API secrets weren't available, which led to the Workflow not knowing the owners, and failing gracefully, but with a lot less useful information.

However in this case, I did want those secrets to be available to the forked Workflow.

The "best" option here is to use the pull_request_target event, which then makes these secrets available.

⚠️ Using the pull_request_target can be dangerous. Moreso with public repos, but still has implications for private repos.

⚠️ This is something that should be done at your own risk, taking in mind the risks. Please do your own research.

To do so, I made the following change:

 on:
-  pull_request:
+  pull_request_target:
     branches: [main]
     paths:
       - configuration/tools/*

However, this wasn't quite enough. From here, we'd end up seeing errors in actions/checkout:

  ...
  remote: Repository not found.
  Error: fatal: repository 'https://github.com/{...}/{...}/' not found
  Error: The process '/usr/bin/git' failed with exit code 128

Looking at an actions/checkout issue, various web + AI searches, it looked like it would be unfortunately very painful to check out the branch, as GITHUB_TOKEN doesn't seem to have access to the forked repo.

I was losing hope of it ever working, when my excellent colleague Victor Martinez suggested trying gh pr checkout, using the GITHUB_TOKEN.

I'd originally dismissed this, given using the GITHUB_TOKEN to do a git fetch failed, but it turns out it does work πŸš€

This resulted in the following setup:

on:
  pull_request:
    branches: [main]
    paths:
      - configuration/tools/*

jobs:
  list-changed-files:
    # omitted for brevity

  annotate-tool-changes:
    runs-on: ubuntu-latest
    needs: list-changed-files

    permissions:
      contents: read
      pull-requests: write

    steps:
      # i.e. this allows us to use `origin/HEAD` to compare against
      - name: Check out base repository
        uses: actions/checkout@v4

      - name: Fetch PR branch from fork
        run: |
                    gh pr checkout ${{ github.event.number }}
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Determine PR comments + make them
        env:
          ALL_CHANGED_FILES: ${{ needs.list-changed-files.outputs.changed-files }}
        run: |
          set -o pipefail
          echo "Checking if there are changes in $ALL_CHANGED_FILES"

          # note that we don't glob on purpose
          .scripts/do-the-thing $ALL_CHANGED_FILES          

From here, you are now checked out on the fork's branch, and have access to i.e. origin/HEAD or origin/main, to i.e. diff against.

Written by Jamie Tanna's profile image Jamie Tanna on , and last updated on .

Content for this article is shared under the terms of the Creative Commons Attribution Non Commercial Share Alike 4.0 International, and code is shared under the Apache License 2.0.

#blogumentation #github #github-actions.

This post was filed under articles.

Interactions with this post

Interactions with this post

Below you can find the interactions that this page has had using WebMention.

Have you written a response to this post? Let me know the URL:

Do you not have a website set up with WebMention capabilities? You can use Comment Parade.