From 8b5d5b35ad13758cab7711526d26518ba8196f9c Mon Sep 17 00:00:00 2001 From: Paul Rastoin <45004772+prastoin@users.noreply.github.com> Date: Mon, 17 Mar 2025 15:32:49 +0100 Subject: [PATCH] Workspace seeders with version (#10895) # Introduction close https://github.com/twentyhq/core-team-issues/issues/487 Updated the seeders to infer the workspace's version from the `APP_VERSION` env var To test in local run: `npx nx database:reset twenty-server` with either a defined or not defined `APP_VERSION` in your `.env` ( note that invalid semver values will throw an error and stop the process ) ( valid version ex: `APP_VERSION=1.0.0`) --- .../data-seed-demo-workspace.service.ts | 18 ++++-- .../data-seed-dev-workspace.command.ts | 8 ++- .../database/typeorm-seeds/core/demo/index.ts | 26 +------- .../src/database/typeorm-seeds/core/index.ts | 34 +++++++--- .../database/typeorm-seeds/core/workspaces.ts | 63 +++++++++++-------- 5 files changed, 86 insertions(+), 63 deletions(-) diff --git a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts index 7b1d30a7d..d7be191c3 100644 --- a/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts +++ b/packages/twenty-server/src/database/commands/data-seed-demo-workspace/services/data-seed-demo-workspace.service.ts @@ -3,14 +3,13 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { - deleteCoreSchema, - seedCoreSchema, -} from 'src/database/typeorm-seeds/core/demo'; +import { seedCoreSchema } from 'src/database/typeorm-seeds/core'; +import { deleteCoreSchema } from 'src/database/typeorm-seeds/core/demo'; import { rawDataSource } from 'src/database/typeorm/raw/raw.datasource'; import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service'; @@ -22,6 +21,7 @@ export class DataSeedDemoWorkspaceService { protected readonly workspaceRepository: Repository, @InjectCacheStorage(CacheStorageNamespace.EngineWorkspace) private readonly workspaceSchemaCache: CacheStorageService, + private readonly environmentService: EnvironmentService, ) {} async seedDemo(): Promise { @@ -43,7 +43,15 @@ export class DataSeedDemoWorkspaceService { await deleteCoreSchema(rawDataSource, workspaceId); } - await seedCoreSchema(rawDataSource, workspaceId); + const appVersion = this.environmentService.get('APP_VERSION'); + + await seedCoreSchema({ + workspaceDataSource: rawDataSource, + workspaceId, + appVersion, + seedBilling: false, + seedFeatureFlags: false, + }); await this.workspaceManagerService.initDemo(workspaceId); } } catch (error) { diff --git a/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts b/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts index 5ea2ae50d..7d0cf6c28 100644 --- a/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts +++ b/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts @@ -95,8 +95,14 @@ export class DataSeedWorkspaceCommand extends CommandRunner { await rawDataSource.initialize(); const isBillingEnabled = this.environmentService.get('IS_BILLING_ENABLED'); + const appVersion = this.environmentService.get('APP_VERSION'); - await seedCoreSchema(rawDataSource, workspaceId, isBillingEnabled); + await seedCoreSchema({ + workspaceDataSource: rawDataSource, + workspaceId, + seedBilling: isBillingEnabled, + appVersion, + }); await rawDataSource.destroy(); diff --git a/packages/twenty-server/src/database/typeorm-seeds/core/demo/index.ts b/packages/twenty-server/src/database/typeorm-seeds/core/demo/index.ts index c1e7e4e52..cc35a0f67 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/core/demo/index.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/core/demo/index.ts @@ -1,29 +1,9 @@ import { DataSource } from 'typeorm'; -import { - seedUsers, - deleteUsersByWorkspace, -} from 'src/database/typeorm-seeds/core/demo/users'; -import { - seedWorkspaces, - deleteWorkspaces, -} from 'src/database/typeorm-seeds/core/demo/workspaces'; import { deleteFeatureFlags } from 'src/database/typeorm-seeds/core/demo/feature-flags'; -import { - deleteUserWorkspaces, - seedUserWorkspaces, -} from 'src/database/typeorm-seeds/core/demo/user-workspaces'; - -export const seedCoreSchema = async ( - workspaceDataSource: DataSource, - workspaceId: string, -) => { - const schemaName = 'core'; - - await seedWorkspaces(workspaceDataSource, schemaName, workspaceId); - await seedUsers(workspaceDataSource, schemaName); - await seedUserWorkspaces(workspaceDataSource, schemaName, workspaceId); -}; +import { deleteUserWorkspaces } from 'src/database/typeorm-seeds/core/demo/user-workspaces'; +import { deleteUsersByWorkspace } from 'src/database/typeorm-seeds/core/demo/users'; +import { deleteWorkspaces } from 'src/database/typeorm-seeds/core/demo/workspaces'; export const deleteCoreSchema = async ( workspaceDataSource: DataSource, diff --git a/packages/twenty-server/src/database/typeorm-seeds/core/index.ts b/packages/twenty-server/src/database/typeorm-seeds/core/index.ts index 1aae1bb17..4bdab4b81 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/core/index.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/core/index.ts @@ -6,19 +6,37 @@ import { seedUserWorkspaces } from 'src/database/typeorm-seeds/core/user-workspa import { seedUsers } from 'src/database/typeorm-seeds/core/users'; import { seedWorkspaces } from 'src/database/typeorm-seeds/core/workspaces'; -export const seedCoreSchema = async ( - workspaceDataSource: DataSource, - workspaceId: string, - isBillingEnabled: boolean, -) => { +type SeedCoreSchemaArgs = { + workspaceDataSource: DataSource; + workspaceId: string; + appVersion: string | undefined; + seedBilling?: boolean; + seedFeatureFlags?: boolean; +}; + +export const seedCoreSchema = async ({ + appVersion, + workspaceDataSource, + workspaceId, + seedBilling = true, + seedFeatureFlags: shouldSeedFeatureFlags = true, +}: SeedCoreSchemaArgs) => { const schemaName = 'core'; - await seedWorkspaces(workspaceDataSource, schemaName, workspaceId); + await seedWorkspaces({ + workspaceDataSource, + schemaName, + workspaceId, + appVersion, + }); await seedUsers(workspaceDataSource, schemaName); await seedUserWorkspaces(workspaceDataSource, schemaName, workspaceId); - await seedFeatureFlags(workspaceDataSource, schemaName, workspaceId); - if (isBillingEnabled) { + if (shouldSeedFeatureFlags) { + await seedFeatureFlags(workspaceDataSource, schemaName, workspaceId); + } + + if (seedBilling) { await seedBillingSubscriptions( workspaceDataSource, schemaName, diff --git a/packages/twenty-server/src/database/typeorm-seeds/core/workspaces.ts b/packages/twenty-server/src/database/typeorm-seeds/core/workspaces.ts index 2a48c2463..4aa4bac82 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/core/workspaces.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/core/workspaces.ts @@ -2,57 +2,68 @@ import { WorkspaceActivationStatus } from 'twenty-shared'; import { DataSource } from 'typeorm'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { extractVersionMajorMinorPatch } from 'src/utils/version/extract-version-major-minor-patch'; const tableName = 'workspace'; export const SEED_APPLE_WORKSPACE_ID = '20202020-1c25-4d02-bf25-6aeccf7ea419'; export const SEED_ACME_WORKSPACE_ID = '3b8e6458-5fc1-4e63-8563-008ccddaa6db'; -export const seedWorkspaces = async ( - workspaceDataSource: DataSource, - schemaName: string, - workspaceId: string, -) => { - const workspaces: { - [key: string]: Pick< - Workspace, - | 'id' - | 'displayName' - | 'inviteHash' - | 'logo' - | 'subdomain' - | 'activationStatus' - >; - } = { +export type SeedWorkspaceArgs = { + workspaceDataSource: DataSource; + schemaName: string; + workspaceId: string; + appVersion: string | undefined; +}; + +const workspaceSeederFields = [ + 'id', + 'displayName', + 'subdomain', + 'inviteHash', + 'logo', + 'activationStatus', + 'version', +] as const satisfies (keyof Workspace)[]; + +type WorkspaceSeederFields = Pick< + Workspace, + (typeof workspaceSeederFields)[number] +>; + +export const seedWorkspaces = async ({ + schemaName, + workspaceDataSource, + workspaceId, + appVersion, +}: SeedWorkspaceArgs) => { + const version = extractVersionMajorMinorPatch(appVersion); + + const workspaces: Record = { [SEED_APPLE_WORKSPACE_ID]: { - id: workspaceId, + id: SEED_APPLE_WORKSPACE_ID, displayName: 'Apple', subdomain: 'apple', inviteHash: 'apple.dev-invite-hash', logo: 'https://twentyhq.github.io/placeholder-images/workspaces/apple-logo.png', activationStatus: WorkspaceActivationStatus.ACTIVE, + version: version, }, [SEED_ACME_WORKSPACE_ID]: { - id: workspaceId, + id: SEED_ACME_WORKSPACE_ID, displayName: 'Acme', subdomain: 'acme', inviteHash: 'acme.dev-invite-hash', logo: 'https://logos-world.net/wp-content/uploads/2022/05/Acme-Logo-700x394.png', activationStatus: WorkspaceActivationStatus.ACTIVE, + version: version, }, }; await workspaceDataSource .createQueryBuilder() .insert() - .into(`${schemaName}.${tableName}`, [ - 'id', - 'displayName', - 'subdomain', - 'inviteHash', - 'logo', - 'activationStatus', - ]) + .into(`${schemaName}.${tableName}`, workspaceSeederFields) .orIgnore() .values(workspaces[workspaceId]) .execute();