Skip to content

feat(vercel): Vercel SDK fixes and correct env vars behavior for staging envs#3149

Merged
ericallam merged 1 commit intomainfrom
oskar/fix-vercel-integraiton
Feb 28, 2026
Merged

feat(vercel): Vercel SDK fixes and correct env vars behavior for staging envs#3149
ericallam merged 1 commit intomainfrom
oskar/fix-vercel-integraiton

Conversation

@0ski
Copy link
Collaborator

@0ski 0ski commented Feb 27, 2026

✅ Checklist

  • I have followed every step in the contributing guide
  • The PR title follows the convention.
  • I ran and tested the code works

Testing

Vercel onboarding

Changelog

  • 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.

Screenshots

💯

@changeset-bot
Copy link

changeset-bot bot commented Feb 27, 2026

⚠️ No Changeset found

Latest commit: d366c44

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 27, 2026

Walkthrough

Adds a Vercel SDK recovery layer (new vercelSdkRecovery module with VercelSchemas and recovery helpers) and migrates repository calls to recovery-enabled wrappers. Adds two repository methods to upsert/remove env vars for custom environments and a service method syncStagingKeyForCustomEnvironment to move TRIGGER_SECRET_KEY between custom environments. Updates route handlers to call the sync after relevant updates. UI changes in Vercel build/onboarding components: conditional switches, moved/added Hint blocks, per-env disabled/opacity states, and prevention of outside-click dismissal for onboarding dialogs. Docs: adds an atomic deployments sequence diagram and related notes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: Vercel SDK recovery fixes and corrected environment variable behavior for staging environments.
Description check ✅ Passed The description includes all required template sections: completed checklist, testing details, comprehensive changelog, and follows the expected format.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch oskar/fix-vercel-integraiton

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
apps/webapp/app/components/integrations/VercelBuildSettings.tsx (1)

167-176: Add rel="noopener noreferrer" to external link.

When using target="_blank" on external links, it's best practice to include rel="noopener noreferrer" to prevent potential security issues (reverse tabnapping) and referrer leakage in older browsers.

Suggested fix
-          <TextLink href="https://trigger.dev/docs/vercel-integration#atomic-deployments" target="_blank">
+          <TextLink href="https://trigger.dev/docs/vercel-integration#atomic-deployments" target="_blank" rel="noopener noreferrer">
             Learn more
           </TextLink>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/webapp/app/components/integrations/VercelBuildSettings.tsx` around lines
167 - 176, The external TextLink in VercelBuildSettings (inside the Hint block)
uses target="_blank" but is missing rel="noopener noreferrer"; update the
TextLink component instance used here to include rel="noopener noreferrer"
(i.e., add the rel prop to the TextLink element) to prevent reverse tabnapping
and referrer leakage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/webapp/app/components/integrations/VercelBuildSettings.tsx`:
- Around line 167-176: The external TextLink in VercelBuildSettings (inside the
Hint block) uses target="_blank" but is missing rel="noopener noreferrer";
update the TextLink component instance used here to include rel="noopener
noreferrer" (i.e., add the rel prop to the TextLink element) to prevent reverse
tabnapping and referrer leakage.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 24b92d3 and b20176c.

📒 Files selected for processing (7)
  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
  • apps/webapp/app/components/integrations/VercelOnboardingModal.tsx
  • apps/webapp/app/models/vercelIntegration.server.ts
  • apps/webapp/app/models/vercelSdkRecovery.server.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
  • apps/webapp/app/services/vercelIntegration.server.ts
  • docs/vercel-integration.mdx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
  • GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
  • GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
  • GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
  • GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
  • GitHub Check: typecheck / typecheck
🧰 Additional context used
📓 Path-based instructions (12)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx}: Use types over interfaces for TypeScript
Avoid using enums; prefer string unions or const objects instead

Files:

  • apps/webapp/app/models/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelOnboardingModal.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
  • apps/webapp/app/models/vercelSdkRecovery.server.ts
  • apps/webapp/app/services/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
{packages/core,apps/webapp}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use zod for validation in packages/core and apps/webapp

