Skip to content

Commit

Permalink
implement requested changes
Browse files Browse the repository at this point in the history
  • Loading branch information
SanderKnape committed May 14, 2019
1 parent 5c65d48 commit f2fc1be
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 70 deletions.
14 changes: 7 additions & 7 deletions packages/@aws-cdk/aws-codebuild/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,24 +118,24 @@ You can save time when your project builds by using a cache. A cache can store r
With S3 caching, the cache is stored in an S3 bucket which is available from multiple hosts.

```typescript
new codebuild.Project(stack, 'Project', {
new codebuild.Project(this, 'Project', {
source: new codebuild.CodePipelineSource(),
cache: Cache.bucket(new Bucket(stack, 'Bucket'))
cache: Cache.bucket(new Bucket(this, 'Bucket'))
});
```

### Local Caching

With local caching, the cache is stored on the codebuild instance itself. CodeBuild cannot guarantee a reuse of instance. For example, when a build starts and caches files locally, if two subsequent builds start at the same time afterwards only one of those builds would get the cache. Three different cache modes are supported:

* `LocalCacheMode.SourceCache` caches Git metadata for primary and secondary sources.
* `LocalCacheMode.DockerLayerCache` caches existing Docker layers.
* `LocalCacheMode.CustomCache` caches directories you specify in the buildspec file.
* `LocalCacheMode.Source` caches Git metadata for primary and secondary sources.
* `LocalCacheMode.DockerLayer` caches existing Docker layers.
* `LocalCacheMode.Custom` caches directories you specify in the buildspec file.

```typescript
new codebuild.Project(stack, 'Project', {
new codebuild.Project(this, 'Project', {
source: new codebuild.CodePipelineSource(),
cache: Cache.local(LocalCacheMode.DockerLayerCache)
cache: Cache.local(LocalCacheMode.DockerLayer)
});
```

Expand Down
114 changes: 62 additions & 52 deletions packages/@aws-cdk/aws-codebuild/lib/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,71 +3,81 @@ import { Aws, Fn } from "@aws-cdk/cdk";
import { CfnProject } from "./codebuild.generated";
import { IProject } from "./project";

export interface BucketCacheOptions {
/**
* The prefix to use to store the cache in the bucket
*/
readonly prefix?: string;
}

/**
* Local cache modes to enable for the CodeBuild Project
*/
export enum LocalCacheMode {
SourceCache = 'LOCAL_SOURCE_CACHE',
DockerLayerCache = 'LOCAL_DOCKER_LAYER_CACHE',
CustomCache = 'LOCAL_CUSTOM_CACHE',
}
/**
* Caches Git metadata for primary and secondary sources
*/
Source = 'LOCAL_SOURCE_CACHE',

/**
* If and what strategy to use for build caching
*/
export enum CacheType {
None = 'NO_CACHE',
S3 = 'S3',
Local = 'LOCAL',
/**
* Caches existing Docker layers
*/
DockerLayer = 'LOCAL_DOCKER_LAYER_CACHE',

/**
* Caches directories you specify in the buildspec file
*/
Custom = 'LOCAL_CUSTOM_CACHE',
}

