Skip to content

Commit

Permalink
feat(aws-codecommit): use CloudWatch Events instead of polling by def…
Browse files Browse the repository at this point in the history
…ault in the CodePipeline Action.
  • Loading branch information
skinny85 committed Oct 29, 2018
1 parent 8f4c2ab commit 9232591
Show file tree
Hide file tree
Showing 11 changed files with 215 additions and 5 deletions.
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-cloudformation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"license": "Apache-2.0",
"devDependencies": {
"@aws-cdk/assert": "^0.14.1",
"@aws-cdk/aws-events": "^0.14.1",
"@types/lodash": "^4.14.116",
"cdk-build-tools": "^0.14.1",
"cdk-integ-tools": "^0.14.1",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import cpapi = require('@aws-cdk/aws-codepipeline-api');
import events = require('@aws-cdk/aws-events');
import iam = require('@aws-cdk/aws-iam');
import cdk = require('@aws-cdk/cdk');
import _ = require('lodash');
Expand Down Expand Up @@ -295,6 +296,14 @@ class StageDouble implements cpapi.IStage, cpapi.IInternalStage {
throw new Error('Unsupported');
}

public get pipelineUniqueId(): string {
throw new Error('Unsupported');
}

public get pipelineAsEventTarget(): events.IEventRuleTarget {
throw new Error('Unsupported');
}

public _attachAction(action: cpapi.Action) {
this.actions.push(action);
}
Expand Down
12 changes: 8 additions & 4 deletions packages/@aws-cdk/aws-codecommit/lib/pipeline-action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ export interface CommonPipelineSourceActionProps extends codepipeline.CommonActi
*/
branch?: string;

// TODO: use CloudWatch events instead
/**
* Whether or not AWS CodePipeline should poll for source changes.
* Whether AWS CodePipeline should poll for source changes.
* If this is `false`, the Pipeline will use CloudWatch Events to detect source changes instead.
*
* @default true
* @default false
*/
pollForSourceChanges?: boolean;
}
Expand Down Expand Up @@ -54,11 +54,15 @@ export class PipelineSourceAction extends codepipeline.SourceAction {
configuration: {
RepositoryName: props.repository.repositoryName,
BranchName: props.branch || 'master',
PollForSourceChanges: props.pollForSourceChanges !== undefined ? props.pollForSourceChanges : true
PollForSourceChanges: props.pollForSourceChanges || false,
},
outputArtifactName: props.outputArtifactName
});

if (!props.pollForSourceChanges) {
props.repository.onCommit(props.stage.pipelineUniqueId + 'EventRule', props.stage.pipelineAsEventTarget, props.branch || 'master');
}

