Skip to content
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
26 changes: 25 additions & 1 deletion packages/@aws-cdk/aws-codebuild/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,30 @@ const bbSource = codebuild.Source.bitBucket({
});
```

## Artifacts

CodeBuild Projects can produce Artifacts and upload the to S3. For example:

```ts
const project = codebuild.Project(stack, 'MyProject', {
buildSpec: codebuild.BuildSpec.fromObject({
version: '0.2',
}),
artifacts: codebuild.Artifacts.s3({
bucket,
includeBuildId: false,
packageZip: true,
path: 'another/path',
identifier: 'AddArtifact1',
}),
});
```

Because we've not set the `name` property, this example will set the
`overrideArtifactName` parameter, and produce an artifact named as defined in
the Buildspec file, uploaded to an S3 bucket (`bucket`). The path will be
`another/path` and the artifact will be a zipfile.

## CodePipeline

To add a CodeBuild Project as an Action to CodePipeline,
Expand Down Expand Up @@ -411,4 +435,4 @@ 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)
[Minimal Example](./test/integ.project-file-system-location.ts)
12 changes: 10 additions & 2 deletions packages/@aws-cdk/aws-codebuild/lib/artifacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ export interface S3ArtifactsProps extends ArtifactsProps {
* The path inside of the bucket for the build output .zip file or folder.
* If a value is not specified, then build output will be stored at the root of the
* bucket (or under the <build-id> directory if `includeBuildId` is set to true).
*
* @default the root of the bucket
*/
readonly path?: string;

Expand All @@ -95,8 +97,13 @@ export interface S3ArtifactsProps extends ArtifactsProps {
*
* The full S3 object key will be "<path>/<build-id>/<name>" or
* "<path>/<name>" depending on whether `includeBuildId` is set to true.
*
* If not set, `overrideArtifactName` will be set and the name from the
* buildspec will be used instead.
*
* @default the unique ID of the project node
*/
readonly name: string;
readonly name?: string;

/**
* Indicates if the build ID should be included in the path. If this is set to true,
Expand Down Expand Up @@ -142,9 +149,10 @@ class S3Artifacts extends Artifacts {
location: this.props.bucket.bucketName,
path: this.props.path,
namespaceType: this.props.includeBuildId === false ? 'NONE' : 'BUILD_ID',
name: this.props.name,
name: this.props.name == null ? project.node.uniqueId : this.props.name,
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you test that this is necessary - we can't just leave this as undefined? name is optional in CfnProject.ArtifactsProperty: https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-codebuild.CfnProject.ArtifactsProperty.html#name

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 didn't - I'll do so today and set it to undefined if that works.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done, hopefully the integration tests pass!

Copy link
Contributor

Choose a reason for hiding this comment

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

Just to make sure we're on the same page - by default, the integration tests act like snapshot tests. You need to specifically run the npm integ target to have them deployed. More info here: https://github.com/aws/aws-cdk/blob/master/CONTRIBUTING.md#integration-tests

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, okay! I'll run those this evening and let you know the outcome...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just ran the tests against my own account and all the aws-codebuild integration tests provision and tear down correctly, no errors visible in the CloudFormation console or build logs!

packaging: this.props.packageZip === false ? 'NONE' : 'ZIP',
encryptionDisabled: this.props.encryption === false ? true : undefined,
overrideArtifactName: this.props.name == null ? true : undefined,
},
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
{
"Resources": {
"MyBucketF68F3FF0": {
"DeletionPolicy": "Delete",
"UpdateReplacePolicy": "Delete",
"Type": "AWS::S3::Bucket"
},
"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": [
"s3:GetObject*",
"s3:GetBucket*",
"s3:List*",
"s3:DeleteObject*",
"s3:PutObject*",
"s3:Abort*"
],
"Effect": "Allow",
"Resource": [
{
"Fn::GetAtt": [
"MyBucketF68F3FF0",
"Arn"
]
},
{
"Fn::Join": [
"",
[
{
"Fn::GetAtt": [
"MyBucketF68F3FF0",
"Arn"
]
},
"/*"
]
]
}
]
},
{
"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"
}
]
}
},
"MyProject39F7B0AE": {
"Type": "AWS::CodeBuild::Project",
"Properties": {
"Artifacts": {
"ArtifactIdentifier": "AddArtifact1",
"Location": { "Ref": "MyBucketF68F3FF0" },
"Name": "awscdkcodebuildbuildspecartifactnameMyProjectACDB7F8B",
"NamespaceType": "NONE",
"OverrideArtifactName": true,
"Packaging": "ZIP",
"Path": "another/path",
"Type": "S3"
},
"Environment": {
"ComputeType": "BUILD_GENERAL1_SMALL",
"Image": "aws/codebuild/standard:1.0",
"PrivilegedMode": false,
"Type": "LINUX_CONTAINER"
},
"ServiceRole": {
"Fn::GetAtt": [
"MyProjectRole9BBE5233",
"Arn"
]
},
"Source": {
"BuildSpec": "{\n \"version\": \"0.2\"\n}",
"Type": "NO_SOURCE"
}
}
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as s3 from '@aws-cdk/aws-s3';
import * as cdk from '@aws-cdk/core';
import * as codebuild from '../lib';

const app = new cdk.App();

const stack = new cdk.Stack(app, 'aws-cdk-codebuild-buildspec-artifact-name');

const bucket = new s3.Bucket(stack, 'MyBucket', {
removalPolicy: cdk.RemovalPolicy.DESTROY,
});

new codebuild.Project(stack, 'MyProject', {
buildSpec: codebuild.BuildSpec.fromObject({
version: '0.2',
}),
artifacts:
codebuild.Artifacts.s3({
bucket,
includeBuildId: false,
packageZip: true,
path: 'another/path',
identifier: 'AddArtifact1',
}),
});

app.synth();
55 changes: 54 additions & 1 deletion packages/@aws-cdk/aws-codebuild/test/test.codebuild.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { expect, haveResource, haveResourceLike } from '@aws-cdk/assert';
import { ABSENT, expect, haveResource, haveResourceLike } from '@aws-cdk/assert';
import * as codecommit from '@aws-cdk/aws-codecommit';
import * as ec2 from '@aws-cdk/aws-ec2';
import * as kms from '@aws-cdk/aws-kms';
Expand Down Expand Up @@ -1130,6 +1130,59 @@ export = {
},
}));

test.done();
},
},
'S3': {
'name is not set so use buildspec'(test: Test) {
const stack = new cdk.Stack();
const bucket = new s3.Bucket(stack, 'MyBucket');
new codebuild.Project(stack, 'MyProject', {
source: codebuild.Source.s3({
bucket,
path: 'some/path',
}),
artifacts: codebuild.Artifacts.s3({
bucket,
path: 'another/path',
identifier: 'artifact1',
}),
});

expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', {
'Artifacts':
{
'ArtifactIdentifier': 'artifact1',
'OverrideArtifactName': true,
},
}));

test.done();
},
'name is set so use it'(test: Test) {
const stack = new cdk.Stack();
const bucket = new s3.Bucket(stack, 'MyBucket');
new codebuild.Project(stack, 'MyProject', {
source: codebuild.Source.s3({
bucket,
path: 'some/path',
}),
artifacts: codebuild.Artifacts.s3({
bucket,
path: 'another/path',
name: 'name',
identifier: 'artifact1',
}),
});

expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', {
'Artifacts':
{
'ArtifactIdentifier': 'artifact1',
'OverrideArtifactName': ABSENT,
},
}));

test.done();
},
},
Expand Down