@mastra/factory 0.10.1 → 0.10.2-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/LICENSE.md +6 -4
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +5 -1
- package/dist/factory.js.map +1 -1
- package/dist/integrations/base.d.ts +2 -0
- package/dist/integrations/base.d.ts.map +1 -1
- package/dist/integrations/github/integration.d.ts.map +1 -1
- package/dist/integrations/github/integration.js +2 -1
- package/dist/integrations/github/integration.js.map +1 -1
- package/dist/integrations/github/routes.d.ts +2 -0
- package/dist/integrations/github/routes.d.ts.map +1 -1
- package/dist/integrations/github/routes.js +9 -3
- package/dist/integrations/github/routes.js.map +1 -1
- package/dist/integrations/github/webhook.d.ts.map +1 -1
- package/dist/integrations/github/webhook.js +9 -0
- package/dist/integrations/github/webhook.js.map +1 -1
- package/dist/integrations/platform/github/integration.d.ts.map +1 -1
- package/dist/integrations/platform/github/integration.js +2 -1
- package/dist/integrations/platform/github/integration.js.map +1 -1
- package/dist/integrations/slack/slack.d.ts.map +1 -1
- package/dist/integrations/slack/slack.js +5 -5
- package/dist/integrations/slack/slack.js.map +1 -1
- package/dist/routes/projects.d.ts +3 -0
- package/dist/routes/projects.d.ts.map +1 -1
- package/dist/routes/projects.js +1 -0
- package/dist/routes/projects.js.map +1 -1
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +1 -0
- package/dist/routes/surface.js.map +1 -1
- package/dist/sandbox/session-retirement.d.ts +3 -0
- package/dist/sandbox/session-retirement.d.ts.map +1 -1
- package/dist/sandbox/session-retirement.js +8 -1
- package/dist/sandbox/session-retirement.js.map +1 -1
- package/dist/session/factory-session.d.ts.map +1 -1
- package/dist/session/factory-session.js +2 -0
- package/dist/session/factory-session.js.map +1 -1
- package/dist/session/memory-settings-hydration.d.ts +21 -8
- package/dist/session/memory-settings-hydration.d.ts.map +1 -1
- package/dist/session/memory-settings-hydration.js +27 -9
- package/dist/session/memory-settings-hydration.js.map +1 -1
- package/dist/session/org-seed.d.ts +67 -0
- package/dist/session/org-seed.d.ts.map +1 -0
- package/dist/session/org-seed.js +53 -0
- package/dist/session/org-seed.js.map +1 -0
- package/dist/storage/domains/work-items/base.d.ts +9 -0
- package/dist/storage/domains/work-items/base.d.ts.map +1 -1
- package/dist/storage/domains/work-items/base.js +24 -0
- package/dist/storage/domains/work-items/base.js.map +1 -1
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.js","names":[],"sources":["../../../src/integrations/github/webhook.ts"],"sourcesContent":["import { createHmac, timingSafeEqual } from 'node:crypto';\nimport type { MountedMastraCode } from '@mastra/code-sdk';\nimport type { NotificationPriority } from '@mastra/core/notifications';\nimport { RequestContext } from '@mastra/core/request-context';\nimport type { Context } from 'hono';\nimport { GithubAppIdentity } from './app-identity.js';\nimport type { GithubIntegration, GithubRepositoryPermission } from './integration.js';\nimport { listPullRequestSubscriptionsForWebhook, retirePullRequestSubscription } from './subscriptions.js';\nimport type {\n GithubSignalSubscriptionRow,\n GithubSubscriptionStorage,\n GithubWebhookPullRequestTarget,\n} from './subscriptions.js';\n\nexport interface GithubWebhookHandlerOptions {\n /** Integration providing webhook-secret verification + collaborator permission checks. */\n github: GithubIntegration;\n ingestFactoryEvent?: (event: ParsedGithubWebhook) => Promise<unknown>;\n}\n\nconst SUPPORTED_GITHUB_WEBHOOK_EVENTS = new Set([\n 'issues',\n 'issue_comment',\n 'pull_request',\n 'pull_request_review',\n 'pull_request_review_comment',\n // Direct pushes to the default branch drive base-checkpoint rebuilds. The\n // rules engine and subscription dispatcher both ignore push events.\n 'push',\n]);\n\nexport interface GithubWebhookMetadata {\n event: string;\n action?: string;\n deliveryId: string;\n repository?: string;\n repositoryId?: number;\n issueNumber?: number;\n pullRequestNumber?: number;\n sender?: string;\n senderType?: string;\n installationId?: number;\n}\n\nexport interface ParsedGithubWebhook {\n event: string;\n deliveryId: string;\n payload: Record<string, unknown>;\n}\n\nexport type GithubWebhookResult =\n | { status: 202; body: { ok: true; ignored?: true } }\n | { status: 400; body: { error: 'bad_request'; message: string } }\n | { status: 401; body: { error: 'unauthorized'; message: string } };\n\nexport interface GithubWebhookNotification {\n action: string;\n kind: string;\n priority: NotificationPriority;\n summary: string;\n terminal: boolean;\n metadata: GithubWebhookMetadata & { pullRequestNumber: number; repositoryId: number; installationId: number };\n payload: Record<string, unknown>;\n}\n\n/** The Factory session row fields a woken session has to run as. */\nexport type FactorySessionOwner = { userId: string; orgId: string };\n\n/**\n * The integration surface this dispatch uses. Narrow on purpose: the GitHub App\n * integration and the platform-backed one are unrelated classes, and only this\n * much is common to both.\n */\nexport interface GithubWebhookDispatchIntegration {\n /** App slug, used to recognize Factory's own bot identity. */\n readonly slug?: string;\n /**\n * Resolved identity of the App this integration posts as. Preferred over\n * {@link slug}, which names the deployment's own self-hosted App and is unset\n * on deployments that run against Platform's App.\n */\n readonly identity?: GithubAppIdentity;\n readonly integrationStorage: GithubSubscriptionStorage;\n /**\n * Extra bot logins this deployment authorizes to trigger author-gated\n * notifications, merged over `DEFAULT_AUTHORIZED_BOTS`.\n */\n readonly authorizedBots?: readonly string[];\n readonly sourceControlStorage: {\n sessions: { getBySessionId(sessionId: string): Promise<FactorySessionOwner | null> };\n };\n getRepositoryCollaboratorPermission(\n installationId: number,\n repoFullName: string,\n username: string,\n signal?: AbortSignal,\n ): Promise<GithubRepositoryPermission | undefined>;\n}\n\nexport interface GithubWebhookDispatchDependencies {\n controller: MountedMastraCode['controller'];\n /**\n * Integration used by the default sender-authorization check (collaborator\n * permission lookup) and to resolve the owner of a session being recreated.\n * Author-gated notifications fail closed when neither this nor an\n * `isAuthorizedSender` override is supplied.\n */\n github?: GithubWebhookDispatchIntegration;\n listSubscriptions?: (\n target: GithubWebhookPullRequestTarget,\n options?: { includeTerminal?: boolean },\n ) => Promise<GithubSignalSubscriptionRow[]>;\n retireSubscription?: (id: string, status: 'open' | 'closed' | 'merged') => Promise<void>;\n isAuthorizedSender?: (notification: GithubWebhookNotification) => Promise<boolean>;\n /** Called when the sender gate drops a notification, so the drop is observable. */\n onSenderRejected?: (notification: GithubWebhookNotification) => void;\n onTargetError?: (subscription: GithubSignalSubscriptionRow, error: unknown) => void;\n /** Called when a subscription names a thread this deployment does not hold. */\n onTargetSkipped?: (subscription: GithubSignalSubscriptionRow) => void;\n}\n\nfunction normalizeHeader(value: string | undefined | null): string | null {\n if (!value) return null;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction verifySignature(rawBody: string, signature: string, secret: string): boolean {\n if (!signature.startsWith('sha256=')) return false;\n const signatureHex = signature.slice('sha256='.length);\n if (!/^[a-fA-F0-9]{64}$/.test(signatureHex)) return false;\n\n const expectedHex = createHmac('sha256', secret).update(rawBody).digest('hex');\n const received = Buffer.from(signatureHex, 'hex');\n const expected = Buffer.from(expectedHex, 'hex');\n return received.length === expected.length && timingSafeEqual(received, expected);\n}\n\nasync function parseGithubWebhook(\n c: Context,\n secret: string | undefined,\n): Promise<ParsedGithubWebhook | GithubWebhookResult> {\n if (!secret) {\n return { status: 401, body: { error: 'unauthorized', message: 'GitHub webhook secret is not configured' } };\n }\n\n const event = normalizeHeader(c.req.header('x-github-event'));\n const deliveryId = normalizeHeader(c.req.header('x-github-delivery'));\n const signature = normalizeHeader(c.req.header('x-hub-signature-256'));\n\n if (!event) return { status: 400, body: { error: 'bad_request', message: 'Missing x-github-event header' } };\n if (!deliveryId) return { status: 400, body: { error: 'bad_request', message: 'Missing x-github-delivery header' } };\n if (!signature)\n return { status: 401, body: { error: 'unauthorized', message: 'Missing x-hub-signature-256 header' } };\n\n const rawBody = await c.req.text();\n if (!verifySignature(rawBody, signature, secret)) {\n return { status: 401, body: { error: 'unauthorized', message: 'Invalid GitHub webhook signature' } };\n }\n\n let payload: unknown;\n try {\n payload = JSON.parse(rawBody);\n } catch {\n return { status: 400, body: { error: 'bad_request', message: 'Malformed JSON payload' } };\n }\n\n if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {\n return { status: 400, body: { error: 'bad_request', message: 'Payload must be a JSON object' } };\n }\n\n return { event, deliveryId, payload: payload as Record<string, unknown> };\n}\n\nfunction getObject(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : undefined;\n}\n\nfunction getString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction getNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction getBoolean(value: unknown): boolean | undefined {\n return typeof value === 'boolean' ? value : undefined;\n}\n\nexport function normalizeGithubWebhookMetadata(parsed: ParsedGithubWebhook): GithubWebhookMetadata {\n const { event, deliveryId, payload } = parsed;\n const repository = getObject(payload.repository);\n const issue = getObject(payload.issue);\n const pullRequest = getObject(payload.pull_request);\n const sender = getObject(payload.sender);\n const installation = getObject(payload.installation);\n const issuePullRequest = getObject(issue?.pull_request);\n\n return {\n event,\n action: getString(payload.action),\n deliveryId,\n repository: getString(repository?.full_name),\n repositoryId: getNumber(repository?.id),\n issueNumber: getNumber(issue?.number),\n pullRequestNumber:\n getNumber(pullRequest?.number) ??\n (event === 'issue_comment' && issuePullRequest ? getNumber(issue?.number) : undefined),\n sender: getString(sender?.login),\n senderType: getString(sender?.type),\n installationId: getNumber(installation?.id),\n };\n}\n\nfunction notificationSummary(metadata: GithubWebhookMetadata, label: string): string {\n const actor = metadata.sender ? `${metadata.sender} ` : '';\n return `${actor}${label} on ${metadata.repository}#${metadata.pullRequestNumber}`;\n}\n\nfunction notificationTargetUrl(event: string, payload: Record<string, unknown>): string | undefined {\n if (event === 'issue_comment' || event === 'pull_request_review_comment') {\n return getString(getObject(payload.comment)?.html_url);\n }\n if (event === 'pull_request_review') {\n return getString(getObject(payload.review)?.html_url);\n }\n return getString(getObject(payload.pull_request)?.html_url);\n}\n\nexport function classifyGithubWebhook(parsed: ParsedGithubWebhook): GithubWebhookNotification | undefined {\n const metadata = normalizeGithubWebhookMetadata(parsed);\n const { event, payload } = parsed;\n const action = metadata.action;\n if (\n !action ||\n !metadata.repositoryId ||\n !metadata.installationId ||\n !metadata.pullRequestNumber ||\n !metadata.repository\n ) {\n return undefined;\n }\n\n let priority: NotificationPriority;\n let kind: string;\n let label: string;\n let terminal = false;\n\n if (event === 'pull_request_review' && action === 'submitted') {\n const state = getString(getObject(payload.review)?.state)?.toLowerCase().replaceAll('_', '-');\n priority = state === 'approved' || state === 'changes-requested' ? 'urgent' : 'high';\n kind =\n state === 'approved'\n ? 'review-approved'\n : state === 'changes-requested'\n ? 'review-changes-requested'\n : 'review-submitted';\n label =\n state === 'approved'\n ? 'approved the pull request'\n : state === 'changes-requested'\n ? 'requested changes'\n : 'submitted a review';\n } else if (event === 'pull_request' && action === 'closed') {\n const merged = getBoolean(getObject(payload.pull_request)?.merged) === true;\n priority = 'urgent';\n kind = merged ? 'pull-request-merged' : 'pull-request-closed';\n label = merged ? 'merged the pull request' : 'closed the pull request';\n terminal = true;\n } else if (event === 'issue_comment' && action === 'created') {\n priority = 'high';\n kind = 'issue-comment-created';\n label = 'commented';\n } else if (event === 'pull_request_review_comment' && action === 'created') {\n priority = 'high';\n kind = 'review-comment-created';\n label = 'left a review comment';\n } else if (event === 'pull_request' && action === 'reopened') {\n priority = 'high';\n kind = 'pull-request-reopened';\n label = 'reopened the pull request';\n } else if (event === 'pull_request_review' && action === 'dismissed') {\n priority = 'high';\n kind = 'review-dismissed';\n label = 'dismissed a review';\n } else if (\n event === 'pull_request' &&\n [\n 'synchronize',\n 'ready_for_review',\n 'converted_to_draft',\n 'assigned',\n 'unassigned',\n 'review_requested',\n 'review_request_removed',\n ].includes(action)\n ) {\n priority = 'medium';\n kind = `pull-request-${action.replaceAll('_', '-')}`;\n label = action.replaceAll('_', ' ');\n } else if (\n event === 'pull_request' &&\n ['edited', 'labeled', 'unlabeled', 'milestoned', 'demilestoned'].includes(action)\n ) {\n priority = 'low';\n kind = `pull-request-${action.replaceAll('_', '-')}`;\n label = action.replaceAll('_', ' ');\n } else {\n return undefined;\n }\n\n return {\n action,\n kind,\n priority,\n summary: notificationSummary(metadata, label),\n terminal,\n metadata: {\n ...metadata,\n pullRequestNumber: metadata.pullRequestNumber,\n repositoryId: metadata.repositoryId,\n installationId: metadata.installationId,\n },\n payload,\n };\n}\n\nasync function resolveSubscriptionSession(\n controller: MountedMastraCode['controller'],\n subscription: GithubSignalSubscriptionRow,\n github?: GithubWebhookDispatchIntegration,\n) {\n const { sessionId, resourceId, threadId } = subscription;\n if (!sessionId || !resourceId || !threadId) {\n throw new Error(`GitHub subscription ${subscription.id} is missing its session binding.`);\n }\n // Read the thread straight from storage before touching sessions. This answers\n // two questions at once, and `queryThreadById` does it without constructing a\n // session (so no workspace or sandbox is provisioned just to make the check).\n //\n // First: do we even have this thread? A pull request's events can reach a\n // deployment that never owned the subscribed thread, and delivery must not\n // fabricate a session for a thread that lives somewhere else.\n //\n // Second: which resource owns it? The subscription records the Factory project\n // as its `resourceId`, but an unscoped session is registered under its own id,\n // so the stored value routinely names a resource that does not own the thread.\n // The thread row is the authoritative answer; the stored id is only a fallback.\n const thread = await controller.queryThreadById({ threadId });\n if (!thread) return undefined;\n const ownerResourceId = thread.resourceId || resourceId;\n const scope = subscription.sessionScope || undefined;\n let session = await controller.getSessionByResource(ownerResourceId, scope);\n if (!session) {\n const tags = {\n factoryProjectId: resourceId,\n projectRepositoryId: subscription.data.projectRepositoryId,\n ...(scope ? { worktreePath: scope } : {}),\n };\n // Creating the session resolves its workspace, which authorizes the caller\n // against the Factory session row — no signed-in user, so run as its owner.\n // The session is created under the resource that owns the thread, so the\n // thread switch below resolves; the persisted Factory session is keyed by\n // the subscription's session ID.\n const sessionRow = await github?.sourceControlStorage.sessions.getBySessionId(sessionId);\n if (!sessionRow) {\n throw new Error(`GitHub subscription ${subscription.id} has no Factory session ${sessionId} to run as.`);\n }\n const requestContext = new RequestContext();\n requestContext.set('user', { workosId: sessionRow.userId, organizationId: sessionRow.orgId });\n session = await controller.createSession({\n id: sessionId,\n ownerId: sessionRow.userId,\n resourceId: ownerResourceId,\n scope,\n tags,\n requestContext,\n });\n }\n if (session.thread.getId() !== threadId) {\n await session.thread.switch({ threadId, emitEvent: false });\n }\n if (session.thread.getId() !== threadId) {\n throw new Error(`Session ${sessionId} did not bind thread ${threadId}.`);\n }\n return session;\n}\n\n/**\n * Reviewer bots authorized out of the box. Deployments extend — never replace —\n * this set through the integration's `authorizedBots`.\n */\nexport const DEFAULT_AUTHORIZED_BOTS: readonly string[] = ['coderabbitai[bot]', 'devin-ai-integration[bot]'];\n\n/**\n * Parse a comma-separated `MASTRACODE_GITHUB_AUTHORIZED_BOTS` value into extra\n * bot logins. Returns undefined when nothing usable was configured.\n */\nexport function parseAuthorizedBotsEnv(value: string | undefined): string[] | undefined {\n const bots = (value ?? '')\n .split(',')\n .map(bot => bot.trim())\n .filter(Boolean);\n return bots.length > 0 ? bots : undefined;\n}\n\n/** Lowercased union of the default bot logins and any the deployment opted in. */\nexport function resolveAuthorizedBots(extra?: readonly string[]): Set<string> {\n const bots = new Set(DEFAULT_AUTHORIZED_BOTS);\n for (const bot of extra ?? []) {\n const normalized = bot.trim().toLowerCase();\n if (normalized) bots.add(normalized);\n }\n return bots;\n}\n\nconst AUTHORIZED_PERMISSIONS = new Set(['admin', 'maintain', 'write']);\nconst PERMISSION_CHECK_TIMEOUT_MS = 5_000;\nconst AUTHOR_GATED_KINDS = new Set([\n 'issue-comment-created',\n 'review-comment-created',\n 'review-submitted',\n 'review-approved',\n 'review-changes-requested',\n 'review-dismissed',\n]);\n\n/**\n * Recognizes Factory's own GitHub App identity. GitHub forbids an app from\n * reviewing a pull request it authored, so `factory-review` falls back to\n * posting its verdict as a comment under this login. Those comments have to\n * clear the author gate for the review handoff to reach the authoring agent;\n * the rules layer still decides which of them are worth acting on.\n */\nexport function isFactoryAppSender(sender: string | undefined, slug: string | undefined): boolean {\n if (!sender || !slug) return false;\n return sender.toLowerCase() === `${slug.toLowerCase()}[bot]`;\n}\n\nasync function isAuthorizedGithubSender(\n notification: GithubWebhookNotification,\n github:\n | Pick<\n GithubWebhookDispatchIntegration,\n 'getRepositoryCollaboratorPermission' | 'slug' | 'identity' | 'authorizedBots'\n >\n | undefined,\n): Promise<boolean> {\n if (!AUTHOR_GATED_KINDS.has(notification.kind)) return true;\n const sender = notification.metadata.sender;\n const repository = notification.metadata.repository;\n if (!sender || !repository) return false;\n if (github?.identity?.matches(sender)) return true;\n if (isFactoryAppSender(sender, github?.slug)) return true;\n const normalizedSender = sender.toLowerCase();\n if (notification.metadata.senderType?.toLowerCase() === 'bot' || normalizedSender.endsWith('[bot]')) {\n return resolveAuthorizedBots(github?.authorizedBots).has(normalizedSender);\n }\n if (!github) return false;\n const abortController = new AbortController();\n let timeout: ReturnType<typeof setTimeout> | undefined;\n try {\n const permission = await Promise.race([\n github.getRepositoryCollaboratorPermission(\n notification.metadata.installationId,\n repository,\n sender,\n abortController.signal,\n ),\n new Promise<undefined>(resolve => {\n timeout = setTimeout(() => {\n abortController.abort();\n resolve(undefined);\n }, PERMISSION_CHECK_TIMEOUT_MS);\n }),\n ]);\n return permission !== undefined && AUTHORIZED_PERMISSIONS.has(permission);\n } catch {\n return false;\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n}\n\nexport async function dispatchGithubWebhook(\n parsed: ParsedGithubWebhook,\n dependencies: GithubWebhookDispatchDependencies,\n): Promise<{ delivered: number; failed: number; skipped: number; ignored: boolean }> {\n const notification = classifyGithubWebhook(parsed);\n if (!notification) return { delivered: 0, failed: 0, skipped: 0, ignored: true };\n const isAuthorizedSender =\n dependencies.isAuthorizedSender ??\n ((n: GithubWebhookNotification) => isAuthorizedGithubSender(n, dependencies.github));\n if (!(await isAuthorizedSender(notification))) {\n dependencies.onSenderRejected?.(notification);\n return { delivered: 0, failed: 0, skipped: 0, ignored: true };\n }\n\n const target = {\n installationExternalId: notification.metadata.installationId.toString(),\n repositoryExternalId: notification.metadata.repositoryId.toString(),\n changeRequestId: notification.metadata.pullRequestNumber.toString(),\n };\n const listSubscriptions =\n dependencies.listSubscriptions ??\n ((subscriptionTarget: GithubWebhookPullRequestTarget, options?: { includeTerminal?: boolean }) => {\n if (!dependencies.github) throw new Error('GitHub integration is required to load webhook subscriptions.');\n return listPullRequestSubscriptionsForWebhook(\n subscriptionTarget,\n options,\n dependencies.github.integrationStorage,\n );\n });\n const retireSubscription =\n dependencies.retireSubscription ??\n ((id: string, status: 'open' | 'closed' | 'merged') => {\n if (!dependencies.github) throw new Error('GitHub integration is required to retire webhook subscriptions.');\n return retirePullRequestSubscription(id, status, dependencies.github.integrationStorage);\n });\n const subscriptions = await listSubscriptions(target, { includeTerminal: notification.action === 'reopened' });\n let delivered = 0;\n let failed = 0;\n let skipped = 0;\n\n for (const subscription of subscriptions) {\n try {\n const session = await resolveSubscriptionSession(dependencies.controller, subscription, dependencies.github);\n // No session means this deployment does not hold the subscribed thread.\n // That is not a delivery failure, so it must not be retried or counted as\n // one; the subscription is left untouched because the thread may exist\n // wherever the subscription was created.\n if (!session) {\n skipped += 1;\n dependencies.onTargetSkipped?.(subscription);\n continue;\n }\n const result = await session.sendNotificationSignal({\n source: 'github',\n kind: notification.kind,\n summary: notification.summary,\n priority: notification.priority,\n payload: notification.payload,\n sourceId: parsed.deliveryId,\n dedupeKey: `${parsed.deliveryId}:${subscription.sessionId}:${subscription.threadId}`,\n coalesceKey: `github:${subscription.data.repositoryExternalId}:pull-request:${subscription.data.changeRequestId}`,\n metadata: {\n event: notification.metadata.event,\n action: notification.action,\n repository: notification.metadata.repository,\n issueNumber: notification.metadata.issueNumber,\n pullRequestNumber: notification.metadata.pullRequestNumber,\n targetUrl: notificationTargetUrl(parsed.event, parsed.payload),\n deliveryId: parsed.deliveryId,\n },\n });\n await Promise.all([result.persisted, result.accepted].filter(Boolean));\n if (notification.terminal) {\n await retireSubscription(subscription.id, notification.kind === 'pull-request-merged' ? 'merged' : 'closed');\n } else if (notification.action === 'reopened') {\n await retireSubscription(subscription.id, 'open');\n }\n delivered += 1;\n } catch (error) {\n failed += 1;\n dependencies.onTargetError?.(subscription, error);\n }\n }\n\n return { delivered, failed, skipped, ignored: false };\n}\n\nexport async function handleGithubWebhook(\n c: Context,\n options: GithubWebhookHandlerOptions & Partial<Omit<GithubWebhookDispatchDependencies, 'github'>>,\n): Promise<GithubWebhookResult> {\n const parsed = await parseGithubWebhook(c, options.github.webhookSecret);\n if ('status' in parsed) return parsed;\n\n if (!SUPPORTED_GITHUB_WEBHOOK_EVENTS.has(parsed.event)) {\n return { status: 202, body: { ok: true, ignored: true } };\n }\n\n const metadata = normalizeGithubWebhookMetadata(parsed);\n console.info('[GitHub Webhook]', metadata);\n\n if (options.ingestFactoryEvent) {\n await options.ingestFactoryEvent(parsed);\n }\n\n if (!options.controller) {\n return { status: 202, body: { ok: true } };\n }\n\n const result = await dispatchGithubWebhook(parsed, {\n onSenderRejected: notification => {\n console.info('[GitHub Webhook] sender not authorized', {\n deliveryId: parsed.deliveryId,\n repository: notification.metadata.repository,\n sender: notification.metadata.sender,\n kind: notification.kind,\n });\n },\n ...(options as GithubWebhookDispatchDependencies),\n });\n if (result.failed > 0) {\n console.warn(`[GitHub Webhook] ${result.failed} subscribed target(s) failed for delivery ${parsed.deliveryId}.`);\n }\n return { status: 202, body: { ok: true, ...(result.ignored ? { ignored: true as const } : {}) } };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"webhook.js","names":[],"sources":["../../../src/integrations/github/webhook.ts"],"sourcesContent":["import { createHmac, timingSafeEqual } from 'node:crypto';\nimport type { MountedMastraCode } from '@mastra/code-sdk';\nimport type { NotificationPriority } from '@mastra/core/notifications';\nimport { RequestContext } from '@mastra/core/request-context';\nimport type { Context } from 'hono';\nimport { hasResolvedOrg, seedSessionOrg } from '../../session/org-seed.js';\nimport { GithubAppIdentity } from './app-identity.js';\nimport type { GithubIntegration, GithubRepositoryPermission } from './integration.js';\nimport { listPullRequestSubscriptionsForWebhook, retirePullRequestSubscription } from './subscriptions.js';\nimport type {\n GithubSignalSubscriptionRow,\n GithubSubscriptionStorage,\n GithubWebhookPullRequestTarget,\n} from './subscriptions.js';\n\nexport interface GithubWebhookHandlerOptions {\n /** Integration providing webhook-secret verification + collaborator permission checks. */\n github: GithubIntegration;\n ingestFactoryEvent?: (event: ParsedGithubWebhook) => Promise<unknown>;\n}\n\nconst SUPPORTED_GITHUB_WEBHOOK_EVENTS = new Set([\n 'issues',\n 'issue_comment',\n 'pull_request',\n 'pull_request_review',\n 'pull_request_review_comment',\n // Direct pushes to the default branch drive base-checkpoint rebuilds. The\n // rules engine and subscription dispatcher both ignore push events.\n 'push',\n]);\n\nexport interface GithubWebhookMetadata {\n event: string;\n action?: string;\n deliveryId: string;\n repository?: string;\n repositoryId?: number;\n issueNumber?: number;\n pullRequestNumber?: number;\n sender?: string;\n senderType?: string;\n installationId?: number;\n}\n\nexport interface ParsedGithubWebhook {\n event: string;\n deliveryId: string;\n payload: Record<string, unknown>;\n}\n\nexport type GithubWebhookResult =\n | { status: 202; body: { ok: true; ignored?: true } }\n | { status: 400; body: { error: 'bad_request'; message: string } }\n | { status: 401; body: { error: 'unauthorized'; message: string } };\n\nexport interface GithubWebhookNotification {\n action: string;\n kind: string;\n priority: NotificationPriority;\n summary: string;\n terminal: boolean;\n metadata: GithubWebhookMetadata & { pullRequestNumber: number; repositoryId: number; installationId: number };\n payload: Record<string, unknown>;\n}\n\n/** The Factory session row fields a woken session has to run as. */\nexport type FactorySessionOwner = { userId: string; orgId: string };\n\n/**\n * The integration surface this dispatch uses. Narrow on purpose: the GitHub App\n * integration and the platform-backed one are unrelated classes, and only this\n * much is common to both.\n */\nexport interface GithubWebhookDispatchIntegration {\n /** App slug, used to recognize Factory's own bot identity. */\n readonly slug?: string;\n /**\n * Resolved identity of the App this integration posts as. Preferred over\n * {@link slug}, which names the deployment's own self-hosted App and is unset\n * on deployments that run against Platform's App.\n */\n readonly identity?: GithubAppIdentity;\n readonly integrationStorage: GithubSubscriptionStorage;\n /**\n * Extra bot logins this deployment authorizes to trigger author-gated\n * notifications, merged over `DEFAULT_AUTHORIZED_BOTS`.\n */\n readonly authorizedBots?: readonly string[];\n readonly sourceControlStorage: {\n sessions: { getBySessionId(sessionId: string): Promise<FactorySessionOwner | null> };\n };\n getRepositoryCollaboratorPermission(\n installationId: number,\n repoFullName: string,\n username: string,\n signal?: AbortSignal,\n ): Promise<GithubRepositoryPermission | undefined>;\n}\n\nexport interface GithubWebhookDispatchDependencies {\n controller: MountedMastraCode['controller'];\n /**\n * Integration used by the default sender-authorization check (collaborator\n * permission lookup) and to resolve the owner of a session being recreated.\n * Author-gated notifications fail closed when neither this nor an\n * `isAuthorizedSender` override is supplied.\n */\n github?: GithubWebhookDispatchIntegration;\n listSubscriptions?: (\n target: GithubWebhookPullRequestTarget,\n options?: { includeTerminal?: boolean },\n ) => Promise<GithubSignalSubscriptionRow[]>;\n retireSubscription?: (id: string, status: 'open' | 'closed' | 'merged') => Promise<void>;\n isAuthorizedSender?: (notification: GithubWebhookNotification) => Promise<boolean>;\n /** Called when the sender gate drops a notification, so the drop is observable. */\n onSenderRejected?: (notification: GithubWebhookNotification) => void;\n onTargetError?: (subscription: GithubSignalSubscriptionRow, error: unknown) => void;\n /** Called when a subscription names a thread this deployment does not hold. */\n onTargetSkipped?: (subscription: GithubSignalSubscriptionRow) => void;\n}\n\nfunction normalizeHeader(value: string | undefined | null): string | null {\n if (!value) return null;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction verifySignature(rawBody: string, signature: string, secret: string): boolean {\n if (!signature.startsWith('sha256=')) return false;\n const signatureHex = signature.slice('sha256='.length);\n if (!/^[a-fA-F0-9]{64}$/.test(signatureHex)) return false;\n\n const expectedHex = createHmac('sha256', secret).update(rawBody).digest('hex');\n const received = Buffer.from(signatureHex, 'hex');\n const expected = Buffer.from(expectedHex, 'hex');\n return received.length === expected.length && timingSafeEqual(received, expected);\n}\n\nasync function parseGithubWebhook(\n c: Context,\n secret: string | undefined,\n): Promise<ParsedGithubWebhook | GithubWebhookResult> {\n if (!secret) {\n return { status: 401, body: { error: 'unauthorized', message: 'GitHub webhook secret is not configured' } };\n }\n\n const event = normalizeHeader(c.req.header('x-github-event'));\n const deliveryId = normalizeHeader(c.req.header('x-github-delivery'));\n const signature = normalizeHeader(c.req.header('x-hub-signature-256'));\n\n if (!event) return { status: 400, body: { error: 'bad_request', message: 'Missing x-github-event header' } };\n if (!deliveryId) return { status: 400, body: { error: 'bad_request', message: 'Missing x-github-delivery header' } };\n if (!signature)\n return { status: 401, body: { error: 'unauthorized', message: 'Missing x-hub-signature-256 header' } };\n\n const rawBody = await c.req.text();\n if (!verifySignature(rawBody, signature, secret)) {\n return { status: 401, body: { error: 'unauthorized', message: 'Invalid GitHub webhook signature' } };\n }\n\n let payload: unknown;\n try {\n payload = JSON.parse(rawBody);\n } catch {\n return { status: 400, body: { error: 'bad_request', message: 'Malformed JSON payload' } };\n }\n\n if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {\n return { status: 400, body: { error: 'bad_request', message: 'Payload must be a JSON object' } };\n }\n\n return { event, deliveryId, payload: payload as Record<string, unknown> };\n}\n\nfunction getObject(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === 'object' && !Array.isArray(value) ? (value as Record<string, unknown>) : undefined;\n}\n\nfunction getString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction getNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction getBoolean(value: unknown): boolean | undefined {\n return typeof value === 'boolean' ? value : undefined;\n}\n\nexport function normalizeGithubWebhookMetadata(parsed: ParsedGithubWebhook): GithubWebhookMetadata {\n const { event, deliveryId, payload } = parsed;\n const repository = getObject(payload.repository);\n const issue = getObject(payload.issue);\n const pullRequest = getObject(payload.pull_request);\n const sender = getObject(payload.sender);\n const installation = getObject(payload.installation);\n const issuePullRequest = getObject(issue?.pull_request);\n\n return {\n event,\n action: getString(payload.action),\n deliveryId,\n repository: getString(repository?.full_name),\n repositoryId: getNumber(repository?.id),\n issueNumber: getNumber(issue?.number),\n pullRequestNumber:\n getNumber(pullRequest?.number) ??\n (event === 'issue_comment' && issuePullRequest ? getNumber(issue?.number) : undefined),\n sender: getString(sender?.login),\n senderType: getString(sender?.type),\n installationId: getNumber(installation?.id),\n };\n}\n\nfunction notificationSummary(metadata: GithubWebhookMetadata, label: string): string {\n const actor = metadata.sender ? `${metadata.sender} ` : '';\n return `${actor}${label} on ${metadata.repository}#${metadata.pullRequestNumber}`;\n}\n\nfunction notificationTargetUrl(event: string, payload: Record<string, unknown>): string | undefined {\n if (event === 'issue_comment' || event === 'pull_request_review_comment') {\n return getString(getObject(payload.comment)?.html_url);\n }\n if (event === 'pull_request_review') {\n return getString(getObject(payload.review)?.html_url);\n }\n return getString(getObject(payload.pull_request)?.html_url);\n}\n\nexport function classifyGithubWebhook(parsed: ParsedGithubWebhook): GithubWebhookNotification | undefined {\n const metadata = normalizeGithubWebhookMetadata(parsed);\n const { event, payload } = parsed;\n const action = metadata.action;\n if (\n !action ||\n !metadata.repositoryId ||\n !metadata.installationId ||\n !metadata.pullRequestNumber ||\n !metadata.repository\n ) {\n return undefined;\n }\n\n let priority: NotificationPriority;\n let kind: string;\n let label: string;\n let terminal = false;\n\n if (event === 'pull_request_review' && action === 'submitted') {\n const state = getString(getObject(payload.review)?.state)?.toLowerCase().replaceAll('_', '-');\n priority = state === 'approved' || state === 'changes-requested' ? 'urgent' : 'high';\n kind =\n state === 'approved'\n ? 'review-approved'\n : state === 'changes-requested'\n ? 'review-changes-requested'\n : 'review-submitted';\n label =\n state === 'approved'\n ? 'approved the pull request'\n : state === 'changes-requested'\n ? 'requested changes'\n : 'submitted a review';\n } else if (event === 'pull_request' && action === 'closed') {\n const merged = getBoolean(getObject(payload.pull_request)?.merged) === true;\n priority = 'urgent';\n kind = merged ? 'pull-request-merged' : 'pull-request-closed';\n label = merged ? 'merged the pull request' : 'closed the pull request';\n terminal = true;\n } else if (event === 'issue_comment' && action === 'created') {\n priority = 'high';\n kind = 'issue-comment-created';\n label = 'commented';\n } else if (event === 'pull_request_review_comment' && action === 'created') {\n priority = 'high';\n kind = 'review-comment-created';\n label = 'left a review comment';\n } else if (event === 'pull_request' && action === 'reopened') {\n priority = 'high';\n kind = 'pull-request-reopened';\n label = 'reopened the pull request';\n } else if (event === 'pull_request_review' && action === 'dismissed') {\n priority = 'high';\n kind = 'review-dismissed';\n label = 'dismissed a review';\n } else if (\n event === 'pull_request' &&\n [\n 'synchronize',\n 'ready_for_review',\n 'converted_to_draft',\n 'assigned',\n 'unassigned',\n 'review_requested',\n 'review_request_removed',\n ].includes(action)\n ) {\n priority = 'medium';\n kind = `pull-request-${action.replaceAll('_', '-')}`;\n label = action.replaceAll('_', ' ');\n } else if (\n event === 'pull_request' &&\n ['edited', 'labeled', 'unlabeled', 'milestoned', 'demilestoned'].includes(action)\n ) {\n priority = 'low';\n kind = `pull-request-${action.replaceAll('_', '-')}`;\n label = action.replaceAll('_', ' ');\n } else {\n return undefined;\n }\n\n return {\n action,\n kind,\n priority,\n summary: notificationSummary(metadata, label),\n terminal,\n metadata: {\n ...metadata,\n pullRequestNumber: metadata.pullRequestNumber,\n repositoryId: metadata.repositoryId,\n installationId: metadata.installationId,\n },\n payload,\n };\n}\n\nasync function resolveSubscriptionSession(\n controller: MountedMastraCode['controller'],\n subscription: GithubSignalSubscriptionRow,\n github?: GithubWebhookDispatchIntegration,\n) {\n const { sessionId, resourceId, threadId } = subscription;\n if (!sessionId || !resourceId || !threadId) {\n throw new Error(`GitHub subscription ${subscription.id} is missing its session binding.`);\n }\n // Read the thread straight from storage before touching sessions. This answers\n // two questions at once, and `queryThreadById` does it without constructing a\n // session (so no workspace or sandbox is provisioned just to make the check).\n //\n // First: do we even have this thread? A pull request's events can reach a\n // deployment that never owned the subscribed thread, and delivery must not\n // fabricate a session for a thread that lives somewhere else.\n //\n // Second: which resource owns it? The subscription records the Factory project\n // as its `resourceId`, but an unscoped session is registered under its own id,\n // so the stored value routinely names a resource that does not own the thread.\n // The thread row is the authoritative answer; the stored id is only a fallback.\n const thread = await controller.queryThreadById({ threadId });\n if (!thread) return undefined;\n const ownerResourceId = thread.resourceId || resourceId;\n const scope = subscription.sessionScope || undefined;\n let session = await controller.getSessionByResource(ownerResourceId, scope);\n if (!session) {\n const tags = {\n factoryProjectId: resourceId,\n projectRepositoryId: subscription.data.projectRepositoryId,\n ...(scope ? { worktreePath: scope } : {}),\n };\n // Creating the session resolves its workspace, which authorizes the caller\n // against the Factory session row — no signed-in user, so run as its owner.\n // The session is created under the resource that owns the thread, so the\n // thread switch below resolves; the persisted Factory session is keyed by\n // the subscription's session ID.\n const sessionRow = await github?.sourceControlStorage.sessions.getBySessionId(sessionId);\n if (!sessionRow) {\n throw new Error(`GitHub subscription ${subscription.id} has no Factory session ${sessionId} to run as.`);\n }\n const requestContext = new RequestContext();\n requestContext.set('user', { workosId: sessionRow.userId, organizationId: sessionRow.orgId });\n session = await controller.createSession({\n id: sessionId,\n ownerId: sessionRow.userId,\n resourceId: ownerResourceId,\n scope,\n tags,\n requestContext,\n });\n await seedSessionOrg(session, sessionRow.orgId);\n } else if (!hasResolvedOrg(session.state?.get()?.factoryOrgId)) {\n // A session created before the org seed existed carries the project tag and\n // no org, so capture would refuse for the rest of its life even though the\n // org is recoverable. Heal it — but only here, and only when it is missing:\n // hoisting the row fetch above would make an existing-session delivery throw\n // on a missing row where it previously succeeded, and fetching it every time\n // would add a storage read to every delivery. A row that is missing or a\n // lookup that throws leaves the session marked unresolved, and delivery\n // continues either way.\n try {\n const sessionRow = await github?.sourceControlStorage.sessions.getBySessionId(sessionId);\n await seedSessionOrg(session, sessionRow?.orgId);\n } catch (error) {\n console.warn('[GitHub webhook] Unable to resolve the session organization.', error);\n await seedSessionOrg(session, undefined);\n }\n } else if (session.state?.get()?.factoryOrgUnresolved) {\n // The org is present, so an earlier failed resolution left a stale marker\n // behind. Clear it without a storage read — nothing else re-seeds a session\n // once the start hook has run, so the marker would otherwise outlive its\n // cause.\n await seedSessionOrg(session, session.state.get()?.factoryOrgId);\n }\n if (session.thread.getId() !== threadId) {\n await session.thread.switch({ threadId, emitEvent: false });\n }\n if (session.thread.getId() !== threadId) {\n throw new Error(`Session ${sessionId} did not bind thread ${threadId}.`);\n }\n return session;\n}\n\n/**\n * Reviewer bots authorized out of the box. Deployments extend — never replace —\n * this set through the integration's `authorizedBots`.\n */\nexport const DEFAULT_AUTHORIZED_BOTS: readonly string[] = ['coderabbitai[bot]', 'devin-ai-integration[bot]'];\n\n/**\n * Parse a comma-separated `MASTRACODE_GITHUB_AUTHORIZED_BOTS` value into extra\n * bot logins. Returns undefined when nothing usable was configured.\n */\nexport function parseAuthorizedBotsEnv(value: string | undefined): string[] | undefined {\n const bots = (value ?? '')\n .split(',')\n .map(bot => bot.trim())\n .filter(Boolean);\n return bots.length > 0 ? bots : undefined;\n}\n\n/** Lowercased union of the default bot logins and any the deployment opted in. */\nexport function resolveAuthorizedBots(extra?: readonly string[]): Set<string> {\n const bots = new Set(DEFAULT_AUTHORIZED_BOTS);\n for (const bot of extra ?? []) {\n const normalized = bot.trim().toLowerCase();\n if (normalized) bots.add(normalized);\n }\n return bots;\n}\n\nconst AUTHORIZED_PERMISSIONS = new Set(['admin', 'maintain', 'write']);\nconst PERMISSION_CHECK_TIMEOUT_MS = 5_000;\nconst AUTHOR_GATED_KINDS = new Set([\n 'issue-comment-created',\n 'review-comment-created',\n 'review-submitted',\n 'review-approved',\n 'review-changes-requested',\n 'review-dismissed',\n]);\n\n/**\n * Recognizes Factory's own GitHub App identity. GitHub forbids an app from\n * reviewing a pull request it authored, so `factory-review` falls back to\n * posting its verdict as a comment under this login. Those comments have to\n * clear the author gate for the review handoff to reach the authoring agent;\n * the rules layer still decides which of them are worth acting on.\n */\nexport function isFactoryAppSender(sender: string | undefined, slug: string | undefined): boolean {\n if (!sender || !slug) return false;\n return sender.toLowerCase() === `${slug.toLowerCase()}[bot]`;\n}\n\nasync function isAuthorizedGithubSender(\n notification: GithubWebhookNotification,\n github:\n | Pick<\n GithubWebhookDispatchIntegration,\n 'getRepositoryCollaboratorPermission' | 'slug' | 'identity' | 'authorizedBots'\n >\n | undefined,\n): Promise<boolean> {\n if (!AUTHOR_GATED_KINDS.has(notification.kind)) return true;\n const sender = notification.metadata.sender;\n const repository = notification.metadata.repository;\n if (!sender || !repository) return false;\n if (github?.identity?.matches(sender)) return true;\n if (isFactoryAppSender(sender, github?.slug)) return true;\n const normalizedSender = sender.toLowerCase();\n if (notification.metadata.senderType?.toLowerCase() === 'bot' || normalizedSender.endsWith('[bot]')) {\n return resolveAuthorizedBots(github?.authorizedBots).has(normalizedSender);\n }\n if (!github) return false;\n const abortController = new AbortController();\n let timeout: ReturnType<typeof setTimeout> | undefined;\n try {\n const permission = await Promise.race([\n github.getRepositoryCollaboratorPermission(\n notification.metadata.installationId,\n repository,\n sender,\n abortController.signal,\n ),\n new Promise<undefined>(resolve => {\n timeout = setTimeout(() => {\n abortController.abort();\n resolve(undefined);\n }, PERMISSION_CHECK_TIMEOUT_MS);\n }),\n ]);\n return permission !== undefined && AUTHORIZED_PERMISSIONS.has(permission);\n } catch {\n return false;\n } finally {\n if (timeout) clearTimeout(timeout);\n }\n}\n\nexport async function dispatchGithubWebhook(\n parsed: ParsedGithubWebhook,\n dependencies: GithubWebhookDispatchDependencies,\n): Promise<{ delivered: number; failed: number; skipped: number; ignored: boolean }> {\n const notification = classifyGithubWebhook(parsed);\n if (!notification) return { delivered: 0, failed: 0, skipped: 0, ignored: true };\n const isAuthorizedSender =\n dependencies.isAuthorizedSender ??\n ((n: GithubWebhookNotification) => isAuthorizedGithubSender(n, dependencies.github));\n if (!(await isAuthorizedSender(notification))) {\n dependencies.onSenderRejected?.(notification);\n return { delivered: 0, failed: 0, skipped: 0, ignored: true };\n }\n\n const target = {\n installationExternalId: notification.metadata.installationId.toString(),\n repositoryExternalId: notification.metadata.repositoryId.toString(),\n changeRequestId: notification.metadata.pullRequestNumber.toString(),\n };\n const listSubscriptions =\n dependencies.listSubscriptions ??\n ((subscriptionTarget: GithubWebhookPullRequestTarget, options?: { includeTerminal?: boolean }) => {\n if (!dependencies.github) throw new Error('GitHub integration is required to load webhook subscriptions.');\n return listPullRequestSubscriptionsForWebhook(\n subscriptionTarget,\n options,\n dependencies.github.integrationStorage,\n );\n });\n const retireSubscription =\n dependencies.retireSubscription ??\n ((id: string, status: 'open' | 'closed' | 'merged') => {\n if (!dependencies.github) throw new Error('GitHub integration is required to retire webhook subscriptions.');\n return retirePullRequestSubscription(id, status, dependencies.github.integrationStorage);\n });\n const subscriptions = await listSubscriptions(target, { includeTerminal: notification.action === 'reopened' });\n let delivered = 0;\n let failed = 0;\n let skipped = 0;\n\n for (const subscription of subscriptions) {\n try {\n const session = await resolveSubscriptionSession(dependencies.controller, subscription, dependencies.github);\n // No session means this deployment does not hold the subscribed thread.\n // That is not a delivery failure, so it must not be retried or counted as\n // one; the subscription is left untouched because the thread may exist\n // wherever the subscription was created.\n if (!session) {\n skipped += 1;\n dependencies.onTargetSkipped?.(subscription);\n continue;\n }\n const result = await session.sendNotificationSignal({\n source: 'github',\n kind: notification.kind,\n summary: notification.summary,\n priority: notification.priority,\n payload: notification.payload,\n sourceId: parsed.deliveryId,\n dedupeKey: `${parsed.deliveryId}:${subscription.sessionId}:${subscription.threadId}`,\n coalesceKey: `github:${subscription.data.repositoryExternalId}:pull-request:${subscription.data.changeRequestId}`,\n metadata: {\n event: notification.metadata.event,\n action: notification.action,\n repository: notification.metadata.repository,\n issueNumber: notification.metadata.issueNumber,\n pullRequestNumber: notification.metadata.pullRequestNumber,\n targetUrl: notificationTargetUrl(parsed.event, parsed.payload),\n deliveryId: parsed.deliveryId,\n },\n });\n await Promise.all([result.persisted, result.accepted].filter(Boolean));\n if (notification.terminal) {\n await retireSubscription(subscription.id, notification.kind === 'pull-request-merged' ? 'merged' : 'closed');\n } else if (notification.action === 'reopened') {\n await retireSubscription(subscription.id, 'open');\n }\n delivered += 1;\n } catch (error) {\n failed += 1;\n dependencies.onTargetError?.(subscription, error);\n }\n }\n\n return { delivered, failed, skipped, ignored: false };\n}\n\nexport async function handleGithubWebhook(\n c: Context,\n options: GithubWebhookHandlerOptions & Partial<Omit<GithubWebhookDispatchDependencies, 'github'>>,\n): Promise<GithubWebhookResult> {\n const parsed = await parseGithubWebhook(c, options.github.webhookSecret);\n if ('status' in parsed) return parsed;\n\n if (!SUPPORTED_GITHUB_WEBHOOK_EVENTS.has(parsed.event)) {\n return { status: 202, body: { ok: true, ignored: true } };\n }\n\n const metadata = normalizeGithubWebhookMetadata(parsed);\n console.info('[GitHub Webhook]', metadata);\n\n if (options.ingestFactoryEvent) {\n await options.ingestFactoryEvent(parsed);\n }\n\n if (!options.controller) {\n return { status: 202, body: { ok: true } };\n }\n\n const result = await dispatchGithubWebhook(parsed, {\n onSenderRejected: notification => {\n console.info('[GitHub Webhook] sender not authorized', {\n deliveryId: parsed.deliveryId,\n repository: notification.metadata.repository,\n sender: notification.metadata.sender,\n kind: notification.kind,\n });\n },\n ...(options as GithubWebhookDispatchDependencies),\n });\n if (result.failed > 0) {\n console.warn(`[GitHub Webhook] ${result.failed} subscribed target(s) failed for delivery ${parsed.deliveryId}.`);\n }\n return { status: 202, body: { ok: true, ...(result.ignored ? { ignored: true as const } : {}) } };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../../src/integrations/platform/github/integration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAIxD,OAAO,KAAK,EAEV,MAAM,EAIP,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAwBV,cAAc,EACf,MAAM,0CAA0C,CAAC;AAElD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,+CAA+C,CAAC;AAC9F,OAAO,KAAK,EAEV,0BAA0B,EAC3B,MAAM,iDAAiD,CAAC;AACzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAC9F,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EACV,iBAAiB,EACjB,0BAA0B,EAC1B,8BAA8B,EAC9B,+BAA+B,EAC/B,WAAW,EACZ,MAAM,6BAA6B,CAAC;AAKrC,OAAO,KAAK,EAAE,mBAAmB,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAM5F,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AA4I/E,qBAAa,yBAA0B,YAAW,kBAAkB;;IAClE,QAAQ,CAAC,EAAE,YAAY;IAIvB;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC;;;OAGG;IACH,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAc3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAsHrB;IAEF,QAAQ,CAAC,cAAc,EAAE,cAAc,CA0HrC;gBAGA,OAAO,GAAE;QACP,sEAAsE;QACtE,IAAI,CAAC,EAAE,MAAM,CAAC;KACV;IAkCR,kEAAkE;IAClE,IAAI,IAAI,IAAI,MAAM,GAAG,SAAS,CAE7B;IAED,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO;IAIjE,IAAI,OAAO,IAAI,0BAA0B,CAGxC;IAED,IAAI,oBAAoB,IAAI,0BAA0B,CAErD;IAED,IAAI,kBAAkB,IAAI,yBAAyB,CAKlD;IAuBD,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE;QAAE,OAAO,EAAE,wBAAwB,CAAA;KAAE,GAAG,IAAI;IAWpE,MAAM,CAAC,GAAG,EAAE,kBAAkB,GAAG,QAAQ,EAAE;
|
|
1
|
+
{"version":3,"file":"integration.d.ts","sourceRoot":"","sources":["../../../../src/integrations/platform/github/integration.ts"],"names":[],"mappings":"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"}
|
|
@@ -392,7 +392,8 @@ var PlatformGithubIntegration = class {
|
|
|
392
392
|
memorySettings: ctx.storage.memorySettings,
|
|
393
393
|
projects: ctx.storage.projects,
|
|
394
394
|
emitAudit: ctx.hooks?.emitAudit,
|
|
395
|
-
ingestFactoryEvent
|
|
395
|
+
ingestFactoryEvent,
|
|
396
|
+
...ctx.workItems ? { workItems: ctx.workItems } : {}
|
|
396
397
|
}).filter((route) => route.path !== "/web/github/status" && route.path !== "/web/github/webhook" && !route.path.startsWith("/auth/github/"))
|
|
397
398
|
];
|
|
398
399
|
}
|