Skip to content

Commit 9b21f8d

Browse files
authored
feat(webapp): Vercel integration (#2994)
Vercel integration Desc + Vid coming soon For human reviewer: - check the db schema - check if posthog user attribution call is correct (telemetry.server.ts & `referralSource`) <!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/triggerdotdev/trigger.dev/pull/2994" target="_blank"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1"> <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open with Devin"> </picture> </a> <!-- devin-review-badge-end -->
1 parent e536d35 commit 9b21f8d

File tree

66 files changed

+8388
-173
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+8388
-173
lines changed

.changeset/vercel-integration.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@trigger.dev/core": patch
3+
---
4+
5+
Add Vercel integration support to API schemas: `commitSHA` and `integrationDeployments` on deployment responses, and `source` field for environment variable imports.

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@
77
"packages/cli-v3/e2e": true
88
},
99
"vitest.disableWorkspaceWarning": true,
10-
"typescript.experimental.useTsgo": false
10+
"typescript.experimental.useTsgo": true,
11+
"chat.agent.maxRequests": 10000
1112
}

apps/webapp/app/components/GitHubLoginButton.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ export function OctoKitty({ className }: { className?: string }) {
3232
baseProfile="tiny"
3333
id="Layer_1"
3434
xmlns="http://www.w3.org/2000/svg"
35-
x="0px"
36-
y="0px"
3735
viewBox="0 0 2350 2314.8"
3836
xmlSpace="preserve"
3937
fill="currentColor"

apps/webapp/app/components/environments/RegenerateApiKeyModal.tsx

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,27 @@ import { FormButtons } from "../primitives/FormButtons";
1010
import { Input } from "../primitives/Input";
1111
import { InputGroup } from "../primitives/InputGroup";
1212
import { Paragraph } from "../primitives/Paragraph";
13+
import { CheckboxWithLabel } from "../primitives/Checkbox";
1314
import { Spinner } from "../primitives/Spinner";
1415

1516
type ModalProps = {
1617
id: string;
1718
title: string;
19+
hasVercelIntegration: boolean;
20+
isDevelopment: boolean;
1821
};
1922

2023
type ModalContentProps = ModalProps & {
2124
randomWord: string;
2225
closeModal: () => void;
2326
};
2427

25-
export function RegenerateApiKeyModal({ id, title }: ModalProps) {
28+
export function RegenerateApiKeyModal({
29+
id,
30+
title,
31+
hasVercelIntegration,
32+
isDevelopment,
33+
}: ModalProps) {
2634
const randomWord = generateTwoRandomWords();
2735
const [open, setOpen] = useState(false);
2836
return (
@@ -37,6 +45,8 @@ export function RegenerateApiKeyModal({ id, title }: ModalProps) {
3745
<RegenerateApiKeyModalContent
3846
id={id}
3947
title={title}
48+
hasVercelIntegration={hasVercelIntegration}
49+
isDevelopment={isDevelopment}
4050
randomWord={randomWord}
4151
closeModal={() => setOpen(false)}
4252
/>
@@ -45,7 +55,14 @@ export function RegenerateApiKeyModal({ id, title }: ModalProps) {
4555
);
4656
}
4757

48-
const RegenerateApiKeyModalContent = ({ id, randomWord, title, closeModal }: ModalContentProps) => {
58+
const RegenerateApiKeyModalContent = ({
59+
id,
60+
randomWord,
61+
title,
62+
hasVercelIntegration,
63+
isDevelopment,
64+
closeModal,
65+
}: ModalContentProps) => {
4966
const [confirmationText, setConfirmationText] = useState("");
5067
const fetcher = useFetcher();
5168
const isSubmitting = fetcher.state === "submitting";
@@ -83,6 +100,15 @@ const RegenerateApiKeyModalContent = ({ id, randomWord, title, closeModal }: Mod
83100
onChange={(e) => setConfirmationText(e.target.value)}
84101
/>
85102
</InputGroup>
103+
{hasVercelIntegration && !isDevelopment && (
104+
<CheckboxWithLabel
105+
name="syncToVercel"
106+
variant="simple/small"
107+
label="Also update TRIGGER_SECRET_KEY in Vercel"
108+
defaultChecked={true}
109+
value="on"
110+
/>
111+
)}
86112
<FormButtons
87113
confirmButton={
88114
<Button
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
import { Switch } from "~/components/primitives/Switch";
2+
import { Label } from "~/components/primitives/Label";
3+
import { Hint } from "~/components/primitives/Hint";
4+
import { TextLink } from "~/components/primitives/TextLink";
5+
import {
6+
EnvironmentIcon,
7+
environmentFullTitle,
8+
environmentTextClassName,
9+
} from "~/components/environments/EnvironmentLabel";
10+
import { envSlugToType, type EnvSlug } from "~/v3/vercel/vercelProjectIntegrationSchema";
11+
12+
type BuildSettingsFieldsProps = {
13+
availableEnvSlugs: EnvSlug[];
14+
pullEnvVarsBeforeBuild: EnvSlug[];
15+
onPullEnvVarsChange: (slugs: EnvSlug[]) => void;
16+
discoverEnvVars: EnvSlug[];
17+
onDiscoverEnvVarsChange: (slugs: EnvSlug[]) => void;
18+
atomicBuilds: EnvSlug[];
19+
onAtomicBuildsChange: (slugs: EnvSlug[]) => void;
20+
envVarsConfigLink?: string;
21+
};
22+
23+
export function BuildSettingsFields({
24+
availableEnvSlugs,
25+
pullEnvVarsBeforeBuild,
26+
onPullEnvVarsChange,
27+
discoverEnvVars,
28+
onDiscoverEnvVarsChange,
29+
atomicBuilds,
30+
onAtomicBuildsChange,
31+
envVarsConfigLink,
32+
}: BuildSettingsFieldsProps) {
33+
return (
34+
<>
35+
{/* Pull env vars before build */}
36+
<div>
37+
<div className="mb-2 flex items-center justify-between">
38+
<div>
39+
<Label>Pull env vars before build</Label>
40+
<Hint>
41+
Select which environments should pull environment variables from Vercel before each
42+
build.{" "}
43+
{envVarsConfigLink && (
44+
<>
45+
<TextLink to={envVarsConfigLink}>Configure which variables to pull</TextLink>.
46+
</>
47+
)}
48+
</Hint>
49+
</div>
50+
{availableEnvSlugs.length > 1 && (
51+
<Switch
52+
variant="small"
53+
checked={
54+
availableEnvSlugs.length > 0 &&
55+
availableEnvSlugs.every((s) => pullEnvVarsBeforeBuild.includes(s))
56+
}
57+
onCheckedChange={(checked) => {
58+
onPullEnvVarsChange(checked ? [...availableEnvSlugs] : []);
59+
}}
60+
/>
61+
)}
62+
</div>
63+
<div className="flex flex-col gap-2 rounded border bg-charcoal-800 p-3">
64+
{availableEnvSlugs.map((slug) => {
65+
const envType = envSlugToType(slug);
66+
return (
67+
<div key={slug} className="flex items-center justify-between">
68+
<div className="flex items-center gap-1.5">
69+
<EnvironmentIcon environment={{ type: envType }} className="size-4" />
70+
<span className={`text-sm ${environmentTextClassName({ type: envType })}`}>
71+
{environmentFullTitle({ type: envType })}
72+
</span>
73+
</div>
74+
<Switch
75+
variant="small"
76+
checked={pullEnvVarsBeforeBuild.includes(slug)}
77+
onCheckedChange={(checked) => {
78+
onPullEnvVarsChange(
79+
checked
80+
? [...pullEnvVarsBeforeBuild, slug]
81+
: pullEnvVarsBeforeBuild.filter((s) => s !== slug)
82+
);
83+
}}
84+
/>
85+
</div>
86+
);
87+
})}
88+
</div>
89+
</div>
90+
91+
{/* Discover new env vars */}
92+
<div>
93+
<div className="mb-2 flex items-center justify-between">
94+
<div>
95+
<Label>Discover new env vars</Label>
96+
<Hint>
97+
Select which environments should automatically discover and create new environment
98+
variables from Vercel during builds.
99+
</Hint>
100+
</div>
101+
{availableEnvSlugs.length > 1 && (
102+
<Switch
103+
variant="small"
104+
checked={
105+
availableEnvSlugs.length > 0 &&
106+
availableEnvSlugs.every(
107+
(s) => discoverEnvVars.includes(s) || !pullEnvVarsBeforeBuild.includes(s)
108+
) &&
109+
availableEnvSlugs.some((s) => discoverEnvVars.includes(s))
110+
}
111+
disabled={!availableEnvSlugs.some((s) => pullEnvVarsBeforeBuild.includes(s))}
112+
onCheckedChange={(checked) => {
113+
onDiscoverEnvVarsChange(
114+
checked
115+
? availableEnvSlugs.filter((s) => pullEnvVarsBeforeBuild.includes(s))
116+
: []
117+
);
118+
}}
119+
/>
120+
)}
121+
</div>
122+
<div className="flex flex-col gap-2 rounded border bg-charcoal-800 p-3">
123+
{availableEnvSlugs.map((slug) => {
124+
const envType = envSlugToType(slug);
125+
const isPullDisabled = !pullEnvVarsBeforeBuild.includes(slug);
126+
return (
127+
<div
128+
key={slug}
129+
className={`flex items-center justify-between ${isPullDisabled ? "opacity-50" : ""}`}
130+
>
131+
<div className="flex items-center gap-1.5">
132+
<EnvironmentIcon environment={{ type: envType }} className="size-4" />
133+
<span className={`text-sm ${environmentTextClassName({ type: envType })}`}>
134+
{environmentFullTitle({ type: envType })}
135+
</span>
136+
</div>
137+
<Switch
138+
variant="small"
139+
checked={discoverEnvVars.includes(slug)}
140+
disabled={isPullDisabled}
141+
onCheckedChange={(checked) => {
142+
onDiscoverEnvVarsChange(
143+
checked
144+
? [...discoverEnvVars, slug]
145+
: discoverEnvVars.filter((s) => s !== slug)
146+
);
147+
}}
148+
/>
149+
</div>
150+
);
151+
})}
152+
</div>
153+
</div>
154+
155+
{/* Atomic deployments */}
156+
<div>
157+
<div className="flex items-center justify-between">
158+
<div>
159+
<Label>Atomic deployments</Label>
160+
<Hint>
161+
When enabled, production deployments wait for Vercel deployment to complete before
162+
promoting the Trigger.dev deployment.
163+
</Hint>
164+
</div>
165+
<Switch
166+
variant="small"
167+
checked={atomicBuilds.includes("prod")}
168+
onCheckedChange={(checked) => {
169+
onAtomicBuildsChange(checked ? ["prod"] : []);
170+
}}
171+
/>
172+
</div>
173+
</div>
174+
</>
175+
);
176+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
export function VercelLogo({ className }: { className?: string }) {
2+
return (
3+
<svg
4+
viewBox="0 0 76 65"
5+
fill="none"
6+
xmlns="http://www.w3.org/2000/svg"
7+
className={className}
8+
>
9+
<path d="M37.5274 0L75.0548 65H0L37.5274 0Z" fill="currentColor" />
10+
</svg>
11+
);
12+
}

0 commit comments

Comments
 (0)