Skip to content

Commit

Permalink
feat: Added Listeners for github webhooks
Browse files Browse the repository at this point in the history
  • Loading branch information
noahonyejese committed Jan 6, 2025
1 parent 1821630 commit e12db3f
Show file tree
Hide file tree
Showing 2 changed files with 149 additions and 0 deletions.
124 changes: 124 additions & 0 deletions app/api/github/events/projects/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { verifyGitHubRequest } from '@/server/security';
import { createError } from '@/utils/error-handling';
import { NextRequest, NextResponse } from 'next/server';

export const POST = async (req: NextRequest) => {
try {
const rawBody = await req.text();

if (!verifyGitHubRequest(rawBody, req)) {
throw createError({
title: 'Invalid GitHub signature',
message: 'The request signature is invalid',
});
}

const body = JSON.parse(rawBody);
const event = req.headers.get('x-github-event');

switch (event) {
case 'ping':
return NextResponse.json({
status: 'success',
message: 'Pong!',
});

case 'create':
console.log('Create event:', {
ref_type: body.ref_type,
ref: body.ref,
repository: body.repository.full_name,
});
break;

case 'delete':
console.log('Delete event:', {
ref_type: body.ref_type,
ref: body.ref,
repository: body.repository.full_name,
});
break;

case 'check_run':
console.log('Check run event:', {
action: body.action, // created, completed, rerequested
status: body.check_run.status,
conclusion: body.check_run.conclusion,
name: body.check_run.name,
});
break;

case 'deployment_status':
// Deployment status updates
console.log('Deployment status event:', {
action: body.action,
state: body.deployment_status.state,
environment: body.deployment.environment,
});
break;

case 'pull_request_review':
// PR review events
console.log('PR review event:', {
action: body.action,
state: body.review.state,
pr_number: body.pull_request.number,
});
break;

case 'pull_request':
console.log('Pull request event:', {
action: body.action,
number: body.pull_request.number,
state: body.pull_request.state,
merged: body.pull_request.merged,
});
break;

case 'push':
console.log('Push event:', {
ref: body.ref,
commits: body.commits.length,
repository: body.repository.full_name,
});
break;

case 'repository':
console.log('Repository event:', {
action: body.action,
repository: body.repository.full_name,
});
break;

default:
console.log(`Unhandled event type: ${event}`);
}

return NextResponse.json({
success: true,
event: event,
});
} catch (error) {
if (error instanceof Error) {
console.error('Webhook error:', error.message);

return NextResponse.json(
{
success: false,
error: {
message: error.message,
},
},
{ status: 400 }
);
}

return NextResponse.json(
{
success: false,
error: 'Unknown error occurred',
},
{ status: 500 }
);
}
};
25 changes: 25 additions & 0 deletions server/security.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,28 @@ export const verifySlackRequest = (
)
);
};

export const verifyGitHubRequest = (
rawBody: string,
req: NextRequest
): boolean => {
try {
const signature = req.headers.get('x-hub-signature-256');
if (!signature) {
throw new Error('No signature header');
}

const secret = process.env.GITHUB_SIGNITURE_SECRET;
if (!secret) {
throw new Error('GITHUB_WEBHOOK_SECRET is not configured');
}

const hmac = crypto.createHmac('sha256', secret);
const digest = 'sha256=' + hmac.update(rawBody).digest('hex');

return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
} catch (error) {
console.error('Signature verification failed:', error);
return false;
}
};

0 comments on commit e12db3f

Please sign in to comment.