Skip to content

Commit cf21c30

Browse files
committed
Adding Infracost to pull request build
1 parent 2ec79c8 commit cf21c30

File tree

3 files changed

+47
-11
lines changed

3 files changed

+47
-11
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,6 @@ override.tf.json
138138
.terraformrc
139139
terraform.rc
140140

141-
.terraform.lock.hcl
141+
.terraform.lock.hcl
142+
143+
.infracost/

infracost-cdk-pipeline/lib/infracost-cdk-pipeline-stack.ts

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,18 @@ import * as uuid from 'uuid';
1313
export class InfracostCdkPipelineStack extends Stack {
1414
constructor(scope: Construct, id: string, props?: StackProps) {
1515
super(scope, id, props);
16-
const terraformVersion = '1.2.4';
16+
// constants
17+
const terraformVersion = '1.2.4';
18+
const mainBranchName = 'main';
19+
const infracostAPIKeyParameterSecureStringName = '/terraform/infracost/api_key';
20+
21+
// Terraform state management
1722
const terraformStateBucket = new s3.Bucket(this, 'TerraformStateBucket', {
1823
bucketName: `terraform-state-${uuid.v4()}`,
1924
removalPolicy: RemovalPolicy.DESTROY
2025
});
26+
27+
// IAM permissions for CodeBuild
2128
const terraformS3IAMPolicyForCodeBuild = new iam.ManagedPolicy(this, 'ManagedPolicy', {
2229
statements: [
2330
new iam.PolicyStatement({
@@ -33,29 +40,37 @@ export class InfracostCdkPipelineStack extends Stack {
3340
const terraformS3IAMRoleForCodeBuild = new iam.Role(this, 'Role', {
3441
assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com'),
3542
description: 'IAM role for CodeBuild to interact with S3',
36-
managedPolicies: [terraformS3IAMPolicyForCodeBuild]
43+
managedPolicies: [terraformS3IAMPolicyForCodeBuild, iam.ManagedPolicy.fromAwsManagedPolicyName('AWSCodeCommitReadOnly')]
3744
});
45+
46+
// Terraform source code
3847
const terraformRepository = new codecommit.Repository(this, 'TerraformRepository', {
3948
repositoryName: 'TerraformRepository',
40-
code: codecommit.Code.fromDirectory(path.join(__dirname, 'terraform/'), 'main')
49+
code: codecommit.Code.fromDirectory(path.join(__dirname, 'terraform/'), mainBranchName)
4150
});
51+
52+
// pull request build and integration
4253
const pullRequestCodeBuildProject = new codebuild.Project(this, 'TerraformPullRequestCodeBuildProject', {
4354
buildSpec: codebuild.BuildSpec.fromObject({
4455
version: '0.2',
4556
phases: {
4657
install: {
4758
commands: [
4859
`wget https://releases.hashicorp.com/terraform/${terraformVersion}/terraform_${terraformVersion}_linux_amd64.zip`,
49-
'sudo yum -y install unzip',
60+
'sudo yum -y install unzip python3-pip',
5061
`unzip terraform_${terraformVersion}_linux_amd64.zip`,
5162
'sudo mv terraform /usr/local/bin/',
52-
'terraform --version'
63+
'curl -fsSL https://raw.githubusercontent.com/infracost/infracost/master/scripts/install.sh | sh',
64+
'sudo pip3 install git-remote-codecommit',
65+
`git clone ${terraformRepository.repositoryCloneUrlGrc} --branch=${mainBranchName} --single-branch /tmp/main`,
66+
'infracost breakdown --path /tmp/main --usage-file infracost-usage.yml --format json --out-file infracost-base.json'
5367
]
5468
},
5569
build: {
5670
commands:[
5771
`terraform init -backend-config="bucket=${terraformStateBucket.bucketName}"`,
58-
'terraform plan'
72+
'terraform plan',
73+
'infracost diff --path . --compare-to infracost-base.json --usage-file infracost-usage.yml'
5974
]
6075
}
6176
}
@@ -65,13 +80,21 @@ export class InfracostCdkPipelineStack extends Stack {
6580
}),
6681
environment: {
6782
buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_3,
83+
environmentVariables: {
84+
INFRACOST_API_KEY: {
85+
value: infracostAPIKeyParameterSecureStringName,
86+
type: codebuild.BuildEnvironmentVariableType.PARAMETER_STORE
87+
}
88+
},
6889
privileged: true
6990
},
7091
role: terraformS3IAMRoleForCodeBuild
7192
});
7293
const pullRequestStateChangeRule = terraformRepository.onPullRequestStateChange('TerraformRepositoryOnPullRequestStateChange', {
7394
target: new targets.CodeBuildProject(pullRequestCodeBuildProject),
7495
});
96+
97+
// pipeline
7598
const terraformCodeBuildProject = new codebuild.PipelineProject(this, 'TerraformCodeBuildProject', {
7699
buildSpec: codebuild.BuildSpec.fromObject({
77100
version: '0.2',
@@ -82,19 +105,25 @@ export class InfracostCdkPipelineStack extends Stack {
82105
'sudo yum -y install unzip',
83106
`unzip terraform_${terraformVersion}_linux_amd64.zip`,
84107
'sudo mv terraform /usr/local/bin/',
85-
'terraform --version'
108+
'curl -fsSL https://raw.githubusercontent.com/infracost/infracost/master/scripts/install.sh | sh'
86109
]
87110
},
88111
build: {
89112
commands:[
90113
`terraform init -backend-config="bucket=${terraformStateBucket.bucketName}"`,
91-
'terraform plan'
114+
'terraform plan',
115+
'infracost breakdown --path . --usage-file infracost-usage.yml --format table'
92116
]
93117
}
94118
}
95119
}),
96120
environment: {
97121
buildImage: codebuild.LinuxBuildImage.AMAZON_LINUX_2_3,
122+
environmentVariables: {
123+
INFRACOST_API_KEY: {
124+
value: process.env.INFRACOST_API_KEY
125+
}
126+
},
98127
privileged: true
99128
},
100129
role: terraformS3IAMRoleForCodeBuild
@@ -108,7 +137,7 @@ export class InfracostCdkPipelineStack extends Stack {
108137
const sourceArtifact = new codepipeline.Artifact();
109138
sourceStage.addAction(new codepipeline_actions.CodeCommitSourceAction({
110139
actionName: 'Source',
111-
branch: 'main',
140+
branch: mainBranchName,
112141
output: sourceArtifact,
113142
repository: terraformRepository
114143
}));
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
resource "random_string" "random" {
2+
length = 8
3+
special = false
4+
}
5+
16
resource "aws_s3_bucket" "bucket" {
2-
bucket = "scottie-infracost-test-bucket"
7+
bucket = "infracost-test-bucket-${random_string.random.result}"
38
}

0 commit comments

Comments
 (0)