Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
5b5b37c
feat(db): Database changes for Vercel integration
0ski Jan 8, 2026
6bc58cb
feat(vercel): add Vercel integration settings UI and actions
0ski Jan 9, 2026
2f2e81e
feat(integrations): add Vercel integration settings UI and paths
0ski Jan 9, 2026
09492db
feat(telemetry include referralSource in identify and clear cookie fo…
0ski Jan 9, 2026
9546a85
feat(vercel): Vercel side initialized installation
0ski Jan 9, 2026
b27d31b
refactor(vercel): tidy imports, adjust dialog structure, and unify types
0ski Jan 12, 2026
7c6289d
refactor(vercel): normalize env responses and helpers
0ski Jan 12, 2026
852f249
refactor(vercel): AI Deslop
0ski Jan 12, 2026
588761c
feat(vercel): add install param parser and org requirement helper
0ski Jan 12, 2026
78f124e
feat(vercel): update tokens, refine env lookup & cleanup
0ski Jan 12, 2026
9fb56a3
fix(vercel): surface auth failures and handle uninstall flows
0ski Jan 12, 2026
773210a
feat(vercel): implement robust OAuth callback handling
0ski Jan 12, 2026
f52f97d
feat(onboarding): add Vercel onboarding route and OAuth handling
0ski Jan 13, 2026
f62f059
feat(vercel): integrate app slug, update callbacks, and clean UI imports
0ski Jan 14, 2026
aa43913
feat(vercel): pass environment id and centralize OAuth exchange
0ski Jan 16, 2026
4d576d1
feat(api): Add environmentSlug for initialize deployment response body
0ski Jan 23, 2026
ebae7bd
feat(vercel): preserve secret status when syncing env vars&improve se…
0ski Jan 26, 2026
e5de04a
feat(env): skip unchanged env var updates and preserve secrets
0ski Jan 26, 2026
dbc9100
feat(db): add versioning and lastUpdatedBy to env vars
0ski Jan 26, 2026
8ec62cc
feat(env-vars): add updater metadata and include user info
0ski Jan 26, 2026
ee467ad
feat(vercel): add pullNewEnvVars option and modal dismiss control
0ski Jan 28, 2026
5c1beab
feat(vercel): enhance staging environment handling and add preview su…
0ski Jan 29, 2026
ddb32a8
feat(vercel): refine integration defaults and surface settings
0ski Feb 2, 2026
0d8005b
feat(webapp): tidy environment variables table layout
0ski Feb 2, 2026
7994688
feat(api): add source metadata for env var imports
0ski Feb 2, 2026
a8dd4b0
feat(vercel): implement build settings fields for Vercel integration
0ski Feb 3, 2026
fc1f9b2
feat(vercel): add Vercel onboarding modal component
0ski Feb 3, 2026
35d085f
fix(webapp): Fix typings
0ski Feb 3, 2026
fe203ef
feat(vercel): PR feedback changes
0ski Feb 3, 2026
9893b56
chore(webapp): Logging cleanup
0ski Feb 3, 2026
b209431
chore(core): Remove unused enum
0ski Feb 3, 2026
39e6a84
feat(core): Add Vercel integration changelog
0ski Feb 3, 2026
b7ad2ed
chore(vercel): Rewrite logic to use neverthrow instead of try-catch
0ski Feb 3, 2026
9287310
refactor(vercel): Enhance Vercel integration handling with ResultAsyn…
0ski Feb 5, 2026
3b8f6da
feat(vercel): Enhance RegenerateApiKeyModal to include Vercel integra…
0ski Feb 5, 2026
45ba388
feat(vercel): Add onboarding completion state to Vercel integration a…
0ski Feb 5, 2026
72f2b4a
feat(vercel): Refactor Vercel integration components for improved fun…
0ski Feb 5, 2026
12c62a0
feat(vercel): Update Vercel SDK and enhance environment variable hand…
0ski Feb 6, 2026
05d877a
feat(vercel): persist team slug and surface Vercel joins in deployments
0ski Feb 6, 2026
3597818
feat(vercel): enhance Vercel integration with URL sanitization, impro…
0ski Feb 6, 2026
5762f53
feat(vercel): refactor Vercel resource path handling and improve redi…
0ski Feb 6, 2026
d23d10d
feat(vercel): implement envSlugArrayField for JSON-encoded EnvSlug ar…
0ski Feb 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/vercel-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@trigger.dev/core": patch
---

Add Vercel integration support to API schemas: `commitSHA` and `integrationDeployments` on deployment responses, and `source` field for environment variable imports.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
"packages/cli-v3/e2e": true
},
"vitest.disableWorkspaceWarning": true,
"typescript.experimental.useTsgo": false
"typescript.experimental.useTsgo": true,
"chat.agent.maxRequests": 10000
}
2 changes: 0 additions & 2 deletions apps/webapp/app/components/GitHubLoginButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ export function OctoKitty({ className }: { className?: string }) {
baseProfile="tiny"
id="Layer_1"
xmlns="http://www.w3.org/2000/svg"
x="0px"
y="0px"
viewBox="0 0 2350 2314.8"
xmlSpace="preserve"
fill="currentColor"
Expand Down
30 changes: 28 additions & 2 deletions apps/webapp/app/components/environments/RegenerateApiKeyModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,27 @@ import { FormButtons } from "../primitives/FormButtons";
import { Input } from "../primitives/Input";
import { InputGroup } from "../primitives/InputGroup";
import { Paragraph } from "../primitives/Paragraph";
import { CheckboxWithLabel } from "../primitives/Checkbox";
import { Spinner } from "../primitives/Spinner";

type ModalProps = {
id: string;
title: string;
hasVercelIntegration: boolean;
isDevelopment: boolean;
};

type ModalContentProps = ModalProps & {
randomWord: string;
closeModal: () => void;
};

export function RegenerateApiKeyModal({ id, title }: ModalProps) {
export function RegenerateApiKeyModal({
id,
title,
hasVercelIntegration,
isDevelopment,
}: ModalProps) {
const randomWord = generateTwoRandomWords();
const [open, setOpen] = useState(false);
return (
Expand All @@ -37,6 +45,8 @@ export function RegenerateApiKeyModal({ id, title }: ModalProps) {
<RegenerateApiKeyModalContent
id={id}
title={title}
hasVercelIntegration={hasVercelIntegration}
isDevelopment={isDevelopment}
randomWord={randomWord}
closeModal={() => setOpen(false)}
/>
Expand All @@ -45,7 +55,14 @@ export function RegenerateApiKeyModal({ id, title }: ModalProps) {
);
}

const RegenerateApiKeyModalContent = ({ id, randomWord, title, closeModal }: ModalContentProps) => {
const RegenerateApiKeyModalContent = ({
id,
randomWord,
title,
hasVercelIntegration,
isDevelopment,
closeModal,
}: ModalContentProps) => {
const [confirmationText, setConfirmationText] = useState("");
const fetcher = useFetcher();
const isSubmitting = fetcher.state === "submitting";
Expand Down Expand Up @@ -83,6 +100,15 @@ const RegenerateApiKeyModalContent = ({ id, randomWord, title, closeModal }: Mod
onChange={(e) => setConfirmationText(e.target.value)}
/>
</InputGroup>
{hasVercelIntegration && !isDevelopment && (
<CheckboxWithLabel
name="syncToVercel"
variant="simple/small"
label="Also update TRIGGER_SECRET_KEY in Vercel"
defaultChecked={true}
value="on"
/>
)}
<FormButtons
confirmButton={
<Button
Expand Down
176 changes: 176 additions & 0 deletions apps/webapp/app/components/integrations/VercelBuildSettings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import { Switch } from "~/components/primitives/Switch";
import { Label } from "~/components/primitives/Label";
import { Hint } from "~/components/primitives/Hint";
import { TextLink } from "~/components/primitives/TextLink";
import {
EnvironmentIcon,
environmentFullTitle,
environmentTextClassName,
} from "~/components/environments/EnvironmentLabel";
import { envSlugToType, type EnvSlug } from "~/v3/vercel/vercelProjectIntegrationSchema";

type BuildSettingsFieldsProps = {
availableEnvSlugs: EnvSlug[];
pullEnvVarsBeforeBuild: EnvSlug[];
onPullEnvVarsChange: (slugs: EnvSlug[]) => void;
discoverEnvVars: EnvSlug[];
onDiscoverEnvVarsChange: (slugs: EnvSlug[]) => void;
atomicBuilds: EnvSlug[];
onAtomicBuildsChange: (slugs: EnvSlug[]) => void;
envVarsConfigLink?: string;
};

export function BuildSettingsFields({
availableEnvSlugs,
pullEnvVarsBeforeBuild,
onPullEnvVarsChange,
discoverEnvVars,
onDiscoverEnvVarsChange,
atomicBuilds,
onAtomicBuildsChange,
envVarsConfigLink,
}: BuildSettingsFieldsProps) {
return (
<>
{/* Pull env vars before build */}
<div>
<div className="mb-2 flex items-center justify-between">
<div>
<Label>Pull env vars before build</Label>
<Hint>
Select which environments should pull environment variables from Vercel before each
build.{" "}
{envVarsConfigLink && (
<>
<TextLink to={envVarsConfigLink}>Configure which variables to pull</TextLink>.
</>
)}
</Hint>
</div>
{availableEnvSlugs.length > 1 && (
<Switch
variant="small"
checked={
availableEnvSlugs.length > 0 &&
availableEnvSlugs.every((s) => pullEnvVarsBeforeBuild.includes(s))
}
onCheckedChange={(checked) => {
onPullEnvVarsChange(checked ? [...availableEnvSlugs] : []);
}}
/>
)}
</div>
<div className="flex flex-col gap-2 rounded border bg-charcoal-800 p-3">
{availableEnvSlugs.map((slug) => {
const envType = envSlugToType(slug);
return (
<div key={slug} className="flex items-center justify-between">
<div className="flex items-center gap-1.5">
<EnvironmentIcon environment={{ type: envType }} className="size-4" />
<span className={`text-sm ${environmentTextClassName({ type: envType })}`}>
{environmentFullTitle({ type: envType })}
</span>
</div>
<Switch
variant="small"
checked={pullEnvVarsBeforeBuild.includes(slug)}
onCheckedChange={(checked) => {
onPullEnvVarsChange(
checked
? [...pullEnvVarsBeforeBuild, slug]
: pullEnvVarsBeforeBuild.filter((s) => s !== slug)
);
}}
/>
</div>
);
})}
</div>
</div>

{/* Discover new env vars */}
<div>
<div className="mb-2 flex items-center justify-between">
<div>
<Label>Discover new env vars</Label>
<Hint>
Select which environments should automatically discover and create new environment
variables from Vercel during builds.
</Hint>
</div>
{availableEnvSlugs.length > 1 && (
<Switch
variant="small"
checked={
availableEnvSlugs.length > 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))
: []
);
}}
/>
)}
</div>
<div className="flex flex-col gap-2 rounded border bg-charcoal-800 p-3">
{availableEnvSlugs.map((slug) => {
const envType = envSlugToType(slug);
const isPullDisabled = !pullEnvVarsBeforeBuild.includes(slug);
return (
<div
key={slug}
className={`flex items-center justify-between ${isPullDisabled ? "opacity-50" : ""}`}
>
<div className="flex items-center gap-1.5">
<EnvironmentIcon environment={{ type: envType }} className="size-4" />
<span className={`text-sm ${environmentTextClassName({ type: envType })}`}>
{environmentFullTitle({ type: envType })}
</span>
</div>
<Switch
variant="small"
checked={discoverEnvVars.includes(slug)}
disabled={isPullDisabled}
onCheckedChange={(checked) => {
onDiscoverEnvVarsChange(
checked
? [...discoverEnvVars, slug]
: discoverEnvVars.filter((s) => s !== slug)
);
}}
/>
</div>
);
})}
</div>
</div>

{/* Atomic deployments */}
<div>
<div className="flex items-center justify-between">
<div>
<Label>Atomic deployments</Label>
<Hint>
When enabled, production deployments wait for Vercel deployment to complete before
promoting the Trigger.dev deployment.
</Hint>
</div>
<Switch
variant="small"
checked={atomicBuilds.includes("prod")}
onCheckedChange={(checked) => {
onAtomicBuildsChange(checked ? ["prod"] : []);
}}
/>
</div>
</div>
</>
);
}
12 changes: 12 additions & 0 deletions apps/webapp/app/components/integrations/VercelLogo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export function VercelLogo({ className }: { className?: string }) {
return (
<svg
viewBox="0 0 76 65"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
>
<path d="M37.5274 0L75.0548 65H0L37.5274 0Z" fill="currentColor" />
</svg>
);
}
Loading