How to trigger a GitHub action workflow in another repository
Tags: github, githubactions, ci, cicd
Published: 2024-02-07 16:01:07

Do you need to trigger a GitHub action workflow from another workflow? This is possible! You can use the GitHub API to trigger a workflow from basically anywhere. Let's dive into how this works and think of some practical use cases where this could be handy.

In this blog post I'm going to trigger a GitHub action workflow from a workflow in another repository. I'll reference to these repository by "target repository" and "trigger repository".

## The repository dispatch event

At the base of this is the "repository dispatch event". This is an event that can be triggered using the GitHub API and can be acted upon by listening to the `repository_dispatch` Webhook event payload.

Documentation about the GitHub API endpoint can be found [here](https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#create-a-repository-dispatch-event) and documentation about triggering the workflow based on the event can be found [here](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#repository_dispatch). This should be enough information to get you going. However, if you want a practical example, please read on!

## Target action

This article is not about all the fancy stuff you can do with GitHub actions. This means that the target action will be an incredibly simple one that only serves to prove that the functionality is working.

According to [the docs](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#repository_dispatch) we need to use the `repository_dispatch` activity type and specify the type of the dispatch we want to listen to. Let's create the following action in the target repository:

```yaml
name: Receive repository dispatch event

on:
  # Listen to a repository dispatch event by the name of `dispatch-event`
  repository_dispatch:
    types: [dispatch-event]

jobs:
  log:
    runs-on: ubuntu-latest
    steps:
      - name: Event received
        run: echo "Event received"
```

This action will start once it receives a repository dispatch message of the type `dispatch-event`. Then all it will do is log "Event received" to the shell, just to prove it works.

## Trigger action

Next, we'll setup an action in the trigger repository that will be responsible for firing the repository dispatch event. This is done by sending a request to the [GitHub POST /repos/{owner}/{repo}/dispatches API endpoint])https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#create-a-repository-dispatch-event). Let's use the following curl command to do this.

```sh
curl -L \
  -X POST \
  -H "Accept: application/vnd.github+json" \
  -H "Authorization: Bearer <YOUR-TOKEN>" \
  -H "X-GitHub-Api-Version: 2022-11-28" \
  https://api.github.com/repos/<OWNER>/<REPO>/dispatches \
  -d '{"event_type":"<EVENT-TYPE>"}'
```

There is a few things we need to replace to make the request work.

### Personal access token

Replace `<YOUR-TOKEN>` with a personal access token. The access token needs to have full repo access and the account that is connected to the personal access token should at least have write access to the target repository. If either of these two things is not setup correctly the API will return `Error: fatal: repository 'https://github.com/<OWNER>/<REPOSITORY>' not found`.

![Screenshot of the setup of a personal access token. It shows the settings that need to be enabled (all repo related checkboxes should be ticked).](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0mvbmhpmjdymh6gz2683.png)

Make sure to use a secret when using your personal access token in the GitHub action. This prevents leaking it.

### Owner and repository

Replace `<OWNER>` and `<REPO>` with the target owner and the repository. In my case: `https://api.github.com/repos/ngnijland/repository-dispatch-target-repo/dispatches`.

### Event type

Replace `<EVENT-TYPE>` with the name of the repository dispatch event that the target action will listen to. In this example: `dispatch-event`.

### The trigger action

Now create an action in the trigger repository that executes the curl command. For our example this action looks like this:

```yaml
name: Send repository dispatch event

on:
  workflow_dispatch:

jobs:
  trigger-event:
    runs-on: ubuntu-latest
    steps:
      - name: Fire event
        run: |
          curl -L \
            -X POST \
            -H "Accept: application/vnd.github+json" \
            -H "Authorization: Bearer ${{ secrets.REPOSITORY_ACCESS_TOKEN }}" \
            -H "X-GitHub-Api-Version: 2022-11-28" \
            https://api.github.com/repos/ngnijland/repository-dispatch-target-repo/dispatches \
            -d '{"event_type":"dispatch-event"}'
```

This action can be triggered manually. In its turn it will sent the repository dispatch request using the GitHub API.

**Tip:** You can use the [Repository Dispatch](https://github.com/marketplace/actions/repository-dispatch) action from the actions marketplace for better readability.

## The result!

![An animated GIF showing that the trigger action triggers the target action.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gw54vf6xrq1ack6okx4x.gif)

The workflow from the trigger repository triggers the workflow from the target repository. That's how it's done!

## Passing context

To send extra information with the repository dispatch event you can send a payload in JSON format. Do this by adding the `client_payload` key to the data object and add a JSON object as value.

```yaml
# ...
-d '{"event_type":"dispatch-event", "client_payload": {"message": "Hello from the trigger repository!"}}'
```

To read it in the target action use `${{ github.event.client_payload.<KEY> }}`.

```yaml
# ...
run: echo ${{ github.event.client_payload.message }}
```

Resulting in:

![Screenshot of the target action logging the message that is send with the repository dispatch event.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m57xcpxu56n1mrpcwxi5.png)

**Note:** If you want to send files you can upload the files as an artifact in the trigger repository, send `${{ github.run_id }}` in the `client_payload` and then download the artifact in the target repository using [the run-id option](https://github.com/actions/download-artifact?tab=readme-ov-file#download-artifacts-from-other-workflow-runs-or-repositories).

## When to use this?

Now you know how it works you can unleash all your creativity to apply this to day to day tasks! Some ideas on where to apply this:

- Open PR's in other repositories that update the dependency version of the dependency you just released using GitHub actions.
- Upload e2e test reports as artifacts and download them in the target repository to deploy them to GitHub Pages (we do this at Polarsteps!).
- Trigger a deployment of any sort of internal tool. Using this method you can move the source code of these tools to a separate repository. Preventing you from cluttering the main repository.
- Don't restrict yourself to a trigger action. You can trigger an action from anywhere using the GitHub API. Did someone say something about a physical launch button?! ;)

## Conclusion

I hope you learned how to use repository dispatch events to trigger GitHub workflow actions. Hopefully, it sparks some inspiration to start using it for day to day processes. Please let me know of any ways you will or already have implemented this via [Twitter!](https://twitter.com/ngnijland) I'm curious about all your implementations!

If you liked this article and want to read more make sure to check the [my other articles](https://www.nieknijland.nl/blog). Feel free to contact me on [Twitter](https://twitter.com/ngnijland) with tips, feedback or questions!