Skip to content

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 satisfied
  • POST /github/force-merges — merges with the bot token (the ruleset bypass actor), records a GithubForceMerge audit row, comments on the PR and announces it in #eng_oncall_operations with actor + justification
  • GET /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") }}

OpenAPI

GitHub Pull Requests webhook on ReDoc ⧉