Triggering GitHub Actions across different repositories


Introduction

In this post, I’ll show you how one GitHub Actions workflow from a repository can invoke a workflow from a different repository. The first part describes the different events that can trigger a workflow, focusing on the repository_dispatch event. The second part is a practical example showing how two repositories trigger their workflows mutually.

Events that trigger workflows

As you may already know, there are several events that can trigger a GitHub Actions workflow execution. The most common events that can trigger this execution are push, pull_request and schedule. These events cover most of the use cases, as regularly you want your workflows to trigger when certain events happen on the repository. Sometimes this is not enough, and you require a workflow trigger to respond to an external event (chatbot, external CI,  manual deploy to prod after QA, etc.).

This is where the repository_dispatch event can be used (in this post it will be utilized to trigger workflows across different repositories).

In order to trigger this event, you need to send an HTTP POST request to this endpoint https://api.github.com/repos/:owner/:repo/dispatches.

This endpoint expects 2 input parameters:

  • event_type: This will be received in the workflow event payload as the action field.
  • client_payload: JSON object with any custom information that you want to propagate to the workflow, this will be available in the client_payload field of the event payload.

In order to be able to use the endpoint, you will need to be authenticated and authorized to access the repository. For that purpose, you can create a personal access token.

The endpoint can be invoked by using cURL:

Notice the Accept header has application/vnd.github.everest-preview+json custom media type value. As of now, this endpoint is still in the preview period and the API can change without previous notice.

Triggering events across repository workflows

In order to show how we can use repository_dispatch event to trigger workflow executions from one repository to another, I’ve designed two repository pipelines named A and B:

Actions Remote Dispatch Sequence DiagramThere are two repositories, A and B. Repository A will trigger its workflow execution when push or repository_dispatch event is received. Respository B will only trigger its workflow execution when a repository_dispatch event is received.

The sequence starts with a regular push to repository A (there’s also a schedule so that the sequence gets executed at least once a day). This will trigger an initial workflow execution in repository A, this workflow will perform a request to the dispatches endpoint in repository B with a ping action type and end its execution.

Repository B will start a new workflow execution. For the received ping event, the workflow is configured to send a request to repository A with a pong action type and end its execution.

Repository A will start a new workflow execution. For the received pong event, the workflow will send a request to repository B with an ack (acknowledge) action type and end its execution. This will be the last workflow execution in the sequence for this repository.

Finally, repository B will start a final workflow execution. For the ack event, the workflow is configured to simply print an informative message with the name of the repository that invoked the action. The workflow execution ends and the sequence concludes.

Access token

One of the main requirements to be able to perform requests to the repository dispatch endpoint is to use authentication.

First, we must create a personal access token following GitHub’s guide.

Next, we need to set these credentials in a secret in each of the repositories (A & B). For each of the repositories, we’ll access the settings->secrets page and add a new secret named ACCESS_TOKEN. The value for the token will be our username a colon and the personal access token obtained in the previous step (username:token).

GitHub Secrets - Access Token

Repository A workflow (ping)

This repository contains the “initiating” workflow. It will be triggered on repository_dispatch but also on push and schedule. Push and schedule events will be used to trigger the initiating ping action. On the other hand, dispatch events will be used to trigger the acknowledge action. Both these executions can be seen in the jobs section of the workflow.

There is only a single job for this workflow with two steps. The first step will trigger only when github.event.action != 'pong'. For our current example, this means that it will trigger for any push or schedule  event or any repository_dispatch event which is not of pong type. So every time a user pushes a commit to the repo or every day at 12:00, this step will be executed. The run action is executing the curl command described previously. In this case, the event_type is ping and is targeting repository B, in the custom payload we’re including the name of the current repo available in $GITHUB_REPOSITORY environment variable. Notice also how we set our credentials with the secret defined in the previous step using the expression ${{ secrets.ACCESS_TOKEN }}.

The second step in the job will trigger whenever github.event.action == 'pong', which will only happen whenever a respository_dispatch event of type pong is received. This step will (again using curl) send an acknowledgment request to repository B.

Repository B workflow (pong)

This repository contains the workflow that will be remotely invoked, i.e. it will only be triggered for repository_dispatch events.

The workflow contains a single job with 2 steps. The first step (Event Information) will run always, it basically prints information about the event that triggered the invocation. The second step (PONG) will only run if a ping event action is received, it will send a request (using the described curl command) to repository A with a pong event_type.

Conclusion

In this post we’ve seen how we can use GitHub Actions repository_dispatch event to trigger workflow executions across different GitHub repositories. The same approach could be used to trigger manual action executions from a remote environment, a different CI tool, a chatbot, etc.

The full source code for this post can be found at Github (A & B).

References

GitHub Actions

Leave a comment

Your email address will not be published. Required fields are marked *