kaneo (minimalist kanban) fork to experiment adding a tangled integration
github.com/usekaneo/kaneo
1import { getGithubApp } from "./utils/github-app";
2import { handleIssueClosed } from "./webhooks/issue-closed";
3import { handleIssueCommentCreated } from "./webhooks/issue-comment-created";
4import { handleIssueEdited } from "./webhooks/issue-edited";
5import { handleIssueLabeled } from "./webhooks/issue-labeled";
6import { handleIssueOpened } from "./webhooks/issue-opened";
7import { handleLabelCreated } from "./webhooks/label-created";
8import { handlePullRequestClosed } from "./webhooks/pull-request-closed";
9import { handlePullRequestOpened } from "./webhooks/pull-request-opened";
10import { handlePush } from "./webhooks/push";
11
12export async function handleGitHubWebhook(
13 body: string,
14 signature: string,
15 eventName: string,
16 deliveryId: string,
17): Promise<{ success: boolean; error?: string }> {
18 console.log(
19 `[GitHub Webhook] Received event: ${eventName}, delivery: ${deliveryId}`,
20 );
21
22 const githubApp = getGithubApp();
23
24 if (!githubApp) {
25 console.error("[GitHub Webhook] GitHub App not configured");
26 return { success: false, error: "GitHub integration not configured" };
27 }
28
29 try {
30 console.log(`[GitHub Webhook] Verifying and processing ${eventName}...`);
31 await githubApp.webhooks.verifyAndReceive({
32 id: deliveryId,
33 name: eventName as
34 | "issues"
35 | "pull_request"
36 | "push"
37 | "label"
38 | "issue_comment",
39 signature,
40 payload: body,
41 });
42
43 console.log(`[GitHub Webhook] Successfully processed ${eventName}`);
44 return { success: true };
45 } catch (error) {
46 console.error("[GitHub Webhook] Verification/processing failed:", error);
47 return {
48 success: false,
49 error:
50 error instanceof Error ? error.message : "Webhook verification failed",
51 };
52 }
53}
54
55export function setupWebhookHandlers() {
56 const githubApp = getGithubApp();
57
58 if (!githubApp) {
59 console.log("GitHub App not configured, skipping webhook handlers");
60 return;
61 }
62
63 githubApp.webhooks.on("issues.opened", async ({ payload }) => {
64 console.log("[GitHub Webhook] Handling issues.opened");
65 try {
66 await handleIssueOpened(
67 payload as Parameters<typeof handleIssueOpened>[0],
68 );
69 console.log("[GitHub Webhook] issues.opened handled successfully");
70 } catch (error) {
71 console.error("[GitHub Webhook] issues.opened handler error:", error);
72 throw error;
73 }
74 });
75
76 githubApp.webhooks.on("issues.closed", async ({ payload }) => {
77 console.log("[GitHub Webhook] Handling issues.closed");
78 try {
79 await handleIssueClosed(
80 payload as Parameters<typeof handleIssueClosed>[0],
81 );
82 console.log("[GitHub Webhook] issues.closed handled successfully");
83 } catch (error) {
84 console.error("[GitHub Webhook] issues.closed handler error:", error);
85 throw error;
86 }
87 });
88
89 githubApp.webhooks.on("issues.labeled", async ({ payload }) => {
90 console.log("[GitHub Webhook] Handling issues.labeled");
91 try {
92 await handleIssueLabeled(
93 payload as Parameters<typeof handleIssueLabeled>[0],
94 );
95 console.log("[GitHub Webhook] issues.labeled handled successfully");
96 } catch (error) {
97 console.error("[GitHub Webhook] issues.labeled handler error:", error);
98 throw error;
99 }
100 });
101
102 githubApp.webhooks.on("issues.unlabeled", async ({ payload }) => {
103 console.log("[GitHub Webhook] Handling issues.unlabeled");
104 try {
105 await handleIssueLabeled(
106 payload as Parameters<typeof handleIssueLabeled>[0],
107 );
108 console.log("[GitHub Webhook] issues.unlabeled handled successfully");
109 } catch (error) {
110 console.error("[GitHub Webhook] issues.unlabeled handler error:", error);
111 throw error;
112 }
113 });
114
115 githubApp.webhooks.on("issues.edited", async ({ payload }) => {
116 console.log("[GitHub Webhook] Handling issues.edited");
117 try {
118 await handleIssueEdited(
119 payload as Parameters<typeof handleIssueEdited>[0],
120 );
121 console.log("[GitHub Webhook] issues.edited handled successfully");
122 } catch (error) {
123 console.error("[GitHub Webhook] issues.edited handler error:", error);
124 throw error;
125 }
126 });
127
128 githubApp.webhooks.on("push", async ({ payload }) => {
129 console.log("[GitHub Webhook] Handling push");
130 try {
131 await handlePush(payload as Parameters<typeof handlePush>[0]);
132 console.log("[GitHub Webhook] push handled successfully");
133 } catch (error) {
134 console.error("[GitHub Webhook] push handler error:", error);
135 throw error;
136 }
137 });
138
139 githubApp.webhooks.on("pull_request.opened", async ({ payload }) => {
140 console.log("[GitHub Webhook] Handling pull_request.opened");
141 try {
142 await handlePullRequestOpened(
143 payload as Parameters<typeof handlePullRequestOpened>[0],
144 );
145 console.log("[GitHub Webhook] pull_request.opened handled successfully");
146 } catch (error) {
147 console.error(
148 "[GitHub Webhook] pull_request.opened handler error:",
149 error,
150 );
151 throw error;
152 }
153 });
154
155 githubApp.webhooks.on("pull_request.closed", async ({ payload }) => {
156 console.log("[GitHub Webhook] Handling pull_request.closed");
157 try {
158 await handlePullRequestClosed(
159 payload as Parameters<typeof handlePullRequestClosed>[0],
160 );
161 console.log("[GitHub Webhook] pull_request.closed handled successfully");
162 } catch (error) {
163 console.error(
164 "[GitHub Webhook] pull_request.closed handler error:",
165 error,
166 );
167 throw error;
168 }
169 });
170
171 githubApp.webhooks.on("pull_request.reopened", async ({ payload }) => {
172 console.log("[GitHub Webhook] Handling pull_request.reopened");
173 try {
174 await handlePullRequestOpened(
175 payload as Parameters<typeof handlePullRequestOpened>[0],
176 );
177 console.log(
178 "[GitHub Webhook] pull_request.reopened handled successfully",
179 );
180 } catch (error) {
181 console.error(
182 "[GitHub Webhook] pull_request.reopened handler error:",
183 error,
184 );
185 throw error;
186 }
187 });
188
189 githubApp.webhooks.on("label.created", async ({ payload }) => {
190 console.log("[GitHub Webhook] Handling label.created");
191 try {
192 await handleLabelCreated(
193 payload as Parameters<typeof handleLabelCreated>[0],
194 );
195 console.log("[GitHub Webhook] label.created handled successfully");
196 } catch (error) {
197 console.error("[GitHub Webhook] label.created handler error:", error);
198 throw error;
199 }
200 });
201
202 githubApp.webhooks.on("issue_comment.created", async ({ payload }) => {
203 console.log("[GitHub Webhook] Handling issue_comment.created");
204 try {
205 await handleIssueCommentCreated(
206 payload as Parameters<typeof handleIssueCommentCreated>[0],
207 );
208 console.log(
209 "[GitHub Webhook] issue_comment.created handled successfully",
210 );
211 } catch (error) {
212 console.error(
213 "[GitHub Webhook] issue_comment.created handler error:",
214 error,
215 );
216 throw error;
217 }
218 });
219
220 githubApp.webhooks.onError((error) => {
221 console.error("[GitHub Webhook] Error in webhook handler:", error);
222 });
223
224 console.log("✓ GitHub webhook handlers registered");
225}