Files:

  • apps/webapp/app/models/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelOnboardingModal.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
  • apps/webapp/app/models/vercelSdkRecovery.server.ts
  • apps/webapp/app/services/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Use function declarations instead of default exports

Files:

  • apps/webapp/app/models/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelOnboardingModal.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
  • apps/webapp/app/models/vercelSdkRecovery.server.ts
  • apps/webapp/app/services/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
apps/webapp/app/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Access all environment variables through the env export of env.server.ts instead of directly accessing process.env in the Trigger.dev webapp

Files:

  • apps/webapp/app/models/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelOnboardingModal.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
  • apps/webapp/app/models/vercelSdkRecovery.server.ts
  • apps/webapp/app/services/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
apps/webapp/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

apps/webapp/**/*.{ts,tsx}: When importing from @trigger.dev/core in the webapp, use subpath exports from the package.json instead of importing from the root path
Follow the Remix 2.1.0 and Express server conventions when updating the main trigger.dev webapp

Files:

  • apps/webapp/app/models/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelOnboardingModal.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
  • apps/webapp/app/models/vercelSdkRecovery.server.ts
  • apps/webapp/app/services/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/otel-metrics.mdc)

**/*.ts: When creating or editing OTEL metrics (counters, histograms, gauges), ensure metric attributes have low cardinality by using only enums, booleans, bounded error codes, or bounded shard IDs
Do not use high-cardinality attributes in OTEL metrics such as UUIDs/IDs (envId, userId, runId, projectId, organizationId), unbounded integers (itemCount, batchSize, retryCount), timestamps (createdAt, startTime), or free-form strings (errorMessage, taskName, queueName)
When exporting OTEL metrics via OTLP to Prometheus, be aware that the exporter automatically adds unit suffixes to metric names (e.g., 'my_duration_ms' becomes 'my_duration_ms_milliseconds', 'my_counter' becomes 'my_counter_total'). Account for these transformations when writing Grafana dashboards or Prometheus queries

Files:

  • apps/webapp/app/models/vercelIntegration.server.ts
  • apps/webapp/app/models/vercelSdkRecovery.server.ts
  • apps/webapp/app/services/vercelIntegration.server.ts
**/*.{js,ts,jsx,tsx,json,md,yaml,yml}

📄 CodeRabbit inference engine (AGENTS.md)

Format code using Prettier before committing

Files:

  • apps/webapp/app/models/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelOnboardingModal.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
  • apps/webapp/app/models/vercelSdkRecovery.server.ts
  • apps/webapp/app/services/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
apps/{webapp,supervisor}/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

When modifying only server components in apps/webapp/, apps/supervisor/, etc. with no package changes, add a .server-changes/ file instead of a changeset

Files:

  • apps/webapp/app/models/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelOnboardingModal.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
  • apps/webapp/app/models/vercelSdkRecovery.server.ts
  • apps/webapp/app/services/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

Import from @trigger.dev/core using subpaths only, never the root

Files:

  • apps/webapp/app/models/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelOnboardingModal.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
  • apps/webapp/app/models/vercelSdkRecovery.server.ts
  • apps/webapp/app/services/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
apps/webapp/**/*.server.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

Access environment variables via the env export from apps/webapp/app/env.server.ts, never use process.env directly

Files:

  • apps/webapp/app/models/vercelIntegration.server.ts
  • apps/webapp/app/models/vercelSdkRecovery.server.ts
  • apps/webapp/app/services/vercelIntegration.server.ts
**/{src,app}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/{src,app}/**/*.{ts,tsx}: Always import Trigger.dev tasks from @trigger.dev/sdk. Never use @trigger.dev/sdk/v3 or deprecated client.defineJob pattern
Every Trigger.dev task must be exported and include a unique id string property

Files:

  • apps/webapp/app/models/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelOnboardingModal.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
  • apps/webapp/app/models/vercelSdkRecovery.server.ts
  • apps/webapp/app/services/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
