in lib/toolchain-stack.ts [32:185]
constructor(scope: cdk.Construct, id: string, props: cdk.StackProps) {
super(scope, id, props);
const deploymentTable = new dynamodb.Table(this, 'deployment-table', {
tableName: DEPLOYMENT_TABLE_NAME,
partitionKey: {
name: 'id',
type: dynamodb.AttributeType.STRING,
},
stream: dynamodb.StreamViewType.NEW_AND_OLD_IMAGES,
billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
removalPolicy: cdk.RemovalPolicy.DESTROY,
});
// Importing pre-created CodeCommit repository by name.
const sourceRepository = codecommit.Repository.fromRepositoryName(this, 'repository', REPOSITORY_NAME);
const synthStep = new pipelines.CodeBuildStep('synth', {
input: pipelines.CodePipelineSource.codeCommit(sourceRepository, 'main'),
commands: [
'npm ci',
'npx cdk synth -q --verbose',
],
});
const pipeline = new pipelines.CodePipeline(this, 'cicd-pipeline', {
pipelineName: 'CICD-Pipeline',
selfMutation: true,
synth: synthStep,
cliVersion: CDK_VERSION,
});
const updateDeploymentsRole = new iam.Role(this, 'update-deployments-role', {
assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com'),
inlinePolicies: {
'deployment-policy': new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
actions: [
'codepipeline:StartPipelineExecution',
'codepipeline:GetPipelineExecution',
'codepipeline:GetPipelineState',
],
resources: [
'arn:aws:codepipeline:' + this.region + ':' + this.account + ':silo-*-pipeline',
'arn:aws:codepipeline:' + this.region + ':' + this.account + ':pool-*-pipeline',
],
effect: iam.Effect.ALLOW,
}),
new iam.PolicyStatement({
actions: ['cloudformation:ListStacks'],
effect: iam.Effect.ALLOW,
resources: ['*'],
}),
new iam.PolicyStatement({
actions: ['dynamodb:Query', 'dynamodb:Scan'],
effect: iam.Effect.ALLOW,
resources: [deploymentTable.tableArn, deploymentTable.tableArn + '/index/*'],
}),
new iam.PolicyStatement({
actions: ['ec2:DescribeRegions'],
effect: iam.Effect.ALLOW,
resources: ['*'],
}),
],
}),
},
});
pipeline.addWave('UpdateDeployments', {
post: [
new pipelines.CodeBuildStep('update-deployments', {
commands: [
'npm ci',
'npx ts-node bin/get-deployments.ts',
'npx ts-node bin/update-deployments.ts',
],
buildEnvironment: {
buildImage: codebuild.LinuxBuildImage.STANDARD_5_0,
},
role: updateDeploymentsRole,
}),
],
});
// CodeBuild Project for Provisioning Build Job
const project = new codebuild.Project(this, 'provisioning-project', {
projectName: 'provisioning-project',
source: codebuild.Source.codeCommit({
repository: sourceRepository,
branchOrRef: 'refs/heads/main',
}),
environment: {
buildImage: codebuild.LinuxBuildImage.STANDARD_5_0,
},
buildSpec: codebuild.BuildSpec.fromObject({
version: '0.2',
phases: {
build: {
commands: [
'npm ci',
'npx ts-node bin/provision-deployment.ts',
],
},
},
}),
});
// Allow provision project to use CDK bootstrap roles. These are required when provision project runs CDK deploy
project.addToRolePolicy(new iam.PolicyStatement({
actions: ['sts:AssumeRole'],
resources: [
'arn:aws:iam::' + this.account + ':role/cdk-' + cdk.DefaultStackSynthesizer.DEFAULT_QUALIFIER + '-deploy-role-' + this.account + '-' + this.region,
'arn:aws:iam::' + this.account + ':role/cdk-' + cdk.DefaultStackSynthesizer.DEFAULT_QUALIFIER + '-file-publishing-role-' + this.account + '-' + this.region,
'arn:aws:iam::' + this.account + ':role/cdk-' + cdk.DefaultStackSynthesizer.DEFAULT_QUALIFIER + '-image-publishing-role-' + this.account + '-' + this.region,
],
effect: iam.Effect.ALLOW,
}));
// Allow provision project to get AWS regions.
// This is required for deployment information validation.
project.addToRolePolicy(new iam.PolicyStatement({
actions: ['ec2:DescribeRegions'],
effect: iam.Effect.ALLOW,
resources: ['*'],
}));
// Lambda Function for DynamoDB Streams
const streamLambda = new lambda.Function(this, 'stream-lambda', {
runtime: lambda.Runtime.NODEJS_14_X,
handler: 'index.handler',
code: lambda.Code.fromAsset(path.join(__dirname, 'lambdas/stream-lambda')),
environment: {
PROJECT_NAME: 'provisioning-project',
},
});
streamLambda.role?.attachInlinePolicy(new iam.Policy(this, 'start-pipeline-policy', {
document: new iam.PolicyDocument({
statements: [
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
resources: [project.projectArn],
actions: ['codebuild:StartBuild'],
}),
],
}),
}));
streamLambda.addEventSource(new DynamoEventSource(deploymentTable, {
startingPosition: lambda.StartingPosition.LATEST,
}));
}