hugex-gh / app /routes /webhook.github.tsx
drbh
fix: improve token rention
c202a37
import { json } from "@remix-run/node";
import type { ActionFunctionArgs } from "@remix-run/node";
import { githubApp } from "~/lib/github-app.server";
import { hugexService } from "~/lib/hugex-service.server";
import type { HugExJobCreationParams } from "~/lib/hugex-service.server";
export async function action({ request }: ActionFunctionArgs) {
if (request.method !== "POST") {
return json({ error: "Method not allowed" }, { status: 405 });
}
let payload: string;
let eventData: any;
try {
payload = await request.text();
const signature = request.headers.get("x-hub-signature-256") || "";
const event = request.headers.get("x-github-event") || "";
const delivery = request.headers.get("x-github-delivery") || "";
console.log(`πŸ“₯ Received GitHub webhook: ${event} (${delivery})`);
// // Verify webhook signature
// if (!githubApp.verifyWebhookSignature(payload, signature)) {
// console.error("Invalid webhook signature");
// return json({ error: "Invalid signature" }, { status: 401 });
// }
try {
eventData = JSON.parse(payload);
} catch (parseError) {
console.error("Failed to parse webhook payload:", parseError);
return json({ error: "Invalid JSON payload" }, { status: 400 });
}
// Only log event data for specific events we care about
if (["installation", "installation_repositories"].includes(event)) {
console.log("Event data:", JSON.stringify(eventData, null, 2));
}
// Handle different webhook events
switch (event) {
case "installation":
await handleInstallationEvent(eventData);
break;
case "installation_repositories":
await handleInstallationRepositoriesEvent(eventData);
break;
case "push":
await handlePushEvent(eventData);
break;
case "pull_request":
await handlePullRequestEvent(eventData);
break;
case "issues":
await handleIssuesEvent(eventData);
break;
default:
console.log(`Unhandled event type: ${event}`);
}
return json({ success: true, event, delivery });
} catch (error) {
console.error("Webhook error:", error);
return json({ error: "Internal server error" }, { status: 500 });
}
}
async function handleInstallationEvent(data: any) {
const { action, installation, repositories } = data;
console.log(`πŸ”§ Installation ${action}:`, {
installationId: installation.id,
account: installation.account.login,
repositoryCount: repositories?.length || 0,
});
if (action === "created") {
// App was installed - you can store installation info here
console.log(`βœ… App installed by ${installation.account.login}`);
} else if (action === "deleted") {
// App was uninstalled
console.log(`❌ App uninstalled by ${installation.account.login}`);
}
}
async function handleInstallationRepositoriesEvent(data: any) {
const { action, installation, repositories_added, repositories_removed } =
data;
console.log(`πŸ“ Installation repositories ${action}:`, {
installationId: installation.id,
added: repositories_added?.length || 0,
removed: repositories_removed?.length || 0,
});
}
async function handlePushEvent(data: any) {
const { repository, pusher, commits } = data;
console.log(`πŸš€ Push to ${repository.full_name}:`, {
pusher: pusher.name,
commits: commits.length,
branch: data.ref.replace("refs/heads/", ""),
});
// Example: Use the pusher's authenticated session
try {
const userAuth = githubApp.getUserAuth(pusher.name);
if (userAuth) {
console.log(`πŸ”‘ Found authenticated user: ${pusher.name}`);
const environment = {
LLM_MODEL: "gpt-4",
LLM_PROVIDER: "openai",
};
const secrets = {
OPENAI_API_KEY: "sk-test", //userAuth.token, // Use the user's token for authentication
};
const params = {
title: `Push by ${pusher.name} to ${repository.full_name}`,
description: `New push to ${repository.full_name} by ${pusher.name}`,
repository: {
url: repository.html_url,
},
branch: data.ref.replace("refs/heads/", ""),
environment,
secrets,
};
console.log("Creating HugEx job with params:", params);
// Create HugEx job
const jobId = await hugexService.createJob(pusher.name, params);
if (jobId) {
console.log(`βœ… Created HugEx job for push event: ${jobId}`);
} else {
console.warn(
`⚠️ Failed to create HugEx job for push event by ${pusher.name}`
);
}
} else {
console.log(`⚠️ No authentication found for user: ${pusher.name}`);
}
} catch (error) {
console.error("Error handling push event:", error);
}
}
async function handlePullRequestEvent(data: any) {
const { action, pull_request, repository } = data;
console.log(`πŸ”€ Pull request ${action} in ${repository.full_name}:`, {
number: pull_request.number,
title: pull_request.title,
author: pull_request.user.login,
});
// Example: Use the PR author's authenticated session
try {
const userAuth = githubApp.getUserAuth(pull_request.user.login);
if (userAuth) {
console.log(`πŸ”‘ Found authenticated user: ${pull_request.user.login}`);
// You can now use the user's authentication to perform actions
} else {
console.log(
`⚠️ No authentication found for user: ${pull_request.user.login}`
);
}
} catch (error) {
console.error("Error handling pull request event:", error);
}
}
async function handleIssuesEvent(data: any) {
const { action, issue, repository } = data;
console.log(`πŸ› Issue ${action} in ${repository.full_name}:`, {
number: issue.number,
title: issue.title,
author: issue.user.login,
});
// Process issue for HugEx if action is 'opened' or 'edited'
if (["opened", "edited"].includes(action)) {
try {
// Check for @hugex mention and create job if found
const jobCreated = await hugexService.processGitHubIssue(
issue,
repository
);
if (jobCreated) {
console.log(`βœ… Created HugEx job for issue #${issue.number}`);
}
} catch (error) {
console.error("Error processing issue for HugEx:", error);
}
}
// Example: Use the issue author's authenticated session
try {
const userAuth = githubApp.getUserAuth(issue.user.login);
if (userAuth) {
console.log(`πŸ”‘ Found authenticated user: ${issue.user.login}`);
// You can now use the user's authentication to perform actions
} else {
console.log(`⚠️ No authentication found for user: ${issue.user.login}`);
}
} catch (error) {
console.error("Error handling issues event:", error);
}
}
// Prevent GET requests
export async function loader() {
return json(
{ error: "This endpoint only accepts POST requests from GitHub webhooks" },
{ status: 405 }
);
}