/**
* Cache options for CodeBuild Project
* Cache options for CodeBuild Project.
* A cache can store reusable pieces of your build environment and use them across multiple builds.
* @see https://docs.aws.amazon.com/codebuild/latest/userguide/build-caching.html
*/
export abstract class Cache {
public static none(): Cache {
return { _toCloudFormation: () => undefined, _bind: () => { return; } };
}
public static none(): Cache {
return { _toCloudFormation: () => undefined, _bind: () => { return; } };
}

/**
* Create a local caching strategy
* @param modes the mode(s) to enable for local caching
*/
public static local(...modes: LocalCacheMode[]): Cache {
return {
_toCloudFormation: () => ({
type: CacheType.Local,
modes
}),
_bind: () => {
return;
}
};
}
/**
* Create a local caching strategy.
* @param modes the mode(s) to enable for local caching
*/
public static local(...modes: LocalCacheMode[]): Cache {
return {
_toCloudFormation: () => ({
type: 'LOCAL',
modes
}),
_bind: () => { return; }
};
}

/**
* Create an S3 caching strategy
* @param bucket the S3 bucket to use for caching
* @param prefix the optional prefix to use to store the cache in the bucket
*/
public static bucket(bucket: IBucket, prefix?: string): Cache {
return {
_toCloudFormation: () => ({
type: CacheType.S3,
location: Fn.join('/', [bucket.bucketName, prefix || Aws.noValue])
}),
_bind: (project) => {
if (project.role) {
bucket.grantReadWrite(project.role);
}
}
};
}
/**
* Create an S3 caching strategy.
* @param bucket the S3 bucket to use for caching
* @param options additional options to pass to the S3 caching
*/
public static bucket(bucket: IBucket, options?: BucketCacheOptions): Cache {
return {
_toCloudFormation: () => ({
type: 'S3',
location: Fn.join('/', [bucket.bucketName, options && options.prefix || Aws.noValue])
}),
_bind: (project) => {
bucket.grantReadWrite(project);
}
};
}

/** @internal */
public abstract _toCloudFormation(): CfnProject.ProjectCacheProperty | undefined;
/**
* @internal
*/
public abstract _toCloudFormation(): CfnProject.ProjectCacheProperty | undefined;

/** @internal */
public abstract _bind(project: IProject): void;
/**
* @internal
*/
public abstract _bind(project: IProject): void;
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-codebuild/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './pipeline-project';
export * from './project';
export * from './source';
export * from './artifacts';
export * from './cache';

// AWS::CodeBuild CloudFormation Resources:
export * from './codebuild.generated';
9 changes: 5 additions & 4 deletions packages/@aws-cdk/aws-codebuild/lib/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ import ecr = require('@aws-cdk/aws-ecr');
import events = require('@aws-cdk/aws-events');
import iam = require('@aws-cdk/aws-iam');
import kms = require('@aws-cdk/aws-kms');
import s3 = require('@aws-cdk/aws-s3');
import { Aws, CfnOutput, Construct, Fn, IResource, Resource, Token } from '@aws-cdk/cdk';
import { Aws, CfnOutput, Construct, IResource, Resource, Token } from '@aws-cdk/cdk';
import { BuildArtifacts, CodePipelineBuildArtifacts, NoBuildArtifacts } from './artifacts';
import { Cache } from './cache';
import { CfnProject } from './codebuild.generated';
import { BuildSource, NoSource, SourceType } from './source';
import { Cache } from './cache';

const CODEPIPELINE_TYPE = 'CODEPIPELINE';
const S3_BUCKET_ENV = 'SCRIPT_S3_BUCKET';
Expand Down Expand Up @@ -629,6 +628,8 @@ export class Project extends ProjectBase {
props.cache._bind(this);
}

const cache = props.cache || Cache.none();

// Inject download commands for asset if requested
const environmentVariables = props.environmentVariables || {};
const buildSpec = props.buildSpec || {};
Expand Down Expand Up @@ -686,7 +687,7 @@ export class Project extends ProjectBase {
environment: this.renderEnvironment(props.environment, environmentVariables),
encryptionKey: props.encryptionKey && props.encryptionKey.keyArn,
badgeEnabled: props.badge,
cache: props.cache && props.cache._toCloudFormation() || Cache.none()._toCloudFormation(),
cache: cache._toCloudFormation(),
name: props.projectName,
timeoutInMinutes: props.timeout,
secondarySources: new Token(() => this.renderSecondarySources()),
Expand Down
3 changes: 2 additions & 1 deletion packages/@aws-cdk/aws-codebuild/test/integ.caching.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import s3 = require('@aws-cdk/aws-s3');
import cdk = require('@aws-cdk/cdk');
import codebuild = require('../lib');
import { Cache } from '../lib/cache';

const app = new cdk.App();

Expand All @@ -12,7 +13,7 @@ const bucket = new s3.Bucket(stack, 'CacheBucket', {
});

new codebuild.Project(stack, 'MyProject', {
cacheBucket: bucket,
cache: Cache.bucket(bucket),
buildSpec: {
build: {
commands: ['echo Hello']
Expand Down
42 changes: 36 additions & 6 deletions packages/@aws-cdk/aws-codebuild/test/test.project.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { expect, haveResource, haveResourceLike } from '@aws-cdk/assert';
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 codebuild = require('../lib');
import { ProjectCacheModes } from '../lib';
import { Cache, LocalCacheMode } from '../lib/cache';

// tslint:disable:object-literal-key-quotes
Expand Down Expand Up @@ -172,14 +171,27 @@ export = {
// WHEN
new codebuild.Project(stack, 'Project', {
source: new codebuild.CodePipelineSource(),
cache: Cache.bucket(new Bucket(stack, 'Bucket'))
cache: Cache.bucket(new Bucket(stack, 'Bucket'), {
prefix: "cache-prefix"
})
});

// THEN
expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', {
Cache: {
Type: "S3"
}
Type: "S3",
Location: {
"Fn::Join": [
"/",
[
{
"Ref": "Bucket83908E77"
},
"cache-prefix"
]
]
}
},
}));

test.done();
Expand All @@ -192,12 +204,13 @@ export = {
// WHEN
new codebuild.Project(stack, 'Project', {
source: new codebuild.CodePipelineSource(),
cache: Cache.local(LocalCacheMode.CustomCache, LocalCacheMode.DockerLayerCache, LocalCacheMode.SourceCache)
cache: Cache.local(LocalCacheMode.Custom, LocalCacheMode.DockerLayer, LocalCacheMode.Source)
});

// THEN
expect(stack).to(haveResourceLike('AWS::CodeBuild::Project', {
Cache: {
Type: "LOCAL",
Modes: [
"LOCAL_CUSTOM_CACHE",
"LOCAL_DOCKER_LAYER_CACHE",
Expand All @@ -208,4 +221,21 @@ export = {

test.done();
},

'project by default has no cache modes'(test: Test) {
// GIVEN
const stack = new cdk.Stack();

// WHEN
new codebuild.Project(stack, 'Project', {
source: new codebuild.CodePipelineSource()
});

// THEN
expect(stack).to(not(haveResourceLike('AWS::CodeBuild::Project', {
Cache: {}
})));

test.done();
},
};

0 comments on commit f2fc1be

Please sign in to comment.