Deploy hooks
A deploy hook is a URL you call every time you ship. When something breaks, the incident shows what you deployed in the 30 minutes before it, so "was it the release?" already has an answer.
What you get
- Deploys on the incident timeline. Anything you shipped in the 30 minutes before an incident shows up on it, marked as a deploy.
- A quiet window after each deploy. Error-rate alerts hold off for 90 seconds, so the errors of a normal restart don't page anyone.
- Deploy stats on your dashboard. Every deploy is an event, so a Bar chart or an Activity calendar can count them per day.
What counts as a deploy
An event whose name starts with deploy or contains deployment. Vercel's events are already named that way, and the GitHub step below sends deploy. Any other event still arrives and still shows on the timeline, it just isn't treated as a deploy.
Vercel
- On the Connect page, press Deploy hooks and copy the URL.
- In Vercel, open your team's Settings, then Webhooks, and create a webhook with that URL.
- Pick Deployment Succeeded and Deployment Error, then choose the projects it covers.
GitHub Actions
Save the URL as a repository secret named UPCONTROL_HOOK_URL, then add this step at the end of your deploy job:
- name: Tell upcontrol the deploy finishedif: success()continue-on-error: truerun: |curl -fsS -m 10 -X POST "${{ secrets.UPCONTROL_HOOK_URL }}" \-H "Content-Type: application/json" \-d '{"event":"deploy","sha":"${{ github.sha }}"}'
continue-on-errormeans an upcontrol outage can never fail your deploy.if: success()skips the call when the job failed, so a deploy that never shipped isn't recorded.-m 10gives up after 10 seconds, so a slow answer never holds the runner.
Why not a repository webhook
It works, but its events arrive under names like github_completed or github_created, which don't count as deploys. The step above sends deploy exactly when you ship.
Any other CI or script
POST JSON to the same URL. The event field names the event, and every other string field is kept as a label:
curl -fsS -m 10 -X POST "$UPCONTROL_HOOK_URL" \-H "Content-Type: application/json" \-d '{"event":"deploy","env":"production"}'
Checking it worked
Ship once. The Deploy hooks panel on the Connect page shows what arrived and when, for example: Received vercel_deployment.succeeded · 5s ago.
No test button
A test we sent to ourselves would prove nothing about your side. Use Redeliver in Vercel or re-run the workflow instead.
When it does not work
- Nothing arrives
- Check the delivery log in Vercel, or the step's output in GitHub. If they show a delivery and the panel still waits, the URL there isn't the one on the card, so copy it again.
- The URL leaked
- Anyone with the URL can post to it, so keep it in a secret, never in a committed file. Disconnect the source to kill it; connecting again gives you a new URL.
- Same URL every time
- On purpose. A project has one hook and its URL never changes, so nothing you already pasted breaks.
- Paused, but events keep coming
- A paused source answers 200 and drops the event, so Vercel and GitHub don't retry or switch the webhook off.