GitHub Actions workflows side effects

Sponsored
RevenueCat logo
RevenueCat Paywalls

Add paywalls to your iOS app's in one line of code! With RevenueCat Paywalls you can remotely configure and edit your entire paywall view without waiting on App Review.

One of the features that I like the most about GitHub Actions is the number of different events that you can use to trigger a workflow.

Triggers are defined using the on rule in the workflow file and there is a wide range of options available such as pushes to all or specific branches or changes to a pull request.

I recently learnt, thanks to this tweet from James Sherlock, that you can also use GitHub webhook events to trigger workflow runs. I have since used one of GitHub’s available webhook events to trigger a workflow based on the completion of another workflow.

The workflow James refers to in his tweet is used in the Swift Package Index project to generate PRs from issues using the issues event as a trigger.

If you’d like to find out which events are available to trigger a GitHub Actions workflow, check out this page in the GitHub Actions documentation.

What is a webhook?

Webhooks are automated messages that a website sends to a URL based on the occurrence of specific events. For example, when a workflow finishes running, GitHub sends a workflow_url event to the URL configured to receive such events.

GitHub webhooks are configurable on a per-repository basis and provide a great way to build custom integrations and automations. If you want a more in-depth example of a practical use case which involves webhooks and Xcode Cloud check out this article on my blog.

Triggering a workflow based on the workflow_run event

While webhooks can be very powerful, building integrations with them is not straightforward. They are POST network requests with a payload containing context and information about the action which triggered the event and hence require you to build, set up and maintain a back-end service that can receive POST network requests, parse their bodies and perform a set of actions when needed.

The great news is that GitHub Actions provide a way to define a webhook event as the trigger or start condition for a workflow directly from the definition file, which removes the need to build and maintain a back-end service 🎉.

In my specific use case, I want to set up a workflow that runs after a specific workflow or set of workflows finish executing, which is as simple as:

  1. Adding the workflow_run event to the on rule in the workflow file. This is the same you would do if you were using a different event such as push or pull_request.
  2. Filtering the event based on the workflow_run’s activity types. Out of the three available types (completed, requested and in_progress), I am only interested in the completed activity type.
  3. Specifying the workflow name to trigger on. This is required and in my case, I am only interested in triggering the log workflow when the Lint workflow completes.
.github/workflows/log.yml
name: Log workflow run metrics
on:
  workflow_run:
    workflows: [Lint]
    types:
      - completed
jobs:
  log:
    runs-on: macos-latest
    env:
      ANALYTICS_ENDPOINT: ${{ secrets.ANALYTICS_ENDPOINT }}
    steps:
      - uses: actions/checkout@v3
        with:
          repository: polpielladev/metrics
      - run: |
          swift run GithubActionsMetricsCLI \
            "${{ github.event.workflow_run.name }}" \
            "${{ github.event.workflow_run.updated_at }}" \
            "${{ github.event.workflow_run.run_started_at }}" \
            "${{ github.event.workflow_run.head_repository.name }}" \
            "${{ github.event.workflow_run.conclusion }}" \
            "${{ github.event.workflow_run.head_commit.author.name }}"

As part of its execution, the workflow above checks out an external repository and then runs a script to log metrics from the Lint’s workflow run to a third-party service.

As you can see in the code above, the workflow can access the webhook payload data using the github.event.workflow_run context variable and pass the relevant information from the event to the metrics script.