Manually Trigger A GitHub Actions Workflow

Currently, the GitHub UI doesn’t provide any mechanism to manually trigger a GitHub Actions workflow. The exception being that you can re-run a failed workflow.

Recently at Pixite, we created a new GitHub Actions workflow to help update the contents of our app’s home screen on a daily basis. This setup is easy to do with GitHub Actions, and is serving it’s purpose as expected.

However, re ran into the challenge of wanting to run our workflow outside of its pre-scheduled time.

Since there isn’t any means of triggering a workflow from within the current GitHub UI, we had to explore how to manually trigger a GitHub Actions workflow.

Can you manually trigger GitHub Actions?

Yes. Using the GitHub api and repository dispatch events.

What events trigger GitHub Actions workflows?

There are three event types that will trigger your workflow. Webhook events (thins like commit and push), scheduled events, and external events via repository dispatch events.

Repository Dispatch Events

The solution to this problem comes in the form of sending a repository dispatch event using the GitHub api. The repository_dispatch event is a webhook event which can be treated as a trigger for a GitHub Actions workflow.

By externally triggering a repository_dispatch event, we can run our desired workflow on command.

Scheduling a GitHub Actions workflow

To illustrate how we can manually trigger a GitHub actions workflow, we can walk through a simple example from my sandbox project: https://github.com/n8ebel/GitHubActionsAutomationSandbox

To start, we can define a trivial workflow which prints a message to the terminal. We’ll schedule this workflow to run every 5 minutes.

name: Do Something That Needs Scheduled

on:
  schedule:
    - cron:  '*/5 * * * *'

jobs:
  build:
    name: Run Some Scheduled Thing
    runs-on: ubuntu-latest
    steps:

      - name: Do Something
        run: echo Doing Something...

Now, we can walk through the steps for how we can manually trigger this workflow.

Triggering A repository_dispatch Event Using Curl

To manually trigger the repository_dispatch event, we need to interact with the following GitHub api endpoint:

POST /repos/:owner/:repo/dispatches

Using the repository name (GitHubActionsAutomationSandbox), along with my GitHub username (n8ebel), we can build the full path for the endpoint we’ll be interacting with:

https://api.github.com/repos/n8ebel/GitHubActionsAutomationSandbox/dispatches

To make the POST request to this endpoint, we need to do several things:

  1. Add a custom media type in the Accept header
  2. Authenticate the call using an Authorization header and a personal access token with repo permissions for the repository we’re working with
  3. Specify an event_type in the POST body

Adding the custom media type

The following custom media type is required to make the call to the /repos/:owner/:repo/dispatches endpoint:

application/vnd.github.everest-preview+json

To add this to our curl command, we will add an Accept header as follows:

-H "Accept: application/vnd.github.everest-preview+json"

Authenticating the POST request

To authenticate the request, you’ll need to use, or generate, a new personal access token that has access to the repository you’re working with. That token must have the repo scope provided to it.

To understand how to do that, you can follow the steps outlined in the GitHub documentation.

Once you have your token, we’ll update our curl command by adding an Authorization header as follows:

-H "Authorization: token your-token-here"

Adding an event_type

The last part of building our request is to define the event_type property in the POST body.

event_typeStringRequired webhook event name

In this example, we’ll name our event “do-something”.

To add our POST body in JSON format, we can use the following snippet:

--data '{"event_type": "do-something"}'

Building the final curl command

With all of our command components defined, we can build our final curl command like this:

curl -H "Accept: application/vnd.github.everest-preview+json" \
    -H "Authorization: token <your-token-here>" \
    --request POST \
    --data '{"event_type": "do-something"}' \
    https://api.github.com/repos/n8ebel/GitHubActionsAutomationSandbox/dispatches

When we run this command, a webhook event will be received by our repository. To manually trigger a GitHub actions workflow from this webhook event, we can update our action to respond to the repository_dispatch trigger.

Responding to the repository_dispatch event in a GitHub Actions workflow

Responding to the repository_dispatch trigger in our workflow requires a small update as seen in the following snippet:

name: Do Something That Needs Scheduled

on:
  repository_dispatch:
    types: do-something
  schedule:
    - cron:  '*/5 * * * *'

jobs:
  ...

In the on: block of our workflow configuration, we’ve added repository_dispatch. Additionally, we’ve passed a type which matches the event_type we specified in our curl command.

At this point, we’ve done it! We can now manually trigger our GitHub actions workflow using curl from the command line.

If we do not specify the types property of the repository_dispatch trigger, our workflow will run in response to any repository_dispatch event. Specifying the type enables us to control which workflows are run when we send the repository_dispatch event.

