Skip to content

Commit 423f985

Browse files
committed
feat(vercel): enhance staging environment handling and add preview support
Refactor the Vercel integration to change the structure of the `vercelStagingEnvironment` to an object containing `environmentId` and `displayName`. Update related logic to utilize the new structure, ensuring that the environment ID is correctly referenced in various parts of the application.Additionally, introduce support for a preview environment by adding `hasPreviewEnvironment` and `customEnvironments` to the Vercel settings presenter. Update the UI components and routes to accommodate these changes, allowing for better management of Vercel environments in the application.
1 parent 99e1f81 commit 423f985

File tree

7 files changed

+208
-139
lines changed

7 files changed

+208
-139
lines changed

apps/webapp/app/models/vercelIntegration.server.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,7 @@ export class VercelIntegrationRepository {
904904
projectId: string;
905905
vercelProjectId: string;
906906
teamId: string | null;
907-
vercelStagingEnvironment?: string | null;
907+
vercelStagingEnvironment?: { environmentId: string; displayName: string } | null;
908908
orgIntegration: OrganizationIntegration & { tokenReference: SecretReference };
909909
}): Promise<{ success: boolean; errors: string[] }> {
910910
const errors: string[] = [];
@@ -952,7 +952,7 @@ export class VercelIntegrationRepository {
952952
});
953953
continue;
954954
}
955-
vercelTarget = [params.vercelStagingEnvironment];
955+
vercelTarget = [params.vercelStagingEnvironment.environmentId];
956956
break;
957957
case "PREVIEW":
958958
vercelTarget = ["preview"];
@@ -1073,7 +1073,7 @@ export class VercelIntegrationRepository {
10731073
});
10741074
return { success: true };
10751075
}
1076-
vercelTarget = [vercelStagingEnvironment];
1076+
vercelTarget = [vercelStagingEnvironment.environmentId];
10771077
break;
10781078
case "PREVIEW":
10791079
vercelTarget = ["preview"];
@@ -1120,7 +1120,7 @@ export class VercelIntegrationRepository {
11201120
projectId: string;
11211121
vercelProjectId: string;
11221122
teamId: string | null;
1123-
vercelStagingEnvironment?: string | null;
1123+
vercelStagingEnvironment?: { environmentId: string; displayName: string } | null;
11241124
syncEnvVarsMapping: SyncEnvVarsMapping;
11251125
orgIntegration: OrganizationIntegration & { tokenReference: SecretReference };
11261126
}): Promise<{ success: boolean; errors: string[]; syncedCount: number }> {
@@ -1172,7 +1172,7 @@ export class VercelIntegrationRepository {
11721172
if (params.vercelStagingEnvironment) {
11731173
envMapping.push({
11741174
triggerEnvType: "STAGING",
1175-
vercelTarget: params.vercelStagingEnvironment,
1175+
vercelTarget: params.vercelStagingEnvironment.environmentId,
11761176
runtimeEnvironmentId: env.id,
11771177
});
11781178
}

apps/webapp/app/presenters/v3/VercelSettingsPresenter.server.ts

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ export type VercelSettingsResult = {
3333
};
3434
isGitHubConnected: boolean;
3535
hasStagingEnvironment: boolean;
36+
hasPreviewEnvironment: boolean;
37+
customEnvironments: VercelCustomEnvironment[];
3638
};
3739

3840
export type VercelAvailableProject = {
@@ -81,6 +83,8 @@ export class VercelSettingsPresenter extends BasePresenter {
8183
connectedProject: undefined,
8284
isGitHubConnected: false,
8385
hasStagingEnvironment: false,
86+
hasPreviewEnvironment: false,
87+
customEnvironments: [],
8488
} as VercelSettingsResult);
8589
}
8690

@@ -107,6 +111,8 @@ export class VercelSettingsPresenter extends BasePresenter {
107111
connectedProject: undefined,
108112
isGitHubConnected: false,
109113
hasStagingEnvironment: false,
114+
hasPreviewEnvironment: false,
115+
customEnvironments: [],
110116
} as VercelSettingsResult);
111117
}
112118
}
@@ -159,6 +165,24 @@ export class VercelSettingsPresenter extends BasePresenter {
159165
})
160166
).map((env) => env !== null);
161167

