Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(aws-codebuild): add enableBatchBuilds() to Project #12531

Merged
merged 20 commits into from
Jan 26, 2021
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions packages/@aws-cdk/aws-codebuild/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -600,3 +600,19 @@ new codebuild.Project(stack, 'MyProject', {
Here's a CodeBuild project with a simple example that creates a project mounted on AWS EFS:

[Minimal Example](./test/integ.project-file-system-location.ts)

## Batch builds

To enable batch builds you should call `enableBatchBuilds()` on the project instance.

It returns an object containing the batch service role that was created, or `undefined` if batch builds could not be enabled, for example if the project was imported.

```ts
import * as codebuild from '@aws-cdk/aws-codebuild';

const project = new codebuild.Project(this, 'MyProject', { ... });

if (project.enableBatchBuilds()) {
console.log('Batch builds were enabled');
}
```
55 changes: 51 additions & 4 deletions packages/@aws-cdk/aws-codebuild/lib/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ export interface IProject extends IResource, iam.IGrantable, ec2.IConnectable {
/** The IAM service Role of this Project. Undefined for imported Projects. */
readonly role?: iam.IRole;

/**
* Enable batch builds.
*
* Returns an object contining the batch service role if batch builds
* could be enabled.
*/
enableBatchBuilds(): IEnableBatchBuildsReturn | undefined;

addToRolePolicy(policyStatement: iam.PolicyStatement): void;

/**
Expand Down Expand Up @@ -156,6 +164,14 @@ export interface IProject extends IResource, iam.IGrantable, ec2.IConnectable {
metricFailedBuilds(props?: cloudwatch.MetricOptions): cloudwatch.Metric;
}

/**
* The return value for the {@link Project} `enableBatchBuilds()` method.
*/
export interface IEnableBatchBuildsReturn {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@skinny85 I named this this instead of BatchBuildConfig because I didn't want it to get confused with the actual buildBatchConfig in L1

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meh. The type on the L1 level is called ProjectBuildBatchConfigProperty, so I'm not too worried about this one being called BatchBuildConfig.

The name is not a coincidence - it's actually a convention we use for return types (see examples [1], [2]).

A name ending in Return seems a little weird given that, so if you could change it, I would appreciate it 🙂.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem will update then. Thanks for the examples

/** The IAM batch service Role of this Project. */
readonly role: iam.IRole;
}

/**
* Represents a reference to a CodeBuild Project.
*
Expand Down Expand Up @@ -196,6 +212,10 @@ abstract class ProjectBase extends Resource implements IProject {
return this._connections;
}

public enableBatchBuilds(): IEnableBatchBuildsReturn | undefined {
return undefined;
}

/**
* Add a permission only if there's a policy attached.
* @param statement The permissions statement to add
Expand Down Expand Up @@ -729,6 +749,7 @@ export class Project extends ProjectBase {
private readonly _secondaryArtifacts: CfnProject.ArtifactsProperty[];
private _encryptionKey?: kms.IKey;
private readonly _fileSystemLocations: CfnProject.ProjectFileSystemLocationProperty[];
private _batchServiceRole?: iam.Role;

constructor(scope: Construct, id: string, props: ProjectProps) {
super(scope, id, {
Expand Down Expand Up @@ -813,6 +834,14 @@ export class Project extends ProjectBase {
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;
},
}),
skinny85 marked this conversation as resolved.
Show resolved Hide resolved
});

this.addVpcRequiredPermissions(props, resource);
Expand Down Expand Up @@ -853,6 +882,24 @@ export class Project extends ProjectBase {
}
}

public enableBatchBuilds(): IEnableBatchBuildsReturn | undefined {
if (!this._batchServiceRole) {
this._batchServiceRole = new iam.Role(this, 'BatchServiceRole', {
roleName: PhysicalName.GENERATE_IF_NEEDED,
tjenkinson marked this conversation as resolved.
Show resolved Hide resolved
assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com'),
});
this._batchServiceRole.addToPrincipalPolicy(new iam.PolicyStatement({
resources: [Lazy.string({
skinny85 marked this conversation as resolved.
Show resolved Hide resolved
produce: () => this.projectArn,
})],
actions: ['codebuild:StartBuild', 'codebuild:StopBuild', 'codebuild:RetryBuild'],
tjenkinson marked this conversation as resolved.
Show resolved Hide resolved
}));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. The docs don't mention it and it worked when I tested this in a different account.

Think this is so that internally non batch builds can be triggered as part of a batch. Don't think a batch can trigger another batch?

}
return {
role: this._batchServiceRole,
};
}

/**
* Adds a secondary source to the Project.
*
Expand Down Expand Up @@ -1139,8 +1186,8 @@ export class Project extends ProjectBase {
return undefined;
}

let s3Config: CfnProject.S3LogsConfigProperty|undefined = undefined;
let cloudwatchConfig: CfnProject.CloudWatchLogsConfigProperty|undefined = undefined;
let s3Config: CfnProject.S3LogsConfigProperty | undefined = undefined;
let cloudwatchConfig: CfnProject.CloudWatchLogsConfigProperty | undefined = undefined;

if (props.s3) {
const s3Logs = props.s3;
Expand Down Expand Up @@ -1350,10 +1397,10 @@ export interface IBuildImage {
}

/** Optional arguments to {@link IBuildImage.binder} - currently empty. */
export interface BuildImageBindOptions {}
export interface BuildImageBindOptions { }

/** The return type from {@link IBuildImage.binder} - currently empty. */
export interface BuildImageConfig {}
export interface BuildImageConfig { }

// @deprecated(not in tsdoc on purpose): add bind() to IBuildImage
// and get rid of IBindableBuildImage
Expand Down
11 changes: 9 additions & 2 deletions packages/@aws-cdk/aws-codebuild/lib/source.ts
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,8 @@ interface ThirdPartyGitSourceProps extends GitSourceProps {
/**
* Trigger a batch build from a webhook instead of a standard one.
*
* Enabling this will enable batch builds on the CodeBuild project.
*
* @default false
*/
readonly webhookTriggersBatchBuild?: boolean;
Expand Down Expand Up @@ -518,7 +520,7 @@ abstract class ThirdPartyGitSource extends GitSource {
this.webhookTriggersBatchBuild = props.webhookTriggersBatchBuild;
}

public bind(_scope: CoreConstruct, _project: IProject): SourceConfig {
public bind(_scope: CoreConstruct, project: IProject): SourceConfig {
const anyFilterGroupsProvided = this.webhookFilters.length > 0;
const webhook = this.webhook === undefined ? (anyFilterGroupsProvided ? true : undefined) : this.webhook;

Expand All @@ -530,7 +532,12 @@ abstract class ThirdPartyGitSource extends GitSource {
throw new Error('`webhookTriggersBatchBuild` cannot be used when `webhook` is `false`');
}

const superConfig = super.bind(_scope, _project);
const superConfig = super.bind(_scope, project);

if (this.webhookTriggersBatchBuild) {
project.enableBatchBuilds();
}

return {
sourceProperty: {
...superConfig.sourceProperty,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
{
"Resources": {
"MyProjectRole9BBE5233": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "codebuild.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
},
"MyProjectRoleDefaultPolicyB19B7C29": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Effect": "Allow",
"Resource": [
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":logs:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":log-group:/aws/codebuild/",
{
"Ref": "MyProject39F7B0AE"
}
]
]
},
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":logs:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":log-group:/aws/codebuild/",
{
"Ref": "MyProject39F7B0AE"
},
":*"
]
]
}
]
}
],
"Version": "2012-10-17"
},
"PolicyName": "MyProjectRoleDefaultPolicyB19B7C29",
"Roles": [
{
"Ref": "MyProjectRole9BBE5233"
}
]
}
},
"MyProjectBatchServiceRole6B35CF0E": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "codebuild.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
},
"MyProjectBatchServiceRoleDefaultPolicy7A0E5721": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": [
"codebuild:StartBuild",
"codebuild:StopBuild",
"codebuild:RetryBuild"
],
"Effect": "Allow",
"Resource": {
"Fn::GetAtt": [
"MyProject39F7B0AE",
"Arn"
]
}
}
],
"Version": "2012-10-17"
},
"PolicyName": "MyProjectBatchServiceRoleDefaultPolicy7A0E5721",
"Roles": [
{
"Ref": "MyProjectBatchServiceRole6B35CF0E"
}
]
}
},
"MyProject39F7B0AE": {
"Type": "AWS::CodeBuild::Project",
"Properties": {
"Artifacts": {
"Type": "NO_ARTIFACTS"
},
"Environment": {
"ComputeType": "BUILD_GENERAL1_SMALL",
"Image": "aws/codebuild/standard:1.0",
"ImagePullCredentialsType": "CODEBUILD",
"PrivilegedMode": false,
"Type": "LINUX_CONTAINER"
},
"ServiceRole": {
"Fn::GetAtt": [
"MyProjectRole9BBE5233",
"Arn"
]
},
"Source": {
"Location": "https://github.com/aws/aws-cdk.git",
"ReportBuildStatus": false,
"Type": "GITHUB"
},
"BuildBatchConfig": {
"ServiceRole": {
"Fn::GetAtt": [
"MyProjectBatchServiceRole6B35CF0E",
"Arn"
]
}
},
"EncryptionKey": "alias/aws/s3",
"Triggers": {
"BuildType": "BUILD_BATCH",
"FilterGroups": [
[
{
"Pattern": "PUSH",
"Type": "EVENT"
}
]
],
"Webhook": true
}
}
}
}
}
29 changes: 29 additions & 0 deletions packages/@aws-cdk/aws-codebuild/test/integ.github-webhook-batch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as cdk from '@aws-cdk/core';
import * as codebuild from '../lib';

class TestStack extends cdk.Stack {
tjenkinson marked this conversation as resolved.
Show resolved Hide resolved
constructor(scope: cdk.App, id: string) {
super(scope, id);

const source = codebuild.Source.gitHub({
owner: 'aws',
repo: 'aws-cdk',
reportBuildStatus: false,
tjenkinson marked this conversation as resolved.
Show resolved Hide resolved
webhook: true,
webhookTriggersBatchBuild: true,
webhookFilters: [
codebuild.FilterGroup.inEventOf(codebuild.EventAction.PUSH),
],
});
new codebuild.Project(this, 'MyProject', {
source,
grantReportGroupPermissions: false,
});
}
}

const app = new cdk.App();

new TestStack(app, 'test-codebuild-github-webhook-batch');

app.synth();
Loading