apps/webapp/app/services/**/*.server.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)

Separate testable services from configuration files; follow the pattern of realtimeClient.server.ts (testable service) and realtimeClientGlobal.server.ts (configuration) in the webapp

Files:

  • apps/webapp/app/services/vercelIntegration.server.ts
🧠 Learnings (18)
📓 Common learnings
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/presenters/v3/BranchesPresenter.server.ts:45-45
Timestamp: 2026-02-03T18:27:05.229Z
Learning: In the Vercel integration feature, the GitHub app is responsible for builds and provides git metadata (using source: "trigger_github_app"). The Vercel integration is only for linking deployments between platforms, not for triggering builds or providing git metadata.
📚 Learning: 2026-02-04T16:34:48.876Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/routes/vercel.connect.tsx:13-27
Timestamp: 2026-02-04T16:34:48.876Z
Learning: In apps/webapp/app/routes/vercel.connect.tsx, configurationId may be absent for "dashboard" flows but must be present for "marketplace" flows. Enforce this with a Zod superRefine and pass installationId to repository methods only when configurationId is defined (omit the field otherwise).

Applied to files:

  • apps/webapp/app/models/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelOnboardingModal.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
  • apps/webapp/app/models/vercelSdkRecovery.server.ts
  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
📚 Learning: 2025-11-27T16:26:58.661Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/webapp.mdc:0-0
Timestamp: 2025-11-27T16:26:58.661Z
Learning: Applies to apps/webapp/app/**/*.{ts,tsx} : Access all environment variables through the `env` export of `env.server.ts` instead of directly accessing `process.env` in the Trigger.dev webapp

Applied to files:

  • apps/webapp/app/models/vercelIntegration.server.ts
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
  • apps/webapp/app/services/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
📚 Learning: 2026-02-03T18:27:05.229Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/presenters/v3/BranchesPresenter.server.ts:45-45
Timestamp: 2026-02-03T18:27:05.229Z
Learning: In the Vercel integration feature, the GitHub app is responsible for builds and provides git metadata (using source: "trigger_github_app"). The Vercel integration is only for linking deployments between platforms, not for triggering builds or providing git metadata.

Applied to files:

  • docs/vercel-integration.mdx
  • apps/webapp/app/services/vercelIntegration.server.ts
  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use the `task()` function from `trigger.dev/sdk/v3` to define tasks with id and run properties

Applied to files:

  • docs/vercel-integration.mdx
📚 Learning: 2026-02-11T16:37:32.429Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3019
File: apps/webapp/app/components/primitives/charts/Card.tsx:26-30
Timestamp: 2026-02-11T16:37:32.429Z
Learning: In projects using react-grid-layout, avoid relying on drag-handle class to imply draggability. Ensure drag-handle elements only affect dragging when the parent grid item is configured draggable in the layout; conditionally apply cursor styles based on the draggable prop. This improves correctness and accessibility.

Applied to files:

  • apps/webapp/app/components/integrations/VercelOnboardingModal.tsx
  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
