mirror of
https://github.com/lingble/twenty.git
synced 2025-10-30 20:27:55 +00:00
feat: add dry-run option to sync-metadata command (#3758)
* feat: add dry-run option to sync-metadata command * feat: save metadata logs in dry-run mode
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -18,3 +18,5 @@
|
|||||||
!.yarn/versions
|
!.yarn/versions
|
||||||
coverage
|
coverage
|
||||||
.vercel
|
.vercel
|
||||||
|
|
||||||
|
**/**/logs/**
|
||||||
@@ -6,6 +6,7 @@ import { WorkspaceSyncMetadataService } from 'src/workspace/workspace-sync-metad
|
|||||||
// TODO: implement dry-run
|
// TODO: implement dry-run
|
||||||
interface RunWorkspaceMigrationsOptions {
|
interface RunWorkspaceMigrationsOptions {
|
||||||
workspaceId: string;
|
workspaceId: string;
|
||||||
|
dryRun?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command({
|
@Command({
|
||||||
@@ -35,6 +36,7 @@ export class SyncWorkspaceMetadataCommand extends CommandRunner {
|
|||||||
workspaceId: options.workspaceId,
|
workspaceId: options.workspaceId,
|
||||||
dataSourceId: dataSourceMetadata.id,
|
dataSourceId: dataSourceMetadata.id,
|
||||||
},
|
},
|
||||||
|
{ dryRun: options.dryRun },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,4 +48,13 @@ export class SyncWorkspaceMetadataCommand extends CommandRunner {
|
|||||||
parseWorkspaceId(value: string): string {
|
parseWorkspaceId(value: string): string {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Option({
|
||||||
|
flags: '-d, --dry-run',
|
||||||
|
description: 'Dry run without applying changes',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
dryRun(): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
|
||||||
|
import { WorkspaceSyncStorage } from 'src/workspace/workspace-sync-metadata/storage/workspace-sync.storage';
|
||||||
|
import { WorkspaceMigrationEntity } from 'src/metadata/workspace-migration/workspace-migration.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class WorkspaceLogsService {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
async saveLogs(
|
||||||
|
storage: WorkspaceSyncStorage,
|
||||||
|
workspaceMigrations: WorkspaceMigrationEntity[],
|
||||||
|
) {
|
||||||
|
// Save workspace migrations
|
||||||
|
await fs.writeFile(
|
||||||
|
'./logs/workspace-migrations.json',
|
||||||
|
JSON.stringify(workspaceMigrations, null, 2),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save object metadata create collection
|
||||||
|
await fs.writeFile(
|
||||||
|
'./logs/object-metadata-create-collection.json',
|
||||||
|
JSON.stringify(storage.objectMetadataCreateCollection, null, 2),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save object metadata update collection
|
||||||
|
await fs.writeFile(
|
||||||
|
'./logs/object-metadata-update-collection.json',
|
||||||
|
JSON.stringify(storage.objectMetadataUpdateCollection, null, 2),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save object metadata delete collection
|
||||||
|
await fs.writeFile(
|
||||||
|
'./logs/object-metadata-delete-collection.json',
|
||||||
|
JSON.stringify(storage.objectMetadataDeleteCollection, null, 2),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save field metadata create collection
|
||||||
|
await fs.writeFile(
|
||||||
|
'./logs/field-metadata-create-collection.json',
|
||||||
|
JSON.stringify(storage.fieldMetadataCreateCollection, null, 2),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save field metadata update collection
|
||||||
|
await fs.writeFile(
|
||||||
|
'./logs/field-metadata-update-collection.json',
|
||||||
|
JSON.stringify(storage.fieldMetadataUpdateCollection, null, 2),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save field metadata delete collection
|
||||||
|
await fs.writeFile(
|
||||||
|
'./logs/field-metadata-delete-collection.json',
|
||||||
|
JSON.stringify(storage.fieldMetadataDeleteCollection, null, 2),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save relation metadata create collection
|
||||||
|
await fs.writeFile(
|
||||||
|
'./logs/relation-metadata-create-collection.json',
|
||||||
|
JSON.stringify(storage.relationMetadataCreateCollection, null, 2),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Save relation metadata delete collection
|
||||||
|
await fs.writeFile(
|
||||||
|
'./logs/relation-metadata-delete-collection.json',
|
||||||
|
JSON.stringify(storage.relationMetadataDeleteCollection, null, 2),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ export class WorkspaceSyncObjectMetadataService {
|
|||||||
manager: EntityManager,
|
manager: EntityManager,
|
||||||
storage: WorkspaceSyncStorage,
|
storage: WorkspaceSyncStorage,
|
||||||
workspaceFeatureFlagsMap: FeatureFlagMap,
|
workspaceFeatureFlagsMap: FeatureFlagMap,
|
||||||
): Promise<void> {
|
): Promise<WorkspaceMigrationEntity[]> {
|
||||||
const objectMetadataRepository =
|
const objectMetadataRepository =
|
||||||
manager.getRepository(ObjectMetadataEntity);
|
manager.getRepository(ObjectMetadataEntity);
|
||||||
const workspaceMigrationRepository = manager.getRepository(
|
const workspaceMigrationRepository = manager.getRepository(
|
||||||
@@ -153,6 +153,10 @@ export class WorkspaceSyncObjectMetadataService {
|
|||||||
this.logger.log('Saving migrations');
|
this.logger.log('Saving migrations');
|
||||||
|
|
||||||
// Save migrations into DB
|
// Save migrations into DB
|
||||||
await workspaceMigrationRepository.save(workspaceObjectMigrations);
|
const workspaceMigrations = await workspaceMigrationRepository.save(
|
||||||
|
workspaceObjectMigrations,
|
||||||
|
);
|
||||||
|
|
||||||
|
return workspaceMigrations;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export class WorkspaceSyncRelationMetadataService {
|
|||||||
manager: EntityManager,
|
manager: EntityManager,
|
||||||
storage: WorkspaceSyncStorage,
|
storage: WorkspaceSyncStorage,
|
||||||
workspaceFeatureFlagsMap: FeatureFlagMap,
|
workspaceFeatureFlagsMap: FeatureFlagMap,
|
||||||
): Promise<void> {
|
): Promise<WorkspaceMigrationEntity[]> {
|
||||||
const objectMetadataRepository =
|
const objectMetadataRepository =
|
||||||
manager.getRepository(ObjectMetadataEntity);
|
manager.getRepository(ObjectMetadataEntity);
|
||||||
const workspaceMigrationRepository = manager.getRepository(
|
const workspaceMigrationRepository = manager.getRepository(
|
||||||
@@ -106,6 +106,10 @@ export class WorkspaceSyncRelationMetadataService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Save migrations into DB
|
// Save migrations into DB
|
||||||
await workspaceMigrationRepository.save(workspaceRelationMigrations);
|
const workspaceMigrations = await workspaceMigrationRepository.save(
|
||||||
|
workspaceRelationMigrations,
|
||||||
|
);
|
||||||
|
|
||||||
|
return workspaceMigrations;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { workspaceSyncMetadataComparators } from 'src/workspace/workspace-sync-m
|
|||||||
import { WorkspaceMetadataUpdaterService } from 'src/workspace/workspace-sync-metadata/services/workspace-metadata-updater.service';
|
import { WorkspaceMetadataUpdaterService } from 'src/workspace/workspace-sync-metadata/services/workspace-metadata-updater.service';
|
||||||
import { WorkspaceSyncObjectMetadataService } from 'src/workspace/workspace-sync-metadata/services/workspace-sync-object-metadata.service';
|
import { WorkspaceSyncObjectMetadataService } from 'src/workspace/workspace-sync-metadata/services/workspace-sync-object-metadata.service';
|
||||||
import { WorkspaceSyncRelationMetadataService } from 'src/workspace/workspace-sync-metadata/services/workspace-sync-relation-metadata.service';
|
import { WorkspaceSyncRelationMetadataService } from 'src/workspace/workspace-sync-metadata/services/workspace-sync-relation-metadata.service';
|
||||||
|
import { WorkspaceLogsService } from 'src/workspace/workspace-sync-metadata/services/workspace-logs.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -37,6 +38,7 @@ import { WorkspaceSyncRelationMetadataService } from 'src/workspace/workspace-sy
|
|||||||
WorkspaceSyncObjectMetadataService,
|
WorkspaceSyncObjectMetadataService,
|
||||||
WorkspaceSyncRelationMetadataService,
|
WorkspaceSyncRelationMetadataService,
|
||||||
WorkspaceSyncMetadataService,
|
WorkspaceSyncMetadataService,
|
||||||
|
WorkspaceLogsService,
|
||||||
],
|
],
|
||||||
exports: [WorkspaceSyncMetadataService],
|
exports: [WorkspaceSyncMetadataService],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { FeatureFlagFactory } from 'src/workspace/workspace-sync-metadata/factor
|
|||||||
import { WorkspaceSyncObjectMetadataService } from 'src/workspace/workspace-sync-metadata/services/workspace-sync-object-metadata.service';
|
import { WorkspaceSyncObjectMetadataService } from 'src/workspace/workspace-sync-metadata/services/workspace-sync-object-metadata.service';
|
||||||
import { WorkspaceSyncRelationMetadataService } from 'src/workspace/workspace-sync-metadata/services/workspace-sync-relation-metadata.service';
|
import { WorkspaceSyncRelationMetadataService } from 'src/workspace/workspace-sync-metadata/services/workspace-sync-relation-metadata.service';
|
||||||
import { WorkspaceSyncStorage } from 'src/workspace/workspace-sync-metadata/storage/workspace-sync.storage';
|
import { WorkspaceSyncStorage } from 'src/workspace/workspace-sync-metadata/storage/workspace-sync.storage';
|
||||||
|
import { WorkspaceLogsService } from 'src/workspace/workspace-sync-metadata/services/workspace-logs.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WorkspaceSyncMetadataService {
|
export class WorkspaceSyncMetadataService {
|
||||||
@@ -22,6 +23,7 @@ export class WorkspaceSyncMetadataService {
|
|||||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||||
private readonly workspaceSyncObjectMetadataService: WorkspaceSyncObjectMetadataService,
|
private readonly workspaceSyncObjectMetadataService: WorkspaceSyncObjectMetadataService,
|
||||||
private readonly workspaceSyncRelationMetadataService: WorkspaceSyncRelationMetadataService,
|
private readonly workspaceSyncRelationMetadataService: WorkspaceSyncRelationMetadataService,
|
||||||
|
private readonly workspaceLogsService: WorkspaceLogsService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,6 +36,7 @@ export class WorkspaceSyncMetadataService {
|
|||||||
*/
|
*/
|
||||||
public async syncStandardObjectsAndFieldsMetadata(
|
public async syncStandardObjectsAndFieldsMetadata(
|
||||||
context: WorkspaceSyncContext,
|
context: WorkspaceSyncContext,
|
||||||
|
options?: { dryRun?: boolean },
|
||||||
) {
|
) {
|
||||||
this.logger.log('Syncing standard objects and fields metadata');
|
this.logger.log('Syncing standard objects and fields metadata');
|
||||||
const queryRunner = this.metadataDataSource.createQueryRunner();
|
const queryRunner = this.metadataDataSource.createQueryRunner();
|
||||||
@@ -52,6 +55,7 @@ export class WorkspaceSyncMetadataService {
|
|||||||
|
|
||||||
this.logger.log('Syncing standard objects and fields metadata');
|
this.logger.log('Syncing standard objects and fields metadata');
|
||||||
|
|
||||||
|
const workspaceObjectMigrations =
|
||||||
await this.workspaceSyncObjectMetadataService.synchronize(
|
await this.workspaceSyncObjectMetadataService.synchronize(
|
||||||
context,
|
context,
|
||||||
manager,
|
manager,
|
||||||
@@ -59,6 +63,7 @@ export class WorkspaceSyncMetadataService {
|
|||||||
workspaceFeatureFlagsMap,
|
workspaceFeatureFlagsMap,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const workspaceRelationMigrations =
|
||||||
await this.workspaceSyncRelationMetadataService.synchronize(
|
await this.workspaceSyncRelationMetadataService.synchronize(
|
||||||
context,
|
context,
|
||||||
manager,
|
manager,
|
||||||
@@ -66,6 +71,22 @@ export class WorkspaceSyncMetadataService {
|
|||||||
workspaceFeatureFlagsMap,
|
workspaceFeatureFlagsMap,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// If we're running a dry run, rollback the transaction and do not execute migrations
|
||||||
|
if (options?.dryRun) {
|
||||||
|
const workspaceMigrations = [
|
||||||
|
...workspaceObjectMigrations,
|
||||||
|
...workspaceRelationMigrations,
|
||||||
|
];
|
||||||
|
|
||||||
|
this.logger.log('Running in dry run mode, rolling back transaction');
|
||||||
|
|
||||||
|
await queryRunner.rollbackTransaction();
|
||||||
|
|
||||||
|
await this.workspaceLogsService.saveLogs(storage, workspaceMigrations);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await queryRunner.commitTransaction();
|
await queryRunner.commitTransaction();
|
||||||
|
|
||||||
// Execute migrations
|
// Execute migrations
|
||||||
|
|||||||
Reference in New Issue
Block a user