GitHub Pull Requests Webhook¶
Route & Auth¶
| Property | Value |
|---|---|
| Method | POST |
| Path | /webhooks/github/pull-requests |
| Auth type | sha256 |
| Header | X-Hub-Signature-256 |
| Secret | GITHUB_PULL_REQUESTS_WEBHOOK_SECRET |
| Service account | github-webhook@alan-eu-tools.iam.gserviceaccount.com |
| Response | 200 OK |
Payload¶
| Field | Type | Description |
|---|---|---|
X-Github-Event |
header | GitHub event type (pull_request or pull_request_review) |
action |
string |
Event action (opened, reopened, ready_for_review, closed, submitted) |
pull_request |
dict |
PR details (number, title, user, draft, merged) |
review |
dict? |
Review details (state, user) — for pull_request_review events |
Behavior¶
PR opened/reopened/ready for review¶
Trigger: pull_request event + opened/reopened/ready_for_review action on non-draft PRs.
Action: Posts a Slack message announcing the new PR.
PR closed¶
Trigger: pull_request event + closed action.
Action: Updates the Slack message with a close reaction. If merged, checks PR compliance (CI checks passed + required reviews).
PR review submitted¶
Trigger: pull_request_review event + submitted action (excludes dismissed reviews, self-reviews, and bot reviews).
Action: Updates the Slack message with a review reaction.
Review digest (scheduled)¶
Trigger: flask github_pr post_review_digest, scheduled twice daily on weekdays
(07:00 and 13:00 Paris) via cron.yaml.
Action: For every crew that opted into the digest (send_pull_request_digest_to_slack),
posts a fresh Block Kit digest of the crew's open non-draft PRs (authored by crew
members) that have a pending review request — i.e. awaiting a first review or
re-requested after changes were addressed; approved/merge-ready PRs and PRs with
unanswered change requests are excluded. PRs are grouped by urgency then sorted by
age. Urgency and risk are parsed from the ## Tags checkboxes in the PR description
template, defaulting to normal when unfilled. Crews with no waiting PRs are skipped.
PRs are fetched via GitHub search scoped to the opted-in crews' members, so when no
crew has opted in the run makes zero GitHub API calls.
This is additive — the per-PR notifications above are unchanged.
Force merge form (Eng Tools)¶
Engineers force merge alan-eu PRs through the Eng Tools form (/github/pulls/force-merge, shareable with ?repo=...&pr=...) instead of GitHub admin rights (the form defaults to alan-apps when given a bare PR number). The API (api.py):
GET /github/repos/<repo>/pull-requests/<pr_number>/merge-readiness— which safeguards (CI, approved review) are satisfiedPOST /github/force-merges— merges with the bot token (the ruleset bypass actor), records aGithubForceMergeaudit row, comments on the PR and announces it in#eng_oncall_operationswith actor + justificationGET /github/force-merges— recent force merges (history table in the form)
PRs force-merged this way are skipped by the compliance alert above (already announced with a justification). A non-compliant merge with no GithubForceMerge row is the anomaly signal.
Integrations¶
- Slack API: message posting, reaction updates
- GitHub API: PR and review details
Code reference¶
{{ package_reference("apps.eu_tools.github_pull_requests.webhook") }}