Sending data to your triggered workflow

At this point, our GitHub actions workflow is only using the event_type property of the repository_dispatch event. However, that event also has a client_payload property we can use to add additional data with which to customize our workflow.

client_payloadObjectA JSON field to pass additional data

With this client_payload property, we can pass configuration values, text, etc.

Let’s imagine we want to send some simple text with our repository_dispatch event and then print that text out during our workflow.

To start, we can update the body of our POST request to include a client_payload JSON object that includes a text property as in the following example:

{
  "event_type": "do-something",
  "client_payload": {
    "text": "a title"
  }
}

We can add this updated POST body JSON to our existing curl command to end up with something like the following:

curl -H "Accept: application/vnd.github.everest-preview+json" \
    -H "Authorization: token <your-token-here>" \
    --request POST \
    --data '{"event_type": "do-something", "client_payload": { "text": "a title"}}' \
    https://api.github.com/repos/n8ebel/GitHubActionsAutomationSandbox/dispatches

Now, when our workflow receives this event, it will contain this additional data which we can then use within the workflow.

For example, to print out the value of our client_payload.text property, we can add an additional workflow step which accesses that property using the following syntax:

github.event.client_payload.text

The full task to print this value during the execution of our workflow might look something like this:

- name: Do Something Based On Triggered Event Data
        run: 'echo "Event text: ${{ github.event.client_payload.text }}"'

When the repository_dispatch event is received, and this step is run, we will see the passed text value printed out to the workflow output as in this screenshot:

The full workflow will now look something like the following:

name: Do Something That Needs Scheduled

on:
  repository_dispatch:
    types: do-something
  schedule:
    - cron:  '*/5 * * * *'

jobs:
  build:
    name: Run Some Scheduled Thing
    runs-on: ubuntu-latest
    steps:

      - name: Do Something
        run: echo Doing Something...

      - name: Do Something Based On Triggered Event Data
        run: 'echo "Triggered event text: ${{ github.event.client_payload.text }}"'

Conclusion

In this post, we’ve walked through how to manually trigger a GitHub Actions workflow using curl from the command line.

We saw how we could update an existing workflow, running on a schedule, to respond to repository_dispatch events so they can be triggered manually.

Finally, we explored how to pass additional data to our workflows using the client_payload property of the repository_dispatch event enabling us to dynamically control the output of our workflows based on what data we send when manually triggering the workflow.

In a future post, we’ll explore a more practical example of how the client_payload property could be a helpful tool in our CI pipeline.

To learn more about using GitHub Actions, check out my talk from Øredev 2019.

To learn how to trigger your workflows using Postman, check out the followup post.


I love to meet/talk/discuss and help where I can. If you want to chat or ask a question feel free to reach out via Twitter, YouTube, and LinkedIn.

Check Out My YouTube Channel



Categories: DevOps, Software Development

Tags: , ,

12 replies

  1. Thanks for the write up. This only works for the master branch, though right?

  2. This doesn’t seem to work. Can you please help?

  3. Really useful, thank you.

  4. Hi all!

    I’m hoping posting here won’t be a problem.

    I wanted to share a small project that I’ve been working on with a buddy that solves this problem.

    https://www.actionspanel.app/

    ActionsPanel uses this same `repository_dispatch` API but does so with a GitHub App token so that you don’t need to worry about managing your own PAT. This also makes it much easier to trigger your actions across teams with multiple people. Then you don’t need to share the PAT with each other or each create your own PATs.

    Based on user requests and feedback, we’ve built in features to specify which branch to send the `repository_dispatch` to, and we’ve even built in a way to inject parameters when you want to execute the action.

    You configure your buttons with a declarative yaml file that you leave in the repo, and ActionsPanel will read that file and dynamically create your UI for you to trigger your actions.

    We’d love to get your feedback on this project. It’s very simple still but solves the core problem of triggering your actions.

    If you do have feedback or any questions, feel free to post in this thread, or email us directly at support (at) actionspanel (dot) app

    Looking forward to your feedback!

  5. First of all – great write up!

    I have a problem with the repo… seems like the `/dispatches` endpoint is not available on my repo.
    The repo belongs to an organization, not to an individual user, if that makes any difference?

    When I call the endpoint, I get the following error:

    {
    “message”: “Not Found”,
    “documentation_url”: “https://developer.github.com/v3/repos/#create-a-repository-dispatch-event”
    }

Trackbacks

  1. CH Show HN: ActionsPanel – Manually Trigger Your GitHub Actions - CyberHero.TV

Leave a Reply