|
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})`); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try { |
|
eventData = JSON.parse(payload); |
|
} catch (parseError) { |
|
console.error("Failed to parse webhook payload:", parseError); |
|
return json({ error: "Invalid JSON payload" }, { status: 400 }); |
|
} |
|
|
|
|
|
if (["installation", "installation_repositories"].includes(event)) { |
|
console.log("Event data:", JSON.stringify(eventData, null, 2)); |
|
} |
|
|
|
|
|
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") { |
|
|
|
console.log(`β
App installed by ${installation.account.login}`); |
|
} else if (action === "deleted") { |
|
|
|
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/", ""), |
|
}); |
|
|
|
|
|
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", |
|
}; |
|
|
|
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); |
|
|
|
|
|
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, |
|
}); |
|
|
|
|
|
try { |
|
const userAuth = githubApp.getUserAuth(pull_request.user.login); |
|
if (userAuth) { |
|
console.log(`π Found authenticated user: ${pull_request.user.login}`); |
|
|
|
} 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, |
|
}); |
|
|
|
|
|
if (["opened", "edited"].includes(action)) { |
|
try { |
|
|
|
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); |
|
} |
|
} |
|
|
|
|
|
try { |
|
const userAuth = githubApp.getUserAuth(issue.user.login); |
|
if (userAuth) { |
|
console.log(`π Found authenticated user: ${issue.user.login}`); |
|
|
|
} else { |
|
console.log(`β οΈ No authentication found for user: ${issue.user.login}`); |
|
} |
|
} catch (error) { |
|
console.error("Error handling issues event:", error); |
|
} |
|
} |
|
|
|
|
|
export async function loader() { |
|
return json( |
|
{ error: "This endpoint only accepts POST requests from GitHub webhooks" }, |
|
{ status: 405 } |
|
); |
|
} |
|
|