Invoking webhooks from your Github workflow actions
Tags: github, deployment, productivity
Published: 2020-01-17 09:02:04

Github webhooks are great for triggering deployments (or performing any other task) on certain repository events, such as a push to master. But they can't do so conditionally. For example, you may first want to run some tests and then invoke a webhook only if they passed. In this case you could just run the tests on the webhook implementation itself before doing deployment. However, if you really have to call a webhook only in conjunction with a certain condition (other than the repository event such as a push to master), then you would need additional tooling.

This is where Github Actions can provide a clean workflow solution, which can perform any number of tasks in a pipeline fashion. For more info on Github Action workflows and how to use them, see <https://github.com/features/actions>. Unfortunately, by default, Github  workflows cannot trigger a webhook. There are community developed Actions available from the Github Marketplace which can help in this regard. Of course, they are not official Github webhooks, but an alternate mechanism with which to invoke an endpoint, and in such a way emulate the functionality of a webhook. 

At the time of writing this post, none of the Actions available in the Github Marketplace (that I could find) supported the invocation of webhooks with the same hash signature as that used by official Github webhook calls. This is unfortunate, since one would not be able to re-use any existing webhook signature validation methods. It would be nice if the method for validating an official Github webhook call and those from an Action in a Github workflow were interchangeable. I don't currently have any actual use case that would require a webhook to be called from both, but still it would be nice. 

Since I couldn't find a suitable Action from the Marketplace with such signature validation, I decided to implement one myself. It's available at <https://github.com/marketplace/actions/workflow-webhook-action>. 

This Github workflow action will call a webhook endpoint with a **text/csv** or **json** payload, and has support for BASIC authentication. A hash signature is derived from the payload of the POST along with a configurable secret token, and it is identical to the hash which a regular Github webhook call would generate. This signature is sent in a header named **X-Hub-Signature**, therefore any existing Github webhook signature validation will continue to work. For more information on how to validate the signature, see <https://developer.github.com/webhooks/securing>.

By default, the values of the following workflow environment variables are sent in the payload: GITHUB_REPOSITORY, GITHUB_REF, GITHUB_SHA, GITHUB_EVENT_NAME and GITHUB_WORKFLOW. Additional data can also added to the payload along with these.

This post won't go into the details of how to configure a Github Action workflow, but as a simple example, to configure your workflow to invoke a webhook, you can add something like this to your workflow configuration file:

```yml
    - name: Invoke deployment hook
      uses: distributhor/workflow-webhook@v1
      env:
        webhook_url: ${{ secrets.WEBHOOK_URL }}
        webhook_secret: ${{ secrets.WEBHOOK_SECRET }}
```

Which will deliver a payload with the following properties:

```json
{
    "repository": "owner/project",
    "ref": "refs/heads/master",
    "commit": "a636b6f0861bbee98039bf3df66ee13d8fbc9c74",
    "event": "push",
    "workflow": "Build and deploy"
}
```

For more details on configuration and all the available options, visit the official page for the Github Action at <https://github.com/marketplace/actions/workflow-webhook-action>.