-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
feat: harden webhook zod validation for reliability #3354
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,290 +2,54 @@ import { z } from "zod"; | |||||||||||||||||||||||||||||||||||
| import { RunStatus } from "./api.js"; | ||||||||||||||||||||||||||||||||||||
| import { RuntimeEnvironmentTypeSchema, TaskRunError } from "./common.js"; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| /** Represents a failed run alert webhook payload */ | ||||||||||||||||||||||||||||||||||||
| const AlertWebhookRunFailedObject = z.object({ | ||||||||||||||||||||||||||||||||||||
| /** Task information */ | ||||||||||||||||||||||||||||||||||||
| const ID_PATTERNS = { | ||||||||||||||||||||||||||||||||||||
| RUN: /^run_[a-zA-Z0-9]+$/, | ||||||||||||||||||||||||||||||||||||
| TASK: /^task_[a-zA-Z0-9]+$/, | ||||||||||||||||||||||||||||||||||||
| ENV: /^env_[a-zA-Z0-9]+$/, | ||||||||||||||||||||||||||||||||||||
| ORG: /^org_[a-zA-Z0-9]+$/, | ||||||||||||||||||||||||||||||||||||
| PROJECT: /^proj_[a-zA-Z0-9]+$/, | ||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+5
to
+11
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 environment.id, organization.id, and project.id regex patterns reject all valid database CUIDs The ID patterns
Suggested change
Was this helpful? React with 👍 or 👎 to provide feedback. |
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| const idWithPrefix = (pattern: RegExp) => z.string().regex(pattern, "Invalid ID format"); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| export const AlertWebhookRunFailedObject = z.object({ | ||||||||||||||||||||||||||||||||||||
| task: z.object({ | ||||||||||||||||||||||||||||||||||||
| /** Unique identifier for the task */ | ||||||||||||||||||||||||||||||||||||
| id: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** File path where the task is defined */ | ||||||||||||||||||||||||||||||||||||
| filePath: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Name of the exported task function */ | ||||||||||||||||||||||||||||||||||||
| id: idWithPrefix(ID_PATTERNS.TASK), | ||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 task.id regex pattern rejects all valid task identifiers The
Suggested change
Was this helpful? React with 👍 or 👎 to provide feedback. |
||||||||||||||||||||||||||||||||||||
| filePath: z.string().min(1), | ||||||||||||||||||||||||||||||||||||
| exportName: z.string().optional(), | ||||||||||||||||||||||||||||||||||||
| /** Version of the task */ | ||||||||||||||||||||||||||||||||||||
| version: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Version of the SDK used */ | ||||||||||||||||||||||||||||||||||||
| sdkVersion: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Version of the CLI used */ | ||||||||||||||||||||||||||||||||||||
| cliVersion: z.string(), | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** Run information */ | ||||||||||||||||||||||||||||||||||||
| run: z.object({ | ||||||||||||||||||||||||||||||||||||
| /** Unique identifier for the run */ | ||||||||||||||||||||||||||||||||||||
| id: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Run number */ | ||||||||||||||||||||||||||||||||||||
| number: z.number(), | ||||||||||||||||||||||||||||||||||||
| /** Current status of the run */ | ||||||||||||||||||||||||||||||||||||
| id: idWithPrefix(ID_PATTERNS.RUN), | ||||||||||||||||||||||||||||||||||||
| number: z.number().int().positive(), | ||||||||||||||||||||||||||||||||||||
| status: RunStatus, | ||||||||||||||||||||||||||||||||||||
| /** When the run was created */ | ||||||||||||||||||||||||||||||||||||
| createdAt: z.coerce.date(), | ||||||||||||||||||||||||||||||||||||
| /** When the run started executing */ | ||||||||||||||||||||||||||||||||||||
| startedAt: z.coerce.date().optional(), | ||||||||||||||||||||||||||||||||||||
| /** When the run finished executing */ | ||||||||||||||||||||||||||||||||||||
| completedAt: z.coerce.date().optional(), | ||||||||||||||||||||||||||||||||||||
| /** Whether this is a test run */ | ||||||||||||||||||||||||||||||||||||
| isTest: z.boolean(), | ||||||||||||||||||||||||||||||||||||
| /** Idempotency key for the run */ | ||||||||||||||||||||||||||||||||||||
| idempotencyKey: z.string().optional(), | ||||||||||||||||||||||||||||||||||||
| /** Associated tags */ | ||||||||||||||||||||||||||||||||||||
| tags: z.array(z.string()), | ||||||||||||||||||||||||||||||||||||
| /** Error information */ | ||||||||||||||||||||||||||||||||||||
| tags: z.array(z.string().max(50)).max(20), | ||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🚩 Tags validation constraints may reject existing valid payloads The new schema adds Was this helpful? React with 👍 or 👎 to provide feedback. |
||||||||||||||||||||||||||||||||||||
| error: TaskRunError, | ||||||||||||||||||||||||||||||||||||
| /** Whether the run was an out-of-memory error */ | ||||||||||||||||||||||||||||||||||||
| isOutOfMemoryError: z.boolean(), | ||||||||||||||||||||||||||||||||||||
| /** Machine preset used for the run */ | ||||||||||||||||||||||||||||||||||||
| machine: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** URL to view the run in the dashboard */ | ||||||||||||||||||||||||||||||||||||
| dashboardUrl: z.string(), | ||||||||||||||||||||||||||||||||||||
| dashboardUrl: z.string().url(), | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** Environment information */ | ||||||||||||||||||||||||||||||||||||
| environment: z.object({ | ||||||||||||||||||||||||||||||||||||
| /** Environment ID */ | ||||||||||||||||||||||||||||||||||||
| id: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Environment type */ | ||||||||||||||||||||||||||||||||||||
| id: idWithPrefix(ID_PATTERNS.ENV), | ||||||||||||||||||||||||||||||||||||
| type: RuntimeEnvironmentTypeSchema, | ||||||||||||||||||||||||||||||||||||
| /** Environment slug */ | ||||||||||||||||||||||||||||||||||||
| slug: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Environment branch name */ | ||||||||||||||||||||||||||||||||||||
| branchName: z.string().optional(), | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
39
to
43
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 Removed The
Suggested change
Was this helpful? React with 👍 or 👎 to provide feedback. |
||||||||||||||||||||||||||||||||||||
| /** Organization information */ | ||||||||||||||||||||||||||||||||||||
| organization: z.object({ | ||||||||||||||||||||||||||||||||||||
| /** Organization ID */ | ||||||||||||||||||||||||||||||||||||
| id: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Organization slug */ | ||||||||||||||||||||||||||||||||||||
| id: idWithPrefix(ID_PATTERNS.ORG), | ||||||||||||||||||||||||||||||||||||
| slug: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Organization name */ | ||||||||||||||||||||||||||||||||||||
| name: z.string(), | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** Project information */ | ||||||||||||||||||||||||||||||||||||
| project: z.object({ | ||||||||||||||||||||||||||||||||||||
| /** Project ID */ | ||||||||||||||||||||||||||||||||||||
| id: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Project reference */ | ||||||||||||||||||||||||||||||||||||
| id: idWithPrefix(ID_PATTERNS.PROJECT), | ||||||||||||||||||||||||||||||||||||
| ref: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Project slug */ | ||||||||||||||||||||||||||||||||||||
| slug: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Project name */ | ||||||||||||||||||||||||||||||||||||
| name: z.string(), | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||
| export type AlertWebhookRunFailedObject = z.infer<typeof AlertWebhookRunFailedObject>; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| /** Represents a deployment error */ | ||||||||||||||||||||||||||||||||||||
| export const DeployError = z.object({ | ||||||||||||||||||||||||||||||||||||
| /** Error name */ | ||||||||||||||||||||||||||||||||||||
| name: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Error message */ | ||||||||||||||||||||||||||||||||||||
| message: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Error stack trace */ | ||||||||||||||||||||||||||||||||||||
| stack: z.string().optional(), | ||||||||||||||||||||||||||||||||||||
| /** Standard error output */ | ||||||||||||||||||||||||||||||||||||
| stderr: z.string().optional(), | ||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||
| export type DeployError = z.infer<typeof DeployError>; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| const deploymentCommonProperties = { | ||||||||||||||||||||||||||||||||||||
| /** Environment information */ | ||||||||||||||||||||||||||||||||||||
| environment: z.object({ | ||||||||||||||||||||||||||||||||||||
| id: z.string(), | ||||||||||||||||||||||||||||||||||||
| type: RuntimeEnvironmentTypeSchema, | ||||||||||||||||||||||||||||||||||||
| slug: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Environment branch name */ | ||||||||||||||||||||||||||||||||||||
| branchName: z.string().optional(), | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** Organization information */ | ||||||||||||||||||||||||||||||||||||
| organization: z.object({ | ||||||||||||||||||||||||||||||||||||
| id: z.string(), | ||||||||||||||||||||||||||||||||||||
| slug: z.string(), | ||||||||||||||||||||||||||||||||||||
| name: z.string(), | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** Project information */ | ||||||||||||||||||||||||||||||||||||
| project: z.object({ | ||||||||||||||||||||||||||||||||||||
| id: z.string(), | ||||||||||||||||||||||||||||||||||||
| ref: z.string(), | ||||||||||||||||||||||||||||||||||||
| slug: z.string(), | ||||||||||||||||||||||||||||||||||||
| name: z.string(), | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** Git metadata for the deployment source code */ | ||||||||||||||||||||||||||||||||||||
| git: z | ||||||||||||||||||||||||||||||||||||
| .object({ | ||||||||||||||||||||||||||||||||||||
| branch: z.string(), | ||||||||||||||||||||||||||||||||||||
| commitSha: z.string(), | ||||||||||||||||||||||||||||||||||||
| commitMessage: z.string(), | ||||||||||||||||||||||||||||||||||||
| commitUrl: z.string(), | ||||||||||||||||||||||||||||||||||||
| branchUrl: z.string(), | ||||||||||||||||||||||||||||||||||||
| pullRequestNumber: z.number().optional(), | ||||||||||||||||||||||||||||||||||||
| pullRequestTitle: z.string().optional(), | ||||||||||||||||||||||||||||||||||||
| pullRequestUrl: z.string().optional(), | ||||||||||||||||||||||||||||||||||||
| provider: z.string().optional(), | ||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||
| .optional(), | ||||||||||||||||||||||||||||||||||||
| /** Vercel integration data */ | ||||||||||||||||||||||||||||||||||||
| vercel: z | ||||||||||||||||||||||||||||||||||||
| .object({ | ||||||||||||||||||||||||||||||||||||
| deploymentUrl: z.string(), | ||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||
| .optional(), | ||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| const deploymentDeploymentCommonProperties = { | ||||||||||||||||||||||||||||||||||||
| /** Deployment ID */ | ||||||||||||||||||||||||||||||||||||
| id: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Deployment status */ | ||||||||||||||||||||||||||||||||||||
| status: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Deployment version */ | ||||||||||||||||||||||||||||||||||||
| version: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Short code identifier */ | ||||||||||||||||||||||||||||||||||||
| shortCode: z.string(), | ||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| /** Represents a successful deployment alert webhook payload */ | ||||||||||||||||||||||||||||||||||||
| export const AlertWebhookDeploymentSuccessObject = z.object({ | ||||||||||||||||||||||||||||||||||||
| ...deploymentCommonProperties, | ||||||||||||||||||||||||||||||||||||
| deployment: z.object({ | ||||||||||||||||||||||||||||||||||||
| ...deploymentDeploymentCommonProperties, | ||||||||||||||||||||||||||||||||||||
| /** When the deployment completed */ | ||||||||||||||||||||||||||||||||||||
| deployedAt: z.coerce.date(), | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** Deployed tasks */ | ||||||||||||||||||||||||||||||||||||
| tasks: z.array( | ||||||||||||||||||||||||||||||||||||
| z.object({ | ||||||||||||||||||||||||||||||||||||
| /** Task ID */ | ||||||||||||||||||||||||||||||||||||
| id: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** File path where the task is defined */ | ||||||||||||||||||||||||||||||||||||
| filePath: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Name of the exported task function */ | ||||||||||||||||||||||||||||||||||||
| exportName: z.string().optional(), | ||||||||||||||||||||||||||||||||||||
| /** Source of the trigger */ | ||||||||||||||||||||||||||||||||||||
| triggerSource: z.string(), | ||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| /** Represents a failed deployment alert webhook payload */ | ||||||||||||||||||||||||||||||||||||
| export const AlertWebhookDeploymentFailedObject = z.object({ | ||||||||||||||||||||||||||||||||||||
| ...deploymentCommonProperties, | ||||||||||||||||||||||||||||||||||||
| deployment: z.object({ | ||||||||||||||||||||||||||||||||||||
| ...deploymentDeploymentCommonProperties, | ||||||||||||||||||||||||||||||||||||
| /** When the deployment failed */ | ||||||||||||||||||||||||||||||||||||
| failedAt: z.coerce.date(), | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** Error information */ | ||||||||||||||||||||||||||||||||||||
| error: DeployError, | ||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| export type AlertWebhookDeploymentSuccessObject = z.infer< | ||||||||||||||||||||||||||||||||||||
| typeof AlertWebhookDeploymentSuccessObject | ||||||||||||||||||||||||||||||||||||
| >; | ||||||||||||||||||||||||||||||||||||
| export type AlertWebhookDeploymentFailedObject = z.infer<typeof AlertWebhookDeploymentFailedObject>; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| /** Represents an error group alert webhook payload */ | ||||||||||||||||||||||||||||||||||||
| export const AlertWebhookErrorGroupObject = z.object({ | ||||||||||||||||||||||||||||||||||||
| /** Classification of the error alert */ | ||||||||||||||||||||||||||||||||||||
| classification: z.enum(["new_issue", "regression", "unignored"]), | ||||||||||||||||||||||||||||||||||||
| /** Error information */ | ||||||||||||||||||||||||||||||||||||
| error: z.object({ | ||||||||||||||||||||||||||||||||||||
| /** Error fingerprint identifier */ | ||||||||||||||||||||||||||||||||||||
| fingerprint: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Error type */ | ||||||||||||||||||||||||||||||||||||
| type: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Error message */ | ||||||||||||||||||||||||||||||||||||
| message: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Sample stack trace */ | ||||||||||||||||||||||||||||||||||||
| stackTrace: z.string().optional(), | ||||||||||||||||||||||||||||||||||||
| /** When the error was first seen */ | ||||||||||||||||||||||||||||||||||||
| firstSeen: z.coerce.date(), | ||||||||||||||||||||||||||||||||||||
| /** When the error was last seen */ | ||||||||||||||||||||||||||||||||||||
| lastSeen: z.coerce.date(), | ||||||||||||||||||||||||||||||||||||
| /** Number of occurrences */ | ||||||||||||||||||||||||||||||||||||
| occurrenceCount: z.number(), | ||||||||||||||||||||||||||||||||||||
| /** Task identifier where the error occurred */ | ||||||||||||||||||||||||||||||||||||
| taskIdentifier: z.string(), | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** Environment information */ | ||||||||||||||||||||||||||||||||||||
| environment: z.object({ | ||||||||||||||||||||||||||||||||||||
| /** Environment ID */ | ||||||||||||||||||||||||||||||||||||
| id: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Environment name */ | ||||||||||||||||||||||||||||||||||||
| name: z.string(), | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** Organization information */ | ||||||||||||||||||||||||||||||||||||
| organization: z.object({ | ||||||||||||||||||||||||||||||||||||
| /** Organization ID */ | ||||||||||||||||||||||||||||||||||||
| id: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Organization slug */ | ||||||||||||||||||||||||||||||||||||
| slug: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Organization name */ | ||||||||||||||||||||||||||||||||||||
| name: z.string(), | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** Project information */ | ||||||||||||||||||||||||||||||||||||
| project: z.object({ | ||||||||||||||||||||||||||||||||||||
| /** Project ID */ | ||||||||||||||||||||||||||||||||||||
| id: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Project reference */ | ||||||||||||||||||||||||||||||||||||
| ref: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Project slug */ | ||||||||||||||||||||||||||||||||||||
| slug: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** Project name */ | ||||||||||||||||||||||||||||||||||||
| name: z.string(), | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** URL to view the error in the dashboard */ | ||||||||||||||||||||||||||||||||||||
| dashboardUrl: z.string(), | ||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| export type AlertWebhookErrorGroupObject = z.infer<typeof AlertWebhookErrorGroupObject>; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| /** Common properties for all webhooks */ | ||||||||||||||||||||||||||||||||||||
| const commonProperties = { | ||||||||||||||||||||||||||||||||||||
| /** Webhook ID */ | ||||||||||||||||||||||||||||||||||||
| id: z.string(), | ||||||||||||||||||||||||||||||||||||
| /** When the webhook was created */ | ||||||||||||||||||||||||||||||||||||
| created: z.coerce.date(), | ||||||||||||||||||||||||||||||||||||
| /** Version of the webhook */ | ||||||||||||||||||||||||||||||||||||
| webhookVersion: z.string(), | ||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| /** Represents all possible webhook types */ | ||||||||||||||||||||||||||||||||||||
| export const Webhook = z.discriminatedUnion("type", [ | ||||||||||||||||||||||||||||||||||||
| /** Run failed alert webhook */ | ||||||||||||||||||||||||||||||||||||
| z.object({ | ||||||||||||||||||||||||||||||||||||
| ...commonProperties, | ||||||||||||||||||||||||||||||||||||
| type: z.literal("alert.run.failed"), | ||||||||||||||||||||||||||||||||||||
| object: AlertWebhookRunFailedObject, | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** Deployment success alert webhook */ | ||||||||||||||||||||||||||||||||||||
| z.object({ | ||||||||||||||||||||||||||||||||||||
| ...commonProperties, | ||||||||||||||||||||||||||||||||||||
| type: z.literal("alert.deployment.success"), | ||||||||||||||||||||||||||||||||||||
| object: AlertWebhookDeploymentSuccessObject, | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** Deployment failed alert webhook */ | ||||||||||||||||||||||||||||||||||||
| z.object({ | ||||||||||||||||||||||||||||||||||||
| ...commonProperties, | ||||||||||||||||||||||||||||||||||||
| type: z.literal("alert.deployment.failed"), | ||||||||||||||||||||||||||||||||||||
| object: AlertWebhookDeploymentFailedObject, | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| /** Error group alert webhook */ | ||||||||||||||||||||||||||||||||||||
| z.object({ | ||||||||||||||||||||||||||||||||||||
| ...commonProperties, | ||||||||||||||||||||||||||||||||||||
| type: z.literal("alert.error"), | ||||||||||||||||||||||||||||||||||||
| object: AlertWebhookErrorGroupObject, | ||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||
| ]); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| export type Webhook = z.infer<typeof Webhook>; | ||||||||||||||||||||||||||||||||||||
| export type RunFailedWebhook = Extract<Webhook, { type: "alert.run.failed" }>; | ||||||||||||||||||||||||||||||||||||
| export type DeploymentSuccessWebhook = Extract<Webhook, { type: "alert.deployment.success" }>; | ||||||||||||||||||||||||||||||||||||
| export type DeploymentFailedWebhook = Extract<Webhook, { type: "alert.deployment.failed" }>; | ||||||||||||||||||||||||||||||||||||
| export type ErrorWebhook = Extract<Webhook, { type: "alert.error" }>; | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚩 Massive removal of exported schemas and types breaks multiple consumers
This PR removes the following exports that are actively used across the codebase:
Webhook(discriminated union),AlertWebhookDeploymentSuccessObject,AlertWebhookDeploymentFailedObject,AlertWebhookErrorGroupObject,DeployError,RunFailedWebhook,DeploymentSuccessWebhook,DeploymentFailedWebhook,ErrorWebhook, and theAlertWebhookRunFailedObjecttype alias. These are imported and used in:packages/trigger-sdk/src/v3/webhooks.ts:1— importsWebhookand callsWebhook.parse()at line 101apps/webapp/app/v3/services/alerts/deliverAlert.server.ts:11-14— importsDeploymentFailedWebhook,DeploymentSuccessWebhook,RunFailedWebhookas typesapps/webapp/app/v3/services/alerts/errorGroupWebhook.server.ts:2— importsErrorWebhooktypeapps/webapp/test/errorGroupWebhook.test.ts:2andapps/webapp/test/webhookErrorAlerts.test.ts:2— importWebhookfor test validationWhile TypeScript CI should catch the compilation failures, the semantic impact is worth noting: the entire SDK webhook verification flow (
webhooks.constructEvent()) is broken since it depends onWebhook.parse(). This is a breaking change for the published@trigger.dev/sdkpackage, and perpackages/core/CLAUDE.md, changes to@trigger.dev/coreaffect both the customer-facing SDK and the server-side webapp.Was this helpful? React with 👍 or 👎 to provide feedback.