📚 Learning: 2026-02-11T16:50:14.167Z
Learnt from: matt-aitken
Repo: triggerdotdev/trigger.dev PR: 3019
File: apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboards.$dashboardId.widgets.tsx:126-131
Timestamp: 2026-02-11T16:50:14.167Z
Learning: In apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.dashboards.$dashboardId.widgets.tsx, MetricsDashboard entities are intentionally scoped to the organization level, not the project level. The dashboard lookup should filter by organizationId only (not projectId), allowing dashboards to be accessed across projects within the same organization. The optional projectId field on MetricsDashboard serves other purposes and should not be used as an authorization constraint.

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
📚 Learning: 2025-09-05T15:32:41.553Z
Learnt from: myftija
Repo: triggerdotdev/trigger.dev PR: 2464
File: apps/webapp/app/services/projectSettings.server.ts:210-0
Timestamp: 2025-09-05T15:32:41.553Z
Learning: In the ProjectSettingsService.updateGitSettings method in apps/webapp/app/services/projectSettings.server.ts, when productionBranch or stagingBranch parameters are undefined, the method intentionally writes empty objects to clear existing branch configurations. This is the desired behavior, not a bug.

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
📚 Learning: 2025-12-08T15:19:56.823Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2760
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx:278-281
Timestamp: 2025-12-08T15:19:56.823Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam/route.tsx, the tableState search parameter uses intentional double-encoding: the parameter value contains a URL-encoded URLSearchParams string, so decodeURIComponent(value("tableState") ?? "") is required to fully decode it before parsing with new URLSearchParams(). This pattern allows bundling multiple filter/pagination params as a single search parameter.

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
📚 Learning: 2026-02-25T13:54:58.938Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-02-25T13:54:58.938Z
Learning: Applies to {packages,integrations}/**/*.{ts,tsx,js} : When modifying public packages in `packages/*` or `integrations/*`, add a changeset using `pnpm run changeset:add`

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
  • apps/webapp/app/services/vercelIntegration.server.ts
📚 Learning: 2026-02-03T18:27:40.429Z
Learnt from: 0ski
Repo: triggerdotdev/trigger.dev PR: 2994
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx:553-555
Timestamp: 2026-02-03T18:27:40.429Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.environment-variables/route.tsx, the menu buttons (e.g., Edit with PencilSquareIcon) in the TableCellMenu are intentionally icon-only with no text labels as a compact UI pattern. This is a deliberate design choice for this route; preserve the icon-only behavior for consistency in this file.

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
📚 Learning: 2026-02-10T16:18:48.654Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 2980
File: apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.queues/route.tsx:512-515
Timestamp: 2026-02-10T16:18:48.654Z
Learning: In apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.queues/route.tsx, environment.queueSizeLimit is a per-queue maximum that is configured at the environment level, not a shared limit across all queues. Each queue can have up to environment.queueSizeLimit items queued independently.

Applied to files:

  • apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to {packages/core,apps/webapp}/**/*.{ts,tsx} : Use zod for validation in packages/core and apps/webapp

Applied to files:

  • apps/webapp/app/models/vercelSdkRecovery.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger/**/*.{ts,tsx,js,jsx} : Use `schemaTask()` from `trigger.dev/sdk/v3` with Zod schema for payload validation

Applied to files:

  • apps/webapp/app/models/vercelSdkRecovery.server.ts
📚 Learning: 2025-08-19T09:49:07.011Z
Learnt from: julienvanbeveren
Repo: triggerdotdev/trigger.dev PR: 2417
File: apps/webapp/app/routes/api.v1.projects.$projectRef.envvars.$slug.import.ts:56-61
Timestamp: 2025-08-19T09:49:07.011Z
Learning: In the Trigger.dev codebase, environment variables should default to `isSecret: false` when not explicitly marked as secrets in the syncEnvVars functionality. This is the intended behavior for both regular variables and parent variables.

Applied to files:

  • apps/webapp/app/services/vercelIntegration.server.ts
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Configure build process in trigger.config.ts using `build` object with external packages, extensions, and JSX settings

Applied to files:

  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
📚 Learning: 2026-01-28T16:57:47.620Z
Learnt from: samejr
Repo: triggerdotdev/trigger.dev PR: 2964
File: apps/webapp/app/components/AskAI.tsx:121-141
Timestamp: 2026-01-28T16:57:47.620Z
Learning: In the trigger.dev webapp codebase, the Button component (apps/webapp/app/components/primitives/Buttons) does not spread unknown props to the underlying <button> element—it only passes specific props (type, disabled, onClick, name, value, ref, form, autoFocus). When using Radix UI's TooltipTrigger with asChild, a span wrapper around the Button is necessary to receive Radix props (aria-describedby, onPointerEnter, onPointerLeave, data-state) while the Button handles its own behavior. Directly making the Button the child of TooltipTrigger with asChild will break accessibility and tooltip functionality.

