11import { Switch } from "~/components/primitives/Switch" ;
22import { LinkButton } from "~/components/primitives/Buttons" ;
3+ import { Badge } from "~/components/primitives/Badge" ;
34import { Label } from "~/components/primitives/Label" ;
45import {
56 SettingsRow ,
67 SettingsRowDescription ,
78 SettingsRowTitle ,
89} from "~/components/primitives/SettingsLayout" ;
910import { cn } from "~/utils/cn" ;
11+ import { docsPath } from "~/utils/pathBuilder" ;
1012import { Hint } from "~/components/primitives/Hint" ;
1113import { TextLink } from "~/components/primitives/TextLink" ;
1214import { SimpleTooltip } from "~/components/primitives/Tooltip" ;
@@ -17,6 +19,16 @@ import {
1719} from "~/components/environments/EnvironmentLabel" ;
1820import { envSlugToType , type EnvSlug } from "~/v3/vercel/vercelProjectIntegrationSchema" ;
1921
22+ export const SKEW_PROTECTION_DOCS_PATH = docsPath ( "deployment/version-skew-protection" ) ;
23+
24+ const SKEW_PROTECTION_MIN_SDK_VERSION : string | null = "4.5.12" ;
25+
26+ export function skewProtectionVersionRequirement ( ) : string {
27+ return SKEW_PROTECTION_MIN_SDK_VERSION
28+ ? `from SDK and CLI v${ SKEW_PROTECTION_MIN_SDK_VERSION } and later`
29+ : "from a recent SDK and CLI — see the docs for the exact version" ;
30+ }
31+
2032type BuildSettingsFieldsProps = {
2133 availableEnvSlugs : EnvSlug [ ] ;
2234 pullEnvVarsBeforeBuild : EnvSlug [ ] ;
@@ -38,6 +50,7 @@ type BuildSettingsFieldsProps = {
3850 currentTriggerVersionFetchFailed ?: boolean ;
3951 /** Hide the section-level master toggles for "Pull env vars" and "Discover new env vars". */
4052 hideSectionToggles ?: boolean ;
53+ showAtomicDeployments ?: boolean ;
4154 layout ?: "settings" | "card" ;
4255} ;
4356
@@ -56,6 +69,7 @@ export function BuildSettingsFields({
5669 currentTriggerVersion,
5770 currentTriggerVersionFetchFailed,
5871 hideSectionToggles,
72+ showAtomicDeployments = true ,
5973 layout = "card" ,
6074} : BuildSettingsFieldsProps ) {
6175 const isSlugDisabled = ( slug : EnvSlug ) => ! ! disabledEnvSlugs ?. [ slug ] ;
@@ -126,7 +140,7 @@ export function BuildSettingsFields({
126140 ) : null ;
127141
128142 const atomicSections =
129- layout === "settings" ? (
143+ layout === "settings" && showAtomicDeployments ? (
130144 < >
131145 < SettingsRow
132146 action = {
@@ -140,11 +154,25 @@ export function BuildSettingsFields({
140154 }
141155 >
142156 < div className = "flex-1 space-y-1" >
143- < SettingsRowTitle > Atomic deployments</ SettingsRowTitle >
157+ < SettingsRowTitle >
158+ < span className = "flex items-center gap-2" >
159+ Atomic deployments < DeprecatedBadge />
160+ </ span >
161+ </ SettingsRowTitle >
144162 < SettingsRowDescription >
145- Promotes your Vercel deployment and your tasks together in Production, so your app
146- never runs against a mismatched task version. Requires turning off "Auto-assign Custom
147- Production Domains" on your Vercel project, which Trigger.dev does for you.{ " " }
163+ Version skew protection replaces this. It pins every run to the deployment that
164+ triggered it, and works on its own { skewProtectionVersionRequirement ( ) } . Atomic
165+ deployments still work, so turn this off whenever you're ready.{ " " }
166+ < TextLink href = { SKEW_PROTECTION_DOCS_PATH } target = "_blank" >
167+ Read about version skew protection
168+ </ TextLink >
169+ .
170+ </ SettingsRowDescription >
171+ < SettingsRowDescription >
172+ Atomic deployments promote your Vercel deployment and your tasks together in
173+ Production, so your app never runs against a mismatched task version. This needs
174+ "Auto-assign Custom Production Domains" turned off on your Vercel project, and
175+ Trigger.dev takes care of that for you.{ " " }
148176 < TextLink
149177 href = "https://trigger.dev/docs/vercel-integration#atomic-deployments"
150178 target = "_blank"
@@ -172,7 +200,7 @@ export function BuildSettingsFields({
172200 { atomicBuilds . includes ( "prod" ) && onAutoPromoteChange !== undefined && (
173201 < SettingsRow
174202 title = "Auto promotion"
175- description = "Once your tasks finish deploying, Trigger.dev promotes the Vercel deployment for you. Turn this off to promote from the Vercel dashboard yourself, and Trigger.dev will follow as soon as you do."
203+ description = "Part of atomic deployments, and only used while they are on. Once your tasks finish deploying, Trigger.dev promotes the Vercel deployment for you. Turn this off to promote from the Vercel dashboard yourself, and Trigger.dev will follow as soon as you do."
176204 action = {
177205 < Switch
178206 variant = "medium"
@@ -333,10 +361,14 @@ export function BuildSettingsFields({
333361 { atomicSections }
334362
335363 { /* Atomic deployments */ }
336- { layout === "card" && (
364+ { layout === "card" && showAtomicDeployments && (
337365 < div >
338366 < div className = "flex items-center justify-between" >
339- < Label > Atomic deployments</ Label >
367+ < Label >
368+ < span className = "flex items-center gap-2" >
369+ Atomic deployments < DeprecatedBadge />
370+ </ span >
371+ </ Label >
340372 < Switch
341373 variant = "small"
342374 checked = { atomicBuilds . includes ( "prod" ) }
@@ -346,10 +378,18 @@ export function BuildSettingsFields({
346378 />
347379 </ div >
348380 < Hint className = "pr-6" >
349- When enabled, production deployments wait for Vercel deployment to complete before
350- promoting the Trigger.dev deployment. This will disable the "Auto-assign Custom
351- Production Domains" option in your Vercel project settings to perform staged
352- deployments.{ " " }
381+ Version skew protection replaces this, and works on its own{ " " }
382+ { skewProtectionVersionRequirement ( ) } .{ " " }
383+ < TextLink href = { SKEW_PROTECTION_DOCS_PATH } target = "_blank" >
384+ Read about version skew protection
385+ </ TextLink >
386+ .
387+ </ Hint >
388+ < Hint className = "pr-6" >
389+ Atomic deployments promote your Vercel deployment and your tasks together in Production,
390+ so your app never runs against a mismatched task version. This needs "Auto-assign Custom
391+ Production Domains" turned off on your Vercel project, and Trigger.dev takes care of
392+ that for you.{ " " }
353393 < TextLink
354394 href = "https://trigger.dev/docs/vercel-integration#atomic-deployments"
355395 target = "_blank"
@@ -375,27 +415,48 @@ export function BuildSettingsFields({
375415 ) }
376416
377417 { /* Auto promotion — only visible when atomic deployments are on */ }
378- { layout === "card" && atomicBuilds . includes ( "prod" ) && onAutoPromoteChange !== undefined && (
379- < div >
380- < div className = "flex items-center justify-between" >
381- < Label > Auto promotion</ Label >
382- < Switch
383- variant = "small"
384- checked = { autoPromote ?? true }
385- onCheckedChange = { onAutoPromoteChange }
386- />
418+ { layout === "card" &&
419+ showAtomicDeployments &&
420+ atomicBuilds . includes ( "prod" ) &&
421+ onAutoPromoteChange !== undefined && (
422+ < div >
423+ < div className = "flex items-center justify-between" >
424+ < Label > Auto promotion</ Label >
425+ < Switch
426+ variant = "small"
427+ checked = { autoPromote ?? true }
428+ onCheckedChange = { onAutoPromoteChange }
429+ />
430+ </ div >
431+ < Hint className = "pr-6" >
432+ When enabled, the integration automatically promotes the Vercel deployment after the
433+ Trigger.dev build completes. Turn off to manually promote from your Vercel dashboard —
434+ Trigger.dev will then promote automatically once you do.
435+ </ Hint >
387436 </ div >
388- < Hint className = "pr-6" >
389- When enabled, the integration automatically promotes the Vercel deployment after the
390- Trigger.dev build completes. Turn off to manually promote from your Vercel dashboard —
391- Trigger.dev will then promote automatically once you do.
392- </ Hint >
393- </ div >
394- ) }
437+ ) }
395438 </ >
396439 ) ;
397440}
398441
442+ function DeprecatedBadge ( ) {
443+ return (
444+ < SimpleTooltip
445+ asChild
446+ button = {
447+ < Badge
448+ variant = "extra-small"
449+ className = "text-warning system:border-transparent system:bg-warning system:text-white"
450+ >
451+ Deprecated
452+ </ Badge >
453+ }
454+ content = "Use version skew protection instead"
455+ disableHoverableContent
456+ />
457+ ) ;
458+ }
459+
399460function EnvToggleRow ( {
400461 slug,
401462 checked,
0 commit comments