Add command to delete workflow runs (#13736)

Add `workflow:delete-workflow-runs` command to delete workflow runs
Options:
- created-before YYYY-MM-DD default to now
- standard options from
`ActiveOrSuspendedWorkspacesMigrationCommandRunner` commands
This commit is contained in:
martmull
2025-08-07 19:03:11 +02:00
committed by GitHub
parent 6fa34df6f9
commit 713c3d71fb
2 changed files with 92 additions and 3 deletions
@@ -0,0 +1,80 @@
import { InjectRepository } from '@nestjs/typeorm';
import { Command, Option } from 'nest-commander';
import { LessThan, Repository } from 'typeorm';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
import {
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
RunOnWorkspaceArgs,
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
@Command({
name: 'workflow:delete-workflow-runs',
description: 'Delete all workflow runs',
})
export class DeleteWorkflowRunsCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
private createdBeforeDate: string | undefined;
constructor(
@InjectRepository(Workspace, 'core')
protected readonly workspaceRepository: Repository<Workspace>,
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
) {
super(workspaceRepository, twentyORMGlobalManager);
}
@Option({
flags: '--created-before [created_before]',
description:
'created before. Delete workflow runs created before that date (YYYY-MM-DD)',
required: false,
})
parseCreatedBefore(val: string): string | undefined {
const date = new Date(val);
if (isNaN(date.getTime())) {
throw new Error(`Invalid date format: ${val}`);
}
const createdBeforeDate = date.toISOString();
this.createdBeforeDate = createdBeforeDate;
return createdBeforeDate;
}
override async runOnWorkspace({
workspaceId,
options,
}: RunOnWorkspaceArgs): Promise<void> {
try {
const workflowRunRepository =
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkflowRunWorkspaceEntity>(
workspaceId,
'workflowRun',
{ shouldBypassPermissionChecks: true },
);
const createdAtCondition = {
createdAt: LessThan(this.createdBeforeDate || new Date().toISOString()),
};
const workflowRunCount = await workflowRunRepository.count({
where: createdAtCondition,
});
if (!options.dryRun && workflowRunCount > 0) {
await workflowRunRepository.delete(createdAtCondition);
}
this.logger.log(
`${options.dryRun ? ' (DRY RUN): ' : ''}Deleted ${workflowRunCount} workflow runs`,
);
} catch (error) {
this.logger.error('Error while deleting workflowRun', error);
}
}
}
@@ -9,16 +9,25 @@ import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/s
import { WorkflowCommonModule } from 'src/modules/workflow/common/workflow-common.module';
import { WorkflowRunWorkspaceService } from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service';
import { CacheLockModule } from 'src/engine/core-modules/cache-lock/cache-lock.module';
import { DeleteWorkflowRunsCommand } from 'src/modules/workflow/workflow-runner/workflow-run/command/delete-workflow-runs.command';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
@Module({
imports: [
WorkflowCommonModule,
NestjsQueryTypeOrmModule.forFeature([ObjectMetadataEntity], 'core'),
NestjsQueryTypeOrmModule.forFeature(
[ObjectMetadataEntity, Workspace],
'core',
),
RecordPositionModule,
CacheLockModule,
MetricsModule,
],
providers: [WorkflowRunWorkspaceService, ScopedWorkspaceContextFactory],
exports: [WorkflowRunWorkspaceService],
providers: [
WorkflowRunWorkspaceService,
ScopedWorkspaceContextFactory,
DeleteWorkflowRunsCommand,
],
exports: [WorkflowRunWorkspaceService, DeleteWorkflowRunsCommand],
})
export class WorkflowRunModule {}