Skip to content

Commit 4536458

Browse files
feat(github): auto-register webhook on repo connect
- Add webhookId column to github_integration schema + migration - Register GitHub Issues webhook automatically when a repo is connected - Delete and re-register webhook if the repo is changed - Store webhookId and generated webhookSecret on the integration record - Add registerGitHubWebhook and deleteGitHubWebhook utils to github.ts Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 5275615 commit 4536458

6 files changed

Lines changed: 2891 additions & 0 deletions

File tree

server/api/projects/[slug]/github.put.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { githubIntegration } from '~/server/database/schema/feedback'
55
import { createErrorResponse, createSuccessResponse, ErrorCode } from '~/server/utils/response'
66
import { requireProjectCategoryAccess } from '~/server/utils/project-categories'
77
import { validateBody } from '~/server/utils/validation'
8+
import { registerGitHubWebhook, deleteGitHubWebhook } from '~/server/utils/github'
89

910
const updateGithubIntegrationSchema = z.object({
1011
repoFullName: z
@@ -46,6 +47,8 @@ export default defineEventHandler(async (event) => {
4647

4748
const now = new Date()
4849

50+
const webhookUrl = `${getRequestURL(event).origin}/api/github/webhook`
51+
4952
if (existing) {
5053
const [conflict] = await db
5154
.select()
@@ -61,12 +64,26 @@ export default defineEventHandler(async (event) => {
6164
})
6265
}
6366

67+
// Re-register webhook if the repo has changed
68+
const repoChanged = existing.owner !== owner || existing.repo !== repo
69+
const tokenForWebhook = (accessToken !== null ? accessToken : existing.accessToken) as string | null
70+
let webhookFields: { webhookId: string; webhookSecret: string } | null = null
71+
72+
if (repoChanged && tokenForWebhook) {
73+
// Delete webhook from old repo (best-effort)
74+
if (existing.webhookId && existing.accessToken) {
75+
await deleteGitHubWebhook(existing.owner, existing.repo, existing.webhookId, existing.accessToken)
76+
}
77+
webhookFields = await registerGitHubWebhook(owner, repo, tokenForWebhook, webhookUrl)
78+
}
79+
6480
const [updated] = await db
6581
.update(githubIntegration)
6682
.set({
6783
owner,
6884
repo,
6985
...(accessToken !== null && { accessToken }),
86+
...(webhookFields && { webhookId: webhookFields.webhookId, webhookSecret: webhookFields.webhookSecret }),
7087
...(body.syncEnabled !== undefined && { syncEnabled: body.syncEnabled }),
7188
...(body.autoCreateIssues !== undefined && { autoCreateIssues: body.autoCreateIssues }),
7289
...(body.autoSyncStatus !== undefined && { autoSyncStatus: body.autoSyncStatus }),
@@ -91,6 +108,7 @@ export default defineEventHandler(async (event) => {
91108
autoCreateIssues: updated.autoCreateIssues,
92109
autoSyncStatus: updated.autoSyncStatus,
93110
hasAccessToken: Boolean(updated.accessToken),
111+
webhookRegistered: Boolean(updated.webhookId),
94112
updatedAt: updated.updatedAt,
95113
})
96114
}
@@ -109,6 +127,8 @@ export default defineEventHandler(async (event) => {
109127
})
110128
}
111129

130+
const webhook = await registerGitHubWebhook(owner, repo, accessToken!, webhookUrl)
131+
112132
const [created] = await db
113133
.insert(githubIntegration)
114134
.values({
@@ -117,6 +137,8 @@ export default defineEventHandler(async (event) => {
117137
owner,
118138
repo,
119139
accessToken: accessToken!,
140+
webhookId: webhook.webhookId,
141+
webhookSecret: webhook.webhookSecret,
120142
syncEnabled: body.syncEnabled ?? true,
121143
autoCreateIssues: body.autoCreateIssues ?? false,
122144
autoSyncStatus: body.autoSyncStatus ?? true,
@@ -142,6 +164,7 @@ export default defineEventHandler(async (event) => {
142164
autoCreateIssues: created.autoCreateIssues,
143165
autoSyncStatus: created.autoSyncStatus,
144166
hasAccessToken: Boolean(created.accessToken),
167+
webhookRegistered: Boolean(created.webhookId),
145168
updatedAt: created.updatedAt,
146169
})
147170
})
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE "github_integration" ADD COLUMN "webhook_id" text;

0 commit comments

Comments
 (0)