diff --git a/packages/@aws-cdk/app-delivery/test/integ.cicd.ts b/packages/@aws-cdk/app-delivery/test/integ.cicd.ts index cc137847f8f86..e0263b6c3633d 100644 --- a/packages/@aws-cdk/app-delivery/test/integ.cicd.ts +++ b/packages/@aws-cdk/app-delivery/test/integ.cicd.ts @@ -19,7 +19,7 @@ const source = new cpactions.GitHubSourceAction({ owner: 'awslabs', repo: 'aws-cdk', oauthToken: cdk.SecretValue.plainText('DummyToken'), - pollForSourceChanges: true, + trigger: cpactions.GitHubTrigger.Poll, output: sourceOutput, }); pipeline.addStage({ diff --git a/packages/@aws-cdk/aws-codepipeline-actions/README.md b/packages/@aws-cdk/aws-codepipeline-actions/README.md index 7a34c38ce24c3..a0a87107ae2a3 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/README.md +++ b/packages/@aws-cdk/aws-codepipeline-actions/README.md @@ -50,6 +50,7 @@ const sourceAction = new codepipeline_actions.GitHubSourceAction({ oauthToken: token.value, output: sourceOutput, branch: 'develop', // default: 'master' + trigger: codepipeline_actions.GitHubTrigger.Poll // default: 'WebHook', 'None' is also possible for no Source trigger }); pipeline.addStage({ name: 'Source', diff --git a/packages/@aws-cdk/aws-codepipeline-actions/lib/github/source-action.ts b/packages/@aws-cdk/aws-codepipeline-actions/lib/github/source-action.ts index 63f158484a72b..51d85c2edd80d 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/lib/github/source-action.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/lib/github/source-action.ts @@ -2,6 +2,15 @@ import codepipeline = require('@aws-cdk/aws-codepipeline'); import { SecretValue } from '@aws-cdk/cdk'; import { sourceArtifactBounds } from '../common'; +/** + * If and how the GitHub source action should be triggered + */ +export enum GitHubTrigger { + None = 'None', + Poll = 'Poll', + WebHook = 'WebHook', +} + /** * Construction properties of the {@link GitHubSourceAction GitHub source action}. */ @@ -39,12 +48,15 @@ export interface GitHubSourceActionProps extends codepipeline.CommonActionProps readonly oauthToken: SecretValue; /** - * Whether AWS CodePipeline should poll for source changes. - * If this is `false`, the Pipeline will use a webhook to detect source changes instead. + * How AWS CodePipeline should be triggered + * + * With the default value "WebHook", a webhook is created in GitHub that triggers the action + * With "Poll", CodePipeline periodically checks the source for changes + * With "None", the action is not triggered through changes in the source * - * @default false + * @default GitHubTrigger.WebHook */ - readonly pollForSourceChanges?: boolean; + readonly trigger?: GitHubTrigger; } /** @@ -66,7 +78,7 @@ export class GitHubSourceAction extends codepipeline.Action { Repo: props.repo, Branch: props.branch || "master", OAuthToken: props.oauthToken.toString(), - PollForSourceChanges: props.pollForSourceChanges || false, + PollForSourceChanges: props.trigger === GitHubTrigger.Poll, }, }); @@ -74,7 +86,7 @@ export class GitHubSourceAction extends codepipeline.Action { } protected bind(info: codepipeline.ActionBind): void { - if (!this.props.pollForSourceChanges) { + if (!this.props.trigger || this.props.trigger === GitHubTrigger.WebHook) { new codepipeline.CfnWebhook(info.scope, 'WebhookResource', { authentication: 'GITHUB_HMAC', authenticationConfiguration: { 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 2055c76e01e34..00de8197a20cb 100644 --- a/packages/@aws-cdk/aws-codepipeline-actions/test/test.pipeline.ts +++ b/packages/@aws-cdk/aws-codepipeline-actions/test/test.pipeline.ts @@ -1,4 +1,4 @@ -import { expect, haveResource, haveResourceLike, SynthUtils } from '@aws-cdk/assert'; +import { expect, haveResource, haveResourceLike, not, SynthUtils } from '@aws-cdk/assert'; import codebuild = require('@aws-cdk/aws-codebuild'); import codecommit = require('@aws-cdk/aws-codecommit'); import codepipeline = require('@aws-cdk/aws-codepipeline'); @@ -67,6 +67,124 @@ export = { test.done(); }, + 'pipeline with GitHub source with poll trigger'(test: Test) { + const stack = new Stack(); + + const secret = new CfnParameter(stack, 'GitHubToken', { type: 'String', default: 'my-token' }); + + const p = new codepipeline.Pipeline(stack, 'P'); + + p.addStage({ + name: 'Source', + actions: [ + new cpactions.GitHubSourceAction({ + actionName: 'GH', + runOrder: 8, + output: new codepipeline.Artifact('A'), + branch: 'branch', + oauthToken: SecretValue.plainText(secret.stringValue), + owner: 'foo', + repo: 'bar', + trigger: cpactions.GitHubTrigger.Poll + }), + ], + }); + + p.addStage({ + name: 'Two', + actions: [ + new cpactions.ManualApprovalAction({ actionName: 'Boo' }), + ], + }); + + expect(stack).to(not(haveResourceLike('AWS::CodePipeline::Webhook'))); + + expect(stack).to(haveResourceLike('AWS::CodePipeline::Pipeline', { + "Stages": [ + { + "Actions": [ + { + "Configuration": { + "PollForSourceChanges": true + }, + "Name": "GH" + } + ], + "Name": "Source" + }, + { + "Actions": [ + { + "Name": "Boo", + } + ], + "Name": "Two" + } + ] + })); + + test.done(); + }, + + 'pipeline with GitHub source without triggers'(test: Test) { + const stack = new Stack(); + + const secret = new CfnParameter(stack, 'GitHubToken', { type: 'String', default: 'my-token' }); + + const p = new codepipeline.Pipeline(stack, 'P'); + + p.addStage({ + name: 'Source', + actions: [ + new cpactions.GitHubSourceAction({ + actionName: 'GH', + runOrder: 8, + output: new codepipeline.Artifact('A'), + branch: 'branch', + oauthToken: SecretValue.plainText(secret.stringValue), + owner: 'foo', + repo: 'bar', + trigger: cpactions.GitHubTrigger.None + }), + ], + }); + + p.addStage({ + name: 'Two', + actions: [ + new cpactions.ManualApprovalAction({ actionName: 'Boo' }), + ], + }); + + expect(stack).to(not(haveResourceLike('AWS::CodePipeline::Webhook'))); + + expect(stack).to(haveResourceLike('AWS::CodePipeline::Pipeline', { + "Stages": [ + { + "Actions": [ + { + "Configuration": { + "PollForSourceChanges": false + }, + "Name": "GH" + } + ], + "Name": "Source" + }, + { + "Actions": [ + { + "Name": "Boo", + } + ], + "Name": "Two" + } + ] + })); + + test.done(); + }, + 'github action uses ThirdParty owner'(test: Test) { const stack = new Stack(); @@ -96,6 +214,8 @@ export = { ], }); + expect(stack).to(haveResourceLike('AWS::CodePipeline::Webhook')); + expect(stack).to(haveResourceLike('AWS::CodePipeline::Pipeline', { "ArtifactStore": { "Location": {