Remove sync metadata from upgrade (#16491)

# Introduction
Related https://github.com/twentyhq/core-team-issues/issues/1910
From now on the upgrade won't integrate any sync metadata as it's going
to be deprecated very soon
Any updates to about to removes workspace-entity or standard flat entity
will require a dedicated upgrade command, what we've already started
doing during the 1.13 sprint, until we have totally migrated the v2 to
be workspace agnostic
This commit is contained in:
Paul Rastoin
2025-12-11 14:50:56 +01:00
committed by GitHub
parent 9c1197c0b2
commit f06a5ccacd
38 changed files with 34 additions and 7855 deletions
@@ -13,31 +13,18 @@ import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twent
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
import { SyncWorkspaceMetadataCommand } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command';
class BasicUpgradeCommandRunner extends UpgradeCommandRunner {
allCommands = {
'1.0.0': {
beforeSyncMetadata: [],
afterSyncMetadata: [],
},
'2.0.0': {
beforeSyncMetadata: [],
afterSyncMetadata: [],
},
'1.0.0': [],
'2.0.0': [],
};
}
class InvalidUpgradeCommandRunner extends UpgradeCommandRunner {
allCommands = {
invalid: {
beforeSyncMetadata: [],
afterSyncMetadata: [],
},
'2.0.0': {
beforeSyncMetadata: [],
afterSyncMetadata: [],
},
invalid: [],
'2.0.0': [],
};
}
@@ -86,14 +73,12 @@ const buildUpgradeCommandModule = async ({
twentyConfigService: TwentyConfigService,
globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
dataSourceService: DataSourceService,
syncWorkspaceMetadataCommand: SyncWorkspaceMetadataCommand,
) => {
return new commandRunner(
workspaceRepository,
twentyConfigService,
globalWorkspaceOrmManager,
dataSourceService,
syncWorkspaceMetadataCommand,
);
},
inject: [
@@ -101,7 +86,6 @@ const buildUpgradeCommandModule = async ({
TwentyConfigService,
GlobalWorkspaceOrmManager,
DataSourceService,
SyncWorkspaceMetadataCommand,
],
},
{
@@ -146,12 +130,6 @@ const buildUpgradeCommandModule = async ({
provide: DataSourceService,
useValue: mockDataSourceService,
},
{
provide: SyncWorkspaceMetadataCommand,
useValue: {
runOnWorkspace: jest.fn(),
},
},
],
}).compile();
@@ -161,9 +139,6 @@ const buildUpgradeCommandModule = async ({
describe('UpgradeCommandRunner', () => {
let upgradeCommandRunner: BasicUpgradeCommandRunner;
let workspaceRepository: Repository<WorkspaceEntity>;
let syncWorkspaceMetadataCommand: jest.Mocked<SyncWorkspaceMetadataCommand>;
let runAfterSyncMetadataSpy: jest.SpyInstance;
let runBeforeSyncMetadataSpy: jest.SpyInstance;
let runCoreMigrationsSpy: jest.SpyInstance;
let globalWorkspaceOrmManagerSpy: GlobalWorkspaceOrmManager;
@@ -201,14 +176,6 @@ describe('UpgradeCommandRunner', () => {
jest.spyOn(upgradeCommandRunner['logger'], 'error').mockImplementation();
jest.spyOn(upgradeCommandRunner['logger'], 'warn').mockImplementation();
runBeforeSyncMetadataSpy = jest.spyOn(
upgradeCommandRunner,
'runBeforeSyncMetadata',
);
runAfterSyncMetadataSpy = jest.spyOn(
upgradeCommandRunner,
'runAfterSyncMetadata',
);
jest.spyOn(upgradeCommandRunner, 'runOnWorkspace');
runCoreMigrationsSpy = jest
.spyOn(upgradeCommandRunner, 'runCoreMigrations')
@@ -217,7 +184,6 @@ describe('UpgradeCommandRunner', () => {
workspaceRepository = module.get<Repository<WorkspaceEntity>>(
getRepositoryToken(WorkspaceEntity),
);
syncWorkspaceMetadataCommand = module.get(SyncWorkspaceMetadataCommand);
globalWorkspaceOrmManagerSpy = module.get<GlobalWorkspaceOrmManager>(
GlobalWorkspaceOrmManager,
);
@@ -253,12 +219,9 @@ describe('UpgradeCommandRunner', () => {
upgradeCommandRunner.runOnWorkspace,
].forEach((fn) => expect(fn).toHaveBeenCalledTimes(1));
[
upgradeCommandRunner.runBeforeSyncMetadata,
syncWorkspaceMetadataCommand.runOnWorkspace,
upgradeCommandRunner.runAfterSyncMetadata,
workspaceRepository.update,
].forEach((fn) => expect(fn).not.toHaveBeenCalled());
[workspaceRepository.update].forEach((fn) =>
expect(fn).not.toHaveBeenCalled(),
);
});
it('should run upgrade over several workspaces', async () => {
@@ -278,9 +241,6 @@ describe('UpgradeCommandRunner', () => {
[
upgradeCommandRunner.runOnWorkspace,
upgradeCommandRunner.runBeforeSyncMetadata,
upgradeCommandRunner.runAfterSyncMetadata,
syncWorkspaceMetadataCommand.runOnWorkspace,
globalWorkspaceOrmManagerSpy.destroyDataSourceForWorkspace,
].forEach((fn) => expect(fn).toHaveBeenCalledTimes(numberOfWorkspace));
expect(workspaceRepository.update).toHaveBeenNthCalledWith(
@@ -292,35 +252,6 @@ describe('UpgradeCommandRunner', () => {
expect(upgradeCommandRunner.migrationReport.fail.length).toBe(0);
});
it('should run syncMetadataCommand betweensuccessful beforeSyncMetadataUpgradeCommandsToRun and afterSyncMetadataUpgradeCommandsToRun', async () => {
await buildModuleAndSetupSpies({});
// @ts-expect-error legacy noImplicitAny
const passedParams = [];
const options = {};
// @ts-expect-error legacy noImplicitAny
await upgradeCommandRunner.run(passedParams, options);
[
upgradeCommandRunner.runOnWorkspace,
upgradeCommandRunner.runBeforeSyncMetadata,
upgradeCommandRunner.runAfterSyncMetadata,
syncWorkspaceMetadataCommand.runOnWorkspace,
globalWorkspaceOrmManagerSpy.destroyDataSourceForWorkspace,
].forEach((fn) => expect(fn).toHaveBeenCalledTimes(1));
// Verify order of execution
const beforeSyncCall = runBeforeSyncMetadataSpy.mock.invocationCallOrder[0];
const afterSyncCall = runAfterSyncMetadataSpy.mock.invocationCallOrder[0];
const syncMetadataCall =
syncWorkspaceMetadataCommand.runOnWorkspace.mock.invocationCallOrder[0];
expect(beforeSyncCall).toBeLessThan(syncMetadataCall);
expect(syncMetadataCall).toBeLessThan(afterSyncCall);
expect(upgradeCommandRunner.migrationReport.success.length).toBe(1);
expect(upgradeCommandRunner.migrationReport.fail.length).toBe(0);
});
describe('Workspace upgrade should succeed ', () => {
const successfulTestUseCases: EachTestingContext<{
input: Omit<BuildModuleAndSetupSpiesArgs, 'numberOfWorkspace'>;
@@ -379,8 +310,6 @@ describe('UpgradeCommandRunner', () => {
expect(failReport.length).toBe(0);
expect(successReport.length).toBe(1);
expect(runCoreMigrationsSpy).toHaveBeenCalledTimes(1);
expect(runAfterSyncMetadataSpy).toHaveBeenCalledTimes(1);
expect(runBeforeSyncMetadataSpy).toHaveBeenCalledTimes(1);
const { workspaceId } = successReport[0];
expect(workspaceId).toBe('workspace_0');
@@ -21,23 +21,16 @@ import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twent
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { type DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
import { SyncWorkspaceMetadataCommand } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command';
import {
type CompareVersionMajorAndMinorReturnType,
compareVersionMajorAndMinor,
} from 'src/utils/version/compare-version-minor-and-major';
import { getPreviousVersion } from 'src/utils/version/get-previous-version';
export type VersionCommands = {
beforeSyncMetadata: (
| WorkspacesMigrationCommandRunner
| ActiveOrSuspendedWorkspacesMigrationCommandRunner
)[];
afterSyncMetadata: (
| WorkspacesMigrationCommandRunner
| ActiveOrSuspendedWorkspacesMigrationCommandRunner
)[];
};
export type VersionCommands = (
| WorkspacesMigrationCommandRunner
| ActiveOrSuspendedWorkspacesMigrationCommandRunner
)[];
export type AllCommands = Record<string, VersionCommands>;
const execPromise = promisify(exec);
@@ -54,7 +47,6 @@ export abstract class UpgradeCommandRunner extends ActiveOrSuspendedWorkspacesMi
protected readonly twentyConfigService: TwentyConfigService,
protected readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
protected readonly dataSourceService: DataSourceService,
protected readonly syncWorkspaceMetadataCommand: SyncWorkspaceMetadataCommand,
) {
super(workspaceRepository, globalWorkspaceOrmManager, dataSourceService);
}
@@ -184,7 +176,7 @@ export abstract class UpgradeCommandRunner extends ActiveOrSuspendedWorkspacesMi
'Initialized upgrade context with:',
`- currentVersion (migrating to): ${currentAppVersion}`,
`- fromWorkspaceVersion: ${previousVersion}`,
`- ${this.commands.beforeSyncMetadata.length + this.commands.afterSyncMetadata.length} commands`,
`- ${this.commands.length} commands`,
];
this.logger.log(chalk.blue(message.join('\n ')));
@@ -269,9 +261,9 @@ If any workspaces are not on the previous minor version, roll back to that versi
);
}
case 'equal': {
await this.runBeforeSyncMetadata(args);
await this.syncWorkspaceMetadataCommand.runOnWorkspace(args);
await this.runAfterSyncMetadata(args);
for (const command of this.commands) {
await command.runOnWorkspace(args);
}
if (!options.dryRun) {
await this.workspaceRepository.update(
@@ -303,18 +295,6 @@ If any workspaces are not on the previous minor version, roll back to that versi
}
}
public readonly runBeforeSyncMetadata = async (args: RunOnWorkspaceArgs) => {
for (const command of this.commands.beforeSyncMetadata) {
await command.runOnWorkspace(args);
}
};
public readonly runAfterSyncMetadata = async (args: RunOnWorkspaceArgs) => {
for (const command of this.commands.afterSyncMetadata) {
await command.runOnWorkspace(args);
}
};
private retrieveCurrentAppVersion() {
const appVersion = this.twentyConfigService.get('APP_VERSION');