GitHub
Trigger workflows from GitHub events like push, pull requests, and issues.
The GitHub trigger receives events from a GitHub repository or organization webhook. Push, PR, issue, and any of the 60+ GitHub event types fire the workflow with the full event payload preserved.
How to configure
- On the GitHub repository (or org) open Settings → Webhooks → Add webhook. Paste the Webhook URL from the trigger as the
Payload URLand selectapplication/jsonas the content type. - Generate a strong random string and paste it into BOTH the GitHub Secret field AND the trigger's Signing secret. GitHub signs the raw body with HMAC-SHA256 and sends
X-Hub-Signature-256: sha256=<hex>. With a secret configured the trigger default-denies — bad signatures get401. - Pick the events you care about (
Just the push event, or Let me select individual events forPull requests,Issues, etc.). The trigger normalizes them — read<github1.event_type>forpull_request/push/ etc., and<github1.action>foropened/closed/synchronize. - Click Add webhook. GitHub immediately sends a
pingdelivery — the trigger ACKs it without firing the workflow. To verify, push a commit or open a PR; Recent Deliveries in GitHub should show200within seconds. Re-deliver from the GitHub UI to replay during testing.
Signature format
| Header | Value |
|---|---|
X-Hub-Signature-256 | sha256=<hex> HMAC-SHA256 over the raw request body |
X-GitHub-Event | The event type (push, pull_request, issues, ping, …) |
X-GitHub-Delivery | UUID per delivery; used as the webhook_event_dedup key |
ping events are auto-acknowledged with 200 and do not fire the workflow. All other events are deduped on X-GitHub-Delivery, so GitHub's redelivery feature is idempotent.
Sample payload (pull_request.opened)
{
"action": "opened",
"number": 42,
"pull_request": {
"id": 1234567890,
"node_id": "PR_kwDOABCDE",
"number": 42,
"state": "open",
"title": "Add OAuth refresh token rotation",
"user": { "login": "octocat", "id": 583231, "type": "User" },
"body": "Closes #41. Rotates refresh tokens on every access-token mint.",
"created_at": "2026-04-26T20:00:00Z",
"updated_at": "2026-04-26T20:00:00Z",
"head": {
"label": "octocat:feat/oauth-rotation",
"ref": "feat/oauth-rotation",
"sha": "abcdef1234567890abcdef1234567890abcdef12"
},
"base": {
"label": "octocat:main",
"ref": "main",
"sha": "1111111111111111111111111111111111111111"
},
"draft": false,
"merged": false,
"additions": 142,
"deletions": 17,
"changed_files": 6
},
"repository": {
"id": 987654321,
"name": "hello-world",
"full_name": "octocat/hello-world",
"private": false,
"html_url": "https://github.com/octocat/hello-world",
"default_branch": "main",
"owner": { "login": "octocat", "id": 583231, "type": "User" }
},
"sender": { "login": "octocat", "id": 583231, "type": "User" }
}For push events, commits[] and head_commit are present at the top level; <github1.branch> is derived from ref.
Verify with the bundled scripts
bun apps/sat/tests/staging/triggers/github/verify.ts \
https://mybotbox.com/api/webhooks/trigger/<path> \
--secret=<github-webhook-secret> \
--event=pull_requestpython3 apps/sat/tests/staging/triggers/github/verify.py \
https://mybotbox.com/api/webhooks/trigger/<path> \
--secret=<github-webhook-secret> \
--event=pull_request--event= defaults to pull_request; pass push, issues, etc. to swap the X-GitHub-Event header. Source: apps/sat/tests/staging/triggers/github/.
Troubleshooting
401on every delivery — secret in GitHub's webhook settings does not match the trigger's signing-secret. TheX-Hub-Signature-256header value GitHub computes uses the secret you save, not the previous one.- Workflow runs twice for one push — confirm the GitHub webhook isn't installed at both repo and org level pointing at the same trigger. Otherwise
webhook_event_dedupshould already collapse duplicates byX-GitHub-Delivery. pingevent silent — that's intentional; the trigger replies200to GitHub's ping but does not fire the workflow. To test the workflow itself, redeliver a real event from Recent Deliveries.- Missing fields in
<github1.action>— only event types likepull_request/issuescarryaction.pushdoes not — branch on<github1.event_type>instead.