From d366c4481dd9eaa2ee66a65a774c409a9b5a2dac Mon Sep 17 00:00:00 2001 From: Oskar Otwinowski Date: Fri, 27 Feb 2026 18:49:01 +0100 Subject: [PATCH] feat(vercel): add recovery-wrapped Vercel SDK callsReplace direct wrapVercelCall and raw ResultAsync promises with newrecovery helpers to improve error handling and schema validation whencalling the Vercel SDK. - Import callVercelWithRecovery, wrapVercelCallWithRecovery and VercelSchemas and plug them into vercelIntegration flows. - Use wrapVercelCallWithRecovery for team/user lookups, project env listings, environment variable listings and shared env endpoints so responses are validated and errors are converted consistently. - Replace several ResultAsync.fromPromise usages with callVercelWithRecovery to attach schema checks and contextual metadata (e.g. validateVercelToken, resolveEnvVarValue). - Thread through toVercelApiError where appropriate to normalize error mapping. These changes improve robustness by validating API responses againstschemas and providing consistent recovery/context for transient orunexpected Vercel API failures. --- .../integrations/VercelBuildSettings.tsx | 116 ++++---- .../integrations/VercelOnboardingModal.tsx | 16 +- .../app/models/vercelIntegration.server.ts | 276 +++++++++++++----- .../app/models/vercelSdkRecovery.server.ts | 195 +++++++++++++ ...cts.$projectParam.env.$envParam.vercel.tsx | 21 ++ .../app/services/vercelIntegration.server.ts | 75 +++++ docs/vercel-integration.mdx | 28 ++ 7 files changed, 593 insertions(+), 134 deletions(-) create mode 100644 apps/webapp/app/models/vercelSdkRecovery.server.ts diff --git a/apps/webapp/app/components/integrations/VercelBuildSettings.tsx b/apps/webapp/app/components/integrations/VercelBuildSettings.tsx index 0111168ccfa..fb6410507c3 100644 --- a/apps/webapp/app/components/integrations/VercelBuildSettings.tsx +++ b/apps/webapp/app/components/integrations/VercelBuildSettings.tsx @@ -34,31 +34,31 @@ export function BuildSettingsFields({ <> {/* Pull env vars before build */}
-
-
+
+
- - Select which environments should pull environment variables from Vercel before each - build.{" "} - {envVarsConfigLink && ( - <> - Configure which variables to pull. - - )} - + {availableEnvSlugs.length > 1 && ( + 0 && + availableEnvSlugs.every((s) => pullEnvVarsBeforeBuild.includes(s)) + } + onCheckedChange={(checked) => { + onPullEnvVarsChange(checked ? [...availableEnvSlugs] : []); + }} + /> + )}
- {availableEnvSlugs.length > 1 && ( - 0 && - availableEnvSlugs.every((s) => pullEnvVarsBeforeBuild.includes(s)) - } - onCheckedChange={(checked) => { - onPullEnvVarsChange(checked ? [...availableEnvSlugs] : []); - }} - /> - )} + + Select which environments should pull environment variables from Vercel before each + build.{" "} + {envVarsConfigLink && ( + <> + Configure which variables to pull. + + )} +
{availableEnvSlugs.map((slug) => { @@ -90,34 +90,34 @@ export function BuildSettingsFields({ {/* Discover new env vars */}
-
-
+
+
- - Select which environments should automatically discover and create new environment - variables from Vercel during builds. - + {availableEnvSlugs.length > 1 && ( + 0 && + availableEnvSlugs.every( + (s) => discoverEnvVars.includes(s) || !pullEnvVarsBeforeBuild.includes(s) + ) && + availableEnvSlugs.some((s) => discoverEnvVars.includes(s)) + } + disabled={!availableEnvSlugs.some((s) => pullEnvVarsBeforeBuild.includes(s))} + onCheckedChange={(checked) => { + onDiscoverEnvVarsChange( + checked + ? availableEnvSlugs.filter((s) => pullEnvVarsBeforeBuild.includes(s)) + : [] + ); + }} + /> + )}
- {availableEnvSlugs.length > 1 && ( - 0 && - availableEnvSlugs.every( - (s) => discoverEnvVars.includes(s) || !pullEnvVarsBeforeBuild.includes(s) - ) && - availableEnvSlugs.some((s) => discoverEnvVars.includes(s)) - } - disabled={!availableEnvSlugs.some((s) => pullEnvVarsBeforeBuild.includes(s))} - onCheckedChange={(checked) => { - onDiscoverEnvVarsChange( - checked - ? availableEnvSlugs.filter((s) => pullEnvVarsBeforeBuild.includes(s)) - : [] - ); - }} - /> - )} + + Select which environments should automatically discover and create new environment + variables from Vercel during builds. +
{availableEnvSlugs.map((slug) => { @@ -155,13 +155,7 @@ export function BuildSettingsFields({ {/* Atomic deployments */}
-
- - - When enabled, production deployments wait for Vercel deployment to complete before - promoting the Trigger.dev deployment. - -
+
+ + When enabled, production deployments wait for Vercel deployment to complete before + promoting the Trigger.dev deployment. This will disable the "Auto-assign Custom + Production Domains" option in your Vercel project settings to perform staged + deployments.{" "} + + Learn more + + . +
); diff --git a/apps/webapp/app/components/integrations/VercelOnboardingModal.tsx b/apps/webapp/app/components/integrations/VercelOnboardingModal.tsx index f3635dbd08e..6c3e0e3b4df 100644 --- a/apps/webapp/app/components/integrations/VercelOnboardingModal.tsx +++ b/apps/webapp/app/components/integrations/VercelOnboardingModal.tsx @@ -679,7 +679,7 @@ export function VercelOnboardingModal({ onClose(); } }}> - + e.preventDefault()}>
@@ -800,6 +800,20 @@ export function VercelOnboardingModal({ ))} + +

+ If you skip this step, the{" "} + TRIGGER_SECRET_KEY{" "} + will not be installed for the staging environment in Vercel. You can configure this later in + project settings. +

+
+ + + Make sure the staging branch in your Vercel project's Git settings matches the staging branch + configured in your GitHub integration. + +