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
+101
View File
@@ -863,6 +863,71 @@ export function createCloudRoutes(injectedService?: CloudProxyService) {
})
})
app.post('/:cloud/services/codebuild/resources/:id/builds', async (c) => {
if (c.req.param('cloud') !== 'aws') return c.json({error: 'Unknown cloud or service'}, 404)
return withRuntime(c, async () => {
const body = await jsonBody<{environmentVariablesOverride?: unknown}>(c)
const overrides = body.environmentVariablesOverride
if (overrides !== undefined && (!Array.isArray(overrides) || overrides.some((item) => !item || typeof item !== 'object' || typeof (item as {name?: unknown}).name !== 'string' || typeof (item as {value?: unknown}).value !== 'string' || ((item as {type?: unknown}).type !== undefined && !['PLAINTEXT', 'PARAMETER_STORE', 'SECRETS_MANAGER'].includes((item as {type: string}).type))))) {
throw new ValidationError('environmentVariablesOverride must contain name, value, and an optional supported type')
}
return c.json(await svc(c).startCodeBuild('aws', c.req.param('id'), {environmentVariablesOverride: overrides as never}), 201)
})
})
app.get('/:cloud/services/codebuild/resources/:id/builds', async (c) => {
if (c.req.param('cloud') !== 'aws') return c.json({error: 'Unknown cloud or service'}, 404)
return withRuntime(c, async () => c.json(await svc(c).listCodeBuilds('aws', c.req.param('id'))))
})
app.get('/:cloud/services/codebuild/resources/:id/builds/:buildId', async (c) => {
if (c.req.param('cloud') !== 'aws') return c.json({error: 'Unknown cloud or service'}, 404)
return withRuntime(c, async () => {
const build = await svc(c).getCodeBuild('aws', c.req.param('buildId'))
return build ? c.json(build) : c.json({error: 'Build not found'}, 404)
})
})
app.post('/:cloud/services/codepipeline/resources/:id/executions', async (c) => {
if (c.req.param('cloud') !== 'aws') return c.json({error: 'Unknown cloud or service'}, 404)
return withRuntime(c, async () => c.json(await svc(c).startPipeline('aws', c.req.param('id')), 201))
})
app.post('/:cloud/services/codedeploy/resources/:id/deployments', async (c) => {
if (c.req.param('cloud') !== 'aws') return c.json({error: 'Unknown cloud or service'}, 404)
return withRuntime(c, async () => {
const body = await jsonBody<{functionName?: unknown; alias?: unknown; currentVersion?: unknown; targetVersion?: unknown; beforeAllowTrafficHook?: unknown; afterAllowTrafficHook?: unknown}>(c)
const [applicationName, deploymentGroupName] = codeDeployGroupId(c.req.param('id'))
if (typeof body.functionName !== 'string' || typeof body.alias !== 'string' || typeof body.currentVersion !== 'string' || typeof body.targetVersion !== 'string') throw new ValidationError('functionName, alias, currentVersion, and targetVersion are required')
return c.json(await svc(c).startCodeDeployDeployment('aws', applicationName, deploymentGroupName, {functionName: body.functionName, alias: body.alias, currentVersion: body.currentVersion, targetVersion: body.targetVersion, beforeAllowTrafficHook: typeof body.beforeAllowTrafficHook === 'string' ? body.beforeAllowTrafficHook : undefined, afterAllowTrafficHook: typeof body.afterAllowTrafficHook === 'string' ? body.afterAllowTrafficHook : undefined}), 201)
})
})
app.get('/:cloud/services/codedeploy/resources/:id/deployments', async (c) => {
if (c.req.param('cloud') !== 'aws') return c.json({error: 'Unknown cloud or service'}, 404)
return withRuntime(c, async () => { const [applicationName, deploymentGroupName] = codeDeployGroupId(c.req.param('id')); return c.json(await svc(c).listCodeDeployDeployments('aws', applicationName, deploymentGroupName)) })
})
app.get('/:cloud/services/codedeploy/deployments/:deploymentId', async (c) => {
if (c.req.param('cloud') !== 'aws') return c.json({error: 'Unknown cloud or service'}, 404)
return withRuntime(c, async () => c.json(await svc(c).getCodeDeployDeployment('aws', c.req.param('deploymentId'))))
})
app.post('/:cloud/services/codedeploy/deployments/:deploymentId/stop', async (c) => {
if (c.req.param('cloud') !== 'aws') return c.json({error: 'Unknown cloud or service'}, 404)
return withRuntime(c, async () => { const body = await jsonBody<{rollback?: unknown}>(c); await svc(c).stopCodeDeployDeployment('aws', c.req.param('deploymentId'), body.rollback === true); return c.json({ok: true}) })
})
app.get('/:cloud/services/codepipeline/resources/:id/executions', async (c) => {
if (c.req.param('cloud') !== 'aws') return c.json({error: 'Unknown cloud or service'}, 404)
return withRuntime(c, async () => c.json(await svc(c).listPipelineExecutions('aws', c.req.param('id'))))
})
app.get('/:cloud/services/codepipeline/resources/:id/state', async (c) => {
if (c.req.param('cloud') !== 'aws') return c.json({error: 'Unknown cloud or service'}, 404)
return withRuntime(c, async () => c.json(await svc(c).getPipelineState('aws', c.req.param('id'))))
})
app.get('/:cloud/services/serverless/resources/:id/sqs-event-source-mappings', async (c) => {
const cloud = c.req.param('cloud') as CloudProvider
if (cloud !== 'aws') return c.json({error: 'Unknown cloud or service'}, 404)
@@ -1110,6 +1175,36 @@ export function createCloudRoutes(injectedService?: CloudProxyService) {
})
})
app.post('/:cloud/services/:service/resources/:id/start', async (c) => {
const cloud = c.req.param('cloud') as CloudProvider
const serviceType = c.req.param('service') as CloudServiceType
if (!isCloudProvider(cloud) || !isServiceType(serviceType)) return c.json({error: 'Unknown cloud or service'}, 404)
return withRuntime(c, async () => {
await svc(c).startResource(cloud, serviceType, c.req.param('id'))
return c.json({ok: true})
})
})
app.post('/:cloud/services/:service/resources/:id/stop', async (c) => {
const cloud = c.req.param('cloud') as CloudProvider
const serviceType = c.req.param('service') as CloudServiceType
if (!isCloudProvider(cloud) || !isServiceType(serviceType)) return c.json({error: 'Unknown cloud or service'}, 404)
return withRuntime(c, async () => {
await svc(c).stopResource(cloud, serviceType, c.req.param('id'))
return c.json({ok: true})
})
})
app.post('/:cloud/services/:service/resources/:id/reboot', async (c) => {
const cloud = c.req.param('cloud') as CloudProvider
const serviceType = c.req.param('service') as CloudServiceType
if (!isCloudProvider(cloud) || !isServiceType(serviceType)) return c.json({error: 'Unknown cloud or service'}, 404)
return withRuntime(c, async () => {
await svc(c).rebootResource(cloud, serviceType, c.req.param('id'))
return c.json({ok: true})
})
})
app.post('/:cloud/services/notifications/resources/:id/publish', async (c) => {
const cloud = c.req.param('cloud') as CloudProvider
if (!isCloudProvider(cloud)) return c.json({error: 'Unknown cloud'}, 404)
@@ -1366,6 +1461,12 @@ function pageQuery(c: Context): PageQuery {
return {cursor: c.req.query('cursor'), limit: clampLimit(c.req.query('limit'))}
}
function codeDeployGroupId(id: string): [string, string] {
const separator = id.indexOf('/')
if (separator <= 0 || separator === id.length - 1) throw new ValidationError('Deployment group id must be applicationName/deploymentGroupName')
return [id.slice(0, separator), id.slice(separator + 1)]
}
async function withRuntime(c: Context, handler: () => Promise<Response>): Promise<Response> {
try {
return await handler()