Why Use GitHub Webhooks?
GitHub webhooks enable real-time automation for your development workflow:
✓ Automated Deployments
Deploy to production when code is pushed to main branch
✓ CI/CD Pipelines
Trigger tests and builds on every pull request
✓ Team Notifications
Send Slack/Discord alerts for new issues or PRs
✓ Custom Automation
Build custom workflows for your team's needs
Step 1: Create Webhook Endpoint
Node.js / Express.js
const express = require('express');
const crypto = require('crypto');
const app = express();
app.post('/webhooks/github',
express.json(),
async (req, res) => {
const signature = req.headers['x-hub-signature-256'];
const event = req.headers['x-github-event'];
const payload = req.body;
// Verify signature (we'll add this next)
if (!verifySignature(signature, JSON.stringify(payload))) {
return res.sendStatus(401);
}
console.log(`Received ${event} event`);
res.sendStatus(200);
}
);
app.listen(3000);Step 2: Configure Webhook in GitHub
- 1.Go to your repository → Settings → Webhooks → Add webhook
- 2.Enter Payload URL:
https://yourapp.com/webhooks/github - 3.Content type:
application/json - 4.Generate a secret (random string) and save it securely
- 5.Select events: "Just the push event" or "Let me select individual events"
- 6.Click "Add webhook"
Step 3: Verify Webhook Signatures
Signature Verification
const crypto = require('crypto');
function verifySignature(signature, payload) {
const secret = process.env.GITHUB_WEBHOOK_SECRET;
// Compute expected signature
const hmac = crypto.createHmac('sha256', secret);
const expectedSignature = 'sha256=' + hmac.update(payload).digest('hex');
// Timing-safe comparison
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
app.post('/webhooks/github',
express.json(),
async (req, res) => {
const signature = req.headers['x-hub-signature-256'];
const payload = JSON.stringify(req.body);
if (!verifySignature(signature, payload)) {
console.error('Invalid signature');
return res.sendStatus(401);
}
// Process webhook...
res.sendStatus(200);
}
);Step 4: Handle Webhook Events
Event Handling Example
app.post('/webhooks/github',
express.json(),
async (req, res) => {
const signature = req.headers['x-hub-signature-256'];
const event = req.headers['x-github-event'];
const payload = req.body;
if (!verifySignature(signature, JSON.stringify(payload))) {
return res.sendStatus(401);
}
switch (event) {
case 'push':
await handlePush(payload);
break;
case 'pull_request':
await handlePullRequest(payload);
break;
case 'issues':
await handleIssue(payload);
break;
case 'release':
await handleRelease(payload);
break;
default:
console.log(`Unhandled event: ${event}`);
}
res.sendStatus(200);
}
);
async function handlePush(payload) {
const branch = payload.ref.replace('refs/heads/', '');
const commits = payload.commits;
console.log(`Push to ${branch}: ${commits.length} commits`);
// Trigger deployment for main branch
if (branch === 'main') {
await triggerDeployment({
branch,
commit: payload.after,
pusher: payload.pusher.name
});
}
}
async function handlePullRequest(payload) {
const action = payload.action; // opened, closed, synchronize
const pr = payload.pull_request;
if (action === 'opened') {
console.log(`New PR #${pr.number}: ${pr.title}`);
await runTests(pr.head.sha);
}
}Common GitHub Events
pushCode pushed to repositorypull_requestPR opened, closed, or updatedissuesIssue created or updatedreleaseRelease publishedworkflow_runGitHub Actions workflow completedReal-World Use Cases
Automated Deployments
Deploy to production when code is pushed to the main branch:
async function handlePush(payload) {
const branch = payload.ref.replace('refs/heads/', '');
if (branch === 'main') {
await deployToProduction({
commit: payload.after,
author: payload.pusher.name
});
}
}PR Notifications
Send Slack notifications when PRs are opened:
async function handlePullRequest(payload) {
if (payload.action === 'opened') {
await sendSlackMessage({
text: `New PR: ${payload.pull_request.title}`,
url: payload.pull_request.html_url,
author: payload.pull_request.user.login
});
}
}Best Practices
Always verify signatures
Prevent unauthorized webhook requests
Process asynchronously
Return 200 quickly, queue long-running tasks
Handle idempotency
GitHub may send duplicate webhooks
Simplify GitHub Webhook Management
hookVM provides a dashboard to inspect, replay, and debug GitHub webhooks. Perfect for CI/CD automation.