CI/CD - CodeBuild + CodeDeploy + CodePipeline

This commit is contained in:
Zakaria
2026-10-01 09:18:04 -04:00
parent aa02cdb7f6
commit 7f0d707578
41 changed files with 1817 additions and 78 deletions
@@ -86,6 +86,9 @@ import type {
import {NotSupportedError} from '../cloud-spi/errors'
import {CloudAdapterRegistry} from '../registry/CloudAdapterRegistry'
import type {StartWorkflowExecutionInput, WorkflowExecutionDetail, WorkflowExecutionHistoryPage, WorkflowExecutionSummary} from '../cloud-spi/workflowExecutions'
import type {CodeBuildBuild, StartCodeBuildInput} from '../cloud-spi/codebuild'
import type {PipelineExecutionSummary, PipelineState} from '../cloud-spi/codepipeline'
import type {CodeDeployDeployment, StartCodeDeployDeploymentInput} from '../cloud-spi/codedeploy'
import {SERVICE_CATALOG_ENTRIES, displayNameFor, routeFor} from '../cloud-spi/serviceCatalog'
import {toHttpError} from '../cloud-spi/errors'
import {mapAwsSdkError} from '../adapter-aws/awsErrors'
@@ -482,6 +485,24 @@ export class CloudProxyService {
await this.requireAdapter(cloud, service).delete(id)
}
async startResource(cloud: CloudProvider, service: CloudServiceType, id: string): Promise<void> {
const adapter = this.requireAdapter(cloud, service)
if (!adapter.start) throw new NotSupportedError(`Resource start is not supported for ${cloud}/${service}`)
await adapter.start(id)
}
async stopResource(cloud: CloudProvider, service: CloudServiceType, id: string): Promise<void> {
const adapter = this.requireAdapter(cloud, service)
if (!adapter.stop) throw new NotSupportedError(`Resource stop is not supported for ${cloud}/${service}`)
await adapter.stop(id)
}
async rebootResource(cloud: CloudProvider, service: CloudServiceType, id: string): Promise<void> {
const adapter = this.requireAdapter(cloud, service)
if (!adapter.reboot) throw new NotSupportedError(`Resource reboot is not supported for ${cloud}/${service}`)
await adapter.reboot(id)
}
async encryptKms(cloud: CloudProvider, keyId: string, input: KmsEncryptInput): Promise<KmsEncryptResult> {
const adapter = this.requireAdapter(cloud, 'kms')
if (!adapter.encrypt) throw new NotSupportedError(`${cloud}/kms encrypt is not supported`)
@@ -852,6 +873,46 @@ export class CloudProxyService {
await this.workflowAdapter(cloud).stopExecution(executionArn)
}
async startCodeBuild(cloud: CloudProvider, projectName: string, input: StartCodeBuildInput): Promise<CodeBuildBuild> {
return this.codeBuildAdapter(cloud).startBuild!(projectName, input)
}
async listCodeBuilds(cloud: CloudProvider, projectName: string): Promise<CodeBuildBuild[]> {
return this.codeBuildAdapter(cloud).listBuilds!(projectName)
}
async getCodeBuild(cloud: CloudProvider, id: string): Promise<CodeBuildBuild | null> {
return this.codeBuildAdapter(cloud).getBuild!(id)
}
async startPipeline(cloud: CloudProvider, id: string): Promise<{id: string}> {
return this.codePipelineAdapter(cloud).startPipeline!(id)
}
async listPipelineExecutions(cloud: CloudProvider, id: string): Promise<PipelineExecutionSummary[]> {
return this.codePipelineAdapter(cloud).listPipelineExecutions!(id)
}
async getPipelineState(cloud: CloudProvider, id: string): Promise<PipelineState> {
return this.codePipelineAdapter(cloud).getPipelineState!(id)
}
async startCodeDeployDeployment(cloud: CloudProvider, applicationName: string, deploymentGroupName: string, input: StartCodeDeployDeploymentInput): Promise<CodeDeployDeployment> {
return this.codeDeployAdapter(cloud).startCodeDeployDeployment!(applicationName, deploymentGroupName, input)
}
async listCodeDeployDeployments(cloud: CloudProvider, applicationName: string, deploymentGroupName: string): Promise<CodeDeployDeployment[]> {
return this.codeDeployAdapter(cloud).listCodeDeployDeployments!(applicationName, deploymentGroupName)
}
async getCodeDeployDeployment(cloud: CloudProvider, id: string): Promise<CodeDeployDeployment> {
return this.codeDeployAdapter(cloud).getCodeDeployDeployment!(id)
}
async stopCodeDeployDeployment(cloud: CloudProvider, id: string, rollback: boolean): Promise<void> {
await this.codeDeployAdapter(cloud).stopCodeDeployDeployment!(id, rollback)
}
private workflowAdapter(cloud: CloudProvider) {
const adapter = this.requireAdapter(cloud, 'workflows')
if (!('startExecution' in adapter) || !('listExecutions' in adapter) || !('describeExecution' in adapter) || !('getExecutionHistory' in adapter) || !('stopExecution' in adapter)) {
@@ -860,6 +921,30 @@ export class CloudProxyService {
return adapter as import('../adapter-aws/AwsStepFunctionsAdapter').AwsStepFunctionsAdapter
}
private codeBuildAdapter(cloud: CloudProvider) {
const adapter = this.requireAdapter(cloud, 'codebuild')
if (!adapter.startBuild || !adapter.listBuilds || !adapter.getBuild) {
throw new NotSupportedError(`CodeBuild builds are not supported for ${cloud}`)
}
return adapter
}
private codePipelineAdapter(cloud: CloudProvider) {
const adapter = this.requireAdapter(cloud, 'codepipeline')
if (!adapter.startPipeline || !adapter.listPipelineExecutions || !adapter.getPipelineState) {
throw new NotSupportedError(`CodePipeline executions are not supported for ${cloud}`)
}
return adapter
}
private codeDeployAdapter(cloud: CloudProvider) {
const adapter = this.requireAdapter(cloud, 'codedeploy')
if (!adapter.startCodeDeployDeployment || !adapter.listCodeDeployDeployments || !adapter.getCodeDeployDeployment || !adapter.stopCodeDeployDeployment) {
throw new NotSupportedError(`CodeDeploy deployments are not supported for ${cloud}`)
}
return adapter
}
private requireAdapter(cloud: CloudProvider, service: CloudServiceType) {
const adapter = this.registry.get(cloud, service)
if (!adapter) throw new NotSupportedError(`No adapter registered for ${cloud}/${service}`)