A small express server to run commands for GitHub webhooks.
git clone
cd github-webhook-handler
npm install
echo "{}" > config.json
npm run start
Deno should be able to run this without modification:
deno run --allow-env --allow-read --allow-net --allow-run index.js
A config.json
file is necessary. It should look like this:
{
"port": 2999,
"secret": "your_secret",
"webhooks": [
{
"path": "/path/to/project/",
"repository": "user/projectName",
"ref": "refs/heads/master",
"command": "git pull; echo $EVENT",
"env": {
"headers.x-github-event": "EVENT"
}
}
]
}
-
port
is the express port the server will be running on. -
secret
is the secret configured in the GitHub webook.- The secret can also be provided via the environment variable
WEBHOOK_SECRET
.
- The secret can also be provided via the environment variable
-
verbosity
allows controlling which output is logged.log
adds default logging (which webhooks are executed, etc.) as well as error logging for executed commands (default)verbose
is the same aslog
, but also logs standout output of executed commandsall
is the same asverbose
, but also logs the full body of unmatched requestswarn
skip all logging, except warnings and error logging for executed commandserror
skip all logging, except error logging for executed commandsnone
disables all logging
-
webhooks
is an array of objects with the propertiespath
(absolute path of the project folder; will be the user's home folder by default)command
(command which to run in the project folder, e.g.git pull
)- A webhook can also have a separate GitHub
secret
configured to override the global secret. - A webhook can also have a separate GitHub
verbosity
configured to override the global verbosity. - A webhook can also have a
filter
property where the keys are key paths on thereq
object (likeheaders.x-github-event
orbody.action
). The values will be compared and only if all filters match, the webook is executed. - There are multiple shortcuts for these filters that can be given directly in the webhook object (not the filter object):
repository
(will be moved intofilter["body.repository.full_name"]
), e.g. "gbv/cocoda"event
(will be moved intofilter["headers.x-github-event"]
), e.g. "release"action
(will be moved intofilter["body.action"]
), e.g. "released"ref
(will be moved intofilter["body.ref"]
), e.g. "refs/heads/dev"
skipReleaseCheck
(see below)skipValidation
(allows skipping validation if no secret is given)- It is also possible to provide environment variables based on the
req
object for the command. These are defined as an objectenv
where the keys are key paths onreq
(like infilter
) and the values are the names of the variable that will be set before exectuing the command.- In the example above, the "x-github-event" header will be made available as
$EVENT
.
- In the example above, the "x-github-event" header will be made available as
If event
is set to "release" and action
is set to "released" or "published", the release version number is checked against the package.json
file in path
, if it exists. If it is a new major release or a downgrade (compared to the local version), the command is not executed. This behavior can be overridden by setting skipReleaseCheck
to true
on the webhook.
It is possible to configure webhooks without signature validation. Experimental feature! Please use with caution! To use this, do not configure a secret (or if a global secret is configured, set the webhook's secret to an empty string) and set skipValidation
to true
.
- Status 200 (OK) will be returned when a matching webhook was found (the command itself is run asynchronously, so a failed command will not return an error code).
- Status 400 (Bad Request) will be returned when there is an issue parsing the request body.
- Status 403 (Forbidden) will be returned when there was a matching webhook, but the signature could not be validated.
- Status 404 (Not Found) will be returned when no matching webhook was found.
It's necessary to select application/json
content type.