diff --git a/packages/@aws-cdk/aws-codebuild/README.md b/packages/@aws-cdk/aws-codebuild/README.md index d0ffce917b540..b61d736c11d29 100644 --- a/packages/@aws-cdk/aws-codebuild/README.md +++ b/packages/@aws-cdk/aws-codebuild/README.md @@ -115,6 +115,30 @@ const bbSource = codebuild.Source.bitBucket({ }); ``` +## Artifacts + +CodeBuild Projects can produce Artifacts and upload them 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, @@ -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) \ No newline at end of file +[Minimal Example](./test/integ.project-file-system-location.ts) diff --git a/packages/@aws-cdk/aws-codebuild/lib/artifacts.ts b/packages/@aws-cdk/aws-codebuild/lib/artifacts.ts index bdf9d3a89a335..eda705fe16860 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/artifacts.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/artifacts.ts @@ -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 directory if `includeBuildId` is set to true). + * + * @default the root of the bucket */ readonly path?: string; @@ -95,8 +97,13 @@ export interface S3ArtifactsProps extends ArtifactsProps { * * The full S3 object key will be "//" or * "/" 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 undefined, and use the name from the buildspec */ - readonly name: string; + readonly name?: string; /** * Indicates if the build ID should be included in the path. If this is set to true, @@ -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 ? undefined : this.props.name, packaging: this.props.packageZip === false ? 'NONE' : 'ZIP', encryptionDisabled: this.props.encryption === false ? true : undefined, + overrideArtifactName: this.props.name == null ? true : undefined, }, }; } diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.project-buildspec-artifacts.expected.json b/packages/@aws-cdk/aws-codebuild/test/integ.project-buildspec-artifacts.expected.json new file mode 100644 index 0000000000000..fff6b92d11f44 --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/test/integ.project-buildspec-artifacts.expected.json @@ -0,0 +1,163 @@ +{ + "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" }, + "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" + } + } + } + } +} + diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.project-buildspec-artifacts.ts b/packages/@aws-cdk/aws-codebuild/test/integ.project-buildspec-artifacts.ts new file mode 100644 index 0000000000000..6cf42d7a3e102 --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/test/integ.project-buildspec-artifacts.ts @@ -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(); diff --git a/packages/@aws-cdk/aws-codebuild/test/test.codebuild.ts b/packages/@aws-cdk/aws-codebuild/test/test.codebuild.ts index c2cc72aec345b..29cf00c193719 100644 --- a/packages/@aws-cdk/aws-codebuild/test/test.codebuild.ts +++ b/packages/@aws-cdk/aws-codebuild/test/test.codebuild.ts @@ -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'; @@ -1130,6 +1130,61 @@ 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': + { + 'Name': ABSENT, + '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: 'specificname', + identifier: 'artifact1', + }), + }); + + expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', { + 'Artifacts': + { + 'ArtifactIdentifier': 'artifact1', + 'Name': 'specificname', + 'OverrideArtifactName': ABSENT, + }, + })); + test.done(); }, },