Applied to files:

  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Use `TriggerAuthContext` provider to supply Public Access Token to Trigger.dev React hooks

Applied to files:

  • apps/webapp/app/components/integrations/VercelBuildSettings.tsx
🧬 Code graph analysis (4)
apps/webapp/app/models/vercelIntegration.server.ts (1)
apps/webapp/app/models/vercelSdkRecovery.server.ts (3)
  • wrapVercelCallWithRecovery (98-110)
  • VercelSchemas (117-188)
  • callVercelWithRecovery (78-90)
apps/webapp/app/components/integrations/VercelOnboardingModal.tsx (3)
apps/webapp/app/components/primitives/Dialog.tsx (1)
  • DialogContent (119-119)
apps/webapp/app/components/primitives/Callout.tsx (1)
  • Callout (73-170)
apps/webapp/app/components/primitives/Paragraph.tsx (1)
  • Paragraph (88-107)
apps/webapp/app/services/vercelIntegration.server.ts (1)
apps/webapp/app/models/vercelIntegration.server.ts (1)
  • VercelIntegrationRepository (246-1817)
apps/webapp/app/components/integrations/VercelBuildSettings.tsx (3)
apps/webapp/app/components/primitives/Label.tsx (1)
  • Label (25-41)
apps/webapp/app/components/primitives/Switch.tsx (1)
  • Switch (64-119)
apps/webapp/app/components/primitives/TextLink.tsx (1)
  • TextLink (29-94)
🔇 Additional comments (17)
docs/vercel-integration.mdx (2)

116-142: LGTM!

The Mermaid sequence diagram accurately illustrates the atomic deployment flow. The syntax is correct, and the interaction between GitHub, Vercel, and Trigger.dev aligns with the described gating mechanism where Trigger.dev holds the deployment check pending until the task build completes, then triggers a redeployment with the correct TRIGGER_VERSION.


146-150: LGTM!

The Note appropriately warns users about the automatic disabling of Auto-assign Custom Production Domains and clearly explains why this is necessary for atomic deployments to function correctly.

apps/webapp/app/components/integrations/VercelBuildSettings.tsx (3)

37-61: LGTM – Pull env vars section reorganization looks good.

The conditional header Switch and integrated Hint with the config link improve usability. The logic correctly toggles all available environments.

Minor nit: The availableEnvSlugs.length > 0 check on line 44 is redundant since you're already inside the availableEnvSlugs.length > 1 conditional block.


93-121: Discover section logic is sound.

The dependency between "Pull" and "Discover" is correctly enforced—the master toggle only affects environments that have pull enabled, and it's disabled when no environments can be discovered from.

Same minor nit as above: the availableEnvSlugs.length > 0 check on line 100 is redundant within the length > 1 block.


122-152: LGTM – Per-environment disabled state handling.

The isPullDisabled logic correctly ties the visual feedback (reduced opacity) to the functional disabled state on the Switch. This provides clear UX indication that "Discover" depends on "Pull" being enabled.

apps/webapp/app/components/integrations/VercelOnboardingModal.tsx (2)

652-652: LGTM - Consistent outside-click prevention for onboarding dialogs.

The onInteractOutside handlers prevent accidental dismissal during the onboarding flow, which is appropriate UX for a multi-step wizard.

Also applies to: 682-682


803-815: LGTM - Helpful guidance for staging environment mapping.

The informational Callout and Paragraph provide clear guidance about the implications of skipping the env-mapping step and the importance of matching staging branch configuration.

apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx (2)

247-268: LGTM - Proper staging key synchronization on config update.

The logic correctly:

  1. Captures the previous staging environment before the update
  2. Performs the update
  3. Syncs the staging key only if the environment actually changed

The comparison handles all migration scenarios (add, remove, change).


339-344: LGTM - Staging key upsert during onboarding env-mapping.

Passing null as previousCustomEnvironmentId is correct since this is the initial setup during onboarding—there's no previous custom environment to remove from.

apps/webapp/app/services/vercelIntegration.server.ts (1)

