From 28e79de7b04fdc2a43380089aeb6ab31690a2634 Mon Sep 17 00:00:00 2001 From: Paul Rastoin <45004772+prastoin@users.noreply.github.com> Date: Thu, 8 Jan 2026 15:12:57 +0100 Subject: [PATCH] Fix workspace application fk command re-run (#17018) # Introduction The command is not idempotent, try to create an already existing FK fails - Always dropping the FK before recreating it in order to prevent this - Removed the `remoteTable` and `remoteServer` from the command We still have the `hasRunOnce` static var that will avoid re running it if a workspace successfully passed the migration Note: This is shared between both the upgrade command and the typeorm migration ## Test locally ```ts atedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Object person (20202020-e674-48e5-a542-72570eee7213) already has updatedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Object pet (custom) already has updatedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Object surveyResult (custom) already has updatedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Object rocket (custom) already has updatedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] All objects already have updatedBy field for workspace 20202020-1c25-4d02-bf25-6aeccf7ea419 [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [AddWorkspaceForeignKeysMigrationCommand] Successfully run AddWorkspaceForeignKeysMigrationCommand [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [UpgradeCommand] Upgrade for workspace 20202020-1c25-4d02-bf25-6aeccf7ea419 completed. [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [UpgradeCommand] Running command on workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db 2/2 [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [UpgradeCommand] Upgrading workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db from=1.14.0 to=1.15.0 2/2 [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [MigratePageLayoutWidgetConfigurationCommand] Starting migration of page layout widget configurations for workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [MigratePageLayoutWidgetConfigurationCommand] Found 0 widget(s) needing migration out of 16 total query: SELECT COUNT(1) AS "cnt" FROM "workspace_3ixj3i1a5avy16ptijtb3lae3"."note" "note" WHERE ( (("note"."position" = $1)) ) AND ( "note"."deletedAt" IS NULL ) -- PARAMETERS: ["NaN"] [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [FixNanPositionValuesInNotesCommand] Found 0 note(s) with NaN position values in workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [FixNanPositionValuesInNotesCommand] No NaN position values to fix [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Starting backfill of updatedBy field for workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Object note (20202020-0b00-45cd-b6f6-6cd806fc6804) already has updatedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Object task (20202020-1ba1-48ba-bc83-ef7e5990ed10) already has updatedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Object dashboard (20202020-3840-4b6d-9425-0c5188b05ca8) already has updatedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Object workflowRun (20202020-4e28-4e95-a9d7-6c00874f843c) already has updatedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Object workflow (20202020-62be-406c-b9ca-8caa50d51392) already has updatedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Object opportunity (20202020-9549-49dd-b2b2-883999db8938) already has updatedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Object company (20202020-b374-4779-a561-80086cb2e17f) already has updatedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Object attachment (20202020-bd3d-4c60-8dca-571c71d4447a) already has updatedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Object person (20202020-e674-48e5-a542-72570eee7213) already has updatedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] Object surveyResult (custom) already has updatedBy field, skipping [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [BackfillUpdatedByFieldCommand] All objects already have updatedBy field for workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [AddWorkspaceForeignKeysMigrationCommand] Skipping has already been run once AddWorkspaceForeignKeysMigrationCommand [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [UpgradeCommand] Upgrade for workspace 3b8e6458-5fc1-4e63-8563-008ccddaa6db completed. [Nest] 17395 - 01/08/2026, 3:04:18 PM LOG [UpgradeCommand] Command completed! ``` --- ...7002571103-addWorkspaceForeignKeys.util.ts | 61 +++++++++++++++++-- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/packages/twenty-server/src/database/typeorm/core/migrations/utils/1767002571103-addWorkspaceForeignKeys.util.ts b/packages/twenty-server/src/database/typeorm/core/migrations/utils/1767002571103-addWorkspaceForeignKeys.util.ts index ed6f8d0c16..3aca4041b8 100644 --- a/packages/twenty-server/src/database/typeorm/core/migrations/utils/1767002571103-addWorkspaceForeignKeys.util.ts +++ b/packages/twenty-server/src/database/typeorm/core/migrations/utils/1767002571103-addWorkspaceForeignKeys.util.ts @@ -3,52 +3,101 @@ import { type QueryRunner } from 'typeorm'; export const addWorkspaceForeignKeysQueries = async ( queryRunner: QueryRunner, ): Promise => { + await queryRunner.query( + `ALTER TABLE "core"."indexMetadata" DROP CONSTRAINT IF EXISTS "FK_5c988136a6d6f25a100c1064789"`, + ); await queryRunner.query( `ALTER TABLE "core"."indexMetadata" ADD CONSTRAINT "FK_5c988136a6d6f25a100c1064789" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); + + await queryRunner.query( + `ALTER TABLE "core"."roleTarget" DROP CONSTRAINT IF EXISTS "FK_a86894bed7b7e1cc8b3f1d6186f"`, + ); await queryRunner.query( `ALTER TABLE "core"."roleTarget" ADD CONSTRAINT "FK_a86894bed7b7e1cc8b3f1d6186f" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); + + await queryRunner.query( + `ALTER TABLE "core"."role" DROP CONSTRAINT IF EXISTS "FK_d2532f520d84f8c22ee45681c5a"`, + ); await queryRunner.query( `ALTER TABLE "core"."role" ADD CONSTRAINT "FK_d2532f520d84f8c22ee45681c5a" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); + + await queryRunner.query( + `ALTER TABLE "core"."fieldMetadata" DROP CONSTRAINT IF EXISTS "FK_9ce5ba7878f498bcf79e447a9a6"`, + ); await queryRunner.query( `ALTER TABLE "core"."fieldMetadata" ADD CONSTRAINT "FK_9ce5ba7878f498bcf79e447a9a6" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); + + await queryRunner.query( + `ALTER TABLE "core"."objectMetadata" DROP CONSTRAINT IF EXISTS "FK_d82a05a204136c01388ea80bc7a"`, + ); await queryRunner.query( `ALTER TABLE "core"."objectMetadata" ADD CONSTRAINT "FK_d82a05a204136c01388ea80bc7a" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); + + await queryRunner.query( + `ALTER TABLE "core"."cronTrigger" DROP CONSTRAINT IF EXISTS "FK_058c319eeb9799a4637908ce362"`, + ); await queryRunner.query( `ALTER TABLE "core"."cronTrigger" ADD CONSTRAINT "FK_058c319eeb9799a4637908ce362" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); + + await queryRunner.query( + `ALTER TABLE "core"."databaseEventTrigger" DROP CONSTRAINT IF EXISTS "FK_cf158c3199dcf2d52b0da05c33b"`, + ); await queryRunner.query( `ALTER TABLE "core"."databaseEventTrigger" ADD CONSTRAINT "FK_cf158c3199dcf2d52b0da05c33b" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); + + await queryRunner.query( + `ALTER TABLE "core"."routeTrigger" DROP CONSTRAINT IF EXISTS "FK_5e004929fcf5e67398544b43885"`, + ); await queryRunner.query( `ALTER TABLE "core"."routeTrigger" ADD CONSTRAINT "FK_5e004929fcf5e67398544b43885" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); + + await queryRunner.query( + `ALTER TABLE "core"."serverlessFunction" DROP CONSTRAINT IF EXISTS "FK_ef5dde6a681970b9c1e10563498"`, + ); await queryRunner.query( `ALTER TABLE "core"."serverlessFunction" ADD CONSTRAINT "FK_ef5dde6a681970b9c1e10563498" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); + + await queryRunner.query( + `ALTER TABLE "core"."dataSource" DROP CONSTRAINT IF EXISTS "FK_e1914827ee8b22fba4254578311"`, + ); await queryRunner.query( `ALTER TABLE "core"."dataSource" ADD CONSTRAINT "FK_e1914827ee8b22fba4254578311" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); + + await queryRunner.query( + `ALTER TABLE "core"."objectPermission" DROP CONSTRAINT IF EXISTS "FK_edcd87df18d3284141757bf6e16"`, + ); await queryRunner.query( `ALTER TABLE "core"."objectPermission" ADD CONSTRAINT "FK_edcd87df18d3284141757bf6e16" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); + + await queryRunner.query( + `ALTER TABLE "core"."permissionFlag" DROP CONSTRAINT IF EXISTS "FK_835bc9f7ef959debfc5cd268049"`, + ); await queryRunner.query( `ALTER TABLE "core"."permissionFlag" ADD CONSTRAINT "FK_835bc9f7ef959debfc5cd268049" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); + + await queryRunner.query( + `ALTER TABLE "core"."serverlessFunctionLayer" DROP CONSTRAINT IF EXISTS "FK_ca0699c3c906e903d7381c6a771"`, + ); await queryRunner.query( `ALTER TABLE "core"."serverlessFunctionLayer" ADD CONSTRAINT "FK_ca0699c3c906e903d7381c6a771" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); + + await queryRunner.query( + `ALTER TABLE "core"."workspaceMigration" DROP CONSTRAINT IF EXISTS "FK_bebfcf8dcb299fd39ad04ed4c7f"`, + ); await queryRunner.query( `ALTER TABLE "core"."workspaceMigration" ADD CONSTRAINT "FK_bebfcf8dcb299fd39ad04ed4c7f" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); - await queryRunner.query( - `ALTER TABLE "core"."remoteTable" ADD CONSTRAINT "FK_30b429b14ddc6aab7495fa884f3" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, - ); - await queryRunner.query( - `ALTER TABLE "core"."remoteServer" ADD CONSTRAINT "FK_d1293835c5a0bb89fc0ed45713f" FOREIGN KEY ("workspaceId") REFERENCES "core"."workspace"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, - ); };