168+
// Check if preview environment exists
169+
const checkPreviewEnvironment = () =>
170+
fromPromise(
171+
(this._replica as PrismaClient).runtimeEnvironment.findFirst({
172+
select: {
173+
id: true,
174+
},
175+
where: {
176+
projectId,
177+
type: "PREVIEW",
178+
},
179+
}),
180+
(error) => ({
181+
type: "other" as const,
182+
cause: error,
183+
})
184+
).map((env) => env !== null);
185+
162186
// Get Vercel project integration
163187
const getVercelProjectIntegration = () =>
164188
fromPromise(
@@ -207,15 +231,39 @@ export class VercelSettingsPresenter extends BasePresenter {
207231
checkOrgIntegration(),
208232
checkGitHubConnection(),
209233
checkStagingEnvironment(),
234+
checkPreviewEnvironment(),
210235
getVercelProjectIntegration(),
211-
]).map(([hasOrgIntegration, isGitHubConnected, hasStagingEnvironment, connectedProject]) => ({
212-
enabled: true,
213-
hasOrgIntegration,
214-
authInvalid: false,
215-
connectedProject,
216-
isGitHubConnected,
217-
hasStagingEnvironment,
218-
})).mapErr((error) => {
236+
]).andThen(([hasOrgIntegration, isGitHubConnected, hasStagingEnvironment, hasPreviewEnvironment, connectedProject]) => {
237+
const fetchCustomEnvs = async (): Promise<VercelCustomEnvironment[]> => {
238+
if (!connectedProject || !orgIntegration) return [];
239+
try {
240+
const client = await VercelIntegrationRepository.getVercelClient(orgIntegration);
241+
const teamId = await VercelIntegrationRepository.getTeamIdFromIntegration(orgIntegration);
242+
const result = await VercelIntegrationRepository.getVercelCustomEnvironments(
243+
client,
244+
connectedProject.vercelProjectId,
245+
teamId
246+
);
247+
return result.success ? result.data : [];
248+
} catch {
249+
return [];
250+
}
251+
};
252+
253+
return fromPromise(
254+
fetchCustomEnvs(),
255+
(error) => ({ type: "other" as const, cause: error })
256+
).map((customEnvironments) => ({
257+
enabled: true,
258+
hasOrgIntegration,
259+
authInvalid: false,
260+
connectedProject,
261+
isGitHubConnected,
262+
hasStagingEnvironment,
263+
hasPreviewEnvironment,
264+
customEnvironments,
265+
} as VercelSettingsResult));
266+
}).mapErr((error) => {
219267
// Log the error and return a safe fallback
220268
console.error("Error in VercelSettingsPresenter.call:", error);
221269
return error;
@@ -230,6 +278,8 @@ export class VercelSettingsPresenter extends BasePresenter {
230278
connectedProject: undefined,
231279
isGitHubConnected: false,
232280
hasStagingEnvironment: false,
281+
hasPreviewEnvironment: false,
282+
customEnvironments: [],
233283
} as VercelSettingsResult);
234284
}
235285
} catch (error) {
@@ -242,6 +292,8 @@ export class VercelSettingsPresenter extends BasePresenter {
242292
connectedProject: undefined,
243293
isGitHubConnected: false,
244294
hasStagingEnvironment: false,
295+
hasPreviewEnvironment: false,
296+
customEnvironments: [],
245297
} as VercelSettingsResult);
246298
}
247299
}

apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.settings/route.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,7 @@ export default function Page() {
621621
projectSlug={project.slug}
622622
environmentSlug={environment.slug}
623623
hasStagingEnvironment={vercelFetcher.data?.hasStagingEnvironment ?? false}
624+
hasPreviewEnvironment={vercelFetcher.data?.hasPreviewEnvironment ?? false}
624625
hasOrgIntegration={vercelFetcher.data?.hasOrgIntegration ?? false}
625626
nextUrl={nextUrl ?? undefined}
626627
onDataReload={(vercelEnvironmentId) => {

0 commit comments

Comments
 (0)