// https://docs.aws.amazon.com/codecommit/latest/userguide/auth-and-access-control-permissions-reference.html#aa-acp
const actions = [
'codecommit:GetBranch',
Expand Down
10 changes: 10 additions & 0 deletions packages/@aws-cdk/aws-codepipeline-api/lib/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,21 @@ export interface IStage {
*/
readonly pipelineArn: string;

/**
* The unique ID of the Pipeline Construct.
*/
readonly pipelineUniqueId: string;

/**
* The service Role of the Pipeline.
*/
readonly pipelineRole: iam.Role;

/**
* Allows accessing the Pipeline as the Target for CloudWatch Events.
*/
readonly pipelineAsEventTarget: events.IEventRuleTarget;

/**
* The API of Stage used internally by the CodePipeline Construct.
* You should never need to call any of the methods inside of it yourself.
Expand Down
8 changes: 8 additions & 0 deletions packages/@aws-cdk/aws-codepipeline/lib/stage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,18 @@ export class Stage extends cdk.Construct implements actions.IStage, actions.IInt
return this.pipeline.pipelineArn;
}

public get pipelineUniqueId(): string {
return this.pipeline.uniqueId;
}

public get pipelineRole(): iam.Role {
return this.pipeline.role;
}

public get pipelineAsEventTarget(): events.IEventRuleTarget {
return this.pipeline;
}

// can't make this method private like Pipeline#_attachStage,
// as it comes from the IStage interface
public _attachAction(action: actions.Action): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const source = new codecommit.PipelineSourceAction(stack, 'Source', {
stage: sourceStage,
repository: repo,
outputArtifactName: 'SourceArtifact',
pollForSourceChanges: true,
});

// Deployment stage: create and deploy changeset with manual approval
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ new codecommit.PipelineSourceAction(stack, 'source', {
stage: sourceStage,
outputArtifactName: 'SourceArtifact',
repository,
pollForSourceChanges: true,
});

const project = new codebuild.Project(stack, 'MyBuildProject', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,70 @@
"Triggers": []
}
},
"MyRepoawscdkcodepipelinecodecommitPipelineF780CA18EventRuleC207C969": {
"Type": "AWS::Events::Rule",
"Properties": {
"EventPattern": {
"source": [
"aws.codecommit"
],
"resources": [
{
"Fn::GetAtt": [
"MyRepoF4F48043",
"Arn"
]
}
],
"detail-type": [
"CodeCommit Repository State Change"
],
"detail": {
"event": [
"referenceUpdated"
],
"referenceName": [
"master"
]
}
},
"State": "ENABLED",
"Targets": [
{
"Arn": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":codepipeline:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":",
{
"Ref": "PipelineC660917D"
}
]
]
},
"Id": "Pipeline",
"RoleArn": {
"Fn::GetAtt": [
"PipelineEventsRole46BEEA7C",
"Arn"
]
}
}
]
}
},
"PipelineArtifactsBucket22248F97": {
"Type": "AWS::S3::Bucket",
"DeletionPolicy": "Retain"
Expand Down Expand Up @@ -126,7 +190,7 @@
]
},
"BranchName": "master",
"PollForSourceChanges": true
"PollForSourceChanges": false
},
"InputArtifacts": [],
"Name": "source",
Expand Down Expand Up @@ -163,6 +227,66 @@
"PipelineRoleD68726F7",
"PipelineRoleDefaultPolicyC7A05455"
]
},
"PipelineEventsRole46BEEA7C": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "events.amazonaws.com"
}
}
],
"Version": "2012-10-17"
}
}
},
"PipelineEventsRoleDefaultPolicyFF4FCCE0": {
"Type": "AWS::IAM::Policy",
"Properties": {
"PolicyDocument": {
"Statement": [
{
"Action": "codepipeline:StartPipelineExecution",
"Effect": "Allow",
"Resource": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":codepipeline:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":",
{
"Ref": "PipelineC660917D"
}
]
]
}
}
],
"Version": "2012-10-17"
},
"PolicyName": "PipelineEventsRoleDefaultPolicyFF4FCCE0",
"Roles": [
{
"Ref": "PipelineEventsRole46BEEA7C"
}
]
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const sourceAction = new codecommit.PipelineSourceAction(pipeline, 'CodeCommitSo
stage: sourceStage,
outputArtifactName: 'Source',
repository,
pollForSourceChanges: true,
});
new codebuild.PipelineBuildAction(stack, 'CodeBuildAction', {
stage: buildStage,
Expand Down
50 changes: 50 additions & 0 deletions packages/@aws-cdk/aws-codepipeline/test/test.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,56 @@ export = {

test.done();
},

'CodeCommit Action': {
'does not poll for source changes by default'(test: Test) {
const stack = new cdk.Stack();
const pipeline = new codepipeline.Pipeline(stack, 'pipeline');
const stage = pipeline.addStage('Source');
const repository = new codecommit.Repository(stack, 'Repsotiory', { repositoryName: 'Repository' });
repository.addToPipeline(stage, 'CodeCommit');

expect(stack, true).to(haveResource('AWS::CodePipeline::Pipeline', {
"Stages": [
{
"Actions": [
{
"Configuration": {
"PollForSourceChanges": false,
},
},
],
},
],
}));

test.done();
},

'does not poll for source changes when explicitly set to false'(test: Test) {
const stack = new cdk.Stack();
const pipeline = new codepipeline.Pipeline(stack, 'pipeline');
const stage = pipeline.addStage('Source');
const repository = new codecommit.Repository(stack, 'Repsotiory', { repositoryName: 'Repository' });
repository.addToPipeline(stage, 'CodeCommit', { pollForSourceChanges: false });

expect(stack, true).to(haveResource('AWS::CodePipeline::Pipeline', {
"Stages": [
{
"Actions": [
{
"Configuration": {
"PollForSourceChanges": false,
},
},
],
},
],
}));

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

function boundsValidationResult(numberOfArtifacts: number, min: number, max: number): string[] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export = {
stage: sourceStage,
outputArtifactName: 'SourceArtifact',
repository: repo,
pollForSourceChanges: true,
});

/** Build! */
Expand Down

0 comments on commit 9232591

Please sign in to comment.