350-423: LGTM - Well-structured staging key synchronization method.

The method correctly handles all synchronization scenarios:

  • Migration from one custom environment to another
  • Initial setup (previous = null)
  • Removal (new = null, handled by the conditional check)

The fire-and-forget pattern with error logging is appropriate here since the primary update operation has already succeeded.

apps/webapp/app/models/vercelIntegration.server.ts (4)

30-34: LGTM - Recovery utilities import.

Clean import of the new recovery layer utilities that will be used throughout the repository methods.


322-337: LGTM - Team/user lookup migrated to recovery wrappers.

The migration to wrapVercelCallWithRecovery with VercelSchemas.getTeam and VercelSchemas.getAuthUser provides consistent error handling and recovery from SDK validation errors.


1085-1144: LGTM - New method for upserting env vars in custom environments.

The method correctly:

  1. Fetches existing env vars with recovery
  2. Finds matching env var by key and customEnvironmentId
  3. Updates if exists, creates if not

The as any casts are pragmatic workarounds for SDK type limitations around customEnvironmentIds.


1146-1188: LGTM - New method for removing env vars from custom environments.

The method correctly:

  1. Fetches existing env vars with recovery
  2. Finds matching env var by key and customEnvironmentId
  3. Removes via batch delete if found (no-op if not found)

This complements upsertEnvVarForCustomEnvironment for complete lifecycle management.

apps/webapp/app/models/vercelSdkRecovery.server.ts (3)

1-70: LGTM - Well-designed recovery layer for Vercel SDK validation errors.

The module is well-documented with clear explanation of:

  • The problem (Speakeasy-generated SDK with strict Zod validation)
  • The error hierarchy (rawValue vs body)
  • The recovery strategy

The implementation properly uses:

  • Result.fromThrowable for safe JSON parsing
  • ResultAsync.orElse for recovery flow
  • Warn-level logging for successful recoveries (useful for observability)

78-110: LGTM - Clean ResultAsync wrappers with recovery.

Both callVercelWithRecovery and wrapVercelCallWithRecovery provide ergonomic APIs:

  • The former is lightweight for internal use
  • The latter adds structured error logging and transformation for public repository methods

117-188: LGTM - Minimal Zod schemas with passthrough.

The schemas validate only the fields actually consumed by the codebase while using .passthrough() to preserve extra API fields. This is a robust approach that:

  1. Enables recovery from SDK validation errors on fields we don't use
  2. Preserves full API responses for downstream processing

devin-ai-integration[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

…pVercelCall 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.
coderabbitai[bot]

This comment was marked as resolved.

@0ski 0ski marked this pull request as ready for review February 27, 2026 19:02
Copy link

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 7 additional findings in Devin Review.

Open in Devin Review

Comment on lines 260 to 270
if (result) {
// Sync staging TRIGGER_SECRET_KEY if the custom environment changed
if (previousStagingEnvId !== newStagingEnvId) {
await vercelService.syncStagingKeyForCustomEnvironment(
project.id,
previousStagingEnvId,
newStagingEnvId
);
}

return redirectWithSuccessMessage(settingsPath, request, "Vercel settings updated successfully");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 Staging key sync errors are silently swallowed in update-config action

In the update-config action at apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.vercel.tsx:260-268, syncStagingKeyForCustomEnvironment is awaited but its errors are only logged internally (at apps/webapp/app/services/vercelIntegration.server.ts:379-384 and 415-420). The user always sees "Vercel settings updated successfully" regardless of whether the key sync succeeded. This means the config could be updated to point to a new custom environment, but the TRIGGER_SECRET_KEY might not actually exist in Vercel for that environment. The next build with pullEnvVarsBeforeBuild would eventually catch this, but the user has no immediate feedback that the sync failed.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@ericallam ericallam merged commit 10d6f01 into main Feb 28, 2026
43 checks passed
@ericallam ericallam deleted the oskar/fix-vercel-integraiton branch February 28, 2026 07:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants