in packages/@aws-cdk/aws-codebuild/lib/project.ts [1015:1144]
constructor(scope: Construct, id: string, props: ProjectProps) {
super(scope, id, {
physicalName: props.projectName,
});
this.role = props.role || new iam.Role(this, 'Role', {
roleName: PhysicalName.GENERATE_IF_NEEDED,
assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com'),
});
this.grantPrincipal = this.role;
this.buildImage = (props.environment && props.environment.buildImage) || LinuxBuildImage.STANDARD_1_0;
// let source "bind" to the project. this usually involves granting permissions
// for the code build role to interact with the source.
this.source = props.source || new NoSource();
const sourceConfig = this.source.bind(this, this);
if (props.badge && !this.source.badgeSupported) {
throw new Error(`Badge is not supported for source type ${this.source.type}`);
}
const artifacts = props.artifacts
? props.artifacts
: (this.source.type === CODEPIPELINE_SOURCE_ARTIFACTS_TYPE
? new CodePipelineArtifacts()
: new NoArtifacts());
const artifactsConfig = artifacts.bind(this, this);
const cache = props.cache || Cache.none();
// give the caching strategy the option to grant permissions to any required resources
cache._bind(this);
// Inject download commands for asset if requested
const environmentVariables = props.environmentVariables || {};
const buildSpec = props.buildSpec;
if (this.source.type === NO_SOURCE_TYPE && (buildSpec === undefined || !buildSpec.isImmediate)) {
throw new Error("If the Project's source is NoSource, you need to provide a concrete buildSpec");
}
this._secondarySources = [];
this._secondarySourceVersions = [];
this._fileSystemLocations = [];
for (const secondarySource of props.secondarySources || []) {
this.addSecondarySource(secondarySource);
}
this._secondaryArtifacts = [];
for (const secondaryArtifact of props.secondaryArtifacts || []) {
this.addSecondaryArtifact(secondaryArtifact);
}
this.validateCodePipelineSettings(artifacts);
for (const fileSystemLocation of props.fileSystemLocations || []) {
this.addFileSystemLocation(fileSystemLocation);
}
const resource = new CfnProject(this, 'Resource', {
description: props.description,
source: {
...sourceConfig.sourceProperty,
buildSpec: buildSpec && buildSpec.toBuildSpec(),
},
artifacts: artifactsConfig.artifactsProperty,
serviceRole: this.role.roleArn,
environment: this.renderEnvironment(props, environmentVariables),
fileSystemLocations: Lazy.any({ produce: () => this.renderFileSystemLocations() }),
// lazy, because we have a setter for it in setEncryptionKey
// The 'alias/aws/s3' default is necessary because leaving the `encryptionKey` field
// empty will not remove existing encryptionKeys during an update (ref. t/D17810523)
encryptionKey: Lazy.string({ produce: () => this._encryptionKey ? this._encryptionKey.keyArn : 'alias/aws/s3' }),
badgeEnabled: props.badge,
cache: cache._toCloudFormation(),
name: this.physicalName,
timeoutInMinutes: props.timeout && props.timeout.toMinutes(),
queuedTimeoutInMinutes: props.queuedTimeout && props.queuedTimeout.toMinutes(),
concurrentBuildLimit: props.concurrentBuildLimit,
secondarySources: Lazy.any({ produce: () => this.renderSecondarySources() }),
secondarySourceVersions: Lazy.any({ produce: () => this.renderSecondarySourceVersions() }),
secondaryArtifacts: Lazy.any({ produce: () => this.renderSecondaryArtifacts() }),
triggers: sourceConfig.buildTriggers,
sourceVersion: sourceConfig.sourceVersion,
vpcConfig: this.configureVpc(props),
logsConfig: this.renderLoggingConfiguration(props.logging),
buildBatchConfig: Lazy.any({
produce: () => {
const config: CfnProject.ProjectBuildBatchConfigProperty | undefined = this._batchServiceRole ? {
serviceRole: this._batchServiceRole.roleArn,
} : undefined;
return config;
},
}),
});
this.addVpcRequiredPermissions(props, resource);
this.projectArn = this.getResourceArnAttribute(resource.attrArn, {
service: 'codebuild',
resource: 'project',
resourceName: this.physicalName,
});
this.projectName = this.getResourceNameAttribute(resource.ref);
this.addToRolePolicy(this.createLoggingPermission());
// add permissions to create and use test report groups
// with names starting with the project's name,
// unless the customer explicitly opts out of it
if (props.grantReportGroupPermissions !== false) {
this.addToRolePolicy(new iam.PolicyStatement({
actions: [
'codebuild:CreateReportGroup',
'codebuild:CreateReport',
'codebuild:UpdateReport',
'codebuild:BatchPutTestCases',
'codebuild:BatchPutCodeCoverages',
],
resources: [renderReportGroupArn(this, `${this.projectName}-*`)],
}));
}
if (props.encryptionKey) {
this.encryptionKey = props.encryptionKey;
}
// bind
if (isBindableBuildImage(this.buildImage)) {
this.buildImage.bind(this, this, {});
}
}