@@ -8,6 +8,7 @@ import iam = require('@aws-cdk/aws-iam');
8
8
import kms = require( '@aws-cdk/aws-kms' ) ;
9
9
import { Aws , Construct , IResource , Lazy , PhysicalName , Resource , ResourceIdentifiers , Stack } from '@aws-cdk/cdk' ;
10
10
import { BuildArtifacts , CodePipelineBuildArtifacts , NoBuildArtifacts } from './artifacts' ;
11
+ import { BuildSpec , mergeBuildSpecs } from './build-spec' ;
11
12
import { Cache } from './cache' ;
12
13
import { CfnProject } from './codebuild.generated' ;
13
14
import { BuildSource , NoSource , SourceType } from './source' ;
@@ -371,7 +372,7 @@ export interface CommonProjectProps {
371
372
*
372
373
* @default - Empty buildspec.
373
374
*/
374
- readonly buildSpec ?: any ;
375
+ readonly buildSpec ?: BuildSpec ;
375
376
376
377
/**
377
378
* Run a script from an asset as build script
@@ -647,12 +648,14 @@ export class Project extends ProjectBase {
647
648
648
649
// Inject download commands for asset if requested
649
650
const environmentVariables = props . environmentVariables || { } ;
650
- const buildSpec = props . buildSpec || { } ;
651
+ let buildSpec = props . buildSpec ;
651
652
652
653
if ( props . buildScriptAsset ) {
653
654
environmentVariables [ S3_BUCKET_ENV ] = { value : props . buildScriptAsset . s3BucketName } ;
654
655
environmentVariables [ S3_KEY_ENV ] = { value : props . buildScriptAsset . s3ObjectKey } ;
655
- extendBuildSpec ( buildSpec , this . buildImage . runScriptBuildspec ( props . buildScriptAssetEntrypoint || 'build.sh' ) ) ;
656
+
657
+ const runScript = this . buildImage . runScriptBuildspec ( props . buildScriptAssetEntrypoint || 'build.sh' ) ;
658
+ buildSpec = buildSpec ? mergeBuildSpecs ( buildSpec , runScript ) : runScript ;
656
659
props . buildScriptAsset . grantRead ( this . role ) ;
657
660
}
658
661
@@ -662,24 +665,15 @@ export class Project extends ProjectBase {
662
665
throw new Error ( `Badge is not supported for source type ${ this . source . type } ` ) ;
663
666
}
664
667
665
- const sourceJson = this . source . _toSourceJSON ( ) ;
666
- if ( typeof buildSpec === 'string' ) {
667
- return {
668
- ...sourceJson ,
669
- buildSpec // Filename to buildspec file
670
- } ;
671
- } else if ( Object . keys ( buildSpec ) . length > 0 ) {
672
- // We have to pretty-print the buildspec, otherwise
673
- // CodeBuild will not recognize it as an inline buildspec.
674
- return {
675
- ...sourceJson ,
676
- buildSpec : JSON . stringify ( buildSpec , undefined , 2 )
677
- } ;
678
- } else if ( this . source . type === SourceType . None ) {
679
- throw new Error ( "If the Project's source is NoSource, you need to provide a buildSpec" ) ;
680
- } else {
681
- return sourceJson ;
668
+ if ( this . source . type === SourceType . None && ( buildSpec === undefined || ! buildSpec . isImmediate ) ) {
669
+ throw new Error ( "If the Project's source is NoSource, you need to provide a concrete buildSpec" ) ;
682
670
}
671
+
672
+ const sourceJson = this . source . _toSourceJSON ( ) ;
673
+ return {
674
+ ...sourceJson ,
675
+ buildSpec : buildSpec && buildSpec . toBuildSpec ( )
676
+ } ;
683
677
} ;
684
678
685
679
this . _secondarySources = [ ] ;
@@ -1025,7 +1019,7 @@ export interface IBuildImage {
1025
1019
/**
1026
1020
* Make a buildspec to run the indicated script
1027
1021
*/
1028
- runScriptBuildspec ( entrypoint : string ) : any ;
1022
+ runScriptBuildspec ( entrypoint : string ) : BuildSpec ;
1029
1023
}
1030
1024
1031
1025
/**
@@ -1124,8 +1118,8 @@ export class LinuxBuildImage implements IBuildImage {
1124
1118
return [ ] ;
1125
1119
}
1126
1120
1127
- public runScriptBuildspec ( entrypoint : string ) : any {
1128
- return {
1121
+ public runScriptBuildspec ( entrypoint : string ) : BuildSpec {
1122
+ return BuildSpec . fromObject ( {
1129
1123
version : '0.2' ,
1130
1124
phases : {
1131
1125
pre_build : {
@@ -1149,7 +1143,7 @@ export class LinuxBuildImage implements IBuildImage {
1149
1143
]
1150
1144
}
1151
1145
}
1152
- } ;
1146
+ } ) ;
1153
1147
}
1154
1148
}
1155
1149
@@ -1220,8 +1214,8 @@ export class WindowsBuildImage implements IBuildImage {
1220
1214
return ret ;
1221
1215
}
1222
1216
1223
- public runScriptBuildspec ( entrypoint : string ) : any {
1224
- return {
1217
+ public runScriptBuildspec ( entrypoint : string ) : BuildSpec {
1218
+ return BuildSpec . fromObject ( {
1225
1219
version : '0.2' ,
1226
1220
phases : {
1227
1221
pre_build : {
@@ -1242,7 +1236,7 @@ export class WindowsBuildImage implements IBuildImage {
1242
1236
]
1243
1237
}
1244
1238
}
1245
- } ;
1239
+ } ) ;
1246
1240
}
1247
1241
}
1248
1242
@@ -1272,33 +1266,6 @@ export enum BuildEnvironmentVariableType {
1272
1266
ParameterStore = 'PARAMETER_STORE'
1273
1267
}
1274
1268
1275
- /**
1276
- * Extend buildSpec phases with the contents of another one
1277
- */
1278
- function extendBuildSpec ( buildSpec : any , extend : any ) {
1279
- if ( typeof buildSpec === 'string' ) {
1280
- throw new Error ( 'Cannot extend buildspec that is given as a string. Pass the buildspec as a structure instead.' ) ;
1281
- }
1282
- if ( buildSpec . version === '0.1' ) {
1283
- throw new Error ( 'Cannot extend buildspec at version "0.1". Set the version to "0.2" or higher instead.' ) ;
1284
- }
1285
- if ( buildSpec . version === undefined ) {
1286
- buildSpec . version = extend . version ;
1287
- }
1288
-
1289
- if ( ! buildSpec . phases ) {
1290
- buildSpec . phases = { } ;
1291
- }
1292
-
1293
- for ( const phaseName of Object . keys ( extend . phases ) ) {
1294
- if ( ! ( phaseName in buildSpec . phases ) ) { buildSpec . phases [ phaseName ] = { } ; }
1295
- const phase = buildSpec . phases [ phaseName ] ;
1296
-
1297
- if ( ! ( phase . commands ) ) { phase . commands = [ ] ; }
1298
- phase . commands . push ( ...extend . phases [ phaseName ] . commands ) ;
1299
- }
1300
- }
1301
-
1302
1269
function ecrAccessForCodeBuildService ( ) : iam . PolicyStatement {
1303
1270
return new iam . PolicyStatement ( )
1304
1271
. describe ( 'CodeBuild' )
0 commit comments