Skip to content

Commit 2fd0cdc

Browse files
committed
feat(vercel): automatic version skew protection at connect + atomic deployments deprecation
Connecting a Vercel project now writes TRIGGER_AUTOMATIC_SKEW_VERSION_PROTECTION=1 (plain, create-if-absent only - an existing value, including "0", is never touched; presence is target-containment aware, branch-scoped records do not count, a truncated env listing skips the write). The onboarding wizard no longer offers automatic atomic deployments (default off); the settings row is labelled Deprecated and enabling it requires confirming a dialog that points to task version skew protection and the docs (TRI-13001).
1 parent 1034b61 commit 2fd0cdc

9 files changed

Lines changed: 485 additions & 46 deletions
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: improvement
4+
---
5+
6+
New Vercel connections now get version skew protection turned on automatically, so each run uses the task version its deployment shipped with. Automatic atomic deployments are deprecated and no longer offered when you connect a project, but stay available in your Vercel integration settings.

apps/webapp/app/components/integrations/VercelBuildSettings.tsx

Lines changed: 81 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { Switch } from "~/components/primitives/Switch";
22
import { LinkButton } from "~/components/primitives/Buttons";
3+
import { Badge } from "~/components/primitives/Badge";
34
import { Label } from "~/components/primitives/Label";
45
import {
56
SettingsRow,
67
SettingsRowDescription,
78
SettingsRowTitle,
89
} from "~/components/primitives/SettingsLayout";
910
import { cn } from "~/utils/cn";
11+
import { docsPath } from "~/utils/pathBuilder";
1012
import { Hint } from "~/components/primitives/Hint";
1113
import { TextLink } from "~/components/primitives/TextLink";
1214
import { SimpleTooltip } from "~/components/primitives/Tooltip";
@@ -17,6 +19,16 @@ import {
1719
} from "~/components/environments/EnvironmentLabel";
1820
import { envSlugToType, type EnvSlug } from "~/v3/vercel/vercelProjectIntegrationSchema";
1921

22+
export const SKEW_PROTECTION_DOCS_PATH = docsPath("deployment/version-skew-protection");
23+
24+
export const SKEW_PROTECTION_MIN_SDK_VERSION: string | null = null;
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+
2032
type 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,7 +154,20 @@ 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>
162+
<SettingsRowDescription>
163+
Superseded by task version skew protection, which pins each run to the deployment that
164+
triggered it, automatically {skewProtectionVersionRequirement()}. Atomic deployments
165+
keep working, and turning them off is your call.{" "}
166+
<TextLink href={SKEW_PROTECTION_DOCS_PATH} target="_blank">
167+
Read about version skew protection
168+
</TextLink>
169+
.
170+
</SettingsRowDescription>
144171
<SettingsRowDescription>
145172
Promotes your Vercel deployment and your tasks together in Production, so your app
146173
never runs against a mismatched task version. Requires turning off "Auto-assign Custom
@@ -172,7 +199,7 @@ export function BuildSettingsFields({
172199
{atomicBuilds.includes("prod") && onAutoPromoteChange !== undefined && (
173200
<SettingsRow
174201
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."
202+
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."
176203
action={
177204
<Switch
178205
variant="medium"
@@ -333,10 +360,14 @@ export function BuildSettingsFields({
333360
{atomicSections}
334361

335362
{/* Atomic deployments */}
336-
{layout === "card" && (
363+
{layout === "card" && showAtomicDeployments && (
337364
<div>
338365
<div className="flex items-center justify-between">
339-
<Label>Atomic deployments</Label>
366+
<Label>
367+
<span className="flex items-center gap-2">
368+
Atomic deployments <DeprecatedBadge />
369+
</span>
370+
</Label>
340371
<Switch
341372
variant="small"
342373
checked={atomicBuilds.includes("prod")}
@@ -345,6 +376,14 @@ export function BuildSettingsFields({
345376
}}
346377
/>
347378
</div>
379+
<Hint className="pr-6">
380+
Superseded by task version skew protection, which is automatic{" "}
381+
{skewProtectionVersionRequirement()}.{" "}
382+
<TextLink href={SKEW_PROTECTION_DOCS_PATH} target="_blank">
383+
Read about version skew protection
384+
</TextLink>
385+
.
386+
</Hint>
348387
<Hint className="pr-6">
349388
When enabled, production deployments wait for Vercel deployment to complete before
350389
promoting the Trigger.dev deployment. This will disable the "Auto-assign Custom
@@ -375,27 +414,48 @@ export function BuildSettingsFields({
375414
)}
376415

377416
{/* 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-
/>
417+
{layout === "card" &&
418+
showAtomicDeployments &&
419+
atomicBuilds.includes("prod") &&
420+
onAutoPromoteChange !== undefined && (
421+
<div>
422+
<div className="flex items-center justify-between">
423+
<Label>Auto promotion</Label>
424+
<Switch
425+
variant="small"
426+
checked={autoPromote ?? true}
427+
onCheckedChange={onAutoPromoteChange}
428+
/>
429+
</div>
430+
<Hint className="pr-6">
431+
When enabled, the integration automatically promotes the Vercel deployment after the
432+
Trigger.dev build completes. Turn off to manually promote from your Vercel dashboard —
433+
Trigger.dev will then promote automatically once you do.
434+
</Hint>
387435
</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-
)}
436+
)}
395437
</>
396438
);
397439
}
398440

441+
function DeprecatedBadge() {
442+
return (
443+
<SimpleTooltip
444+
asChild
445+
button={
446+
<Badge
447+
variant="extra-small"
448+
className="text-warning system:border-transparent system:bg-warning system:text-white"
449+
>
450+
Deprecated
451+
</Badge>
452+
}
453+
content="Use version skew protection instead"
454+
disableHoverableContent
455+
/>
456+
);
457+
}
458+
399459
function EnvToggleRow({
400460
slug,
401461
checked,

apps/webapp/app/components/integrations/VercelOnboardingModal.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ export function VercelOnboardingModal({
235235
const [pullEnvVarsBeforeBuild, setPullEnvVarsBeforeBuild] = useState<EnvSlug[]>(
236236
() => availableEnvSlugsForOnboardingBuildSettings
237237
);
238-
const [atomicBuilds, setAtomicBuilds] = useState<EnvSlug[]>(() => ["prod"]);
238+
const [atomicBuilds, setAtomicBuilds] = useState<EnvSlug[]>([]);
239239
const [discoverEnvVars, setDiscoverEnvVars] = useState<EnvSlug[]>(
240240
() => availableEnvSlugsForOnboardingBuildSettings
241241
);
@@ -1164,7 +1164,7 @@ export function VercelOnboardingModal({
11641164
<div className="flex flex-col gap-4">
11651165
<Header3>Build Settings</Header3>
11661166
<Paragraph className="text-sm">
1167-
Configure how environment variables are pulled during builds and atomic deployments.
1167+
Configure how environment variables are pulled during builds.
11681168
</Paragraph>
11691169

11701170
<BuildSettingsFields
@@ -1176,6 +1176,7 @@ export function VercelOnboardingModal({
11761176
atomicBuilds={atomicBuilds}
11771177
onAtomicBuildsChange={setAtomicBuilds}
11781178
disabledEnvSlugs={disabledEnvSlugsForBuildSettings}
1179+
showAtomicDeployments={false}
11791180
/>
11801181

11811182
<FormButtons

0 commit comments

Comments
 (0)