diff --git a/src/deploy-runs/deploy-run.repository.ts b/src/deploy-runs/deploy-run.repository.ts index ae360fb..118aa8a 100644 --- a/src/deploy-runs/deploy-run.repository.ts +++ b/src/deploy-runs/deploy-run.repository.ts @@ -49,6 +49,14 @@ type DeployRunRecord = Prisma.DeployRunGetPayload<{ }; }>; type DeployRunDatabaseClient = PrismaService | Prisma.TransactionClient; +type CreateDeployRunResult = { + run: DeployRunSummary; + created: boolean; +}; +type CreateDatabaseDeployRunResult = { + record: DeployRunRecord; + created: boolean; +}; type DeployRunMetadata = Prisma.InputJsonObject & { jenkinsBuildUrl?: string; @@ -143,16 +151,19 @@ export class DeployRunRepository { return run ? this.toSummary(run) : null; } - async create(input: CreateDeployRunInput): Promise { + async create(input: CreateDeployRunInput): Promise { const idempotencyKey = this.resolveIdempotencyKey(input); if (!this.useDatabase()) { return this.createMemoryRun(input, idempotencyKey); } - const created = await this.createDatabaseRun(input, idempotencyKey); + const result = await this.createDatabaseRun(input, idempotencyKey); - return this.toSummary(created); + return { + run: this.toSummary(result.record), + created: result.created, + }; } async updateStatus( @@ -437,7 +448,7 @@ export class DeployRunRepository { private async createDatabaseRun( input: CreateDeployRunInput, idempotencyKey: string, - ): Promise { + ): Promise { try { return await this.prisma.$transaction(async (tx) => { const existing = await this.findRecordByIdempotencyKey( @@ -446,14 +457,17 @@ export class DeployRunRepository { ); if (existing) { - return existing; + return { + record: existing, + created: false, + }; } const target = await this.findTargetProjectEnvironment(input, tx); const initialRun = this.buildInitialRun(input, idempotencyKey); const metadata = this.inputMetadata(input); - return tx.deployRun.create({ + const record = await tx.deployRun.create({ data: { projectId: target.project.id, environmentId: target.environment.id, @@ -483,13 +497,21 @@ export class DeployRunRepository { }, }, }); + + return { + record, + created: true, + }; }); } catch (error) { if (this.isIdempotencyUniqueConflict(error)) { const existing = await this.findRecordByIdempotencyKey(idempotencyKey); if (existing) { - return existing; + return { + record: existing, + created: false, + }; } } @@ -565,16 +587,22 @@ export class DeployRunRepository { private createMemoryRun( input: CreateDeployRunInput, idempotencyKey: string, - ): DeployRunSummary { + ): CreateDeployRunResult { const existing = this.memoryRuns.find((run) => run.id === idempotencyKey); if (existing) { - return existing; + return { + run: existing, + created: false, + }; } const run = this.buildInitialRun(input, idempotencyKey); this.memoryRuns.unshift(run); - return run; + return { + run, + created: true, + }; } private buildInitialRun( diff --git a/src/deploy-runs/deploy-runs.service.ts b/src/deploy-runs/deploy-runs.service.ts index 95ca20a..167cf3c 100644 --- a/src/deploy-runs/deploy-runs.service.ts +++ b/src/deploy-runs/deploy-runs.service.ts @@ -114,11 +114,12 @@ export class DeployRunsService { const project = await this.projectsService.getProject(input.projectKey); await this.validateReleaseRequest(input, project); - const run = await this.deployRunRepository.create(input); + const creation = await this.deployRunRepository.create(input); + const run = creation.run; const confirmation = this.productionConfirmationDigest(input); await this.auditService.record({ - action: 'DEPLOY_REQUESTED', + action: creation.created ? 'DEPLOY_REQUESTED' : 'DEPLOY_REQUEST_REUSED', resourceType: 'deploy_run', resourceId: run.id, actorName: input.operator, @@ -132,6 +133,10 @@ export class DeployRunsService { }, }); + if (!creation.created) { + return run; + } + return this.deployExecutionService.execute(run, project); }