From 66fef16c34995b5734c5553952c389b3ad4361d2 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 08:12:32 +0000 Subject: [PATCH 1/2] fix: sync declarative schedules on deployment rollback When rolling back a deployment via ChangeCurrentDeploymentService, declarative schedules were not being synced to match the rolled-back deployment's worker metadata. This caused schedules to remain as configured by the most recent deployment instead of reflecting the target deployment's schedule configuration. The fix adds a call to syncDeclarativeSchedules after the deployment promotion is updated, using the target deployment's worker metadata to restore the correct schedule state. Co-Authored-By: nick <55853254+nicktrn@users.noreply.github.com> --- .../changeCurrentDeployment.server.ts | 67 ++++++++++++++++--- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/apps/webapp/app/v3/services/changeCurrentDeployment.server.ts b/apps/webapp/app/v3/services/changeCurrentDeployment.server.ts index ee788397a08..288374ec61a 100644 --- a/apps/webapp/app/v3/services/changeCurrentDeployment.server.ts +++ b/apps/webapp/app/v3/services/changeCurrentDeployment.server.ts @@ -1,9 +1,10 @@ -import { tryCatch } from "@trigger.dev/core/v3"; +import { BackgroundWorkerMetadata, tryCatch } from "@trigger.dev/core/v3"; import { CURRENT_DEPLOYMENT_LABEL } from "@trigger.dev/core/v3/isomorphic"; import { WorkerDeployment } from "@trigger.dev/database"; import { logger } from "~/services/logger.server"; import { syncTaskIdentifiers } from "~/services/taskIdentifierRegistry.server"; import { BaseService, ServiceValidationError } from "./baseService.server"; +import { syncDeclarativeSchedules } from "./createBackgroundWorker.server"; import { ExecuteTasksWaitingForDeployService } from "./executeTasksWaitingForDeploy"; import { compareDeploymentVersions } from "../utils/deploymentVersions"; @@ -53,10 +54,8 @@ export class ChangeCurrentDeploymentService extends BaseService { switch (direction) { case "promote": { if ( - compareDeploymentVersions( - currentPromotion.deployment.version, - deployment.version - ) >= 0 + compareDeploymentVersions(currentPromotion.deployment.version, deployment.version) >= + 0 ) { throw new ServiceValidationError( "Cannot promote a deployment that is older than the current deployment." @@ -66,10 +65,8 @@ export class ChangeCurrentDeploymentService extends BaseService { } case "rollback": { if ( - compareDeploymentVersions( - currentPromotion.deployment.version, - deployment.version - ) <= 0 + compareDeploymentVersions(currentPromotion.deployment.version, deployment.version) <= + 0 ) { throw new ServiceValidationError( "Cannot rollback to a deployment that is newer than the current deployment." @@ -118,6 +115,58 @@ export class ChangeCurrentDeploymentService extends BaseService { logger.error("Error syncing task identifiers on deployment change", { error: syncError }); } + const [scheduleSyncError] = await tryCatch(this.#syncSchedulesForDeployment(deployment)); + + if (scheduleSyncError) { + logger.error("Error syncing declarative schedules on deployment change", { + error: scheduleSyncError, + }); + } + await ExecuteTasksWaitingForDeployService.enqueue(deployment.workerId); } + + async #syncSchedulesForDeployment(deployment: WorkerDeployment) { + const worker = await this._prisma.backgroundWorker.findFirst({ + where: { id: deployment.workerId! }, + }); + + if (!worker) { + logger.error("Worker not found for deployment schedule sync", { + deploymentId: deployment.id, + workerId: deployment.workerId, + }); + return; + } + + const parsed = BackgroundWorkerMetadata.safeParse(worker.metadata); + + if (!parsed.success) { + logger.error("Failed to parse worker metadata for schedule sync", { + deploymentId: deployment.id, + workerId: deployment.workerId, + error: parsed.error, + }); + return; + } + + const environment = await this._prisma.runtimeEnvironment.findFirst({ + where: { id: deployment.environmentId }, + include: { + project: true, + organization: true, + orgMember: true, + }, + }); + + if (!environment) { + logger.error("Environment not found for deployment schedule sync", { + deploymentId: deployment.id, + environmentId: deployment.environmentId, + }); + return; + } + + await syncDeclarativeSchedules(parsed.data.tasks, worker, environment, this._prisma); + } } From 91d7096b64540208de9de41b2d6119011d209a8c Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 08:53:59 +0000 Subject: [PATCH 2/2] chore: add server changes file Co-Authored-By: nick <55853254+nicktrn@users.noreply.github.com> --- .server-changes/fix-rollback-schedule-sync.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .server-changes/fix-rollback-schedule-sync.md diff --git a/.server-changes/fix-rollback-schedule-sync.md b/.server-changes/fix-rollback-schedule-sync.md new file mode 100644 index 00000000000..c9f3d14f59b --- /dev/null +++ b/.server-changes/fix-rollback-schedule-sync.md @@ -0,0 +1,6 @@ +--- +area: webapp +type: fix +--- + +Sync declarative schedules when rolling back or promoting deployments