From 965cd2290205a06c8b6ad8294a4c654cf1d78a1b Mon Sep 17 00:00:00 2001 From: myftija Date: Thu, 18 Sep 2025 12:21:33 +0200 Subject: [PATCH 01/10] Enable setting the initial status on deployment creation --- apps/webapp/app/routes/api.v1.deployments.ts | 4 ++-- .../app/v3/services/initializeDeployment.server.ts | 9 +++++++-- packages/core/src/v3/schemas/api.ts | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/webapp/app/routes/api.v1.deployments.ts b/apps/webapp/app/routes/api.v1.deployments.ts index c80e180d89..8b3280cbb2 100644 --- a/apps/webapp/app/routes/api.v1.deployments.ts +++ b/apps/webapp/app/routes/api.v1.deployments.ts @@ -1,8 +1,8 @@ -import { ActionFunctionArgs, json } from "@remix-run/server-runtime"; +import { type ActionFunctionArgs, json } from "@remix-run/server-runtime"; import { ApiDeploymentListSearchParams, InitializeDeploymentRequestBody, - InitializeDeploymentResponseBody, + type InitializeDeploymentResponseBody, } from "@trigger.dev/core/v3"; import { $replica } from "~/db.server"; import { authenticateApiRequest } from "~/services/apiAuth.server"; diff --git a/apps/webapp/app/v3/services/initializeDeployment.server.ts b/apps/webapp/app/v3/services/initializeDeployment.server.ts index 234cfa1270..014b9fdb42 100644 --- a/apps/webapp/app/v3/services/initializeDeployment.server.ts +++ b/apps/webapp/app/v3/services/initializeDeployment.server.ts @@ -99,6 +99,10 @@ export class InitializeDeploymentService extends BaseService { const { imageRef, isEcr, repoCreated } = imageRefResult; + // we keep using `BUILDING` as the initial status if not explicitly set + // to avoid changing the behavior for deployments not created in the build server + const initialStatus = payload.initialStatus ?? "BUILDING"; + logger.debug("Creating deployment", { environmentId: environment.id, projectId: environment.projectId, @@ -108,6 +112,7 @@ export class InitializeDeploymentService extends BaseService { imageRef, isEcr, repoCreated, + initialStatus, }); const deployment = await this._prisma.workerDeployment.create({ @@ -116,7 +121,7 @@ export class InitializeDeploymentService extends BaseService { contentHash: payload.contentHash, shortCode: deploymentShortCode, version: nextVersion, - status: "BUILDING", + status: initialStatus, environmentId: environment.id, projectId: environment.projectId, externalBuildData, @@ -131,7 +136,7 @@ export class InitializeDeploymentService extends BaseService { await TimeoutDeploymentService.enqueue( deployment.id, - "BUILDING", + deployment.status, "Building timed out", new Date(Date.now() + env.DEPLOY_TIMEOUT_MS) ); diff --git a/packages/core/src/v3/schemas/api.ts b/packages/core/src/v3/schemas/api.ts index e4c71bb341..39d64fab84 100644 --- a/packages/core/src/v3/schemas/api.ts +++ b/packages/core/src/v3/schemas/api.ts @@ -419,6 +419,7 @@ export const InitializeDeploymentRequestBody = z.object({ gitMeta: GitMeta.optional(), type: z.enum(["MANAGED", "UNMANAGED", "V1"]).optional(), runtime: z.string().optional(), + initialStatus: z.enum(["PENDING", "BUILDING"]).optional(), }); export type InitializeDeploymentRequestBody = z.infer; From 77a979fd253fd95e569b2cdc84c72e77db2a4108 Mon Sep 17 00:00:00 2001 From: myftija Date: Thu, 18 Sep 2025 14:11:30 +0200 Subject: [PATCH 02/10] Expose endpoint to start deployments --- .../api.v1.deployments.$deploymentId.start.ts | 64 +++++++++++++++++++ .../app/v3/services/deployment.server.ts | 63 ++++++++++++++++++ packages/core/src/v3/schemas/api.ts | 8 +++ 3 files changed, 135 insertions(+) create mode 100644 apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts create mode 100644 apps/webapp/app/v3/services/deployment.server.ts diff --git a/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts b/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts new file mode 100644 index 0000000000..06e84851ff --- /dev/null +++ b/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts @@ -0,0 +1,64 @@ +import { type ActionFunctionArgs, json } from "@remix-run/server-runtime"; +import { StartDeploymentRequestBody } from "@trigger.dev/core/v3"; +import { z } from "zod"; +import { authenticateRequest } from "~/services/apiAuth.server"; +import { logger } from "~/services/logger.server"; +import { DeploymentService } from "~/v3/services/deployment.server"; + +const ParamsSchema = z.object({ + deploymentId: z.string(), +}); + +export async function action({ request, params }: ActionFunctionArgs) { + if (request.method.toUpperCase() !== "POST") { + return json({ error: "Method Not Allowed" }, { status: 405 }); + } + + const parsedParams = ParamsSchema.safeParse(params); + + if (!parsedParams.success) { + return json({ error: "Invalid params" }, { status: 400 }); + } + + const authenticationResult = await authenticateRequest(request, { + apiKey: true, + organizationAccessToken: false, + personalAccessToken: false, + }); + + if (!authenticationResult || !authenticationResult.result.ok) { + logger.info("Invalid or missing api key", { url: request.url }); + return json({ error: "Invalid or Missing API key" }, { status: 401 }); + } + + const { environment: authenticatedEnv } = authenticationResult.result; + const { deploymentId } = parsedParams.data; + + const rawBody = await request.json(); + const body = StartDeploymentRequestBody.safeParse(rawBody); + + if (!body.success) { + return json({ error: "Invalid request body", issues: body.error.issues }, { status: 400 }); + } + + const deploymentService = new DeploymentService(); + + const result = await deploymentService.startDeployment(authenticatedEnv, deploymentId, body.data); + return result.match( + () => { + return json(null, { status: 204 }); + }, + (error) => { + switch (error.type) { + case "deployment_not_found": + return json({ error: "Deployment not found" }, { status: 404 }); + case "deployment_not_pending": + return json({ error: "Deployment is not pending" }, { status: 409 }); + case "other": + default: + error.type satisfies "other"; + return json({ error: "Internal server error" }, { status: 500 }); + } + } + ); +} diff --git a/apps/webapp/app/v3/services/deployment.server.ts b/apps/webapp/app/v3/services/deployment.server.ts new file mode 100644 index 0000000000..aae775e8c4 --- /dev/null +++ b/apps/webapp/app/v3/services/deployment.server.ts @@ -0,0 +1,63 @@ +import { type AuthenticatedEnvironment } from "~/services/apiAuth.server"; +import { BaseService } from "./baseService.server"; +import { errAsync, fromPromise, okAsync } from "neverthrow"; +import { type WorkerDeployment } from "@trigger.dev/database"; +import { type GitMeta } from "@trigger.dev/core/v3"; + +export class DeploymentService extends BaseService { + public async startDeployment( + authenticatedEnv: AuthenticatedEnvironment, + friendlyId: string, + updates: Partial & { git: GitMeta }> + ) { + const getDeployment = () => + fromPromise( + this._prisma.workerDeployment.findFirst({ + where: { + friendlyId, + environmentId: authenticatedEnv.id, + }, + select: { + status: true, + id: true, + }, + }), + (error) => ({ + type: "other" as const, + cause: error, + }) + ).andThen((deployment) => { + if (!deployment) { + return errAsync({ type: "deployment_not_found" as const }); + } + return okAsync(deployment); + }); + + const validateDeployment = (deployment: Pick) => { + if (deployment.status !== "PENDING") { + return errAsync({ type: "deployment_not_pending" as const }); + } + + return okAsync(deployment); + }; + + const updateDeployment = (deployment: Pick) => + fromPromise( + this._prisma.workerDeployment.updateMany({ + where: { id: deployment.id, status: "PENDING" }, // status could've changed in the meantime, we're not locking the row + data: { ...updates, status: "BUILDING" }, + }), + (error) => ({ + type: "other" as const, + cause: error, + }) + ).andThen((result) => { + if (result.count === 0) { + return errAsync({ type: "deployment_not_pending" as const }); + } + return okAsync(undefined); + }); + + return getDeployment().andThen(validateDeployment).andThen(updateDeployment); + } +} diff --git a/packages/core/src/v3/schemas/api.ts b/packages/core/src/v3/schemas/api.ts index 39d64fab84..7bfd4e23d3 100644 --- a/packages/core/src/v3/schemas/api.ts +++ b/packages/core/src/v3/schemas/api.ts @@ -377,6 +377,14 @@ export const FinalizeDeploymentRequestBody = z.object({ export type FinalizeDeploymentRequestBody = z.infer; +export const StartDeploymentRequestBody = z.object({ + contentHash: z.string().optional(), + gitMeta: GitMeta.optional(), + runtime: z.string().optional(), +}); + +export type StartDeploymentRequestBody = z.infer; + export const ExternalBuildData = z.object({ buildId: z.string(), buildToken: z.string(), From 3e5277d1d608324cd2afc3a44662ba7a14c05c4a Mon Sep 17 00:00:00 2001 From: myftija Date: Thu, 18 Sep 2025 14:17:40 +0200 Subject: [PATCH 03/10] Extend build timeout on deployment start --- .../api.v1.deployments.$deploymentId.start.ts | 2 ++ .../app/v3/services/deployment.server.ts | 25 ++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts b/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts index 06e84851ff..b312d2a5df 100644 --- a/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts +++ b/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts @@ -50,6 +50,8 @@ export async function action({ request, params }: ActionFunctionArgs) { }, (error) => { switch (error.type) { + case "failed_to_extend_deployment_timeout": + return json(null, { status: 204 }); // ignore these errors for now case "deployment_not_found": return json({ error: "Deployment not found" }, { status: 404 }); case "deployment_not_pending": diff --git a/apps/webapp/app/v3/services/deployment.server.ts b/apps/webapp/app/v3/services/deployment.server.ts index aae775e8c4..71fe246df9 100644 --- a/apps/webapp/app/v3/services/deployment.server.ts +++ b/apps/webapp/app/v3/services/deployment.server.ts @@ -1,8 +1,10 @@ import { type AuthenticatedEnvironment } from "~/services/apiAuth.server"; import { BaseService } from "./baseService.server"; import { errAsync, fromPromise, okAsync } from "neverthrow"; -import { type WorkerDeployment } from "@trigger.dev/database"; +import { type WorkerDeploymentStatus, type WorkerDeployment } from "@trigger.dev/database"; import { type GitMeta } from "@trigger.dev/core/v3"; +import { TimeoutDeploymentService } from "./timeoutDeployment.server"; +import { env } from "~/env.server"; export class DeploymentService extends BaseService { public async startDeployment( @@ -55,9 +57,26 @@ export class DeploymentService extends BaseService { if (result.count === 0) { return errAsync({ type: "deployment_not_pending" as const }); } - return okAsync(undefined); + return okAsync({ id: deployment.id }); }); - return getDeployment().andThen(validateDeployment).andThen(updateDeployment); + const extendTimeout = (deployment: Pick) => + fromPromise( + TimeoutDeploymentService.enqueue( + deployment.id, + "BUILDING" satisfies WorkerDeploymentStatus, + "Building timed out", + new Date(Date.now() + env.DEPLOY_TIMEOUT_MS) + ), + (error) => ({ + type: "failed_to_extend_deployment_timeout" as const, + cause: error, + }) + ); + + return getDeployment() + .andThen(validateDeployment) + .andThen(updateDeployment) + .andThen(extendTimeout); } } From 0f6b0f12572d16138a89c04d619355e44cf8d64a Mon Sep 17 00:00:00 2001 From: myftija Date: Thu, 18 Sep 2025 14:22:28 +0200 Subject: [PATCH 04/10] Use separate timeout value for queued deployments --- apps/webapp/app/env.server.ts | 4 ++++ apps/webapp/app/v3/services/initializeDeployment.server.ts | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/webapp/app/env.server.ts b/apps/webapp/app/env.server.ts index 2d8384ec19..8f9b5274c5 100644 --- a/apps/webapp/app/env.server.ts +++ b/apps/webapp/app/env.server.ts @@ -312,6 +312,10 @@ const EnvironmentSchema = z .number() .int() .default(60 * 1000 * 8), // 8 minutes + DEPLOY_QUEUE_TIMEOUT_MS: z.coerce + .number() + .int() + .default(60 * 1000 * 15), // 15 minutes OBJECT_STORE_BASE_URL: z.string().optional(), OBJECT_STORE_ACCESS_KEY_ID: z.string().optional(), diff --git a/apps/webapp/app/v3/services/initializeDeployment.server.ts b/apps/webapp/app/v3/services/initializeDeployment.server.ts index 014b9fdb42..d629f7edb2 100644 --- a/apps/webapp/app/v3/services/initializeDeployment.server.ts +++ b/apps/webapp/app/v3/services/initializeDeployment.server.ts @@ -138,7 +138,11 @@ export class InitializeDeploymentService extends BaseService { deployment.id, deployment.status, "Building timed out", - new Date(Date.now() + env.DEPLOY_TIMEOUT_MS) + new Date( + Date.now() + deployment.status === "PENDING" + ? env.DEPLOY_QUEUE_TIMEOUT_MS + : env.DEPLOY_TIMEOUT_MS + ) ); return { From a3fd1c2b225d777c97e7126c587c0d8cd135ee76 Mon Sep 17 00:00:00 2001 From: myftija Date: Thu, 18 Sep 2025 14:30:15 +0200 Subject: [PATCH 05/10] Add startedAt to the deployment schema --- apps/webapp/app/v3/services/deployment.server.ts | 7 +++++-- apps/webapp/app/v3/services/initializeDeployment.server.ts | 1 + .../migration.sql | 1 + internal-packages/database/prisma/schema.prisma | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 internal-packages/database/prisma/migrations/20250918122438_add_started_at_to_deployment_schema/migration.sql diff --git a/apps/webapp/app/v3/services/deployment.server.ts b/apps/webapp/app/v3/services/deployment.server.ts index 71fe246df9..acb2f9e20a 100644 --- a/apps/webapp/app/v3/services/deployment.server.ts +++ b/apps/webapp/app/v3/services/deployment.server.ts @@ -2,7 +2,7 @@ import { type AuthenticatedEnvironment } from "~/services/apiAuth.server"; import { BaseService } from "./baseService.server"; import { errAsync, fromPromise, okAsync } from "neverthrow"; import { type WorkerDeploymentStatus, type WorkerDeployment } from "@trigger.dev/database"; -import { type GitMeta } from "@trigger.dev/core/v3"; +import { logger, type GitMeta } from "@trigger.dev/core/v3"; import { TimeoutDeploymentService } from "./timeoutDeployment.server"; import { env } from "~/env.server"; @@ -37,6 +37,9 @@ export class DeploymentService extends BaseService { const validateDeployment = (deployment: Pick) => { if (deployment.status !== "PENDING") { + logger.warn("Attempted starting deployment that is not in PENDING status", { + deployment, + }); return errAsync({ type: "deployment_not_pending" as const }); } @@ -47,7 +50,7 @@ export class DeploymentService extends BaseService { fromPromise( this._prisma.workerDeployment.updateMany({ where: { id: deployment.id, status: "PENDING" }, // status could've changed in the meantime, we're not locking the row - data: { ...updates, status: "BUILDING" }, + data: { ...updates, status: "BUILDING", startedAt: new Date() }, }), (error) => ({ type: "other" as const, diff --git a/apps/webapp/app/v3/services/initializeDeployment.server.ts b/apps/webapp/app/v3/services/initializeDeployment.server.ts index d629f7edb2..a318375be1 100644 --- a/apps/webapp/app/v3/services/initializeDeployment.server.ts +++ b/apps/webapp/app/v3/services/initializeDeployment.server.ts @@ -131,6 +131,7 @@ export class InitializeDeploymentService extends BaseService { imagePlatform: env.DEPLOY_IMAGE_PLATFORM, git: payload.gitMeta ?? undefined, runtime: payload.runtime ?? undefined, + startedAt: initialStatus === "BUILDING" ? new Date() : undefined, }, }); diff --git a/internal-packages/database/prisma/migrations/20250918122438_add_started_at_to_deployment_schema/migration.sql b/internal-packages/database/prisma/migrations/20250918122438_add_started_at_to_deployment_schema/migration.sql new file mode 100644 index 0000000000..83a251cd12 --- /dev/null +++ b/internal-packages/database/prisma/migrations/20250918122438_add_started_at_to_deployment_schema/migration.sql @@ -0,0 +1 @@ +ALTER TABLE "public"."WorkerDeployment" ADD COLUMN "startedAt" TIMESTAMP(3); diff --git a/internal-packages/database/prisma/schema.prisma b/internal-packages/database/prisma/schema.prisma index d15b2692d0..041a7a0cc4 100644 --- a/internal-packages/database/prisma/schema.prisma +++ b/internal-packages/database/prisma/schema.prisma @@ -1764,6 +1764,7 @@ model WorkerDeployment { triggeredBy User? @relation(fields: [triggeredById], references: [id], onDelete: SetNull, onUpdate: Cascade) triggeredById String? + startedAt DateTime? builtAt DateTime? deployedAt DateTime? From 84fbd779c5c1891670fd1b2456260b9a70932c71 Mon Sep 17 00:00:00 2001 From: myftija Date: Thu, 18 Sep 2025 14:37:42 +0200 Subject: [PATCH 06/10] Show the new startedAt instead of createdAt in the dashboard --- .../app/presenters/v3/DeploymentPresenter.server.ts | 2 ++ .../route.tsx | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/webapp/app/presenters/v3/DeploymentPresenter.server.ts b/apps/webapp/app/presenters/v3/DeploymentPresenter.server.ts index 35e6e4184f..21f2b79a81 100644 --- a/apps/webapp/app/presenters/v3/DeploymentPresenter.server.ts +++ b/apps/webapp/app/presenters/v3/DeploymentPresenter.server.ts @@ -102,6 +102,7 @@ export class DeploymentPresenter { builtAt: true, deployedAt: true, createdAt: true, + startedAt: true, git: true, promotions: { select: { @@ -145,6 +146,7 @@ export class DeploymentPresenter { version: deployment.version, status: deployment.status, createdAt: deployment.createdAt, + startedAt: deployment.startedAt, builtAt: deployment.builtAt, deployedAt: deployment.deployedAt, tasks: deployment.worker?.tasks, diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments.$deploymentParam/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments.$deploymentParam/route.tsx index 0575d7e758..0d3a0477c2 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments.$deploymentParam/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments.$deploymentParam/route.tsx @@ -187,7 +187,13 @@ export default function Page() { Started at - UTC + {deployment.startedAt ? ( + <> + UTC + + ) : ( + "–" + )} From 7041dc30635ecb26be5972bc50405318df4472d9 Mon Sep 17 00:00:00 2001 From: myftija Date: Thu, 18 Sep 2025 14:40:40 +0200 Subject: [PATCH 07/10] Show github user tag also in the deployment details page --- .../route.tsx | 22 +++++++++---------- .../route.tsx | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments.$deploymentParam/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments.$deploymentParam/route.tsx index 0d3a0477c2..069fa61a48 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments.$deploymentParam/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments.$deploymentParam/route.tsx @@ -32,6 +32,7 @@ import { requireUserId } from "~/services/session.server"; import { cn } from "~/utils/cn"; import { v3DeploymentParams, v3DeploymentsPath, v3RunsPath } from "~/utils/pathBuilder"; import { capitalizeWord } from "~/utils/string"; +import { UserTag } from "../_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments/route"; export const loader = async ({ request, params }: LoaderFunctionArgs) => { const userId = await requireUserId(request); @@ -232,17 +233,16 @@ export default function Page() { Deployed by - {deployment.deployedBy ? ( -
- - - {deployment.deployedBy.name ?? deployment.deployedBy.displayName} - -
+ {deployment.git?.source === "trigger_github_app" ? ( + + ) : deployment.deployedBy ? ( + ) : ( "–" )} diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments/route.tsx index 610df3ed61..59b6c58ad7 100644 --- a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments/route.tsx +++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.deployments/route.tsx @@ -358,7 +358,7 @@ export default function Page() { ); } -function UserTag({ name, avatarUrl }: { name: string; avatarUrl?: string }) { +export function UserTag({ name, avatarUrl }: { name: string; avatarUrl?: string }) { return (
From 31a6644260ce0f0ae70d03d20db6568721d6bd6c Mon Sep 17 00:00:00 2001 From: myftija Date: Thu, 18 Sep 2025 15:01:55 +0200 Subject: [PATCH 08/10] Show `pending` deployment status as `queued` in the dashboard --- apps/webapp/app/components/runs/v3/DeploymentStatus.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/webapp/app/components/runs/v3/DeploymentStatus.tsx b/apps/webapp/app/components/runs/v3/DeploymentStatus.tsx index 6adea62f2b..5f5f3e0177 100644 --- a/apps/webapp/app/components/runs/v3/DeploymentStatus.tsx +++ b/apps/webapp/app/components/runs/v3/DeploymentStatus.tsx @@ -2,6 +2,7 @@ import { CheckCircleIcon, ExclamationTriangleIcon, NoSymbolIcon, + RectangleStackIcon, XCircleIcon, } from "@heroicons/react/20/solid"; import type { WorkerDeploymentStatus } from "@trigger.dev/database"; @@ -49,6 +50,9 @@ export function DeploymentStatusIcon({ }) { switch (status) { case "PENDING": + return ( + + ); case "BUILDING": case "DEPLOYING": return ; @@ -73,6 +77,7 @@ export function DeploymentStatusIcon({ export function deploymentStatusClassNameColor(status: WorkerDeploymentStatus): string { switch (status) { case "PENDING": + return "text-charcoal-500"; case "BUILDING": case "DEPLOYING": return "text-pending"; @@ -92,7 +97,7 @@ export function deploymentStatusClassNameColor(status: WorkerDeploymentStatus): export function deploymentStatusTitle(status: WorkerDeploymentStatus, isBuilt: boolean): string { switch (status) { case "PENDING": - return "Pending…"; + return "Queued…"; case "BUILDING": return "Building…"; case "DEPLOYING": @@ -121,6 +126,7 @@ export function deploymentStatusTitle(status: WorkerDeploymentStatus, isBuilt: b // PENDING and CANCELED are not used so are ommited from the UI export const deploymentStatuses: WorkerDeploymentStatus[] = [ + "PENDING", "BUILDING", "DEPLOYING", "DEPLOYED", From 977f023fea18de9df10dce36789dd73948cd96b8 Mon Sep 17 00:00:00 2001 From: myftija Date: Thu, 18 Sep 2025 15:06:14 +0200 Subject: [PATCH 09/10] =?UTF-8?q?Apply=20some=20good=20=F0=9F=90=B0=20sugg?= =?UTF-8?q?estions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api.v1.deployments.$deploymentId.start.ts | 43 +++++++++++-------- .../app/v3/services/deployment.server.ts | 4 +- .../services/initializeDeployment.server.ts | 9 ++-- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts b/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts index b312d2a5df..1a1680e95a 100644 --- a/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts +++ b/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts @@ -43,24 +43,29 @@ export async function action({ request, params }: ActionFunctionArgs) { const deploymentService = new DeploymentService(); - const result = await deploymentService.startDeployment(authenticatedEnv, deploymentId, body.data); - return result.match( - () => { - return json(null, { status: 204 }); - }, - (error) => { - switch (error.type) { - case "failed_to_extend_deployment_timeout": - return json(null, { status: 204 }); // ignore these errors for now - case "deployment_not_found": - return json({ error: "Deployment not found" }, { status: 404 }); - case "deployment_not_pending": - return json({ error: "Deployment is not pending" }, { status: 409 }); - case "other": - default: - error.type satisfies "other"; - return json({ error: "Internal server error" }, { status: 500 }); + await deploymentService + .startDeployment(authenticatedEnv, deploymentId, { + contentHash: body.data.contentHash, + git: body.data.gitMeta, + runtime: body.data.runtime, + }) + .match( + () => { + return json(null, { status: 204 }); + }, + (error) => { + switch (error.type) { + case "failed_to_extend_deployment_timeout": + return json(null, { status: 204 }); // ignore these errors for now + case "deployment_not_found": + return json({ error: "Deployment not found" }, { status: 404 }); + case "deployment_not_pending": + return json({ error: "Deployment is not pending" }, { status: 409 }); + case "other": + default: + error.type satisfies "other"; + return json({ error: "Internal server error" }, { status: 500 }); + } } - } - ); + ); } diff --git a/apps/webapp/app/v3/services/deployment.server.ts b/apps/webapp/app/v3/services/deployment.server.ts index acb2f9e20a..9789cfc07e 100644 --- a/apps/webapp/app/v3/services/deployment.server.ts +++ b/apps/webapp/app/v3/services/deployment.server.ts @@ -7,7 +7,7 @@ import { TimeoutDeploymentService } from "./timeoutDeployment.server"; import { env } from "~/env.server"; export class DeploymentService extends BaseService { - public async startDeployment( + public startDeployment( authenticatedEnv: AuthenticatedEnvironment, friendlyId: string, updates: Partial & { git: GitMeta }> @@ -75,7 +75,7 @@ export class DeploymentService extends BaseService { type: "failed_to_extend_deployment_timeout" as const, cause: error, }) - ); + ).map(() => undefined); return getDeployment() .andThen(validateDeployment) diff --git a/apps/webapp/app/v3/services/initializeDeployment.server.ts b/apps/webapp/app/v3/services/initializeDeployment.server.ts index a318375be1..fe11451bde 100644 --- a/apps/webapp/app/v3/services/initializeDeployment.server.ts +++ b/apps/webapp/app/v3/services/initializeDeployment.server.ts @@ -135,15 +135,14 @@ export class InitializeDeploymentService extends BaseService { }, }); + const timeoutMs = + deployment.status === "PENDING" ? env.DEPLOY_QUEUE_TIMEOUT_MS : env.DEPLOY_TIMEOUT_MS; + await TimeoutDeploymentService.enqueue( deployment.id, deployment.status, "Building timed out", - new Date( - Date.now() + deployment.status === "PENDING" - ? env.DEPLOY_QUEUE_TIMEOUT_MS - : env.DEPLOY_TIMEOUT_MS - ) + new Date(Date.now() + timeoutMs) ); return { From bbc4b16aa014c0aab217375b39def7408abc75a7 Mon Sep 17 00:00:00 2001 From: myftija Date: Thu, 18 Sep 2025 15:37:40 +0200 Subject: [PATCH 10/10] Add missing return --- .../webapp/app/routes/api.v1.deployments.$deploymentId.start.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts b/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts index 1a1680e95a..a82d452383 100644 --- a/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts +++ b/apps/webapp/app/routes/api.v1.deployments.$deploymentId.start.ts @@ -43,7 +43,7 @@ export async function action({ request, params }: ActionFunctionArgs) { const deploymentService = new DeploymentService(); - await deploymentService + return await deploymentService .startDeployment(authenticatedEnv, deploymentId, { contentHash: body.data.contentHash, git: body.data.gitMeta,