From bba36024de3ee0a625bb8c218aacd689738f0cb2 Mon Sep 17 00:00:00 2001 From: Adam Ruka Date: Tue, 9 Oct 2018 09:50:38 -0700 Subject: [PATCH] feat(aws-codepipeline): allow specifying the runOrder property when creating Actions. (#776) Also create a new addToPipeline method on LambdaRef, which was missed when doing these for Code* services. --- .../lib/pipeline-actions.ts | 4 +++- .../aws-codebuild/lib/pipeline-actions.ts | 6 +++-- .../aws-codecommit/lib/pipeline-action.ts | 6 +++-- .../aws-codedeploy/lib/pipeline-action.ts | 10 ++++---- .../aws-codepipeline-api/lib/action.ts | 20 +++++++++++++--- .../aws-codepipeline-api/lib/build-action.ts | 5 ++-- .../aws-codepipeline-api/lib/deploy-action.ts | 5 ++-- .../aws-codepipeline-api/lib/source-action.ts | 5 ++-- .../lib/github-source-action.ts | 4 +++- .../lib/manual-approval-action.ts | 7 +++--- .../test/integ.lambda-pipeline.ts | 5 +--- .../aws-codepipeline/test/test.pipeline.ts | 3 ++- packages/@aws-cdk/aws-lambda/README.md | 18 +++++++-------- .../@aws-cdk/aws-lambda/lib/lambda-ref.ts | 19 +++++++++++++++ .../aws-lambda/lib/pipeline-action.ts | 23 +++++++++++++------ .../@aws-cdk/aws-s3/lib/pipeline-action.ts | 10 ++++---- 16 files changed, 103 insertions(+), 47 deletions(-) diff --git a/packages/@aws-cdk/aws-cloudformation/lib/pipeline-actions.ts b/packages/@aws-cdk/aws-cloudformation/lib/pipeline-actions.ts index 2ed7ccbd5d13a..fd0e445debf37 100644 --- a/packages/@aws-cdk/aws-cloudformation/lib/pipeline-actions.ts +++ b/packages/@aws-cdk/aws-cloudformation/lib/pipeline-actions.ts @@ -5,7 +5,8 @@ import cdk = require('@aws-cdk/cdk'); /** * Properties common to all CloudFormation actions */ -export interface PipelineCloudFormationActionProps extends codepipeline.CommonActionProps { +export interface PipelineCloudFormationActionProps extends codepipeline.CommonActionProps, + codepipeline.CommonActionConstructProps { /** * The name of the stack to apply this action to */ @@ -48,6 +49,7 @@ export abstract class PipelineCloudFormationAction extends codepipeline.DeployAc constructor(parent: cdk.Construct, id: string, props: PipelineCloudFormationActionProps, configuration?: any) { super(parent, id, { stage: props.stage, + runOrder: props.runOrder, artifactBounds: { minInputs: 0, maxInputs: 10, diff --git a/packages/@aws-cdk/aws-codebuild/lib/pipeline-actions.ts b/packages/@aws-cdk/aws-codebuild/lib/pipeline-actions.ts index 083132babbcf2..8cbe6e463a661 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/pipeline-actions.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/pipeline-actions.ts @@ -8,7 +8,7 @@ import { ProjectRef } from './project'; * either directly, through its constructor, * or through {@link ProjectRef#addBuildToPipeline}. */ -export interface CommonPipelineBuildActionProps { +export interface CommonPipelineBuildActionProps extends codepipeline.CommonActionProps { /** * The source to use as input for this build */ @@ -23,7 +23,8 @@ export interface CommonPipelineBuildActionProps { /** * Construction properties of the {@link PipelineBuildAction CodeBuild build CodePipeline Action}. */ -export interface PipelineBuildActionProps extends CommonPipelineBuildActionProps, codepipeline.CommonActionProps { +export interface PipelineBuildActionProps extends CommonPipelineBuildActionProps, + codepipeline.CommonActionConstructProps { /** * The build project */ @@ -40,6 +41,7 @@ export class PipelineBuildAction extends codepipeline.BuildAction { super(parent, name, { stage: props.stage, + runOrder: props.runOrder, provider: 'CodeBuild', inputArtifact: props.inputArtifact, artifactName: props.artifactName, diff --git a/packages/@aws-cdk/aws-codecommit/lib/pipeline-action.ts b/packages/@aws-cdk/aws-codecommit/lib/pipeline-action.ts index e41dbdd6d51bc..017c649bbab87 100644 --- a/packages/@aws-cdk/aws-codecommit/lib/pipeline-action.ts +++ b/packages/@aws-cdk/aws-codecommit/lib/pipeline-action.ts @@ -8,7 +8,7 @@ import { RepositoryRef } from './repository'; * either directly, through its constructor, * or through {@link RepositoryRef#addToPipeline}. */ -export interface CommonPipelineSourceActionProps { +export interface CommonPipelineSourceActionProps extends codepipeline.CommonActionProps { /** * The name of the source's output artifact. * Output artifacts are used by CodePipeline as inputs into other actions. @@ -32,7 +32,8 @@ export interface CommonPipelineSourceActionProps { /** * Construction properties of the {@link PipelineSourceAction CodeCommit source CodePipeline Action}. */ -export interface PipelineSourceActionProps extends CommonPipelineSourceActionProps, codepipeline.CommonActionProps { +export interface PipelineSourceActionProps extends CommonPipelineSourceActionProps, + codepipeline.CommonActionConstructProps { /** * The CodeCommit repository. */ @@ -46,6 +47,7 @@ export class PipelineSourceAction extends codepipeline.SourceAction { constructor(parent: cdk.Construct, name: string, props: PipelineSourceActionProps) { super(parent, name, { stage: props.stage, + runOrder: props.runOrder, provider: 'CodeCommit', configuration: { RepositoryName: props.repository.repositoryName, diff --git a/packages/@aws-cdk/aws-codedeploy/lib/pipeline-action.ts b/packages/@aws-cdk/aws-codedeploy/lib/pipeline-action.ts index 0f79eedc7cbf6..3bf08af45f42c 100644 --- a/packages/@aws-cdk/aws-codedeploy/lib/pipeline-action.ts +++ b/packages/@aws-cdk/aws-codedeploy/lib/pipeline-action.ts @@ -1,11 +1,12 @@ -import actions = require('@aws-cdk/aws-codepipeline-api'); +import codepipeline = require('@aws-cdk/aws-codepipeline-api'); import iam = require('@aws-cdk/aws-iam'); import cdk = require('@aws-cdk/cdk'); /** * Construction properties of the {@link PipelineDeployAction CodeDeploy deploy CodePipeline Action}. */ -export interface PipelineDeployActionProps extends actions.CommonActionProps { +export interface PipelineDeployActionProps extends codepipeline.CommonActionProps, + codepipeline.CommonActionConstructProps { /** * The name of the CodeDeploy application to deploy to. * @@ -25,13 +26,14 @@ export interface PipelineDeployActionProps extends actions.CommonActionProps { /** * The source to use as input for deployment. */ - inputArtifact: actions.Artifact; + inputArtifact: codepipeline.Artifact; } -export class PipelineDeployAction extends actions.DeployAction { +export class PipelineDeployAction extends codepipeline.DeployAction { constructor(parent: cdk.Construct, id: string, props: PipelineDeployActionProps) { super(parent, id, { stage: props.stage, + runOrder: props.runOrder, artifactBounds: { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 0 }, provider: 'CodeDeploy', inputArtifact: props.inputArtifact, diff --git a/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts b/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts index 6430ad95c6ba4..85bd766a6d9a0 100644 --- a/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts +++ b/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts @@ -77,6 +77,20 @@ export interface IStage { * Common properties shared by all Actions. */ export interface CommonActionProps { + /** + * The runOrder property for this Action. + * RunOrder determines the relative order in which multiple Actions in the same Stage execute. + * + * @default 1 + * @see https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html + */ + runOrder?: number; +} + +/** + * Common properties shared by all Action Constructs. + */ +export interface CommonActionConstructProps { /** * The Pipeline Stage to add this Action to. */ @@ -86,7 +100,7 @@ export interface CommonActionProps { /** * Construction properties of the low-level {@link Action Action class}. */ -export interface ActionProps extends CommonActionProps { +export interface ActionProps extends CommonActionProps, CommonActionConstructProps { category: ActionCategory; provider: string; artifactBounds: ActionArtifactBounds; @@ -127,7 +141,7 @@ export abstract class Action extends cdk.Construct { * * https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#action-requirements */ - public runOrder: number; + public readonly runOrder: number; public readonly owner: string; public readonly version: string; @@ -148,7 +162,7 @@ export abstract class Action extends cdk.Construct { this.provider = props.provider; this.configuration = props.configuration; this.artifactBounds = props.artifactBounds; - this.runOrder = 1; + this.runOrder = props.runOrder === undefined ? 1 : props.runOrder; this.stage = props.stage; this.stage._attachAction(this); diff --git a/packages/@aws-cdk/aws-codepipeline-api/lib/build-action.ts b/packages/@aws-cdk/aws-codepipeline-api/lib/build-action.ts index c124234ae38ce..8184ffa39f646 100644 --- a/packages/@aws-cdk/aws-codepipeline-api/lib/build-action.ts +++ b/packages/@aws-cdk/aws-codepipeline-api/lib/build-action.ts @@ -1,11 +1,11 @@ import cdk = require("@aws-cdk/cdk"); -import { Action, ActionCategory, CommonActionProps } from "./action"; +import { Action, ActionCategory, CommonActionConstructProps, CommonActionProps } from "./action"; import { Artifact } from "./artifact"; /** * Construction properties of the low level {@link BuildAction build action}. */ -export interface BuildActionProps extends CommonActionProps { +export interface BuildActionProps extends CommonActionProps, CommonActionConstructProps { /** * The source to use as input for this build. */ @@ -41,6 +41,7 @@ export abstract class BuildAction extends Action { constructor(parent: cdk.Construct, name: string, props: BuildActionProps) { super(parent, name, { stage: props.stage, + runOrder: props.runOrder, artifactBounds: { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 1 }, category: ActionCategory.Build, provider: props.provider, diff --git a/packages/@aws-cdk/aws-codepipeline-api/lib/deploy-action.ts b/packages/@aws-cdk/aws-codepipeline-api/lib/deploy-action.ts index 65d995018b1c7..81a352157e031 100644 --- a/packages/@aws-cdk/aws-codepipeline-api/lib/deploy-action.ts +++ b/packages/@aws-cdk/aws-codepipeline-api/lib/deploy-action.ts @@ -1,8 +1,8 @@ import cdk = require('@aws-cdk/cdk'); -import { Action, ActionArtifactBounds, ActionCategory, CommonActionProps } from "./action"; +import { Action, ActionArtifactBounds, ActionCategory, CommonActionConstructProps, CommonActionProps } from "./action"; import { Artifact } from './artifact'; -export interface DeployActionProps extends CommonActionProps { +export interface DeployActionProps extends CommonActionProps, CommonActionConstructProps { provider: string; artifactBounds: ActionArtifactBounds; @@ -16,6 +16,7 @@ export abstract class DeployAction extends Action { constructor(parent: cdk.Construct, name: string, props: DeployActionProps) { super(parent, name, { stage: props.stage, + runOrder: props.runOrder, category: ActionCategory.Deploy, provider: props.provider, artifactBounds: props.artifactBounds, diff --git a/packages/@aws-cdk/aws-codepipeline-api/lib/source-action.ts b/packages/@aws-cdk/aws-codepipeline-api/lib/source-action.ts index a3f81d1f68519..188df78d37ec7 100644 --- a/packages/@aws-cdk/aws-codepipeline-api/lib/source-action.ts +++ b/packages/@aws-cdk/aws-codepipeline-api/lib/source-action.ts @@ -1,11 +1,11 @@ import cdk = require("@aws-cdk/cdk"); -import { Action, ActionCategory, CommonActionProps } from "./action"; +import { Action, ActionCategory, CommonActionConstructProps, CommonActionProps } from "./action"; import { Artifact } from "./artifact"; /** * Construction properties of the low-level {@link SourceAction source Action}. */ -export interface SourceActionProps extends CommonActionProps { +export interface SourceActionProps extends CommonActionProps, CommonActionConstructProps { /** * The source action owner (could be "AWS", "ThirdParty" or "Custom"). * @@ -53,6 +53,7 @@ export abstract class SourceAction extends Action { constructor(parent: cdk.Construct, name: string, props: SourceActionProps) { super(parent, name, { stage: props.stage, + runOrder: props.runOrder, category: ActionCategory.Source, owner: props.owner, provider: props.provider, diff --git a/packages/@aws-cdk/aws-codepipeline/lib/github-source-action.ts b/packages/@aws-cdk/aws-codepipeline/lib/github-source-action.ts index c94a8992889b4..d73b7168f9bea 100644 --- a/packages/@aws-cdk/aws-codepipeline/lib/github-source-action.ts +++ b/packages/@aws-cdk/aws-codepipeline/lib/github-source-action.ts @@ -4,7 +4,8 @@ import cdk = require('@aws-cdk/cdk'); /** * Construction properties of the {@link GitHubSourceAction GitHub source action}. */ -export interface GitHubSourceActionProps extends actions.CommonActionProps { +export interface GitHubSourceActionProps extends actions.CommonActionProps, + actions.CommonActionConstructProps { /** * The name of the source's output artifact. Output artifacts are used by CodePipeline as * inputs into other actions. @@ -55,6 +56,7 @@ export class GitHubSourceAction extends actions.SourceAction { constructor(parent: cdk.Construct, name: string, props: GitHubSourceActionProps) { super(parent, name, { stage: props.stage, + runOrder: props.runOrder, owner: 'ThirdParty', provider: 'GitHub', configuration: { diff --git a/packages/@aws-cdk/aws-codepipeline/lib/manual-approval-action.ts b/packages/@aws-cdk/aws-codepipeline/lib/manual-approval-action.ts index df4d0d7318c9b..60031f1de5c59 100644 --- a/packages/@aws-cdk/aws-codepipeline/lib/manual-approval-action.ts +++ b/packages/@aws-cdk/aws-codepipeline/lib/manual-approval-action.ts @@ -2,7 +2,8 @@ import actions = require('@aws-cdk/aws-codepipeline-api'); import cdk = require('@aws-cdk/cdk'); // tslint:disable-next-line:no-empty-interface -export interface ManualApprovalActionProps extends actions.CommonActionProps { +export interface ManualApprovalActionProps extends actions.CommonActionProps, + actions.CommonActionConstructProps { } /** @@ -11,10 +12,10 @@ export interface ManualApprovalActionProps extends actions.CommonActionProps { export class ManualApprovalAction extends actions.Action { constructor(parent: cdk.Construct, name: string, props: ManualApprovalActionProps) { super(parent, name, { - stage: props.stage, category: actions.ActionCategory.Approval, provider: 'Manual', - artifactBounds: { minInputs: 0, maxInputs: 0, minOutputs: 0, maxOutputs: 0 } + artifactBounds: { minInputs: 0, maxInputs: 0, minOutputs: 0, maxOutputs: 0 }, + ...props, }); } } diff --git a/packages/@aws-cdk/aws-codepipeline/test/integ.lambda-pipeline.ts b/packages/@aws-cdk/aws-codepipeline/test/integ.lambda-pipeline.ts index ca513ebdcec49..f8f4f5dba7814 100644 --- a/packages/@aws-cdk/aws-codepipeline/test/integ.lambda-pipeline.ts +++ b/packages/@aws-cdk/aws-codepipeline/test/integ.lambda-pipeline.ts @@ -30,9 +30,6 @@ const lambdaFun = new lambda.Function(stack, 'LambdaFun', { runtime: lambda.Runtime.NodeJS610, }); const lambdaStage = new codepipeline.Stage(pipeline, 'Lambda', { pipeline }); -new lambda.PipelineInvokeAction(stack, 'Lambda', { - stage: lambdaStage, - lambda: lambdaFun, -}); +lambdaFun.addToPipeline(lambdaStage, 'Lambda'); app.run(); diff --git a/packages/@aws-cdk/aws-codepipeline/test/test.pipeline.ts b/packages/@aws-cdk/aws-codepipeline/test/test.pipeline.ts index ccbe45851fd78..81c890292bad9 100644 --- a/packages/@aws-cdk/aws-codepipeline/test/test.pipeline.ts +++ b/packages/@aws-cdk/aws-codepipeline/test/test.pipeline.ts @@ -51,6 +51,7 @@ export = { const s1 = new codepipeline.Stage(stack, 'Source', { pipeline: p }); new codepipeline.GitHubSourceAction(stack, 'GH', { stage: s1, + runOrder: 8, artifactName: 'A', branch: 'branch', oauthToken: secret.value, @@ -100,7 +101,7 @@ export = { "Name": "A" } ], - "RunOrder": 1 + "RunOrder": 8 } ], "Name": "Source" diff --git a/packages/@aws-cdk/aws-lambda/README.md b/packages/@aws-cdk/aws-lambda/README.md index 4394d08f5a9db..e122151c3a28c 100644 --- a/packages/@aws-cdk/aws-lambda/README.md +++ b/packages/@aws-cdk/aws-lambda/README.md @@ -42,22 +42,22 @@ This module also contains an Action that allows you to invoke a Lambda function ```ts import codepipeline = require('@aws-cdk/aws-codepipeline'); -import lambda = require('@aws-cdk/aws-lambda'); - -const lambdaFun = new lambda.Function(this, 'MyLambda', { - // some lambda parameters here... -}); const pipeline = new codepipeline.Pipeline(this, 'MyPipeline'); -const lambdaStage = new codepipeline.Stage(this, 'Lambda', { - pipeline, -}); +const lambdaStage = pipeline.addStage('Lambda'); new lambda.PipelineInvokeAction(this, 'Lambda', { stage: lambdaStage, - lambda: lambdaFun, + lambda: fn, }); ``` +You can also add the Lambda to the Pipeline directly: + +```ts +// equivalent to the code above: +fn.addToPipeline(lambdaStage, 'Lambda'); +``` + See [the AWS documentation](https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-invoke-lambda-function.html) on how to write a Lambda function invoked from CodePipeline. diff --git a/packages/@aws-cdk/aws-lambda/lib/lambda-ref.ts b/packages/@aws-cdk/aws-lambda/lib/lambda-ref.ts index d3047a27d6212..4fcdda6e09d2e 100644 --- a/packages/@aws-cdk/aws-lambda/lib/lambda-ref.ts +++ b/packages/@aws-cdk/aws-lambda/lib/lambda-ref.ts @@ -1,4 +1,5 @@ import cloudwatch = require('@aws-cdk/aws-cloudwatch'); +import codepipeline = require('@aws-cdk/aws-codepipeline-api'); import ec2 = require('@aws-cdk/aws-ec2'); import events = require('@aws-cdk/aws-events'); import iam = require('@aws-cdk/aws-iam'); @@ -7,6 +8,7 @@ import s3n = require('@aws-cdk/aws-s3-notifications'); import cdk = require('@aws-cdk/cdk'); import { cloudformation } from './lambda.generated'; import { Permission } from './permission'; +import { CommonPipelineInvokeActionProps, PipelineInvokeAction } from './pipeline-action'; /** * Represents a Lambda function defined outside of this stack. @@ -181,6 +183,23 @@ export abstract class FunctionRef extends cdk.Construct }); } + /** + * Convenience method for creating a new {@link PipelineInvokeAction}, + * and adding it to the given Stage. + * + * @param stage the Pipeline Stage to add the new Action to + * @param name the name of the newly created Action + * @param props the properties of the new Action + * @returns the newly created {@link PipelineInvokeAction} + */ + public addToPipeline(stage: codepipeline.IStage, name: string, props: CommonPipelineInvokeActionProps = {}): PipelineInvokeAction { + return new PipelineInvokeAction(this, name, { + stage, + lambda: this, + ...props, + }); + } + public addToRolePolicy(statement: iam.PolicyStatement) { if (!this.role) { return; diff --git a/packages/@aws-cdk/aws-lambda/lib/pipeline-action.ts b/packages/@aws-cdk/aws-lambda/lib/pipeline-action.ts index 96a666ac175bd..4e37842794d85 100644 --- a/packages/@aws-cdk/aws-lambda/lib/pipeline-action.ts +++ b/packages/@aws-cdk/aws-lambda/lib/pipeline-action.ts @@ -4,14 +4,11 @@ import cdk = require('@aws-cdk/cdk'); import { FunctionRef } from './lambda-ref'; /** - * Construction properties of the {@link PipelineInvokeAction Lambda invoke CodePipeline Action}. + * Common properties for creating a {@link PipelineInvokeAction} - + * either directly, through its constructor, + * or through {@link FunctionRef#addToPipeline}. */ -export interface PipelineInvokeActionProps extends codepipeline.CommonActionProps { - /** - * The lambda function to invoke. - */ - lambda: FunctionRef; - +export interface CommonPipelineInvokeActionProps extends codepipeline.CommonActionProps { /** * String to be used in the event data parameter passed to the Lambda * function @@ -40,6 +37,17 @@ export interface PipelineInvokeActionProps extends codepipeline.CommonActionProp addPutJobResultPolicy?: boolean; } +/** + * Construction properties of the {@link PipelineInvokeAction Lambda invoke CodePipeline Action}. + */ +export interface PipelineInvokeActionProps extends CommonPipelineInvokeActionProps, + codepipeline.CommonActionConstructProps { + /** + * The lambda function to invoke. + */ + lambda: FunctionRef; +} + /** * CodePipeline invoke Action that is provided by an AWS Lambda function. * @@ -49,6 +57,7 @@ export class PipelineInvokeAction extends codepipeline.Action { constructor(parent: cdk.Construct, name: string, props: PipelineInvokeActionProps) { super(parent, name, { stage: props.stage, + runOrder: props.runOrder, category: codepipeline.ActionCategory.Invoke, provider: 'Lambda', artifactBounds: codepipeline.defaultBounds(), diff --git a/packages/@aws-cdk/aws-s3/lib/pipeline-action.ts b/packages/@aws-cdk/aws-s3/lib/pipeline-action.ts index 026beec985ee9..7f8d8285a61ff 100644 --- a/packages/@aws-cdk/aws-s3/lib/pipeline-action.ts +++ b/packages/@aws-cdk/aws-s3/lib/pipeline-action.ts @@ -1,4 +1,4 @@ -import actions = require('@aws-cdk/aws-codepipeline-api'); +import codepipeline = require('@aws-cdk/aws-codepipeline-api'); import cdk = require('@aws-cdk/cdk'); import { BucketRef } from './bucket'; @@ -7,7 +7,7 @@ import { BucketRef } from './bucket'; * either directly, through its constructor, * or through {@link BucketRef#addToPipeline}. */ -export interface CommonPipelineSourceActionProps { +export interface CommonPipelineSourceActionProps extends codepipeline.CommonActionProps { /** * The name of the source's output artifact. Output artifacts are used by CodePipeline as * inputs into other actions. @@ -33,7 +33,8 @@ export interface CommonPipelineSourceActionProps { /** * Construction properties of the {@link PipelineSourceAction S3 source Action}. */ -export interface PipelineSourceActionProps extends CommonPipelineSourceActionProps, actions.CommonActionProps { +export interface PipelineSourceActionProps extends CommonPipelineSourceActionProps, + codepipeline.CommonActionConstructProps { /** * The Amazon S3 bucket that stores the source code */ @@ -43,10 +44,11 @@ export interface PipelineSourceActionProps extends CommonPipelineSourceActionPro /** * Source that is provided by a specific Amazon S3 object. */ -export class PipelineSourceAction extends actions.SourceAction { +export class PipelineSourceAction extends codepipeline.SourceAction { constructor(parent: cdk.Construct, name: string, props: PipelineSourceActionProps) { super(parent, name, { stage: props.stage, + runOrder: props.runOrder, provider: 'S3', configuration: { S3Bucket: props.bucket.bucketName,