GitHub Actions Not Triggering on PR Merge

Recently I've been playing around with GitHub Actions to familiarize myself more with them. I also find it quite satisfying to maintain a certain level of stability and reliability even on my own personal projects, especially given the fact that the amount of free time I have to spend on them varies wildly from week to week. Additionally, I've been exploring the use of dependabot to help me keep dependencies up-to-date, which is particularly useful for me given the number of personal projects I have. So for each project, I've begun to introduce a pull request workflow, that runs tests and ensures that the project builds (usually an Android or JVM project), and the PR will be marked for auto-merge if the author is myself or dependabot and all the required checks pass. Here's an example of what that workflow looks like on one of my personal projects:

pull-request.yml
name: Pull request workflow
on: pull_request

permissions:
  contents: write
  pull-requests: write
  checks: write

jobs:
  test:
    name: Build and Test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-java@v3
        with:
          distribution: temurin
          java-version: 17
      - name: Validate Gradle Wrapper
        uses: gradle/wrapper-validation-action@v1
      - name: Build with Gradle
        uses: gradle/gradle-build-action@v2
        with:
          arguments: --stacktrace build
      - name: Publish JUnit Results
        uses: dorny/test-reporter@v1
        if: always()
        with:
          name: Unit Tests
          path: "*/build/test-results/test/*.xml"
          reporter: java-junit
          fail-on-error: true
  automerge:
    name: Enable automerge
    runs-on: ubuntu-latest
    if: ${{ github.actor == 'wbrawner' || github.actor == 'dependabot[bot]' }}
    steps:
      - name: Enable auto-merge
        run: gh pr merge --auto --rebase "$PR_URL"
        env:
          PR_URL: ${{github.event.pull_request.html_url}}
          GH_TOKEN: ${{secrets.GH_TOKEN}}

Nothing particularly interesting, except that if you look closely, you'll notice that I'm using a different authentication token to enable auto-merge:

          GH_TOKEN: ${{secrets.GH_TOKEN}}

In most cases, when having GitHub Actions execute API calls, you'd use the standard GITHUB_TOKEN provided for authentication with GitHub's APIs from a GitHub Action1. If you do that however, you'll soon realize that none of your other actions will be triggered. Take, for instance, this other action that I have configured to run on pushes to my main branch:

main.yml
name: Publish Docker image
on:
  push:
     branches:
       - main

jobs:
  push_to_registry:
    name: Push Docker image to GitHub Packages
    runs-on: ubuntu-latest
    steps:
      - name: Check out the repo
        uses: actions/checkout@v2
      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: |
            ghcr.io/wbrawner/twigs
          tags: |
            type=schedule
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=semver,pattern={{major}}
            type=sha
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v2
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2
      - name: Login to GitHub Container Registry
        uses: docker/login-action@v2
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and push
        uses: docker/build-push-action@v3
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

This workflow just builds and publishes the docker image for my project on each push to main, be it a direct push or as a result of merging a pull request. I was quite confused as to why this job was triggering when I pushed directly to main, and when I manually merged PRs, but not when PRs were automatically merged by the GitHub bot. Turns out I just needed to slow down a little and read the manual2:

When you use the repository's GITHUB_TOKEN to perform tasks, events triggered by the GITHUB_TOKEN, with the exception of workflow_dispatch and repository_dispatch, will not create a new workflow run. This prevents you from accidentally creating recursive workflow runs. For example, if a workflow run pushes code using the repository's GITHUB_TOKEN, a new workflow will not run even when the repository contains a workflow configured to run when push events occur. For more information, see "Automatic token authentication."

So, if you find yourself in a situation where your GitHub Actions are not being triggered when you auto-merge the PR (or perform some other interaction with GitHub's API) from another GitHub Action, the trick is to just create a token for your own user (or your own bot user with read/write access to the repo) and use that token instead of the default GITHUB_TOKEN. Happy coding!