diff --git a/packages/@aws-cdk/aws-codebuild/README.md b/packages/@aws-cdk/aws-codebuild/README.md index 8bb4d088a57bb..4899ba712181e 100644 --- a/packages/@aws-cdk/aws-codebuild/README.md +++ b/packages/@aws-cdk/aws-codebuild/README.md @@ -42,15 +42,10 @@ methods and attributes. ## Source Build projects are usually associated with a _source_, which is specified via -the `source` property which accepts a class that extends the `BuildSource` -abstract base class. The supported sources are: - -### `NoSource` - -This is the default and implies that no source is associated with this -build project. - -The `buildSpec` option is required in this case. +the `source` property which accepts a class that extends the `Source` +abstract base class. +The default is to have no source associated with the build project; +the `buildSpec` option is required in that case. Here's a CodeBuild project with no source which simply prints `Hello, CodeBuild!`: @@ -67,11 +62,11 @@ import codecommit = require('@aws-cdk/aws-codecommit'); const repository = new codecommit.Repository(this, 'MyRepo', { repositoryName: 'foo' }); new codebuild.Project(this, 'MyFirstCodeCommitProject', { - source: new codebuild.CodeCommitSource({ repository }), + source: codebuild.Source.codeCommit({ repository }), }); ``` -### `S3BucketSource` +### `S3Source` Create a CodeBuild project with an S3 bucket as the source: @@ -81,25 +76,20 @@ import s3 = require('@aws-cdk/aws-s3'); const bucket = new s3.Bucket(this, 'MyBucket'); new codebuild.Project(this, 'MyProject', { - source: new codebuild.S3BucketSource({ + source: codebuild.Source.s3({ bucket: bucket, path: 'path/to/file.zip', }), }); ``` -### `CodePipelineSource` - -Used as a special source type when a CodeBuild project is used as a -CodePipeline action. - ### `GitHubSource` and `GitHubEnterpriseSource` These source types can be used to build code from a GitHub repository. Example: ```typescript -const gitHubSource = new codebuild.GitHubSource({ +const gitHubSource = codebuild.Source.gitHub({ owner: 'awslabs', repo: 'aws-cdk', webhook: true, // optional, default: true if `webhookFilteres` were provided, false otherwise @@ -121,6 +111,23 @@ aws codebuild import-source-credentials --server-type GITHUB --auth-type PERSONA This source type can be used to build code from a BitBucket repository. +## CodePipeline + +To add a CodeBuild Project as an Action to CodePipeline, +use the `PipelineProject` class instead of `Project`. +It's a simple class that doesn't allow you to specify `sources`, +`secondarySources`, `artifacts` or `secondaryArtifacts`, +as these are handled by setting input and output CodePipeline `Artifact` instances on the Action, +instead of setting them on the Project. + +```typescript +const project = new codebuild.PipelineProject(this, 'Project', { + // properties as above... +}) +``` + +For more details, see the readme of the `@aws-cdk/@aws-codepipeline` package. + ## Caching You can save time when your project builds by using a cache. A cache can store reusable pieces of your build environment and use them across multiple builds. Your build project can use one of two types of caching: Amazon S3 or local. In general, S3 caching is a good option for small and intermediate build artifacts that are more expensive to build than to download. Local caching is a good option for large intermediate build artifacts because the cache is immediately available on the build host. @@ -225,13 +232,13 @@ multiple outputs. For example: ```ts const project = new codebuild.Project(this, 'MyProject', { secondarySources: [ - new codebuild.CodeCommitSource({ + codebuild.Source.codeCommit({ identifier: 'source2', repository: repo, }), ], secondaryArtifacts: [ - new codebuild.S3BucketBuildArtifacts({ + codebuild.Artifacts.s3({ identifier: 'artifact2', bucket: bucket, path: 'some/path', @@ -324,7 +331,7 @@ const securityGroup = new ec2.SecurityGroup(stack, 'SecurityGroup1', { vpc: vpc, }); new Project(stack, 'MyProject', { - buildScriptAsset: new assets.ZipDirectoryAsset(stack, 'Bundle', { path: 'script_bundle' }), + buildScript: new assets.ZipDirectoryAsset(stack, 'Bundle', { path: 'script_bundle' }), securityGroups: [securityGroup], vpc: vpc }); diff --git a/packages/@aws-cdk/aws-codebuild/lib/artifacts.ts b/packages/@aws-cdk/aws-codebuild/lib/artifacts.ts index 53c9e835a2766..0e314f8ae5eba 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/artifacts.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/artifacts.ts @@ -1,84 +1,83 @@ import s3 = require('@aws-cdk/aws-s3'); +import { Construct } from '@aws-cdk/cdk'; import { CfnProject } from './codebuild.generated'; -import { Project } from './project'; +import { IProject } from './project'; /** - * Properties common to all Artifacts classes. + * The type returned from {@link IArtifacts#bind}. */ -export interface BuildArtifactsProps { +export interface ArtifactsConfig { /** - * The artifact identifier. - * This property is required on secondary artifacts. + * The low-level CloudFormation artifacts property. */ - readonly identifier?: string; + readonly artifactsProperty: CfnProject.ArtifactsProperty; } /** - * Artifacts definition for a CodeBuild Project. + * The abstract interface of a CodeBuild build output. + * Implemented by {@link Artifacts}. */ -export abstract class BuildArtifacts { - public readonly identifier?: string; - protected abstract readonly type: string; - - constructor(props: BuildArtifactsProps) { - this.identifier = props.identifier; - } - +export interface IArtifacts { /** - * @internal + * The artifact identifier. + * This property is required on secondary artifacts. */ - public _bind(_project: Project) { - return; - } + readonly identifier?: string; - public toArtifactsJSON(): CfnProject.ArtifactsProperty { - const artifactsProp = this.toArtifactsProperty(); - return { - artifactIdentifier: this.identifier, - type: this.type, - ...artifactsProp, - }; - } + /** + * The CodeBuild type of this artifact. + */ + readonly type: string; - protected toArtifactsProperty(): any { - return { - }; - } + /** + * Callback when an Artifacts class is used in a CodeBuild Project. + * + * @param scope a root Construct that allows creating new Constructs + * @param project the Project this Artifacts is used in + */ + bind(scope: Construct, project: IProject): ArtifactsConfig; } /** - * A `NO_ARTIFACTS` CodeBuild Project Artifact definition. - * This is the default artifact type, - * if none was specified when creating the Project - * (and the source was not specified to be CodePipeline). - * *Note*: the `NO_ARTIFACTS` type cannot be used as a secondary artifact, - * and because of that, you're not allowed to specify an identifier for it. + * Properties common to all Artifacts classes. */ -export class NoBuildArtifacts extends BuildArtifacts { - protected readonly type = 'NO_ARTIFACTS'; - - constructor() { - super({}); - } +export interface ArtifactsProps { + /** + * The artifact identifier. + * This property is required on secondary artifacts. + */ + readonly identifier?: string; } /** - * CodePipeline Artifact definition for a CodeBuild Project. - * *Note*: this type cannot be used as a secondary artifact, - * and because of that, you're not allowed to specify an identifier for it. + * Artifacts definition for a CodeBuild Project. */ -export class CodePipelineBuildArtifacts extends BuildArtifacts { - protected readonly type = 'CODEPIPELINE'; +export abstract class Artifacts implements IArtifacts { + public static s3(props: S3ArtifactsProps): Artifacts { + return new S3Artifacts(props); + } - constructor() { - super({}); + public readonly identifier?: string; + public abstract readonly type: string; + + protected constructor(props: ArtifactsProps) { + this.identifier = props.identifier; + } + + public bind(_scope: Construct, _project: IProject): ArtifactsConfig { + return { + artifactsProperty: { + artifactIdentifier: this.identifier, + type: this.type, + }, + }; } } /** - * Construction properties for {@link S3BucketBuildArtifacts}. + * Construction properties for {@link S3Artifacts}. */ -export interface S3BucketBuildArtifactsProps extends BuildArtifactsProps { +export interface S3ArtifactsProps extends ArtifactsProps { /** * The name of the output bucket. */ @@ -119,27 +118,25 @@ export interface S3BucketBuildArtifactsProps extends BuildArtifactsProps { /** * S3 Artifact definition for a CodeBuild Project. */ -export class S3BucketBuildArtifacts extends BuildArtifacts { - protected readonly type = 'S3'; +class S3Artifacts extends Artifacts { + public readonly type = 'S3'; - constructor(private readonly props: S3BucketBuildArtifactsProps) { + constructor(private readonly props: S3ArtifactsProps) { super(props); } - /** - * @internal - */ - public _bind(project: Project) { + public bind(_scope: Construct, project: IProject): ArtifactsConfig { this.props.bucket.grantReadWrite(project); - } - - protected toArtifactsProperty(): any { + const superConfig = super.bind(_scope, project); return { - location: this.props.bucket.bucketName, - path: this.props.path, - namespaceType: this.props.includeBuildId === false ? 'NONE' : 'BUILD_ID', - name: this.props.name, - packaging: this.props.packageZip === false ? 'NONE' : 'ZIP', + artifactsProperty: { + ...superConfig.artifactsProperty, + location: this.props.bucket.bucketName, + path: this.props.path, + namespaceType: this.props.includeBuildId === false ? 'NONE' : 'BUILD_ID', + name: this.props.name, + packaging: this.props.packageZip === false ? 'NONE' : 'ZIP', + } }; } } diff --git a/packages/@aws-cdk/aws-codebuild/lib/codepipeline-artifacts.ts b/packages/@aws-cdk/aws-codebuild/lib/codepipeline-artifacts.ts new file mode 100644 index 0000000000000..8b8d72e6c2cc7 --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/lib/codepipeline-artifacts.ts @@ -0,0 +1,14 @@ +import { Artifacts } from './artifacts'; + +/** + * CodePipeline Artifact definition for a CodeBuild Project. + * *Note*: this type cannot be used as a secondary artifact, + * and because of that, you're not allowed to specify an identifier for it. + */ +export class CodePipelineArtifacts extends Artifacts { + public readonly type = 'CODEPIPELINE'; + + constructor() { + super({}); + } +} diff --git a/packages/@aws-cdk/aws-codebuild/lib/codepipeline-source.ts b/packages/@aws-cdk/aws-codebuild/lib/codepipeline-source.ts new file mode 100644 index 0000000000000..fb72a6b605a4a --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/lib/codepipeline-source.ts @@ -0,0 +1,15 @@ +import { Source } from './source'; +import { CODEPIPELINE_SOURCE_ARTIFACTS_TYPE } from './source-types'; + +/** + * CodePipeline Source definition for a CodeBuild Project. + * *Note*: this type cannot be used as a secondary source, + * and because of that, you're not allowed to specify an identifier for it. + */ +export class CodePipelineSource extends Source { + public readonly type = CODEPIPELINE_SOURCE_ARTIFACTS_TYPE; + + constructor() { + super({}); + } +} diff --git a/packages/@aws-cdk/aws-codebuild/lib/no-artifacts.ts b/packages/@aws-cdk/aws-codebuild/lib/no-artifacts.ts new file mode 100644 index 0000000000000..72bbbd07b9f71 --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/lib/no-artifacts.ts @@ -0,0 +1,19 @@ +import { Artifacts } from './artifacts'; + +/** + * A `NO_ARTIFACTS` CodeBuild Project Artifact definition. + * This is the default artifact type, + * if none was specified when creating the Project + * (and the source was not specified to be CodePipeline). + * *Note*: the `NO_ARTIFACTS` type cannot be used as a secondary artifact, + * and because of that, you're not allowed to specify an identifier for it. + * + * This class is private to the @aws-codebuild package. + */ +export class NoArtifacts extends Artifacts { + public readonly type = 'NO_ARTIFACTS'; + + constructor() { + super({}); + } +} diff --git a/packages/@aws-cdk/aws-codebuild/lib/no-source.ts b/packages/@aws-cdk/aws-codebuild/lib/no-source.ts new file mode 100644 index 0000000000000..eb45884c6f1e7 --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/lib/no-source.ts @@ -0,0 +1,19 @@ +import { Source } from './source'; +import { NO_SOURCE_TYPE } from './source-types'; + +/** + * A `NO_SOURCE` CodeBuild Project Source definition. + * This is the default source type, + * if none was specified when creating the Project. + * *Note*: the `NO_SOURCE` type cannot be used as a secondary source, + * and because of that, you're not allowed to specify an identifier for it. + * + * This class is private to the aws-codebuild package. + */ +export class NoSource extends Source { + public readonly type = NO_SOURCE_TYPE; + + constructor() { + super({}); + } +} diff --git a/packages/@aws-cdk/aws-codebuild/lib/pipeline-project.ts b/packages/@aws-cdk/aws-codebuild/lib/pipeline-project.ts index 7d6e4e4193e09..979850701a862 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/pipeline-project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/pipeline-project.ts @@ -1,7 +1,7 @@ import cdk = require('@aws-cdk/cdk'); -import { CodePipelineBuildArtifacts } from './artifacts'; +import { CodePipelineArtifacts } from './codepipeline-artifacts'; +import { CodePipelineSource } from './codepipeline-source'; import { CommonProjectProps, Project } from './project'; -import { CodePipelineSource } from './source'; // tslint:disable-next-line:no-empty-interface export interface PipelineProjectProps extends CommonProjectProps { @@ -14,7 +14,7 @@ export class PipelineProject extends Project { constructor(scope: cdk.Construct, id: string, props?: PipelineProjectProps) { super(scope, id, { source: new CodePipelineSource(), - artifacts: new CodePipelineBuildArtifacts(), + artifacts: new CodePipelineArtifacts(), ...props }); } diff --git a/packages/@aws-cdk/aws-codebuild/lib/project.ts b/packages/@aws-cdk/aws-codebuild/lib/project.ts index 0fb8136fb8de5..0d21d4cad02e3 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/project.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/project.ts @@ -1,4 +1,3 @@ -import assets = require('@aws-cdk/assets'); import { DockerImageAsset, DockerImageAssetProps } from '@aws-cdk/assets-docker'; import cloudwatch = require('@aws-cdk/aws-cloudwatch'); import ec2 = require('@aws-cdk/aws-ec2'); @@ -7,17 +6,20 @@ import events = require('@aws-cdk/aws-events'); import iam = require('@aws-cdk/aws-iam'); import kms = require('@aws-cdk/aws-kms'); import { Aws, Construct, IResource, Lazy, PhysicalName, Resource, ResourceIdentifiers, Stack } from '@aws-cdk/cdk'; -import { BuildArtifacts, CodePipelineBuildArtifacts, NoBuildArtifacts } from './artifacts'; -import { BuildSpec, mergeBuildSpecs } from './build-spec'; +import { IArtifacts } from './artifacts'; +import { BuildSpec } from './build-spec'; import { Cache } from './cache'; import { CfnProject } from './codebuild.generated'; -import { BuildSource, NoSource, SourceType } from './source'; +import { CodePipelineArtifacts } from './codepipeline-artifacts'; +import { NoArtifacts } from './no-artifacts'; +import { NoSource } from './no-source'; +import { ISource } from './source'; +import { CODEPIPELINE_SOURCE_ARTIFACTS_TYPE, NO_SOURCE_TYPE } from './source-types'; -const CODEPIPELINE_TYPE = 'CODEPIPELINE'; const S3_BUCKET_ENV = 'SCRIPT_S3_BUCKET'; const S3_KEY_ENV = 'SCRIPT_S3_KEY'; -export interface IProject extends IResource, iam.IGrantable { +export interface IProject extends IResource, iam.IGrantable, ec2.IConnectable { /** * The ARN of this Project. * @attribute @@ -33,6 +35,8 @@ export interface IProject extends IResource, iam.IGrantable { /** The IAM service Role of this Project. Undefined for imported Projects. */ readonly role?: iam.IRole; + addToRolePolicy(policyStatement: iam.PolicyStatement): void; + /** * Defines a CloudWatch event rule triggered when something happens with this project. * @@ -165,6 +169,34 @@ abstract class ProjectBase extends Resource implements IProject { /** The IAM service Role of this Project. */ public abstract readonly role?: iam.IRole; + /** + * Actual connections object for this Project. + * May be unset, in which case this Project is not configured to use a VPC. + * @internal + */ + protected _connections: ec2.Connections; + + /** + * Access the Connections object. + * Will fail if this Project does not have a VPC set. + */ + public get connections(): ec2.Connections { + if (!this._connections) { + throw new Error('Only VPC-associated Projects have security groups to manage. Supply the "vpc" parameter when creating the Project'); + } + return this._connections; + } + + /** + * Add a permission only if there's a policy attached. + * @param statement The permissions statement to add + */ + public addToRolePolicy(statement: iam.PolicyStatement) { + if (this.role) { + this.role.addToPolicy(statement); + } + } + /** * Defines a CloudWatch event rule triggered when something happens with this project. * @@ -374,26 +406,6 @@ export interface CommonProjectProps { */ readonly buildSpec?: BuildSpec; - /** - * Run a script from an asset as build script - * - * If supplied together with buildSpec, the asset script will be run - * _after_ the existing commands in buildspec. - * - * This feature can also be used without a source, to simply run an - * arbitrary script in a serverless way. - * - * @default - No asset build script. - */ - readonly buildScriptAsset?: assets.Asset; - - /** - * The script in the asset to run. - * - * @default build.sh - */ - readonly buildScriptAssetEntrypoint?: string; - /** * Service Role to assume while running the build. * @@ -504,15 +516,15 @@ export interface ProjectProps extends CommonProjectProps { * * @default - NoSource */ - readonly source?: BuildSource; + readonly source?: ISource; /** * Defines where build artifacts will be stored. - * Could be: PipelineBuildArtifacts, NoBuildArtifacts and S3BucketBuildArtifacts. + * Could be: PipelineBuildArtifacts, NoArtifacts and S3Artifacts. * - * @default NoBuildArtifacts + * @default NoArtifacts */ - readonly artifacts?: BuildArtifacts; + readonly artifacts?: IArtifacts; /** * The secondary sources for the Project. @@ -521,7 +533,7 @@ export interface ProjectProps extends CommonProjectProps { * @default - No secondary sources. * @see https://docs.aws.amazon.com/codebuild/latest/userguide/sample-multi-in-out.html */ - readonly secondarySources?: BuildSource[]; + readonly secondarySources?: ISource[]; /** * The secondary artifacts for the Project. @@ -530,7 +542,7 @@ export interface ProjectProps extends CommonProjectProps { * @default - No secondary artifacts. * @see https://docs.aws.amazon.com/codebuild/latest/userguide/sample-multi-in-out.html */ - readonly secondaryArtifacts?: BuildArtifacts[]; + readonly secondaryArtifacts?: IArtifacts[]; } /** @@ -610,21 +622,16 @@ export class Project extends ProjectBase { */ public readonly projectName: string; - private readonly source: BuildSource; + private readonly source: ISource; private readonly buildImage: IBuildImage; - private readonly _secondarySources: BuildSource[]; - private readonly _secondaryArtifacts: BuildArtifacts[]; - private _securityGroups: ec2.ISecurityGroup[] = []; + private readonly _secondarySources: CfnProject.SourceProperty[]; + private readonly _secondaryArtifacts: CfnProject.ArtifactsProperty[]; constructor(scope: Construct, id: string, props: ProjectProps) { super(scope, id, { physicalName: props.projectName, }); - if (props.buildScriptAssetEntrypoint && !props.buildScriptAsset) { - throw new Error('To use buildScriptAssetEntrypoint, supply buildScriptAsset as well.'); - } - this.role = props.role || new iam.Role(this, 'Role', { roleName: PhysicalName.auto({ crossEnvironment: true }), assumedBy: new iam.ServicePrincipal('codebuild.amazonaws.com') @@ -636,10 +643,17 @@ export class Project extends ProjectBase { // 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(); - this.source._bind(this); + 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 = this.parseArtifacts(props); - artifacts._bind(this); + 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(); @@ -648,34 +662,11 @@ export class Project extends ProjectBase { // Inject download commands for asset if requested const environmentVariables = props.environmentVariables || {}; - let buildSpec = props.buildSpec; - - if (props.buildScriptAsset) { - environmentVariables[S3_BUCKET_ENV] = { value: props.buildScriptAsset.s3BucketName }; - environmentVariables[S3_KEY_ENV] = { value: props.buildScriptAsset.s3ObjectKey }; - - const runScript = this.buildImage.runScriptBuildspec(props.buildScriptAssetEntrypoint || 'build.sh'); - buildSpec = buildSpec ? mergeBuildSpecs(buildSpec, runScript) : runScript; - props.buildScriptAsset.grantRead(this.role); + 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"); } - // Render the source and add in the buildspec - const renderSource = () => { - if (props.badge && !this.source.badgeSupported) { - throw new Error(`Badge is not supported for source type ${this.source.type}`); - } - - if (this.source.type === SourceType.None && (buildSpec === undefined || !buildSpec.isImmediate)) { - throw new Error("If the Project's source is NoSource, you need to provide a concrete buildSpec"); - } - - const sourceJson = this.source._toSourceJSON(); - return { - ...sourceJson, - buildSpec: buildSpec && buildSpec.toBuildSpec() - }; - }; - this._secondarySources = []; for (const secondarySource of props.secondarySources || []) { this.addSecondarySource(secondarySource); @@ -690,8 +681,11 @@ export class Project extends ProjectBase { const resource = new CfnProject(this, 'Resource', { description: props.description, - source: renderSource(), - artifacts: artifacts.toArtifactsJSON(), + source: { + ...sourceConfig.sourceProperty, + buildSpec: buildSpec && buildSpec.toBuildSpec() + }, + artifacts: artifactsConfig.artifactsProperty, serviceRole: this.role.roleArn, environment: this.renderEnvironment(props.environment, environmentVariables), encryptionKey: props.encryptionKey && props.encryptionKey.keyArn, @@ -701,7 +695,7 @@ export class Project extends ProjectBase { timeoutInMinutes: props.timeout, secondarySources: Lazy.anyValue({ produce: () => this.renderSecondarySources() }), secondaryArtifacts: Lazy.anyValue({ produce: () => this.renderSecondaryArtifacts() }), - triggers: this.source._buildTriggers(), + triggers: sourceConfig.buildTriggers, vpcConfig: this.configureVpc(props), }); @@ -724,20 +718,6 @@ export class Project extends ProjectBase { } } - public get securityGroups(): ec2.ISecurityGroup[] { - return this._securityGroups.slice(); - } - - /** - * Add a permission only if there's a policy attached. - * @param statement The permissions statement to add - */ - public addToRolePolicy(statement: iam.PolicyStatement) { - if (this.role) { - this.role.addToPolicy(statement); - } - } - /** * Add a permission only if there's a policy attached. * @param statement The permissions statement to add @@ -758,12 +738,11 @@ export class Project extends ProjectBase { * @param secondarySource the source to add as a secondary source * @see https://docs.aws.amazon.com/codebuild/latest/userguide/sample-multi-in-out.html */ - public addSecondarySource(secondarySource: BuildSource): void { + public addSecondarySource(secondarySource: ISource): void { if (!secondarySource.identifier) { throw new Error('The identifier attribute is mandatory for secondary sources'); } - secondarySource._bind(this); - this._secondarySources.push(secondarySource); + this._secondarySources.push(secondarySource.bind(this, this).sourceProperty); } /** @@ -772,12 +751,11 @@ export class Project extends ProjectBase { * @param secondaryArtifact the artifact to add as a secondary artifact * @see https://docs.aws.amazon.com/codebuild/latest/userguide/sample-multi-in-out.html */ - public addSecondaryArtifact(secondaryArtifact: BuildArtifacts): any { + public addSecondaryArtifact(secondaryArtifact: IArtifacts): any { if (!secondaryArtifact.identifier) { throw new Error("The identifier attribute is mandatory for secondary artifacts"); } - secondaryArtifact._bind(this); - this._secondaryArtifacts.push(secondaryArtifact); + this._secondaryArtifacts.push(secondaryArtifact.bind(this, this).artifactsProperty); } /** @@ -785,7 +763,7 @@ export class Project extends ProjectBase { */ protected validate(): string[] { const ret = new Array(); - if (this.source.type === SourceType.CodePipeline) { + if (this.source.type === CODEPIPELINE_SOURCE_ARTIFACTS_TYPE) { if (this._secondarySources.length > 0) { ret.push('A Project with a CodePipeline Source cannot have secondary sources. ' + "Use the CodeBuild Pipeline Actions' `extraInputs` property instead"); @@ -852,13 +830,13 @@ export class Project extends ProjectBase { private renderSecondarySources(): CfnProject.SourceProperty[] | undefined { return this._secondarySources.length === 0 ? undefined - : this._secondarySources.map((secondarySource) => secondarySource._toSourceJSON()); + : this._secondarySources; } private renderSecondaryArtifacts(): CfnProject.ArtifactsProperty[] | undefined { return this._secondaryArtifacts.length === 0 ? undefined - : this._secondaryArtifacts.map((secondaryArtifact) => secondaryArtifact.toArtifactsJSON()); + : this._secondaryArtifacts; } /** @@ -878,16 +856,19 @@ export class Project extends ProjectBase { throw new Error(`Configure 'allowAllOutbound' directly on the supplied SecurityGroup.`); } + let securityGroups: ec2.ISecurityGroup[]; if (props.securityGroups && props.securityGroups.length > 0) { - this._securityGroups = props.securityGroups.slice(); + securityGroups = props.securityGroups; } else { const securityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', { vpc: props.vpc, description: 'Automatic generated security group for CodeBuild ' + this.node.uniqueId, allowAllOutbound: props.allowAllOutbound }); - this._securityGroups = [securityGroup]; + securityGroups = [securityGroup]; } + this._connections = new ec2.Connections({ securityGroups }); + this.addToRoleInlinePolicy(new iam.PolicyStatement({ resources: ['*'], actions: [ @@ -911,27 +892,17 @@ export class Project extends ProjectBase { return { vpcId: props.vpc.vpcId, subnets: props.vpc.selectSubnets(props.subnetSelection).subnetIds, - securityGroupIds: this._securityGroups.map(s => s.securityGroupId) + securityGroupIds: this.connections.securityGroups.map(s => s.securityGroupId) }; } - private parseArtifacts(props: ProjectProps) { - if (props.artifacts) { - return props.artifacts; - } - if (this.source._toSourceJSON().type === CODEPIPELINE_TYPE) { - return new CodePipelineBuildArtifacts(); - } else { - return new NoBuildArtifacts(); - } - } - - private validateCodePipelineSettings(artifacts: BuildArtifacts) { - const sourceType = this.source._toSourceJSON().type; - const artifactsType = artifacts.toArtifactsJSON().type; + private validateCodePipelineSettings(artifacts: IArtifacts) { + const sourceType = this.source.type; + const artifactsType = artifacts.type; - if ((sourceType === CODEPIPELINE_TYPE || artifactsType === CODEPIPELINE_TYPE) && - (sourceType !== artifactsType)) { + if ((sourceType === CODEPIPELINE_SOURCE_ARTIFACTS_TYPE || + artifactsType === CODEPIPELINE_SOURCE_ARTIFACTS_TYPE) && + (sourceType !== artifactsType)) { throw new Error('Both source and artifacts must be set to CodePipeline'); } } diff --git a/packages/@aws-cdk/aws-codebuild/lib/source-types.ts b/packages/@aws-cdk/aws-codebuild/lib/source-types.ts new file mode 100644 index 0000000000000..fb9137ec66e8c --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/lib/source-types.ts @@ -0,0 +1,7 @@ +export const NO_SOURCE_TYPE = 'NO_SOURCE'; +export const CODEPIPELINE_SOURCE_ARTIFACTS_TYPE = 'CODEPIPELINE'; +export const S3_SOURCE_TYPE = 'S3'; +export const CODECOMMIT_SOURCE_TYPE = 'CODECOMMIT'; +export const GITHUB_SOURCE_TYPE = 'GITHUB'; +export const GITHUB_ENTERPRISE_SOURCE_TYPE = 'GITHUB_ENTERPRISE'; +export const BITBUCKET_SOURCE_TYPE = 'BITBUCKET'; diff --git a/packages/@aws-cdk/aws-codebuild/lib/source.ts b/packages/@aws-cdk/aws-codebuild/lib/source.ts index 9bd734fad4faa..671a3cf1ba947 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/source.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/source.ts @@ -1,13 +1,44 @@ import codecommit = require('@aws-cdk/aws-codecommit'); import iam = require('@aws-cdk/aws-iam'); import s3 = require('@aws-cdk/aws-s3'); +import { Construct } from '@aws-cdk/cdk'; import { CfnProject } from './codebuild.generated'; -import { Project } from './project'; +import { IProject } from './project'; +import { + BITBUCKET_SOURCE_TYPE, + CODECOMMIT_SOURCE_TYPE, + GITHUB_ENTERPRISE_SOURCE_TYPE, + GITHUB_SOURCE_TYPE, + S3_SOURCE_TYPE +} from './source-types'; + +/** + * The type returned from {@link ISource#bind}. + */ +export interface SourceConfig { + readonly sourceProperty: CfnProject.SourceProperty; + + readonly buildTriggers?: CfnProject.ProjectTriggersProperty; +} + +/** + * The abstract interface of a CodeBuild source. + * Implemented by {@link Source}. + */ +export interface ISource { + readonly identifier?: string; + + readonly type: string; + + readonly badgeSupported: boolean; + + bind(scope: Construct, project: IProject): SourceConfig; +} /** * Properties common to all Source classes. */ -export interface BuildSourceProps { +export interface SourceProps { /** * The source identifier. * This property is required on secondary sources. @@ -18,12 +49,32 @@ export interface BuildSourceProps { /** * Source provider definition for a CodeBuild Project. */ -export abstract class BuildSource { +export abstract class Source implements ISource { + public static s3(props: S3SourceProps): Source { + return new S3Source(props); + } + + public static codeCommit(props: CodeCommitSourceProps): Source { + return new CodeCommitSource(props); + } + + public static gitHub(props: GitHubSourceProps): Source { + return new GitHubSource(props); + } + + public static gitHubEnterprise(props: GitHubEnterpriseSourceProps): Source { + return new GitHubEnterpriseSource(props); + } + + public static bitBucket(props: BitBucketSourceProps): Source { + return new BitBucketSource(props); + } + public readonly identifier?: string; - public abstract readonly type: SourceType; + public abstract readonly type: string; public readonly badgeSupported: boolean = false; - constructor(props: BuildSourceProps) { + protected constructor(props: SourceProps) { this.identifier = props.identifier; } @@ -31,54 +82,21 @@ export abstract class BuildSource { * Called by the project when the source is added so that the source can perform * binding operations on the source. For example, it can grant permissions to the * code build project to read from the S3 bucket. - * - * @internal */ - public _bind(_project: Project) { - // by default, do nothing - return; - } - - /** @internal */ - public _toSourceJSON(): CfnProject.SourceProperty { - const sourceProp = this.toSourceProperty(); - return { - sourceIdentifier: this.identifier, - type: this.type, - ...sourceProp, - }; - } - - /** @internal */ - public _buildTriggers(): CfnProject.ProjectTriggersProperty | undefined { - return undefined; - } - - protected toSourceProperty(): any { + public bind(_scope: Construct, _project: IProject): SourceConfig { return { + sourceProperty: { + sourceIdentifier: this.identifier, + type: this.type, + } }; } } -/** - * A `NO_SOURCE` CodeBuild Project Source definition. - * This is the default source type, - * if none was specified when creating the Project. - * *Note*: the `NO_SOURCE` type cannot be used as a secondary source, - * and because of that, you're not allowed to specify an identifier for it. - */ -export class NoSource extends BuildSource { - public readonly type: SourceType = SourceType.None; - - constructor() { - super({}); - } -} - /** * The construction properties common to all build sources that are backed by Git. */ -export interface GitBuildSourceProps extends BuildSourceProps { +interface GitSourceProps extends SourceProps { /** * The depth of history to download. Minimum value is 0. * If this value is 0, greater than 25, or not provided, @@ -90,20 +108,22 @@ export interface GitBuildSourceProps extends BuildSourceProps { /** * A common superclass of all build sources that are backed by Git. */ -export abstract class GitBuildSource extends BuildSource { +abstract class GitSource extends Source { private readonly cloneDepth?: number; - protected constructor(props: GitBuildSourceProps) { + protected constructor(props: GitSourceProps) { super(props); this.cloneDepth = props.cloneDepth; } - /** @internal */ - public _toSourceJSON(): CfnProject.SourceProperty { + public bind(_scope: Construct, _project: IProject): SourceConfig { + const superConfig = super.bind(_scope, _project); return { - ...super._toSourceJSON(), - gitCloneDepth: this.cloneDepth + sourceProperty: { + ...superConfig.sourceProperty, + gitCloneDepth: this.cloneDepth, + }, }; } } @@ -381,7 +401,7 @@ export class FilterGroup { /** * The construction properties common to all third-party build sources that are backed by Git. */ -export interface ThirdPartyGitBuildSourceProps extends GitBuildSourceProps { +interface ThirdPartyGitSourceProps extends GitSourceProps { /** * Whether to send notifications on your build's start and end. * @@ -409,13 +429,13 @@ export interface ThirdPartyGitBuildSourceProps extends GitBuildSourceProps { /** * A common superclass of all third-party build sources that are backed by Git. */ -export abstract class ThirdPartyGitBuildSource extends GitBuildSource { +abstract class ThirdPartyGitSource extends GitSource { public readonly badgeSupported: boolean = true; protected readonly webhookFilters: FilterGroup[]; private readonly reportBuildStatus: boolean; private readonly webhook?: boolean; - protected constructor(props: ThirdPartyGitBuildSourceProps) { + protected constructor(props: ThirdPartyGitSourceProps) { super(props); this.webhook = props.webhook; @@ -423,21 +443,20 @@ export abstract class ThirdPartyGitBuildSource extends GitBuildSource { this.webhookFilters = props.webhookFilters || []; } - /** @internal */ - public _buildTriggers(): CfnProject.ProjectTriggersProperty | undefined { + public bind(_scope: Construct, _project: IProject): SourceConfig { const anyFilterGroupsProvided = this.webhookFilters.length > 0; const webhook = this.webhook === undefined ? (anyFilterGroupsProvided ? true : undefined) : this.webhook; - return webhook === undefined ? undefined : { - webhook, - filterGroups: anyFilterGroupsProvided ? this.webhookFilters.map(fg => fg._toJson()) : undefined, - }; - } - /** @internal */ - public _toSourceJSON(): CfnProject.SourceProperty { + const superConfig = super.bind(_scope, _project); return { - ...super._toSourceJSON(), - reportBuildStatus: this.reportBuildStatus, + sourceProperty: { + ...superConfig.sourceProperty, + reportBuildStatus: this.reportBuildStatus, + }, + buildTriggers: webhook === undefined ? undefined : { + webhook, + filterGroups: anyFilterGroupsProvided ? this.webhookFilters.map(fg => fg._toJson()) : undefined, + } }; } } @@ -445,15 +464,15 @@ export abstract class ThirdPartyGitBuildSource extends GitBuildSource { /** * Construction properties for {@link CodeCommitSource}. */ -export interface CodeCommitSourceProps extends GitBuildSourceProps { +export interface CodeCommitSourceProps extends GitSourceProps { readonly repository: codecommit.IRepository; } /** * CodeCommit Source definition for a CodeBuild project. */ -export class CodeCommitSource extends GitBuildSource { - public readonly type: SourceType = SourceType.CodeCommit; +class CodeCommitSource extends GitSource { + public readonly type = CODECOMMIT_SOURCE_TYPE; private readonly repo: codecommit.IRepository; constructor(props: CodeCommitSourceProps) { @@ -461,28 +480,27 @@ export class CodeCommitSource extends GitBuildSource { this.repo = props.repository; } - /** - * @internal - */ - public _bind(project: Project) { + public bind(_scope: Construct, project: IProject): SourceConfig { // https://docs.aws.amazon.com/codebuild/latest/userguide/setting-up.html project.addToRolePolicy(new iam.PolicyStatement({ actions: ['codecommit:GitPull'], resources: [this.repo.repositoryArn] })); - } - protected toSourceProperty(): any { + const superConfig = super.bind(_scope, project); return { - location: this.repo.repositoryCloneUrlHttp + sourceProperty: { + ...superConfig.sourceProperty, + location: this.repo.repositoryCloneUrlHttp, + }, }; } } /** - * Construction properties for {@link S3BucketSource}. + * Construction properties for {@link S3Source}. */ -export interface S3BucketSourceProps extends BuildSourceProps { +export interface S3SourceProps extends SourceProps { readonly bucket: s3.IBucket; readonly path: string; } @@ -490,48 +508,34 @@ export interface S3BucketSourceProps extends BuildSourceProps { /** * S3 bucket definition for a CodeBuild project. */ -export class S3BucketSource extends BuildSource { - public readonly type: SourceType = SourceType.S3; +class S3Source extends Source { + public readonly type = S3_SOURCE_TYPE; private readonly bucket: s3.IBucket; private readonly path: string; - constructor(props: S3BucketSourceProps) { + constructor(props: S3SourceProps) { super(props); this.bucket = props.bucket; this.path = props.path; } - /** - * @internal - */ - public _bind(project: Project) { + public bind(_scope: Construct, project: IProject): SourceConfig { this.bucket.grantRead(project); - } - protected toSourceProperty(): any { + const superConfig = super.bind(_scope, project); return { - location: `${this.bucket.bucketName}/${this.path}`, + sourceProperty: { + ...superConfig.sourceProperty, + location: `${this.bucket.bucketName}/${this.path}`, + }, }; } } -/** - * CodePipeline Source definition for a CodeBuild Project. - * *Note*: this type cannot be used as a secondary source, - * and because of that, you're not allowed to specify an identifier for it. - */ -export class CodePipelineSource extends BuildSource { - public readonly type: SourceType = SourceType.CodePipeline; - - constructor() { - super({}); - } -} - /** * Construction properties for {@link GitHubSource} and {@link GitHubEnterpriseSource}. */ -export interface GitHubSourceProps extends ThirdPartyGitBuildSourceProps { +export interface GitHubSourceProps extends ThirdPartyGitSourceProps { /** * The GitHub account/user that owns the repo. * @@ -550,8 +554,8 @@ export interface GitHubSourceProps extends ThirdPartyGitBuildSourceProps { /** * GitHub Source definition for a CodeBuild project. */ -export class GitHubSource extends ThirdPartyGitBuildSource { - public readonly type: SourceType = SourceType.GitHub; +class GitHubSource extends ThirdPartyGitSource { + public readonly type = GITHUB_SOURCE_TYPE; private readonly httpsCloneUrl: string; constructor(props: GitHubSourceProps) { @@ -559,9 +563,14 @@ export class GitHubSource extends ThirdPartyGitBuildSource { this.httpsCloneUrl = `https://github.com/${props.owner}/${props.repo}.git`; } - protected toSourceProperty(): any { + public bind(_scope: Construct, project: IProject): SourceConfig { + const superConfig = super.bind(_scope, project); return { - location: this.httpsCloneUrl, + sourceProperty: { + ...superConfig.sourceProperty, + location: this.httpsCloneUrl, + }, + buildTriggers: superConfig.buildTriggers, }; } } @@ -569,7 +578,7 @@ export class GitHubSource extends ThirdPartyGitBuildSource { /** * Construction properties for {@link GitHubEnterpriseSource}. */ -export interface GitHubEnterpriseSourceProps extends ThirdPartyGitBuildSourceProps { +export interface GitHubEnterpriseSourceProps extends ThirdPartyGitSourceProps { /** * The HTTPS URL of the repository in your GitHub Enterprise installation. */ @@ -586,8 +595,8 @@ export interface GitHubEnterpriseSourceProps extends ThirdPartyGitBuildSourcePro /** * GitHub Enterprise Source definition for a CodeBuild project. */ -export class GitHubEnterpriseSource extends ThirdPartyGitBuildSource { - public readonly type: SourceType = SourceType.GitHubEnterprise; +class GitHubEnterpriseSource extends ThirdPartyGitSource { + public readonly type = GITHUB_ENTERPRISE_SOURCE_TYPE; private readonly httpsCloneUrl: string; private readonly ignoreSslErrors?: boolean; @@ -597,10 +606,15 @@ export class GitHubEnterpriseSource extends ThirdPartyGitBuildSource { this.ignoreSslErrors = props.ignoreSslErrors; } - protected toSourceProperty(): any { + public bind(_scope: Construct, _project: IProject): SourceConfig { + const superConfig = super.bind(_scope, _project); return { - location: this.httpsCloneUrl, - insecureSsl: this.ignoreSslErrors, + sourceProperty: { + ...superConfig.sourceProperty, + location: this.httpsCloneUrl, + insecureSsl: this.ignoreSslErrors, + }, + buildTriggers: superConfig.buildTriggers, }; } } @@ -608,7 +622,7 @@ export class GitHubEnterpriseSource extends ThirdPartyGitBuildSource { /** * Construction properties for {@link BitBucketSource}. */ -export interface BitBucketSourceProps extends ThirdPartyGitBuildSourceProps { +export interface BitBucketSourceProps extends ThirdPartyGitSourceProps { /** * The BitBucket account/user that owns the repo. * @@ -627,8 +641,8 @@ export interface BitBucketSourceProps extends ThirdPartyGitBuildSourceProps { /** * BitBucket Source definition for a CodeBuild project. */ -export class BitBucketSource extends ThirdPartyGitBuildSource { - public readonly type: SourceType = SourceType.BitBucket; +class BitBucketSource extends ThirdPartyGitSource { + public readonly type = BITBUCKET_SOURCE_TYPE; private readonly httpsCloneUrl: any; constructor(props: BitBucketSourceProps) { @@ -636,8 +650,7 @@ export class BitBucketSource extends ThirdPartyGitBuildSource { this.httpsCloneUrl = `https://bitbucket.org/${props.owner}/${props.repo}.git`; } - /** @internal */ - public _buildTriggers(): CfnProject.ProjectTriggersProperty | undefined { + public bind(_scope: Construct, _project: IProject): SourceConfig { // BitBucket sources don't support the PULL_REQUEST_REOPENED event action if (this.anyWebhookFilterContainsPrReopenedEventAction()) { throw new Error('BitBucket sources do not support the PULL_REQUEST_REOPENED webhook event action'); @@ -648,12 +661,13 @@ export class BitBucketSource extends ThirdPartyGitBuildSource { throw new Error('BitBucket sources do not support file path conditions for webhook filters'); } - return super._buildTriggers(); - } - - protected toSourceProperty(): any { + const superConfig = super.bind(_scope, _project); return { - location: this.httpsCloneUrl + sourceProperty: { + ...superConfig.sourceProperty, + location: this.httpsCloneUrl, + }, + buildTriggers: superConfig.buildTriggers, }; } @@ -670,19 +684,6 @@ export class BitBucketSource extends ThirdPartyGitBuildSource { } } -/** - * Source types for CodeBuild Project - */ -export enum SourceType { - None = 'NO_SOURCE', - CodeCommit = 'CODECOMMIT', - CodePipeline = 'CODEPIPELINE', - GitHub = 'GITHUB', - GitHubEnterprise = 'GITHUB_ENTERPRISE', - BitBucket = 'BITBUCKET', - S3 = 'S3', -} - function set2Array(set: Set): T[] { const ret: T[] = []; set.forEach(el => ret.push(el)); diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.github.ts b/packages/@aws-cdk/aws-codebuild/test/integ.github.ts index 955f88bbf1a54..2db2ae3344434 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.github.ts +++ b/packages/@aws-cdk/aws-codebuild/test/integ.github.ts @@ -5,7 +5,7 @@ class TestStack extends cdk.Stack { constructor(scope: cdk.App, id: string) { super(scope, id); - const source = new codebuild.GitHubSource({ + const source = codebuild.Source.gitHub({ owner: 'awslabs', repo: 'aws-cdk', reportBuildStatus: false, diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.project-bucket.ts b/packages/@aws-cdk/aws-codebuild/test/integ.project-bucket.ts index 93383eb9eef38..12626a39514d0 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.project-bucket.ts +++ b/packages/@aws-cdk/aws-codebuild/test/integ.project-bucket.ts @@ -12,7 +12,7 @@ const bucket = new s3.Bucket(stack, 'MyBucket', { }); new codebuild.Project(stack, 'MyProject', { - source: new codebuild.S3BucketSource({ + source: codebuild.Source.s3({ bucket, path: 'path/to/my/source.zip', }), diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.project-secondary-sources-artifacts.ts b/packages/@aws-cdk/aws-codebuild/test/integ.project-secondary-sources-artifacts.ts index 8f33a229d4561..c407760563df1 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.project-secondary-sources-artifacts.ts +++ b/packages/@aws-cdk/aws-codebuild/test/integ.project-secondary-sources-artifacts.ts @@ -15,14 +15,14 @@ new codebuild.Project(stack, 'MyProject', { version: '0.2', }), secondarySources: [ - new codebuild.S3BucketSource({ + codebuild.Source.s3({ bucket, path: 'some/path', identifier: 'AddSource1', }), ], secondaryArtifacts: [ - new codebuild.S3BucketBuildArtifacts({ + codebuild.Artifacts.s3({ bucket, path: 'another/path', name: 'name', diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.project-shell.expected.json b/packages/@aws-cdk/aws-codebuild/test/integ.project-shell.expected.json deleted file mode 100644 index 23577c4af4fa8..0000000000000 --- a/packages/@aws-cdk/aws-codebuild/test/integ.project-shell.expected.json +++ /dev/null @@ -1,243 +0,0 @@ -{ - "Parameters": { - "BundleS3Bucket0EFC11B0": { - "Type": "String", - "Description": "S3 bucket for asset \"aws-cdk-codebuild-project-shell/Bundle\"" - }, - "BundleS3VersionKey720F2199": { - "Type": "String", - "Description": "S3 key for asset version \"aws-cdk-codebuild-project-shell/Bundle\"" - }, - "BundleArtifactHashEA214C27": { - "Type": "String", - "Description": "Artifact hash for asset \"aws-cdk-codebuild-project-shell/Bundle\"" - } - }, - "Resources": { - "MyProjectRole9BBE5233": { - "Type": "AWS::IAM::Role", - "Properties": { - "AssumeRolePolicyDocument": { - "Statement": [ - { - "Action": "sts:AssumeRole", - "Effect": "Allow", - "Principal": { - "Service": { - "Fn::Join": [ - "", - [ - "codebuild.", - { - "Ref": "AWS::URLSuffix" - } - ] - ] - } - } - } - ], - "Version": "2012-10-17" - } - } - }, - "MyProjectRoleDefaultPolicyB19B7C29": { - "Type": "AWS::IAM::Policy", - "Properties": { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":s3:::", - { - "Ref": "BundleS3Bucket0EFC11B0" - } - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":s3:::", - { - "Ref": "BundleS3Bucket0EFC11B0" - }, - "/", - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "BundleS3VersionKey720F2199" - } - ] - } - ] - }, - "*" - ] - ] - } - ] - }, - { - "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": { - "Type": "NO_ARTIFACTS" - }, - "Environment": { - "ComputeType": "BUILD_GENERAL1_SMALL", - "EnvironmentVariables": [ - { - "Name": "SCRIPT_S3_BUCKET", - "Type": "PLAINTEXT", - "Value": { - "Ref": "BundleS3Bucket0EFC11B0" - } - }, - { - "Name": "SCRIPT_S3_KEY", - "Type": "PLAINTEXT", - "Value": { - "Fn::Join": [ - "", - [ - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "BundleS3VersionKey720F2199" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "BundleS3VersionKey720F2199" - } - ] - } - ] - } - ] - ] - } - } - ], - "Image": "aws/codebuild/standard:1.0", - "PrivilegedMode": false, - "Type": "LINUX_CONTAINER" - }, - "ServiceRole": { - "Fn::GetAtt": [ - "MyProjectRole9BBE5233", - "Arn" - ] - }, - "Source": { - "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"pre_build\": {\n \"commands\": [\n \"echo \\\"Downloading scripts from s3://${SCRIPT_S3_BUCKET}/${SCRIPT_S3_KEY}\\\"\",\n \"aws s3 cp s3://${SCRIPT_S3_BUCKET}/${SCRIPT_S3_KEY} /tmp\",\n \"mkdir -p /tmp/scriptdir\",\n \"unzip /tmp/$(basename $SCRIPT_S3_KEY) -d /tmp/scriptdir\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"export SCRIPT_DIR=/tmp/scriptdir\",\n \"echo \\\"Running build.sh\\\"\",\n \"chmod +x /tmp/scriptdir/build.sh\",\n \"/tmp/scriptdir/build.sh\"\n ]\n }\n }\n}", - "Type": "NO_SOURCE" - } - } - } - } -} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.project-shell.ts b/packages/@aws-cdk/aws-codebuild/test/integ.project-shell.ts deleted file mode 100644 index 1f00f2953829a..0000000000000 --- a/packages/@aws-cdk/aws-codebuild/test/integ.project-shell.ts +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env node -import assets = require('@aws-cdk/assets'); -import cdk = require('@aws-cdk/cdk'); -import { Project } from '../lib'; - -const app = new cdk.App(); - -const stack = new cdk.Stack(app, 'aws-cdk-codebuild-project-shell'); - -new Project(stack, 'MyProject', { - buildScriptAsset: new assets.ZipDirectoryAsset(stack, 'Bundle', { path: 'script_bundle' }) -}); - -app.synth(); diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.project-vpc.expected.json b/packages/@aws-cdk/aws-codebuild/test/integ.project-vpc.expected.json index 35f355bfeb053..55fbb665cbe1b 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.project-vpc.expected.json +++ b/packages/@aws-cdk/aws-codebuild/test/integ.project-vpc.expected.json @@ -240,61 +240,6 @@ "Properties": { "PolicyDocument": { "Statement": [ - { - "Action": [ - "s3:GetObject*", - "s3:GetBucket*", - "s3:List*" - ], - "Effect": "Allow", - "Resource": [ - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":s3:::", - { - "Ref": "BundleS3Bucket0EFC11B0" - } - ] - ] - }, - { - "Fn::Join": [ - "", - [ - "arn:", - { - "Ref": "AWS::Partition" - }, - ":s3:::", - { - "Ref": "BundleS3Bucket0EFC11B0" - }, - "/", - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "BundleS3VersionKey720F2199" - } - ] - } - ] - }, - "*" - ] - ] - } - ] - }, { "Action": "ec2:CreateNetworkInterfacePermission", "Condition": { @@ -446,52 +391,6 @@ }, "Environment": { "ComputeType": "BUILD_GENERAL1_SMALL", - "EnvironmentVariables": [ - { - "Name": "SCRIPT_S3_BUCKET", - "Type": "PLAINTEXT", - "Value": { - "Ref": "BundleS3Bucket0EFC11B0" - } - }, - { - "Name": "SCRIPT_S3_KEY", - "Type": "PLAINTEXT", - "Value": { - "Fn::Join": [ - "", - [ - { - "Fn::Select": [ - 0, - { - "Fn::Split": [ - "||", - { - "Ref": "BundleS3VersionKey720F2199" - } - ] - } - ] - }, - { - "Fn::Select": [ - 1, - { - "Fn::Split": [ - "||", - { - "Ref": "BundleS3VersionKey720F2199" - } - ] - } - ] - } - ] - ] - } - } - ], "Image": "aws/codebuild/standard:1.0", "PrivilegedMode": false, "Type": "LINUX_CONTAINER" @@ -503,7 +402,7 @@ ] }, "Source": { - "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"pre_build\": {\n \"commands\": [\n \"echo \\\"Downloading scripts from s3://${SCRIPT_S3_BUCKET}/${SCRIPT_S3_KEY}\\\"\",\n \"aws s3 cp s3://${SCRIPT_S3_BUCKET}/${SCRIPT_S3_KEY} /tmp\",\n \"mkdir -p /tmp/scriptdir\",\n \"unzip /tmp/$(basename $SCRIPT_S3_KEY) -d /tmp/scriptdir\"\n ]\n },\n \"build\": {\n \"commands\": [\n \"export SCRIPT_DIR=/tmp/scriptdir\",\n \"echo \\\"Running build.sh\\\"\",\n \"chmod +x /tmp/scriptdir/build.sh\",\n \"/tmp/scriptdir/build.sh\"\n ]\n }\n }\n}", + "BuildSpec": "{\n \"version\": \"0.2\",\n \"phases\": {\n \"build\": {\n \"commands\": [\n \"echo \\\"Nothing to do!\\\"\"\n ]\n }\n }\n}", "Type": "NO_SOURCE" }, "VpcConfig": { @@ -526,19 +425,5 @@ } } } - }, - "Parameters": { - "BundleS3Bucket0EFC11B0": { - "Type": "String", - "Description": "S3 bucket for asset \"aws-cdk-codebuild-project-vpc/Bundle\"" - }, - "BundleS3VersionKey720F2199": { - "Type": "String", - "Description": "S3 key for asset version \"aws-cdk-codebuild-project-vpc/Bundle\"" - }, - "BundleArtifactHashEA214C27": { - "Type": "String", - "Description": "Artifact hash for asset \"aws-cdk-codebuild-project-vpc/Bundle\"" - } } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-codebuild/test/integ.project-vpc.ts b/packages/@aws-cdk/aws-codebuild/test/integ.project-vpc.ts index 9d118d04ed81b..dd53529eb9748 100644 --- a/packages/@aws-cdk/aws-codebuild/test/integ.project-vpc.ts +++ b/packages/@aws-cdk/aws-codebuild/test/integ.project-vpc.ts @@ -1,8 +1,7 @@ #!/usr/bin/env node -import assets = require('@aws-cdk/assets'); import ec2 = require('@aws-cdk/aws-ec2'); import cdk = require('@aws-cdk/cdk'); -import { Project } from '../lib'; +import codebuild = require('../lib'); const app = new cdk.App(); @@ -17,8 +16,15 @@ const securityGroup = new ec2.SecurityGroup(stack, 'SecurityGroup1', { groupName: 'Bob', vpc, }); -new Project(stack, 'MyProject', { - buildScriptAsset: new assets.ZipDirectoryAsset(stack, 'Bundle', { path: 'script_bundle' }), +new codebuild.Project(stack, 'MyProject', { + buildSpec: codebuild.BuildSpec.fromObject({ + version: '0.2', + phases: { + build: { + commands: ['echo "Nothing to do!"'], + }, + }, + }), securityGroups: [securityGroup], vpc }); diff --git a/packages/@aws-cdk/aws-codebuild/test/test.codebuild.ts b/packages/@aws-cdk/aws-codebuild/test/test.codebuild.ts index c71fc625ac0b0..ac25c92d3279a 100644 --- a/packages/@aws-cdk/aws-codebuild/test/test.codebuild.ts +++ b/packages/@aws-cdk/aws-codebuild/test/test.codebuild.ts @@ -6,6 +6,8 @@ import s3 = require('@aws-cdk/aws-s3'); import cdk = require('@aws-cdk/cdk'); import { Test } from 'nodeunit'; import codebuild = require('../lib'); +import { CodePipelineSource } from '../lib/codepipeline-source'; +import { NoSource } from '../lib/no-source'; // tslint:disable:object-literal-key-quotes @@ -14,10 +16,7 @@ export = { 'with CodePipeline source'(test: Test) { const stack = new cdk.Stack(); - const source = new codebuild.CodePipelineSource(); - new codebuild.Project(stack, 'MyProject', { - source - }); + new codebuild.PipelineProject(stack, 'MyProject'); expect(stack).toMatch({ "Resources": { @@ -144,7 +143,7 @@ export = { const repo = new codecommit.Repository(stack, 'MyRepo', { repositoryName: 'hello-cdk' }); - const source = new codebuild.CodeCommitSource({ repository: repo, cloneDepth: 2 }); + const source = codebuild.Source.codeCommit({ repository: repo, cloneDepth: 2 }); new codebuild.Project(stack, 'MyProject', { source @@ -298,7 +297,7 @@ export = { const bucket = new s3.Bucket(stack, 'MyBucket'); new codebuild.Project(stack, 'MyProject', { - source: new codebuild.S3BucketSource({ + source: codebuild.Source.s3({ bucket, path: 'path/to/source.zip', }), @@ -475,7 +474,7 @@ export = { const stack = new cdk.Stack(); new codebuild.Project(stack, 'Project', { - source: new codebuild.GitHubSource({ + source: codebuild.Source.gitHub({ owner: 'testowner', repo: 'testrepo', cloneDepth: 3, @@ -520,7 +519,7 @@ export = { const pushFilterGroup = codebuild.FilterGroup.inEventOf(codebuild.EventAction.PUSH); new codebuild.Project(stack, 'MyProject', { - source: new codebuild.GitHubEnterpriseSource({ + source: codebuild.Source.gitHubEnterprise({ httpsCloneUrl: 'https://github.testcompany.com/testowner/testrepo', ignoreSslErrors: true, cloneDepth: 4, @@ -570,7 +569,7 @@ export = { const stack = new cdk.Stack(); new codebuild.Project(stack, 'Project', { - source: new codebuild.BitBucketSource({ + source: codebuild.Source.bitBucket({ owner: 'testowner', repo: 'testrepo', cloneDepth: 5, @@ -634,8 +633,8 @@ export = { allowAllOutbound: true, description: 'Example', }); - new codebuild.Project(stack, 'MyProject', { - source: new codebuild.S3BucketSource({ + const project = new codebuild.Project(stack, 'MyProject', { + source: codebuild.Source.s3({ bucket, path: 'path/to/source.zip', }), @@ -668,6 +667,9 @@ export = { } } })); + + test.notEqual(project.connections, undefined); + test.done(); }, 'without VPC configuration but security group identified'(test: Test) { @@ -684,7 +686,7 @@ export = { test.throws(() => new codebuild.Project(stack, 'MyProject', { - source: new codebuild.S3BucketSource({ + source: codebuild.Source.s3({ bucket, path: 'path/to/source.zip', }), @@ -705,7 +707,7 @@ export = { }); test.throws(() => new codebuild.Project(stack, 'MyProject', { - source: new codebuild.S3BucketSource({ + source: codebuild.Source.s3({ bucket, path: 'path/to/source.zip', }), @@ -717,6 +719,17 @@ export = { test.done(); }, + 'without passing a VPC cannot access the connections property'(test: Test) { + const stack = new cdk.Stack(); + + const project = new codebuild.PipelineProject(stack, 'MyProject'); + + test.throws(() => project.connections, + /Only VPC-associated Projects have security groups to manage. Supply the "vpc" parameter when creating the Project/); + + test.done(); + }, + 'with a KMS Key adds decrypt permissions to the CodeBuild Role'(test: Test) { const stack = new cdk.Stack(); @@ -765,7 +778,7 @@ export = { buildSpec: codebuild.BuildSpec.fromObject({ version: '0.2', }), - artifacts: new codebuild.S3BucketBuildArtifacts({ + artifacts: codebuild.Artifacts.s3({ path: 'some/path', name: 'some_name', bucket, @@ -795,7 +808,10 @@ export = { version: '0.2', }), secondarySources: [ - new codebuild.CodePipelineSource(), + codebuild.Source.s3({ + bucket: new s3.Bucket(stack, 'MyBucket'), + path: 'path', + }), ], }); }, /identifier/); @@ -805,11 +821,9 @@ export = { 'are not allowed for a Project with CodePipeline as Source'(test: Test) { const stack = new cdk.Stack(); - const project = new codebuild.Project(stack, 'MyProject', { - source: new codebuild.CodePipelineSource(), - }); + const project = new codebuild.PipelineProject(stack, 'MyProject'); - project.addSecondarySource(new codebuild.S3BucketSource({ + project.addSecondarySource(codebuild.Source.s3({ bucket: new s3.Bucket(stack, 'MyBucket'), path: 'some/path', identifier: 'id', @@ -826,13 +840,13 @@ export = { const stack = new cdk.Stack(); const bucket = new s3.Bucket(stack, 'MyBucket'); const project = new codebuild.Project(stack, 'MyProject', { - source: new codebuild.S3BucketSource({ + source: codebuild.Source.s3({ bucket, path: 'some/path', }), }); - project.addSecondarySource(new codebuild.S3BucketSource({ + project.addSecondarySource(codebuild.Source.s3({ bucket, path: 'another/path', identifier: 'source1', @@ -861,7 +875,7 @@ export = { version: '0.2', }), secondaryArtifacts: [ - new codebuild.S3BucketBuildArtifacts({ + codebuild.Artifacts.s3({ bucket: new s3.Bucket(stack, 'MyBucket'), path: 'some/path', name: 'name', @@ -875,11 +889,9 @@ export = { 'are not allowed for a Project with CodePipeline as Source'(test: Test) { const stack = new cdk.Stack(); - const project = new codebuild.Project(stack, 'MyProject', { - source: new codebuild.CodePipelineSource(), - }); + const project = new codebuild.PipelineProject(stack, 'MyProject'); - project.addSecondaryArtifact(new codebuild.S3BucketBuildArtifacts({ + project.addSecondaryArtifact(codebuild.Artifacts.s3({ bucket: new s3.Bucket(stack, 'MyBucket'), path: 'some/path', name: 'name', @@ -897,13 +909,13 @@ export = { const stack = new cdk.Stack(); const bucket = new s3.Bucket(stack, 'MyBucket'); const project = new codebuild.Project(stack, 'MyProject', { - source: new codebuild.S3BucketSource({ + source: codebuild.Source.s3({ bucket, path: 'some/path', }), }); - project.addSecondaryArtifact(new codebuild.S3BucketBuildArtifacts({ + project.addSecondaryArtifact(codebuild.Artifacts.s3({ bucket, path: 'another/path', name: 'name', @@ -928,41 +940,7 @@ export = { 'both source and artifacs are set to CodePipeline'(test: Test) { const stack = new cdk.Stack(); - new codebuild.Project(stack, 'MyProject', { - source: new codebuild.CodePipelineSource(), - artifacts: new codebuild.CodePipelineBuildArtifacts() - }); - - expect(stack).to(haveResource('AWS::CodeBuild::Project', { - "Source": { - "Type": "CODEPIPELINE" - }, - "Artifacts": { - "Type": "CODEPIPELINE" - }, - "ServiceRole": { - "Fn::GetAtt": [ - "MyProjectRole9BBE5233", - "Arn" - ] - }, - "Environment": { - "Type": "LINUX_CONTAINER", - "PrivilegedMode": false, - "Image": "aws/codebuild/standard:1.0", - "ComputeType": "BUILD_GENERAL1_SMALL" - } - })); - - test.done(); - }, - - 'if source is set to CodePipeline, and artifacts are not set, they are defaulted to CodePipeline'(test: Test) { - const stack = new cdk.Stack(); - - new codebuild.Project(stack, 'MyProject', { - source: new codebuild.CodePipelineSource() - }); + new codebuild.PipelineProject(stack, 'MyProject'); expect(stack).to(haveResource('AWS::CodeBuild::Project', { "Source": { @@ -987,31 +965,16 @@ export = { test.done(); }, - - 'fails if one of source/artifacts is set to CodePipeline and the other isn\'t'(test: Test) { - const stack = new cdk.Stack(); - - test.throws(() => new codebuild.Project(stack, 'MyProject', { - source: new codebuild.CodePipelineSource(), - artifacts: new codebuild.NoBuildArtifacts() - }), /Both source and artifacts must be set to CodePipeline/); - - test.throws(() => new codebuild.Project(stack, 'YourProject', { - source: new codebuild.CodeCommitSource({ - repository: new codecommit.Repository(stack, 'MyRepo', { repositoryName: 'boo' }) - }), - artifacts: new codebuild.CodePipelineBuildArtifacts() - }), /Both source and artifacts must be set to CodePipeline/); - - test.done(); - } - } + }, }, 'events'(test: Test) { const stack = new cdk.Stack(); const project = new codebuild.Project(stack, 'MyProject', { - source: new codebuild.CodePipelineSource() + source: codebuild.Source.s3({ + bucket: new s3.Bucket(stack, 'MyBucket'), + path: 'path', + }), }); project.onBuildFailed('OnBuildFailed', { target: { bind: () => ({ arn: 'ARN', id: 'ID' }) }}); @@ -1130,8 +1093,7 @@ export = { 'environment variables can be overridden at the project level'(test: Test) { const stack = new cdk.Stack(); - new codebuild.Project(stack, 'Project', { - source: new codebuild.CodePipelineSource(), + new codebuild.PipelineProject(stack, 'Project', { environment: { environmentVariables: { FOO: { value: '1234' }, @@ -1196,7 +1158,12 @@ export = { '.metricXxx() methods can be used to obtain Metrics for CodeBuild projects'(test: Test) { const stack = new cdk.Stack(); - const project = new codebuild.Project(stack, 'MyBuildProject', { source: new codebuild.CodePipelineSource() }); + const project = new codebuild.Project(stack, 'MyBuildProject', { + source: codebuild.Source.s3({ + bucket: new s3.Bucket(stack, 'MyBucket'), + path: 'path', + }), + }); const metricBuilds = project.metricBuilds(); test.same(metricBuilds.dimensions!.ProjectName, project.projectName); @@ -1224,7 +1191,10 @@ export = { test.throws(() => { new codebuild.Project(stack, 'MyProject', { - source: new codebuild.CodePipelineSource(), + source: codebuild.Source.s3({ + bucket: new s3.Bucket(stack, 'MyBucket'), + path: 'path', + }), environment: invalidEnvironment, }); }, /Windows images do not support the Small ComputeType/); @@ -1236,7 +1206,7 @@ export = { const stack = new cdk.Stack(); interface BadgeValidationTestCase { - source: codebuild.BuildSource, + source: codebuild.Source, shouldPassValidation: boolean } @@ -1244,13 +1214,13 @@ export = { const bucket = new s3.Bucket(stack, 'MyBucket'); const cases: BadgeValidationTestCase[] = [ - { source: new codebuild.NoSource(), shouldPassValidation: false }, - { source: new codebuild.CodePipelineSource(), shouldPassValidation: false }, - { source: new codebuild.CodeCommitSource({ repository: repo }), shouldPassValidation: false }, - { source: new codebuild.S3BucketSource({ bucket, path: 'path/to/source.zip' }), shouldPassValidation: false }, - { source: new codebuild.GitHubSource({ owner: 'awslabs', repo: 'aws-cdk' }), shouldPassValidation: true }, - { source: new codebuild.GitHubEnterpriseSource({ httpsCloneUrl: 'url' }), shouldPassValidation: true }, - { source: new codebuild.BitBucketSource({ owner: 'awslabs', repo: 'aws-cdk' }), shouldPassValidation: true } + { source: new NoSource(), shouldPassValidation: false }, + { source: new CodePipelineSource(), shouldPassValidation: false }, + { source: codebuild.Source.codeCommit({ repository: repo }), shouldPassValidation: false }, + { source: codebuild.Source.s3({ bucket, path: 'path/to/source.zip' }), shouldPassValidation: false }, + { source: codebuild.Source.gitHub({ owner: 'awslabs', repo: 'aws-cdk' }), shouldPassValidation: true }, + { source: codebuild.Source.gitHubEnterprise({ httpsCloneUrl: 'url' }), shouldPassValidation: true }, + { source: codebuild.Source.bitBucket({ owner: 'awslabs', repo: 'aws-cdk' }), shouldPassValidation: true } ]; cases.forEach(testCase => { @@ -1302,7 +1272,7 @@ export = { test.throws(() => { new codebuild.Project(stack, 'Project', { - source: new codebuild.BitBucketSource({ + source: codebuild.Source.bitBucket({ owner: 'owner', repo: 'repo', webhookFilters: [ @@ -1321,7 +1291,7 @@ export = { test.throws(() => { new codebuild.Project(stack, 'Project', { - source: new codebuild.BitBucketSource({ + source: codebuild.Source.bitBucket({ owner: 'owner', repo: 'repo', webhookFilters: [filterGroup], diff --git a/packages/@aws-cdk/aws-codebuild/test/test.project.ts b/packages/@aws-cdk/aws-codebuild/test/test.project.ts index 8f7372d58b471..6d87439a9e2e6 100644 --- a/packages/@aws-cdk/aws-codebuild/test/test.project.ts +++ b/packages/@aws-cdk/aws-codebuild/test/test.project.ts @@ -1,11 +1,8 @@ import { expect, haveResource, haveResourceLike, not } from '@aws-cdk/assert'; -import assets = require('@aws-cdk/assets'); import { Bucket } from '@aws-cdk/aws-s3'; import cdk = require('@aws-cdk/cdk'); import { Test } from 'nodeunit'; -import path = require('path'); import codebuild = require('../lib'); -import { Cache, LocalCacheMode } from '../lib/cache'; // tslint:disable:object-literal-key-quotes @@ -16,7 +13,10 @@ export = { // WHEN new codebuild.Project(stack, 'Project', { - source: new codebuild.CodePipelineSource(), + source: codebuild.Source.s3({ + bucket: new Bucket(stack, 'Bucket'), + path: 'path', + }), buildSpec: codebuild.BuildSpec.fromSourceFilename('hello.yml'), }); @@ -36,7 +36,6 @@ export = { // WHEN new codebuild.Project(stack, 'Project', { - source: new codebuild.CodePipelineSource(), buildSpec: codebuild.BuildSpec.fromObject({ phases: ['say hi'] }) }); @@ -56,7 +55,6 @@ export = { test.throws(() => { new codebuild.Project(stack, 'Project', { - source: new codebuild.NoSource(), }); }, /you need to provide a concrete buildSpec/); @@ -69,7 +67,6 @@ export = { test.throws(() => { new codebuild.Project(stack, 'Project', { - source: new codebuild.NoSource(), buildSpec: codebuild.BuildSpec.fromSourceFilename('bla.yml'), }); }, /you need to provide a concrete buildSpec/); @@ -84,7 +81,7 @@ export = { // WHEN new codebuild.Project(stack, 'Project', { - source: new codebuild.GitHubSource({ + source: codebuild.Source.gitHub({ owner: 'testowner', repo: 'testrepo', cloneDepth: 3, @@ -110,7 +107,7 @@ export = { // WHEN new codebuild.Project(stack, 'Project', { - source: new codebuild.GitHubSource({ + source: codebuild.Source.gitHub({ owner: 'testowner', repo: 'testrepo', reportBuildStatus: false, @@ -133,7 +130,7 @@ export = { // WHEN new codebuild.Project(stack, 'Project', { - source: new codebuild.GitHubSource({ + source: codebuild.Source.gitHub({ owner: 'testowner', repo: 'testrepo', webhook: true, @@ -151,55 +148,17 @@ export = { }, }, - 'construct from asset'(test: Test) { - // GIVEN - const stack = new cdk.Stack(); - - // WHEN - new codebuild.Project(stack, 'Project', { - buildScriptAsset: new assets.ZipDirectoryAsset(stack, 'Asset', { path: path.join(__dirname, 'script_bundle') }), - buildScriptAssetEntrypoint: 'build.sh', - }); - - // THEN - expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', { - Environment: { - ComputeType: "BUILD_GENERAL1_SMALL", - EnvironmentVariables: [ - { - Name: "SCRIPT_S3_BUCKET", - Type: "PLAINTEXT", - Value: { Ref: "AssetS3Bucket235698C0" } - }, - { - Name: "SCRIPT_S3_KEY", - Type: "PLAINTEXT", - Value: { - "Fn::Join": ["", [ - { "Fn::Select": [0, { "Fn::Split": ["||", { Ref: "AssetS3VersionKeyA852DDAE" }] }] }, - { "Fn::Select": [1, { "Fn::Split": ["||", { Ref: "AssetS3VersionKeyA852DDAE" }] }] } - ]] - } - } - ], - }, - Source: { - // Not testing BuildSpec, it's too big and finicky - Type: "NO_SOURCE" - } - })); - - test.done(); - }, - 'project with s3 cache bucket'(test: Test) { // GIVEN const stack = new cdk.Stack(); // WHEN new codebuild.Project(stack, 'Project', { - source: new codebuild.CodePipelineSource(), - cache: Cache.bucket(new Bucket(stack, 'Bucket'), { + source: codebuild.Source.s3({ + bucket: new Bucket(stack, 'SourceBucket'), + path: 'path', + }), + cache: codebuild.Cache.bucket(new Bucket(stack, 'Bucket'), { prefix: "cache-prefix" }) }); @@ -231,8 +190,12 @@ export = { // WHEN new codebuild.Project(stack, 'Project', { - source: new codebuild.CodePipelineSource(), - cache: Cache.local(LocalCacheMode.Custom, LocalCacheMode.DockerLayer, LocalCacheMode.Source) + source: codebuild.Source.s3({ + bucket: new Bucket(stack, 'Bucket'), + path: 'path', + }), + cache: codebuild.Cache.local(codebuild.LocalCacheMode.Custom, codebuild.LocalCacheMode.DockerLayer, + codebuild.LocalCacheMode.Source) }); // THEN @@ -256,7 +219,10 @@ export = { // WHEN new codebuild.Project(stack, 'Project', { - source: new codebuild.CodePipelineSource() + source: codebuild.Source.s3({ + bucket: new Bucket(stack, 'Bucket'), + path: 'path', + }), }); // THEN diff --git a/packages/@aws-cdk/aws-codepipeline-actions/README.md b/packages/@aws-cdk/aws-codepipeline-actions/README.md index dcabfc3deae42..22b8240bfaa19 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/README.md +++ b/packages/@aws-cdk/aws-codepipeline-actions/README.md @@ -183,17 +183,6 @@ new codepipeline.Pipeline(this, 'MyPipeline', { }); ``` -The `PipelineProject` utility class is a simple sugar around the `Project` -class, it's equivalent to: - -```ts -const project = new codebuild.Project(this, 'MyProject', { - source: new codebuild.CodePipelineSource(), - artifacts: new codebuild.CodePipelineBuildArtifacts(), - // rest of the properties from PipelineProject are passed unchanged... -} -``` - The default category of the CodeBuild Action is `Build`; if you want a `Test` Action instead, override the `type` property: diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/cloudformation/test.cloudformation-pipeline-actions.ts b/packages/@aws-cdk/aws-codepipeline-actions/test/cloudformation/test.cloudformation-pipeline-actions.ts index d0719607d51a7..e9a19f3a8216b 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/test/cloudformation/test.cloudformation-pipeline-actions.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/cloudformation/test.cloudformation-pipeline-actions.ts @@ -1,5 +1,5 @@ import { expect, haveResource, haveResourceLike } from '@aws-cdk/assert'; -import { CodePipelineBuildArtifacts, CodePipelineSource, Project } from '@aws-cdk/aws-codebuild'; +import codebuild = require('@aws-cdk/aws-codebuild'); import { Repository } from '@aws-cdk/aws-codecommit'; import codepipeline = require('@aws-cdk/aws-codepipeline'); import { Role } from '@aws-cdk/aws-iam'; @@ -37,11 +37,7 @@ export = { /** Build! */ - const buildArtifacts = new CodePipelineBuildArtifacts(); - const project = new Project(stack, 'MyBuildProject', { - source: new CodePipelineSource(), - artifacts: buildArtifacts, - }); + const project = new codebuild.PipelineProject(stack, 'MyBuildProject'); const buildOutput = new codepipeline.Artifact('OutputYo'); const buildAction = new cpactions.CodeBuildAction({ diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-code-commit-build.ts b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-code-commit-build.ts index 81b3c0a5733a1..42e64c80c0688 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-code-commit-build.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/integ.pipeline-code-commit-build.ts @@ -19,9 +19,7 @@ const sourceAction = new cpactions.CodeCommitSourceAction({ pollForSourceChanges: true, }); -const project = new codebuild.Project(stack, 'MyBuildProject', { - source: new codebuild.CodePipelineSource(), -}); +const project = new codebuild.PipelineProject(stack, 'MyBuildProject'); const buildAction = new cpactions.CodeBuildAction({ actionName: 'build', project, diff --git a/packages/@aws-cdk/aws-codepipeline-actions/test/test.pipeline.ts b/packages/@aws-cdk/aws-codepipeline-actions/test/test.pipeline.ts index 26a4a702b6432..b4534a812c748 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/test/test.pipeline.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/test.pipeline.ts @@ -33,9 +33,7 @@ export = { actions: [source], }); - const project = new codebuild.Project(stack, 'MyBuildProject', { - source: new codebuild.CodePipelineSource() - }); + const project = new codebuild.PipelineProject(stack, 'MyBuildProject'); pipeline.addStage({ stageName: 'build', actions: [ diff --git a/packages/@aws-cdk/aws-events-targets/test/codebuild/codebuild.test.ts b/packages/@aws-cdk/aws-events-targets/test/codebuild/codebuild.test.ts index adc6bade85faa..cfe94306d06d3 100644 --- a/packages/@aws-cdk/aws-events-targets/test/codebuild/codebuild.test.ts +++ b/packages/@aws-cdk/aws-events-targets/test/codebuild/codebuild.test.ts @@ -7,7 +7,7 @@ import targets = require('../../lib'); test('use codebuild project as an eventrule target', () => { // GIVEN const stack = new Stack(); - const project = new codebuild.Project(stack, 'MyProject', { source: new codebuild.CodePipelineSource() }); + const project = new codebuild.PipelineProject(stack, 'MyProject'); const rule = new events.Rule(stack, 'Rule', { scheduleExpression: 'rate(1 min)' }); // WHEN diff --git a/packages/@aws-cdk/aws-events-targets/test/codebuild/integ.project-events.ts b/packages/@aws-cdk/aws-events-targets/test/codebuild/integ.project-events.ts index e1b4f6d24ec91..a8e6f35f86dcb 100644 --- a/packages/@aws-cdk/aws-events-targets/test/codebuild/integ.project-events.ts +++ b/packages/@aws-cdk/aws-events-targets/test/codebuild/integ.project-events.ts @@ -14,7 +14,7 @@ const stack = new cdk.Stack(app, 'aws-cdk-codebuild-events'); const repo = new codecommit.Repository(stack, 'MyRepo', { repositoryName: 'aws-cdk-codebuild-events' }); const project = new codebuild.Project(stack, 'MyProject', { - source: new codebuild.CodeCommitSource({ repository: repo }), + source: codebuild.Source.codeCommit({ repository: repo }), }); const queue = new sqs.Queue(stack, 'MyQueue');