@@ -13,11 +13,18 @@ import * as uuid from 'uuid';
13
13
export class InfracostCdkPipelineStack extends Stack {
14
14
constructor ( scope : Construct , id : string , props ?: StackProps ) {
15
15
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
17
22
const terraformStateBucket = new s3 . Bucket ( this , 'TerraformStateBucket' , {
18
23
bucketName : `terraform-state-${ uuid . v4 ( ) } ` ,
19
24
removalPolicy : RemovalPolicy . DESTROY
20
25
} ) ;
26
+
27
+ // IAM permissions for CodeBuild
21
28
const terraformS3IAMPolicyForCodeBuild = new iam . ManagedPolicy ( this , 'ManagedPolicy' , {
22
29
statements : [
23
30
new iam . PolicyStatement ( {
@@ -33,29 +40,37 @@ export class InfracostCdkPipelineStack extends Stack {
33
40
const terraformS3IAMRoleForCodeBuild = new iam . Role ( this , 'Role' , {
34
41
assumedBy : new iam . ServicePrincipal ( 'codebuild.amazonaws.com' ) ,
35
42
description : 'IAM role for CodeBuild to interact with S3' ,
36
- managedPolicies : [ terraformS3IAMPolicyForCodeBuild ]
43
+ managedPolicies : [ terraformS3IAMPolicyForCodeBuild , iam . ManagedPolicy . fromAwsManagedPolicyName ( 'AWSCodeCommitReadOnly' ) ]
37
44
} ) ;
45
+
46
+ // Terraform source code
38
47
const terraformRepository = new codecommit . Repository ( this , 'TerraformRepository' , {
39
48
repositoryName : 'TerraformRepository' ,
40
- code : codecommit . Code . fromDirectory ( path . join ( __dirname , 'terraform/' ) , 'main' )
49
+ code : codecommit . Code . fromDirectory ( path . join ( __dirname , 'terraform/' ) , mainBranchName )
41
50
} ) ;
51
+
52
+ // pull request build and integration
42
53
const pullRequestCodeBuildProject = new codebuild . Project ( this , 'TerraformPullRequestCodeBuildProject' , {
43
54
buildSpec : codebuild . BuildSpec . fromObject ( {
44
55
version : '0.2' ,
45
56
phases : {
46
57
install : {
47
58
commands : [
48
59
`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 ' ,
50
61
`unzip terraform_${ terraformVersion } _linux_amd64.zip` ,
51
62
'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'
53
67
]
54
68
} ,
55
69
build : {
56
70
commands :[
57
71
`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'
59
74
]
60
75
}
61
76
}
@@ -65,13 +80,21 @@ export class InfracostCdkPipelineStack extends Stack {
65
80
} ) ,
66
81
environment : {
67
82
buildImage : codebuild . LinuxBuildImage . AMAZON_LINUX_2_3 ,
83
+ environmentVariables : {
84
+ INFRACOST_API_KEY : {
85
+ value : infracostAPIKeyParameterSecureStringName ,
86
+ type : codebuild . BuildEnvironmentVariableType . PARAMETER_STORE
87
+ }
88
+ } ,
68
89
privileged : true
69
90
} ,
70
91
role : terraformS3IAMRoleForCodeBuild
71
92
} ) ;
72
93
const pullRequestStateChangeRule = terraformRepository . onPullRequestStateChange ( 'TerraformRepositoryOnPullRequestStateChange' , {
73
94
target : new targets . CodeBuildProject ( pullRequestCodeBuildProject ) ,
74
95
} ) ;
96
+
97
+ // pipeline
75
98
const terraformCodeBuildProject = new codebuild . PipelineProject ( this , 'TerraformCodeBuildProject' , {
76
99
buildSpec : codebuild . BuildSpec . fromObject ( {
77
100
version : '0.2' ,
@@ -82,19 +105,25 @@ export class InfracostCdkPipelineStack extends Stack {
82
105
'sudo yum -y install unzip' ,
83
106
`unzip terraform_${ terraformVersion } _linux_amd64.zip` ,
84
107
'sudo mv terraform /usr/local/bin/' ,
85
- 'terraform --version '
108
+ 'curl -fsSL https://raw.githubusercontent.com/infracost/infracost/master/scripts/install.sh | sh '
86
109
]
87
110
} ,
88
111
build : {
89
112
commands :[
90
113
`terraform init -backend-config="bucket=${ terraformStateBucket . bucketName } "` ,
91
- 'terraform plan'
114
+ 'terraform plan' ,
115
+ 'infracost breakdown --path . --usage-file infracost-usage.yml --format table'
92
116
]
93
117
}
94
118
}
95
119
} ) ,
96
120
environment : {
97
121
buildImage : codebuild . LinuxBuildImage . AMAZON_LINUX_2_3 ,
122
+ environmentVariables : {
123
+ INFRACOST_API_KEY : {
124
+ value : process . env . INFRACOST_API_KEY
125
+ }
126
+ } ,
98
127
privileged : true
99
128
} ,
100
129
role : terraformS3IAMRoleForCodeBuild
@@ -108,7 +137,7 @@ export class InfracostCdkPipelineStack extends Stack {
108
137
const sourceArtifact = new codepipeline . Artifact ( ) ;
109
138
sourceStage . addAction ( new codepipeline_actions . CodeCommitSourceAction ( {
110
139
actionName : 'Source' ,
111
- branch : 'main' ,
140
+ branch : mainBranchName ,
112
141
output : sourceArtifact ,
113
142
repository : terraformRepository
114
143
} ) ) ;
0 commit comments