diff --git a/packages/@aws-cdk/aws-cloudformation-codepipeline/README.md b/packages/@aws-cdk/aws-cloudformation-codepipeline/README.md deleted file mode 100644 index 4960c60e24674..0000000000000 --- a/packages/@aws-cdk/aws-cloudformation-codepipeline/README.md +++ /dev/null @@ -1,24 +0,0 @@ -## AWS CodePipline Actions for AWS CloudFormation - -This module contains Actions that allows you to deploy to AWS CloudFormation from AWS CodePipeline. - -For example, the following code fragment defines a pipeline that automatically deploys a CloudFormation template -directly from a CodeCommit repository, with a manual approval step in between to confirm the changes: - -[example Pipeline to deploy CloudFormation](test/integ.template-from-repo.lit.ts) - -See [the AWS documentation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline.html) -for more details about using CloudFormation in CodePipeline. - -### Actions defined by this package - -This package defines the following actions: - -* **CreateUpdateStack** - Deploy a CloudFormation template directly from the pipeline. The indicated stack is created, - or updated if it already exists. If the stack is in a failure state, deployment will fail (unless `replaceOnFailure` - is set to `true`, in which case it will be destroyed and recreated). -* **DeleteStackOnly** - Delete the stack with the given name. -* **CreateReplaceChangeSet** - Prepare a change set to be applied later. You will typically use change sets if you want - to manually verify the changes that are being staged, or if you want to separate the people (or system) preparing the - changes from the people (or system) applying the changes. -* **ExecuteChangeSet** - Execute a change set prepared previously. diff --git a/packages/@aws-cdk/aws-cloudformation-codepipeline/lib/index.ts b/packages/@aws-cdk/aws-cloudformation-codepipeline/lib/index.ts deleted file mode 100644 index 9b3db900186ee..0000000000000 --- a/packages/@aws-cdk/aws-cloudformation-codepipeline/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './pipeline-actions'; diff --git a/packages/@aws-cdk/aws-cloudformation-codepipeline/package.json b/packages/@aws-cdk/aws-cloudformation-codepipeline/package.json deleted file mode 100644 index e3743f41783ee..0000000000000 --- a/packages/@aws-cdk/aws-cloudformation-codepipeline/package.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "name": "@aws-cdk/aws-cloudformation-codepipeline", - "version": "0.8.1", - "description": "AWS CodePipeline Actions for AWS CloudFormation", - "main": "lib/index.js", - "types": "lib/index.d.ts", - "jsii": { - "outdir": "dist", - "targets": { - "sphinx": {}, - "java": { - "package": "software.amazon.awscdk.services.cloudformation.codepipeline", - "maven": { - "groupId": "software.amazon.awscdk", - "artifactId": "cloudformation-codepipeline" - } - } - } - }, - "repository": { - "type": "git", - "url": "https://github.com/awslabs/aws-cdk.git" - }, - "scripts": { - "build": "cdk-build", - "watch": "cdk-watch", - "lint": "cdk-lint", - "test": "cdk-test", - "integ": "cdk-integ", - "pkglint": "pkglint -f", - "package": "cdk-package" - }, - "nyc": { - "lines": 60, - "branches": 30 - }, - "keywords": [ - "aws", - "cdk", - "codepipeline", - "constructs", - "cloudformation" - ], - "author": { - "name": "Amazon Web Services", - "url": "https://aws.amazon.com", - "organization": true - }, - "license": "Apache-2.0", - "devDependencies": { - "@aws-cdk/assert": "^0.8.1", - "@aws-cdk/aws-codebuild": "^0.8.1", - "@aws-cdk/aws-codebuild-codepipeline": "^0.8.1", - "@aws-cdk/aws-codecommit": "^0.8.1", - "@aws-cdk/aws-codecommit-codepipeline": "^0.8.1", - "@aws-cdk/aws-s3": "^0.8.1", - "cdk-build-tools": "^0.8.1", - "cdk-integ-tools": "^0.8.1", - "pkglint": "^0.8.1" - }, - "dependencies": { - "@aws-cdk/aws-codepipeline": "^0.8.1", - "@aws-cdk/aws-iam": "^0.8.1", - "@aws-cdk/cdk": "^0.8.1" - }, - "homepage": "https://github.com/awslabs/aws-cdk" -} diff --git a/packages/@aws-cdk/aws-cloudformation-codepipeline/tslint.json b/packages/@aws-cdk/aws-cloudformation-codepipeline/tslint.json deleted file mode 100644 index ddd9bc8e0f437..0000000000000 --- a/packages/@aws-cdk/aws-cloudformation-codepipeline/tslint.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "extends": "tslint:recommended", - "rules": { - "semicolon": [ - true, - "always", - "ignore-interfaces" - ], - "no-invalid-template-strings": false, - "quotemark": false, - "interface-name": false, - "max-classes-per-file": false, - "member-access": { - "severity": "warning" - }, - "interface-over-type-literal": false, - "eofline": false, - "arrow-parens": false, - "no-namespace": false, - "max-line-length": [ - true, - 150 - ], - "object-literal-sort-keys": false, - "trailing-comma": false, - "no-unused-expression": [ - true, - "allow-new" - ], - "variable-name": [ - true, - "ban-keywords", - "check-format", - "allow-leading-underscore", - "allow-pascal-case" - ] - } -} diff --git a/packages/@aws-cdk/aws-cloudformation/README.md b/packages/@aws-cdk/aws-cloudformation/README.md index c7b2799faa549..044f9ecab0780 100644 --- a/packages/@aws-cdk/aws-cloudformation/README.md +++ b/packages/@aws-cdk/aws-cloudformation/README.md @@ -1,6 +1,32 @@ ## CDK Constructs for AWS CloudFormation + This module is part of the [AWS Cloud Development Kit](https://github.com/awslabs/aws-cdk) project. +### CodePipeline Actions for CloudFormation + +This module contains Actions that allows you to deploy to CloudFormation from AWS CodePipeline. + +For example, the following code fragment defines a pipeline that automatically deploys a CloudFormation template +directly from a CodeCommit repository, with a manual approval step in between to confirm the changes: + +[example Pipeline to deploy CloudFormation](../aws-codepipeline/test/integ.cfn-template-from-repo.lit.ts) + +See [the AWS documentation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline.html) +for more details about using CloudFormation in CodePipeline. + +#### Actions defined by this package + +This package defines the following actions: + +* **CreateUpdateStack** - Deploy a CloudFormation template directly from the pipeline. The indicated stack is created, + or updated if it already exists. If the stack is in a failure state, deployment will fail (unless `replaceOnFailure` + is set to `true`, in which case it will be destroyed and recreated). +* **DeleteStackOnly** - Delete the stack with the given name. +* **CreateReplaceChangeSet** - Prepare a change set to be applied later. You will typically use change sets if you want + to manually verify the changes that are being staged, or if you want to separate the people (or system) preparing the + changes from the people (or system) applying the changes. +* **ExecuteChangeSet** - Execute a change set prepared previously. + ### Custom Resources Custom Resources are CloudFormation resources that are implemented by diff --git a/packages/@aws-cdk/aws-cloudformation/lib/index.ts b/packages/@aws-cdk/aws-cloudformation/lib/index.ts index 51f1795578d4d..2a9dc1178f2fe 100644 --- a/packages/@aws-cdk/aws-cloudformation/lib/index.ts +++ b/packages/@aws-cdk/aws-cloudformation/lib/index.ts @@ -1,3 +1,5 @@ +export * from './custom-resource'; +export * from './pipeline-actions'; + // AWS::CloudFormation CloudFormation Resources: export * from './cloudformation.generated'; -export * from './custom-resource'; diff --git a/packages/@aws-cdk/aws-cloudformation-codepipeline/lib/pipeline-actions.ts b/packages/@aws-cdk/aws-cloudformation/lib/pipeline-actions.ts similarity index 89% rename from packages/@aws-cdk/aws-cloudformation-codepipeline/lib/pipeline-actions.ts rename to packages/@aws-cdk/aws-cloudformation/lib/pipeline-actions.ts index 7b5dee76168eb..55887f748dcbe 100644 --- a/packages/@aws-cdk/aws-cloudformation-codepipeline/lib/pipeline-actions.ts +++ b/packages/@aws-cdk/aws-cloudformation/lib/pipeline-actions.ts @@ -1,11 +1,11 @@ -import codepipeline = require('@aws-cdk/aws-codepipeline'); +import codepipeline = require('@aws-cdk/aws-codepipeline-api'); import iam = require('@aws-cdk/aws-iam'); import cdk = require('@aws-cdk/cdk'); /** * Properties common to all CloudFormation actions */ -export interface CloudFormationCommonProps { +export interface CloudFormationCommonProps extends codepipeline.CommonActionProps { /** * The name of the stack to apply this action to */ @@ -45,15 +45,26 @@ export abstract class CloudFormationAction extends codepipeline.DeployAction { */ public artifact?: codepipeline.Artifact; - constructor(parent: codepipeline.Stage, id: string, props: CloudFormationCommonProps, configuration?: any) { - super(parent, id, 'CloudFormation', { minInputs: 0, maxInputs: 10, minOutputs: 0, maxOutputs: 1 }, { - ...configuration, - StackName: props.stackName, - OutputFileName: props.outputFileName, + constructor(parent: cdk.Construct, id: string, props: CloudFormationCommonProps, configuration?: any) { + super(parent, id, { + stage: props.stage, + artifactBounds: { + minInputs: 0, + maxInputs: 10, + minOutputs: 0, + maxOutputs: 1, + }, + provider: 'CloudFormation', + configuration: { + StackName: props.stackName, + OutputFileName: props.outputFileName, + ...configuration, + } }); if (props.outputFileName) { - this.artifact = this.addOutputArtifact(props.outputArtifactName || (parent.name + this.name + 'Artifact')); + this.artifact = this.addOutputArtifact(props.outputArtifactName || + (props.stage.name + this.name + 'Artifact')); } } } @@ -72,7 +83,7 @@ export interface ExecuteChangeSetProps extends CloudFormationCommonProps { * CodePipeline action to execute a prepared change set. */ export class ExecuteChangeSet extends CloudFormationAction { - constructor(parent: codepipeline.Stage, id: string, props: ExecuteChangeSetProps) { + constructor(parent: cdk.Construct, id: string, props: ExecuteChangeSetProps) { super(parent, id, props, { ActionMode: 'CHANGE_SET_EXECUTE', ChangeSetName: props.changeSetName, @@ -168,7 +179,7 @@ export interface CloudFormationDeploymentActionCommonProps extends CloudFormatio export abstract class CloudFormationDeploymentAction extends CloudFormationAction { public readonly role: iam.Role; - constructor(parent: codepipeline.Stage, id: string, props: CloudFormationDeploymentActionCommonProps, configuration: any) { + constructor(parent: cdk.Construct, id: string, props: CloudFormationDeploymentActionCommonProps, configuration: any) { const capabilities = props.fullPermissions && props.capabilities === undefined ? [CloudFormationCapabilities.NamedIAM] : props.capabilities; super(parent, id, props, { @@ -224,7 +235,7 @@ export interface CreateReplaceChangeSetProps extends CloudFormationDeploymentAct * If the change set exists, AWS CloudFormation deletes it, and then creates a new one. */ export class CreateReplaceChangeSet extends CloudFormationDeploymentAction { - constructor(parent: codepipeline.Stage, id: string, props: CreateReplaceChangeSetProps) { + constructor(parent: cdk.Construct, id: string, props: CreateReplaceChangeSetProps) { super(parent, id, props, { ActionMode: 'CHANGE_SET_REPLACE', ChangeSetName: props.changeSetName, @@ -275,7 +286,7 @@ export interface CreateUpdateProps extends CloudFormationDeploymentActionCommonP * troubleshooting them. You would typically choose this mode for testing. */ export class CreateUpdateStack extends CloudFormationDeploymentAction { - constructor(parent: codepipeline.Stage, id: string, props: CreateUpdateProps) { + constructor(parent: cdk.Construct, id: string, props: CreateUpdateProps) { super(parent, id, props, { ActionMode: props.replaceOnFailure ? 'REPLACE_ON_FAILURE' : 'CREATE_UPDATE', TemplatePath: props.templatePath.location @@ -298,7 +309,7 @@ export interface DeleteStackOnlyProps extends CloudFormationDeploymentActionComm * without deleting a stack. */ export class DeleteStackOnly extends CloudFormationDeploymentAction { - constructor(parent: codepipeline.Stage, id: string, props: DeleteStackOnlyProps) { + constructor(parent: cdk.Construct, id: string, props: DeleteStackOnlyProps) { super(parent, id, props, { ActionMode: 'DELETE_ONLY', }); diff --git a/packages/@aws-cdk/aws-cloudformation/package.json b/packages/@aws-cdk/aws-cloudformation/package.json index 8b11ef7286fe5..a3bbcb4e6c495 100644 --- a/packages/@aws-cdk/aws-cloudformation/package.json +++ b/packages/@aws-cdk/aws-cloudformation/package.json @@ -33,6 +33,10 @@ "cdk-build": { "cloudformation": "AWS::CloudFormation" }, + "nyc": { + "lines": 50, + "branches": 20 + }, "keywords": [ "aws", "cdk", @@ -54,6 +58,8 @@ }, "dependencies": { "@aws-cdk/cdk": "^0.8.1", + "@aws-cdk/aws-codepipeline-api": "^0.8.1", + "@aws-cdk/aws-iam": "^0.8.1", "@aws-cdk/aws-lambda": "^0.8.1", "@aws-cdk/aws-sns": "^0.8.1" }, diff --git a/packages/@aws-cdk/aws-codebuild-codepipeline/.gitignore b/packages/@aws-cdk/aws-codebuild-codepipeline/.gitignore deleted file mode 100644 index 2c2ba24ad6150..0000000000000 --- a/packages/@aws-cdk/aws-codebuild-codepipeline/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -*.js -*.js.map -*.d.ts -node_modules -*.generated.ts -dist -tsconfig.json -tslint.json - -.jsii - -.LAST_BUILD -.nyc_output -coverage -.nycrc - -.LAST_PACKAGE \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codebuild-codepipeline/.npmignore b/packages/@aws-cdk/aws-codebuild-codepipeline/.npmignore deleted file mode 100644 index fd40d742b8c54..0000000000000 --- a/packages/@aws-cdk/aws-codebuild-codepipeline/.npmignore +++ /dev/null @@ -1,19 +0,0 @@ -+# Don't include original .ts files when doing `npm pack` -+*.ts -+!*.d.ts -+coverage -+.nyc_output -+*.tgz - -dist -.LAST_PACKAGE -.LAST_BUILD -*.ts -!*.d.ts -!*.js -coverage -.nyc_output -*.tgz - -# Include .jsii -!.jsii diff --git a/packages/@aws-cdk/aws-codebuild-codepipeline/LICENSE b/packages/@aws-cdk/aws-codebuild-codepipeline/LICENSE deleted file mode 100644 index 1739faaebb745..0000000000000 --- a/packages/@aws-cdk/aws-codebuild-codepipeline/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2018-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/packages/@aws-cdk/aws-codebuild-codepipeline/NOTICE b/packages/@aws-cdk/aws-codebuild-codepipeline/NOTICE deleted file mode 100644 index 95fd48569c743..0000000000000 --- a/packages/@aws-cdk/aws-codebuild-codepipeline/NOTICE +++ /dev/null @@ -1,2 +0,0 @@ -AWS Cloud Development Kit (AWS CDK) -Copyright 2018-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-codebuild-codepipeline/README.md b/packages/@aws-cdk/aws-codebuild-codepipeline/README.md deleted file mode 100644 index dbbd8e1d01a2f..0000000000000 --- a/packages/@aws-cdk/aws-codebuild-codepipeline/README.md +++ /dev/null @@ -1,35 +0,0 @@ -## AWS CodePipline Actions for AWS CodeBuild - -This module contains an Action that allows you to use a CodeBuild Project in CodePipeline. - -Example: - -```ts -import codebuildPipeline = require('@aws-cdk/aws-codebuild-codepipeline'); -import codepipeline = require('@aws-cdk/aws-codepipeline'); - -// see the @aws-cdk/aws-codebuild module for more documentation on how to create CodeBuild Projects -const project = new codebuildPipeline.PipelineProject(this, 'MyProject', { - // ... -}); - -const pipeline = new codepipeline.Pipeline(this, 'MyPipeline'); -const buildStage = new codepipeline.Stage(pipeline, 'Build'); -new codebuildPipeline.PipelineBuildAction(buildStage, 'CodeBuild', { - project -}); -``` - -The `PipelineProject` utility class is a simple sugar around the `Project` -class from the `@aws-cdk/aws-codebuild` module, -it's equivalent to: - -```ts -import codebuild = require('@aws-cdk/aws-codebuild'); - -const project = new codebuild.Project(this, 'MyProject', { - source: new codebuild.CodePipelineSource(), - artifacts: new codebuild.CodePipelineBuildArtifacts(), - // rest of the properties from PipelineProject are passed unchanged... -} -``` diff --git a/packages/@aws-cdk/aws-codebuild-codepipeline/lib/index.ts b/packages/@aws-cdk/aws-codebuild-codepipeline/lib/index.ts deleted file mode 100644 index 7dda267e2867d..0000000000000 --- a/packages/@aws-cdk/aws-codebuild-codepipeline/lib/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './pipeline-actions'; -export * from './pipeline-project'; diff --git a/packages/@aws-cdk/aws-codebuild-codepipeline/lib/pipeline-project.ts b/packages/@aws-cdk/aws-codebuild-codepipeline/lib/pipeline-project.ts deleted file mode 100644 index 452757e84ab7d..0000000000000 --- a/packages/@aws-cdk/aws-codebuild-codepipeline/lib/pipeline-project.ts +++ /dev/null @@ -1,19 +0,0 @@ -import codebuild = require('@aws-cdk/aws-codebuild'); -import cdk = require('@aws-cdk/cdk'); - -// tslint:disable-next-line:no-empty-interface -export interface PipelineProjectProps extends codebuild.CommonProjectProps { -} - -/** - * A convenience class for CodeBuild Projects that are used in CodePipeline. - */ -export class PipelineProject extends codebuild.Project { - constructor(parent: cdk.Construct, id: string, props?: PipelineProjectProps) { - super(parent, id, { - source: new codebuild.CodePipelineSource(), - artifacts: new codebuild.CodePipelineBuildArtifacts(), - ...props - }); - } -} diff --git a/packages/@aws-cdk/aws-codebuild-codepipeline/package.json b/packages/@aws-cdk/aws-codebuild-codepipeline/package.json deleted file mode 100644 index 95dd64cfd63b7..0000000000000 --- a/packages/@aws-cdk/aws-codebuild-codepipeline/package.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "name": "@aws-cdk/aws-codebuild-codepipeline", - "version": "0.8.1", - "description": "AWS CodePipline Actions for AWS CodeBuild", - "main": "lib/index.js", - "types": "lib/index.d.ts", - "jsii": { - "outdir": "dist", - "targets": { - "java": { - "package": "software.amazon.awscdk.services.codebuild.codepipeline", - "maven": { - "groupId": "software.amazon.awscdk", - "artifactId": "codebuild-codepipeline" - } - }, - "sphinx": {} - } - }, - "repository": { - "type": "git", - "url": "https://github.com/awslabs/aws-cdk.git" - }, - "scripts": { - "build": "cdk-build", - "watch": "cdk-watch", - "lint": "cdk-lint", - "test": "cdk-test", - "integ": "cdk-integ", - "pkglint": "pkglint -f", - "package": "cdk-package" - }, - "keywords": [ - "aws", - "cdk", - "codebuild", - "codepipeline", - "constructs" - ], - "author": { - "name": "Amazon Web Services", - "url": "https://aws.amazon.com", - "organization": true - }, - "license": "Apache-2.0", - "devDependencies": { - "@aws-cdk/assert": "^0.8.1", - "cdk-build-tools": "^0.8.1", - "cdk-integ-tools": "^0.8.1", - "pkglint": "^0.8.1" - }, - "dependencies": { - "@aws-cdk/aws-codebuild": "^0.8.1", - "@aws-cdk/aws-codecommit": "^0.8.1", - "@aws-cdk/aws-codecommit-codepipeline": "^0.8.1", - "@aws-cdk/aws-codepipeline": "^0.8.1", - "@aws-cdk/aws-s3": "^0.8.1", - "@aws-cdk/aws-sns": "^0.8.1", - "@aws-cdk/cdk": "^0.8.1" - }, - "homepage": "https://github.com/awslabs/aws-cdk" -} diff --git a/packages/@aws-cdk/aws-codebuild/README.md b/packages/@aws-cdk/aws-codebuild/README.md index 9b48621af3d7a..7e96f68ca03ec 100644 --- a/packages/@aws-cdk/aws-codebuild/README.md +++ b/packages/@aws-cdk/aws-codebuild/README.md @@ -1,16 +1,10 @@ ## AWS CodeBuild Construct Library -Define a project. This will also create an IAM Role and IAM Policy for CodeBuildRole to use. +Define a project. This will also create an IAM Role and IAM Policy for CodeBuild to use. -Create a CodeBuild project with CodePipeline as the source: +### Using CodeBuild with other AWS services -```ts -import codebuild = require('@aws-cdk/aws-codebuild'); - -new codebuild.Project(this, 'MyFirstProject', { - source: new codebuild.CodePipelineSource() -}); -``` +#### CodeCommit Create a CodeBuild project with CodeCommit as the source: @@ -24,6 +18,8 @@ new codebuild.Project(this, 'MyFirstCodeCommitProject', { }); ``` +#### S3 + Create a CodeBuild project with an S3 bucket as the source: ```ts @@ -36,6 +32,50 @@ new codebuild.Project(this, 'MyProject', { }); ``` +#### CodePipeline + +Example of a Project used in CodePipeline, +alongside CodeCommit: + +```ts +import codebuild = require('@aws-cdk/aws-codebuild'); +import codecommit = require('@aws-cdk/aws-codecommit'); +import codepipeline = require('@aws-cdk/aws-codepipeline'); + +const repository = new codecommit.Repository(this, 'MyRepository', { + repositoryName: 'MyRepository', +}); + +const project = new codebuild.PipelineProject(this, 'MyProject'); + +const pipeline = new codepipeline.Pipeline(this, 'MyPipeline'); + +const sourceStage = new codepipeline.Stage(pipeline, 'Source'); +const sourceAction = new codecommit.PipelineSource(this, 'CodeCommit', { + stage: sourceStage, + artifactName: 'SourceOutput', + repository, +}); + +const buildStage = new codepipeline.Stage(pipeline, 'Build'); +new codebuild.PipelineBuildAction(this, 'CodeBuild', { + stage: buildStage, + inputArtifact: sourceAction.artifact, + project, +}); +``` + +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... +} +``` + ### Using Project as an event target The `Project` construct implements the `IEventRuleTarget` interface. This means that it can be diff --git a/packages/@aws-cdk/aws-codebuild/lib/index.ts b/packages/@aws-cdk/aws-codebuild/lib/index.ts index 55df0a8ad66cd..77571a2a92c05 100644 --- a/packages/@aws-cdk/aws-codebuild/lib/index.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/index.ts @@ -1,3 +1,5 @@ +export * from './pipeline-actions'; +export * from './pipeline-project'; export * from './project'; export * from './source'; export * from './artifacts'; diff --git a/packages/@aws-cdk/aws-codebuild-codepipeline/lib/pipeline-actions.ts b/packages/@aws-cdk/aws-codebuild/lib/pipeline-actions.ts similarity index 75% rename from packages/@aws-cdk/aws-codebuild-codepipeline/lib/pipeline-actions.ts rename to packages/@aws-cdk/aws-codebuild/lib/pipeline-actions.ts index 66be0d97b6575..74af4d07c8fdd 100644 --- a/packages/@aws-cdk/aws-codebuild-codepipeline/lib/pipeline-actions.ts +++ b/packages/@aws-cdk/aws-codebuild/lib/pipeline-actions.ts @@ -1,11 +1,11 @@ -import codebuild = require('@aws-cdk/aws-codebuild'); -import codepipeline = require('@aws-cdk/aws-codepipeline'); +import codepipeline = require('@aws-cdk/aws-codepipeline-api'); import cdk = require('@aws-cdk/cdk'); +import { ProjectRef } from './project'; /** * Construction properties of the {@link PipelineBuildAction CodeBuild build CodePipeline Action}. */ -export interface PipelineBuildActionProps { +export interface PipelineBuildActionProps extends codepipeline.CommonActionProps { /** * The source to use as input for this build */ @@ -19,18 +19,19 @@ export interface PipelineBuildActionProps { /** * The build project */ - project: codebuild.ProjectRef; + project: ProjectRef; } /** * CodePipeline build Action that uses AWS CodeBuild. */ export class PipelineBuildAction extends codepipeline.BuildAction { - constructor(parent: codepipeline.Stage, name: string, props: PipelineBuildActionProps) { + constructor(parent: cdk.Construct, name: string, props: PipelineBuildActionProps) { // This happened when ProjectName was accidentally set to the project's ARN: // https://qiita.com/ikeisuke/items/2fbc0b80b9bbd981b41f super(parent, name, { + stage: props.stage, provider: 'CodeBuild', inputArtifact: props.inputArtifact, artifactName: props.artifactName, @@ -45,12 +46,12 @@ export class PipelineBuildAction extends codepipeline.BuildAction { 'codebuild:StopBuild', ]; - parent.pipeline.addToRolePolicy(new cdk.PolicyStatement() + props.stage.pipelineRole.addToPolicy(new cdk.PolicyStatement() .addResource(props.project.projectArn) .addActions(...actions)); // allow codebuild to read and write artifacts to the pipline's artifact bucket. - parent.pipeline.artifactBucket.grantReadWrite(props.project.role); + props.stage.grantPipelineBucketReadWrite(props.project.role); // policy must be added as a dependency to the pipeline!! // TODO: grants - build.addResourcePermission() and also make sure permission diff --git a/packages/@aws-cdk/aws-codebuild/lib/pipeline-project.ts b/packages/@aws-cdk/aws-codebuild/lib/pipeline-project.ts new file mode 100644 index 0000000000000..af9ff405d6471 --- /dev/null +++ b/packages/@aws-cdk/aws-codebuild/lib/pipeline-project.ts @@ -0,0 +1,21 @@ +import cdk = require('@aws-cdk/cdk'); +import { CodePipelineBuildArtifacts } from './artifacts'; +import { CommonProjectProps, Project } from './project'; +import { CodePipelineSource } from './source'; + +// tslint:disable-next-line:no-empty-interface +export interface PipelineProjectProps extends CommonProjectProps { +} + +/** + * A convenience class for CodeBuild Projects that are used in CodePipeline. + */ +export class PipelineProject extends Project { + constructor(parent: cdk.Construct, id: string, props?: PipelineProjectProps) { + super(parent, id, { + source: new CodePipelineSource(), + artifacts: new CodePipelineBuildArtifacts(), + ...props + }); + } +} diff --git a/packages/@aws-cdk/aws-codebuild/package.json b/packages/@aws-cdk/aws-codebuild/package.json index bacffe769ee9c..c38854738f6aa 100644 --- a/packages/@aws-cdk/aws-codebuild/package.json +++ b/packages/@aws-cdk/aws-codebuild/package.json @@ -60,6 +60,7 @@ "dependencies": { "@aws-cdk/aws-cloudwatch": "^0.8.1", "@aws-cdk/aws-codecommit": "^0.8.1", + "@aws-cdk/aws-codepipeline-api": "^0.8.1", "@aws-cdk/aws-events": "^0.8.1", "@aws-cdk/aws-iam": "^0.8.1", "@aws-cdk/aws-kms": "^0.8.1", diff --git a/packages/@aws-cdk/aws-codecommit-codepipeline/.gitignore b/packages/@aws-cdk/aws-codecommit-codepipeline/.gitignore deleted file mode 100644 index 2c2ba24ad6150..0000000000000 --- a/packages/@aws-cdk/aws-codecommit-codepipeline/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -*.js -*.js.map -*.d.ts -node_modules -*.generated.ts -dist -tsconfig.json -tslint.json - -.jsii - -.LAST_BUILD -.nyc_output -coverage -.nycrc - -.LAST_PACKAGE \ No newline at end of file diff --git a/packages/@aws-cdk/aws-codecommit-codepipeline/.npmignore b/packages/@aws-cdk/aws-codecommit-codepipeline/.npmignore deleted file mode 100644 index fd40d742b8c54..0000000000000 --- a/packages/@aws-cdk/aws-codecommit-codepipeline/.npmignore +++ /dev/null @@ -1,19 +0,0 @@ -+# Don't include original .ts files when doing `npm pack` -+*.ts -+!*.d.ts -+coverage -+.nyc_output -+*.tgz - -dist -.LAST_PACKAGE -.LAST_BUILD -*.ts -!*.d.ts -!*.js -coverage -.nyc_output -*.tgz - -# Include .jsii -!.jsii diff --git a/packages/@aws-cdk/aws-codecommit-codepipeline/LICENSE b/packages/@aws-cdk/aws-codecommit-codepipeline/LICENSE deleted file mode 100644 index 1739faaebb745..0000000000000 --- a/packages/@aws-cdk/aws-codecommit-codepipeline/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2018-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/packages/@aws-cdk/aws-codecommit-codepipeline/NOTICE b/packages/@aws-cdk/aws-codecommit-codepipeline/NOTICE deleted file mode 100644 index 95fd48569c743..0000000000000 --- a/packages/@aws-cdk/aws-codecommit-codepipeline/NOTICE +++ /dev/null @@ -1,2 +0,0 @@ -AWS Cloud Development Kit (AWS CDK) -Copyright 2018-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-codecommit-codepipeline/README.md b/packages/@aws-cdk/aws-codecommit-codepipeline/README.md deleted file mode 100644 index 15e3ce7e097f5..0000000000000 --- a/packages/@aws-cdk/aws-codecommit-codepipeline/README.md +++ /dev/null @@ -1,21 +0,0 @@ -## AWS CodePipline Actions for AWS CodeCommit - -This module contains an Action that allows you to use a CodeCommit Repository as a Source in CodePipeline. - -Example: - -```ts -import codecommit = require('@aws-cdk/aws-codecommit'); -import codecommitPipeline = require('@aws-cdk/aws-codecommit-codepipeline'); -import codepipeline = require('@aws-cdk/aws-codepipeline'); - -// see the @aws-cdk/aws-codecommit module for more documentation on how to create CodeCommit Repositories -const repository = new codecommit.Repository( // ... -); - -const pipeline = new codepipeline.Pipeline(this, 'MyPipeline'); -const sourceStage = new codepipeline.Stage(pipeline, 'Source'); -new codecommitPipeline.PipelineSource(sourceStage, 'CodeCommit', { - repository: repository, -}); -``` diff --git a/packages/@aws-cdk/aws-codecommit-codepipeline/lib/index.ts b/packages/@aws-cdk/aws-codecommit-codepipeline/lib/index.ts deleted file mode 100644 index 890162998e10d..0000000000000 --- a/packages/@aws-cdk/aws-codecommit-codepipeline/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './pipeline-action'; diff --git a/packages/@aws-cdk/aws-codecommit-codepipeline/test/test.pipeline-action.ts b/packages/@aws-cdk/aws-codecommit-codepipeline/test/test.pipeline-action.ts deleted file mode 100644 index a71c24ffbb43d..0000000000000 --- a/packages/@aws-cdk/aws-codecommit-codepipeline/test/test.pipeline-action.ts +++ /dev/null @@ -1,45 +0,0 @@ -import codecommit = require("@aws-cdk/aws-codecommit"); -import codepipeline = require("@aws-cdk/aws-codepipeline"); -import cdk = require('@aws-cdk/cdk'); -import { Test } from 'nodeunit'; -import codecommitCodepipeline = require('../lib'); - -export = { - 'polling for changes': { - - 'does not poll for changes'(test: Test) { - const stack = new cdk.Stack(); - - const result = new codecommitCodepipeline.PipelineSource(stageForTesting(stack), 'stage', { - artifactName: 'SomeArtifact', - repository: repositoryForTesting(stack), - pollForSourceChanges: false - }); - test.equal(result.configuration.PollForSourceChanges, false); - test.done(); - }, - - 'polls for changes'(test: Test) { - const stack = new cdk.Stack(); - - const result = new codecommitCodepipeline.PipelineSource(stageForTesting(stack), 'stage', { - artifactName: 'SomeArtifact', - repository: repositoryForTesting(stack), - pollForSourceChanges: true - }); - test.equal(result.configuration.PollForSourceChanges, true); - test.done(); - } - } -}; - -function stageForTesting(stack: cdk.Stack): codepipeline.Stage { - const pipeline = new codepipeline.Pipeline(stack, 'pipeline'); - return new codepipeline.Stage(pipeline, 'stage'); -} - -function repositoryForTesting(stack: cdk.Stack): codecommit.Repository { - return new codecommit.Repository(stack, 'Repository', { - repositoryName: 'Repository' - }); -} diff --git a/packages/@aws-cdk/aws-codecommit/README.md b/packages/@aws-cdk/aws-codecommit/README.md index dfa40c3ab4a26..d268be37f5b9b 100644 --- a/packages/@aws-cdk/aws-codecommit/README.md +++ b/packages/@aws-cdk/aws-codecommit/README.md @@ -5,7 +5,7 @@ To add a CodeCommit Repository to your stack: ```ts import codecommit = require('@aws-cdk/aws-codecommit'); -const repository = new codecommit.Repository(stack, 'Repository' ,{ +const repository = new codecommit.Repository(this, 'Repository' ,{ repositoryName: 'MyRepositoryName' }); ``` @@ -15,7 +15,7 @@ To add an SNS trigger to your repository: ```ts import codecommit = require('@aws-cdk/aws-codecommit'); -const repository = new codecommit.Repository(stack, 'Repository', { +const repository = new codecommit.Repository(this, 'Repository', { repositoryName: 'MyRepositoryName' }); @@ -23,11 +23,35 @@ const repository = new codecommit.Repository(stack, 'Repository', { repository.notify('arn:aws:sns:*:123456789012:my_topic'); ``` +### CodePipeline + +To use a CodeCommit Repository in a CodePipeline: + +```ts +import codecommit = require('@aws-cdk/aws-codecommit'); +import codepipeline = require('@aws-cdk/aws-codepipeline'); + +// see above for the details... +const repository = new codecommit.Repository( // ... +); + +const pipeline = new codepipeline.Pipeline(this, 'MyPipeline', { + pipelineName: 'MyPipeline', +}); +const sourceStage = new codepipeline.Stage(pipeline, 'Source'); +const sourceAction = new codecommit.PipelineSource(this, 'CodeCommit', { + stage: sourceStage, + artifactName: 'SourceOutput', //name can be arbitrary + repository, +}); +// use sourceAction.artifact as the inputArtifact to later Actions... +``` + ### Events -CodeCommit repositories emit CloudWatch events for certain activity. Use the -`repo.onXxx` methods to define rules that trigger on these events and invoke -targets as a result: +CodeCommit repositories emit CloudWatch events for certain activity. +Use the `repo.onXxx` methods to define rules that trigger on these events +and invoke targets as a result: ```ts // starts a CodeBuild project when a commit is pushed to the "master" branch of the repo diff --git a/packages/@aws-cdk/aws-codecommit/lib/index.ts b/packages/@aws-cdk/aws-codecommit/lib/index.ts index 2fa63e2e6ef94..d2e8bb4a6494c 100644 --- a/packages/@aws-cdk/aws-codecommit/lib/index.ts +++ b/packages/@aws-cdk/aws-codecommit/lib/index.ts @@ -1,3 +1,4 @@ +export * from './pipeline-action'; export * from './repository'; // AWS::CodeCommit CloudFormation Resources: diff --git a/packages/@aws-cdk/aws-codecommit-codepipeline/lib/pipeline-action.ts b/packages/@aws-cdk/aws-codecommit/lib/pipeline-action.ts similarity index 70% rename from packages/@aws-cdk/aws-codecommit-codepipeline/lib/pipeline-action.ts rename to packages/@aws-cdk/aws-codecommit/lib/pipeline-action.ts index 7c6016378186c..76a118add732a 100644 --- a/packages/@aws-cdk/aws-codecommit-codepipeline/lib/pipeline-action.ts +++ b/packages/@aws-cdk/aws-codecommit/lib/pipeline-action.ts @@ -1,29 +1,30 @@ -import codecommit = require('@aws-cdk/aws-codecommit'); -import codepipeline = require('@aws-cdk/aws-codepipeline'); +import codepipeline = require('@aws-cdk/aws-codepipeline-api'); import cdk = require('@aws-cdk/cdk'); +import { RepositoryRef } from './repository'; /** * Construction properties of the {@link PipelineSource CodeCommit source CodePipeline Action}. */ -export interface PipelineSourceProps { +export interface PipelineSourceProps extends codepipeline.CommonActionProps { /** - * The name of the source's output artifact. Output artifacts are used by CodePipeline as - * inputs into other actions. + * The name of the source's output artifact. + * Output artifacts are used by CodePipeline as inputs into other actions. */ artifactName: string; /** * The CodeCommit repository. */ - repository: codecommit.RepositoryRef; + repository: RepositoryRef; /** * @default 'master' */ branch?: string; + // TODO: use CloudWatch events instead /** - * Whether or not AWS CodePipeline should poll for source changes + * Whether or not AWS CodePipeline should poll for source changes. * * @default true */ @@ -33,9 +34,10 @@ export interface PipelineSourceProps { /** * CodePipeline Source that is provided by an AWS CodeCommit repository. */ -export class PipelineSource extends codepipeline.Source { - constructor(parent: codepipeline.Stage, name: string, props: PipelineSourceProps) { +export class PipelineSource extends codepipeline.SourceAction { + constructor(parent: cdk.Construct, name: string, props: PipelineSourceProps) { super(parent, name, { + stage: props.stage, provider: 'CodeCommit', configuration: { RepositoryName: props.repository.repositoryName, @@ -54,7 +56,7 @@ export class PipelineSource extends codepipeline.Source { 'codecommit:CancelUploadArchive', ]; - parent.pipeline.addToRolePolicy(new cdk.PolicyStatement() + props.stage.pipelineRole.addToPolicy(new cdk.PolicyStatement() .addResource(props.repository.repositoryArn) .addActions(...actions)); } diff --git a/packages/@aws-cdk/aws-codecommit/package.json b/packages/@aws-cdk/aws-codecommit/package.json index f1617659121e0..42c7767b8f11e 100644 --- a/packages/@aws-cdk/aws-codecommit/package.json +++ b/packages/@aws-cdk/aws-codecommit/package.json @@ -59,6 +59,7 @@ "pkglint": "^0.8.1" }, "dependencies": { + "@aws-cdk/aws-codepipeline-api": "^0.8.1", "@aws-cdk/aws-events": "^0.8.1", "@aws-cdk/aws-iam": "^0.8.1", "@aws-cdk/cdk": "^0.8.1" diff --git a/packages/@aws-cdk/aws-cloudformation-codepipeline/.gitignore b/packages/@aws-cdk/aws-codepipeline-api/.gitignore similarity index 96% rename from packages/@aws-cdk/aws-cloudformation-codepipeline/.gitignore rename to packages/@aws-cdk/aws-codepipeline-api/.gitignore index acfc6e27248fe..d25f002f4cf52 100644 --- a/packages/@aws-cdk/aws-cloudformation-codepipeline/.gitignore +++ b/packages/@aws-cdk/aws-codepipeline-api/.gitignore @@ -6,6 +6,7 @@ tslint.json *.generated.ts dist lib/generated/resources.ts +*.tgz .jsii .LAST_BUILD diff --git a/packages/@aws-cdk/aws-cloudformation-codepipeline/.npmignore b/packages/@aws-cdk/aws-codepipeline-api/.npmignore similarity index 100% rename from packages/@aws-cdk/aws-cloudformation-codepipeline/.npmignore rename to packages/@aws-cdk/aws-codepipeline-api/.npmignore diff --git a/packages/@aws-cdk/aws-cloudformation-codepipeline/LICENSE b/packages/@aws-cdk/aws-codepipeline-api/LICENSE similarity index 100% rename from packages/@aws-cdk/aws-cloudformation-codepipeline/LICENSE rename to packages/@aws-cdk/aws-codepipeline-api/LICENSE diff --git a/packages/@aws-cdk/aws-cloudformation-codepipeline/NOTICE b/packages/@aws-cdk/aws-codepipeline-api/NOTICE similarity index 100% rename from packages/@aws-cdk/aws-cloudformation-codepipeline/NOTICE rename to packages/@aws-cdk/aws-codepipeline-api/NOTICE diff --git a/packages/@aws-cdk/aws-codepipeline-api/README.md b/packages/@aws-cdk/aws-codepipeline-api/README.md new file mode 100644 index 0000000000000..2f19570b6d1e0 --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-api/README.md @@ -0,0 +1,10 @@ +## AWS CodePipeline Actions API + +This package contains the abstract API of Pipeline Actions. +It's used by the `aws-codepipeline` module, +and the AWS service modules that integrate with AWS CodePipeline. + +You shoould never need to depend on it directly - +instead, depend on `aws-codepipeline`, +and the module you need the concrete Actions from +(like `aws-codecommit`, `aws-codebuild`, etc.). diff --git a/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts b/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts new file mode 100644 index 0000000000000..c15b98d6bed3e --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-api/lib/action.ts @@ -0,0 +1,313 @@ +import events = require('@aws-cdk/aws-events'); +import iam = require('@aws-cdk/aws-iam'); +import cdk = require('@aws-cdk/cdk'); +import { Artifact } from './artifact'; +import validation = require('./validation'); + +export enum ActionCategory { + Source = 'Source', + Build = 'Build', + Test = 'Test', + Approval = 'Approval', + Deploy = 'Deploy', + Invoke = 'Invoke' +} + +/** + * Specifies the constraints on the number of input and output + * artifacts an action can have. + * + * The constraints for each action type are documented on the + * {@link https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html Pipeline Structure Reference} page. + */ +export interface ActionArtifactBounds { + readonly minInputs: number; + readonly maxInputs: number; + readonly minOutputs: number; + readonly maxOutputs: number; +} + +export function defaultBounds(): ActionArtifactBounds { + return { + minInputs: 0, + maxInputs: 5, + minOutputs: 0, + maxOutputs: 5 + }; +} + +/** + * The abstract interface of a Pipeline Stage that is used by Actions. + */ +export interface IStage { + /** + * The physical, human-readable name of this Pipeline Stage. + */ + readonly name: string; + + /** + * The ARN of the Pipeline. + */ + readonly pipelineArn: cdk.Arn; + + /** + * The service Role of the Pipeline. + */ + readonly pipelineRole: iam.Role; + + /** + * Grants read & write permissions to the Pipeline's S3 Bucket to the given Identity. + * + * @param identity the IAM Identity to grant the permissions to + */ + grantPipelineBucketReadWrite(identity?: iam.IPrincipal): void; + + /** + * Adds an Action to this Stage. + * This is an internal operation - + * an Action is added to a Stage when it's constructed, + * so there's no need to call this method explicitly. + * + * @param action the Action to add to this Stage + */ + _addAction(action: Action): void; +} + +/** + * Common properties shared by all Actions. + */ +export interface CommonActionProps { + /** + * The Pipeline Stage to add this Action to. + */ + stage: IStage; +} + +/** + * Construction properties of the low-level {@link Action Action class}. + */ +export interface ActionProps extends CommonActionProps { + category: ActionCategory; + provider: string; + artifactBounds: ActionArtifactBounds; + configuration?: any; + version?: string; + owner?: string; +} + +/** + * Low-level class for generic CodePipeline Actions. + * It is recommended that concrete types are used instead, such as {@link codecommit.PipelineSource} or + * {@link codebuild.PipelineBuildAction}. + */ +export abstract class Action extends cdk.Construct { + /** + * The category of the action. + * The category defines which action type the owner + * (the entity that performs the action) performs. + */ + public readonly category: ActionCategory; + + /** + * The service provider that the action calls. + */ + public readonly provider: string; + + /** + * The action's configuration. These are key-value pairs that specify input values for an action. + * For more information, see the AWS CodePipeline User Guide. + * + * http://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#action-requirements + */ + public readonly configuration?: any; + + /** + * The order in which AWS CodePipeline runs this action. + * For more information, see the AWS CodePipeline User Guide. + * + * https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#action-requirements + */ + public runOrder: number; + + public readonly owner: string; + public readonly version: string; + + private readonly _inputArtifacts = new Array(); + private readonly _outputArtifacts = new Array(); + private readonly artifactBounds: ActionArtifactBounds; + private readonly stage: IStage; + + constructor(parent: cdk.Construct, id: string, props: ActionProps) { + super(parent, id); + + validation.validateName('Action', id); + + this.owner = props.owner || 'AWS'; + this.version = props.version || '1'; + this.category = props.category; + this.provider = props.provider; + this.configuration = props.configuration; + this.artifactBounds = props.artifactBounds; + this.runOrder = 1; + this.stage = props.stage; + + this.stage._addAction(this); + } + + public validate(): string[] { + return validation.validateArtifactBounds('input', this._inputArtifacts, this.artifactBounds.minInputs, + this.artifactBounds.maxInputs, this.category, this.provider) + .concat(validation.validateArtifactBounds('output', this._outputArtifacts, this.artifactBounds.minOutputs, + this.artifactBounds.maxOutputs, this.category, this.provider) + ); + } + + public onStateChange(name: string, target?: events.IEventRuleTarget, options?: events.EventRuleProps) { + const rule = new events.EventRule(this.parent!!, name, options); + rule.addTarget(target); + rule.addEventPattern({ + detailType: [ 'CodePipeline Stage Execution State Change' ], + source: [ 'aws.codepipeline' ], + resources: [ this.stage.pipelineArn ], + detail: { + stage: [ this.stage.name ], + action: [ this.name ], + }, + }); + return rule; + } + + public get inputArtifacts(): Artifact[] { + return this._inputArtifacts.slice(); + } + + public get outputArtifacts(): Artifact[] { + return this._outputArtifacts.slice(); + } + + protected addChild(child: cdk.Construct, name: string) { + super.addChild(child, name); + if (child instanceof Artifact) { + this._outputArtifacts.push(child); + } + } + + protected addOutputArtifact(name: string): Artifact { + const artifact = new Artifact(this, name); + return artifact; + } + + protected addInputArtifact(artifact: Artifact): Action { + this._inputArtifacts.push(artifact); + return this; + } +} + +// export class TestAction extends Action { +// constructor(parent: Stage, name: string, provider: string, artifactBounds: ActionArtifactBounds, configuration?: any) { +// super(parent, name, { +// category: ActionCategory.Test, +// provider, +// artifactBounds, +// configuration +// }); +// } +// } + +// export class CodeBuildTest extends TestAction { +// constructor(parent: Stage, name: string, project: codebuild.ProjectArnAttribute) { +// super(parent, name, 'CodeBuild', { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 1 }, { +// ProjectName: project +// }); +// } +// } + +// export class CodeDeploy extends DeployAction { +// constructor(parent: Stage, name: string, applicationName: string, deploymentGroupName: string) { +// super(parent, name, 'CodeDeploy', { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 0 }, { +// ApplicationName: applicationName, +// DeploymentGroupName: deploymentGroupName +// }); +// } +// } + +// export class ElasticBeanstalkDeploy extends DeployAction { +// constructor(parent: Stage, name: string, applicationName: string, environmentName: string) { +// super(parent, name, 'ElasticBeanstalk', { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 0 }, { +// ApplicationName: applicationName, +// EnvironmentName: environmentName +// }); +// } +// } + +// export class OpsWorksDeploy extends DeployAction { +// constructor(parent: Stage, name: string, app: string, stack: string, layer?: string) { +// super(parent, name, 'OpsWorks', { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 0 }, { +// Stack: stack, +// App: app, +// Layer: layer, +// }); +// } +// } + +// export class ECSDeploy extends DeployAction { +// constructor(parent: Stage, name: string, clusterName: string, serviceName: string, fileName?: string) { +// super(parent, name, 'ECS', { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 0 }, { +// ClusterName: clusterName, +// ServiceName: serviceName, +// FileName: fileName, +// }); +// } +// } + +/* + TODO: A Jenkins build needs a corresponding custom action for each "Jenkins provider". + This should be created automatically. + + Example custom action created to execute Jenkins: + { + "id": { + "category": "Test", + "provider": "", + "owner": "Custom", + "version": "1" + }, + "outputArtifactDetails": { + "minimumCount": 0, + "maximumCount": 5 + }, + "settings": { + "executionUrlTemplate": "https://www.google.com/job/{Config:ProjectName}/{ExternalExecutionId}", + "entityUrlTemplate": "https://www.google.com/job/{Config:ProjectName}" + }, + "actionConfigurationProperties": [ + { + "queryable": true, + "key": true, + "name": "ProjectName", + "required": true, + "secret": false + } + ], + "inputArtifactDetails": { + "minimumCount": 0, + "maximumCount": 5 + } + } +*/ + +// export class JenkinsBuild extends BuildAction { +// constructor(parent: Stage, name: string, jenkinsProvider: string, project: string) { +// super(parent, name, jenkinsProvider, DefaultBounds(), { +// ProjectName: project +// }); +// } +// } + +// export class JenkinsTest extends TestAction { +// constructor(parent: Stage, name: string, jenkinsProvider: string, project: string) { +// super(parent, name, jenkinsProvider, DefaultBounds(), { +// ProjectName: project +// }); +// } +// } diff --git a/packages/@aws-cdk/aws-codepipeline/lib/artifact.ts b/packages/@aws-cdk/aws-codepipeline-api/lib/artifact.ts similarity index 98% rename from packages/@aws-cdk/aws-codepipeline/lib/artifact.ts rename to packages/@aws-cdk/aws-codepipeline-api/lib/artifact.ts index eb51d721f96e8..6663e5375effa 100644 --- a/packages/@aws-cdk/aws-codepipeline/lib/artifact.ts +++ b/packages/@aws-cdk/aws-codepipeline-api/lib/artifact.ts @@ -1,5 +1,5 @@ import { Construct, Token } from "@aws-cdk/cdk"; -import { Action } from "./actions"; +import { Action } from "./action"; /** * @link https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/continuous-delivery-codepipeline-parameter-override-functions.html diff --git a/packages/@aws-cdk/aws-codepipeline-api/lib/build-action.ts b/packages/@aws-cdk/aws-codepipeline-api/lib/build-action.ts new file mode 100644 index 0000000000000..3e0af470ef214 --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-api/lib/build-action.ts @@ -0,0 +1,55 @@ +import cdk = require("@aws-cdk/cdk"); +import { CommonActionProps, Action, ActionCategory } from "./action"; +import { Artifact } from "./artifact"; + +/** + * Construction properties of the low level {@link BuildAction build action}. + */ +export interface BuildActionProps extends CommonActionProps { + /** + * The source to use as input for this build. + */ + inputArtifact: Artifact; + + /** + * The service provider that the action calls. For example, a valid provider for Source actions is CodeBuild. + */ + provider: string; + + /** + * The name of the build's output artifact. + */ + artifactName?: string; + + /** + * The action's configuration. These are key-value pairs that specify input values for an action. + * For more information, see the AWS CodePipeline User Guide. + * + * http://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#action-requirements + */ + configuration?: any; +} + +/** + * Low level class for build actions. + * It is recommended that concrete types are used instead, + * such as {@link codebuild.PipelineBuildAction}. + */ +export abstract class BuildAction extends Action { + public readonly artifact?: Artifact; + + constructor(parent: cdk.Construct, name: string, props: BuildActionProps) { + super(parent, name, { + stage: props.stage, + artifactBounds: { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 1 }, + category: ActionCategory.Build, + provider: props.provider, + configuration: props.configuration + }); + + this.addInputArtifact(props.inputArtifact); + if (props.artifactName) { + this.artifact = this.addOutputArtifact(props.artifactName); + } + } +} diff --git a/packages/@aws-cdk/aws-codepipeline-api/lib/deploy-action.ts b/packages/@aws-cdk/aws-codepipeline-api/lib/deploy-action.ts new file mode 100644 index 0000000000000..9ab57e392a972 --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-api/lib/deploy-action.ts @@ -0,0 +1,22 @@ +import cdk = require('@aws-cdk/cdk'); +import { CommonActionProps, Action, ActionArtifactBounds, ActionCategory } from "./action"; + +export interface DeployActionProps extends CommonActionProps { + provider: string; + + artifactBounds: ActionArtifactBounds; + + configuration?: any; +} + +export abstract class DeployAction extends Action { + constructor(parent: cdk.Construct, name: string, props: DeployActionProps) { + super(parent, name, { + stage: props.stage, + category: ActionCategory.Deploy, + provider: props.provider, + artifactBounds: props.artifactBounds, + configuration: props.configuration, + }); + } +} diff --git a/packages/@aws-cdk/aws-codepipeline-api/lib/index.ts b/packages/@aws-cdk/aws-codepipeline-api/lib/index.ts new file mode 100644 index 0000000000000..74b5c6eb9d8a4 --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-api/lib/index.ts @@ -0,0 +1,6 @@ +export * from './artifact'; +export * from './action'; +export * from './build-action'; +export * from './deploy-action'; +export * from './source-action'; +export * from './validation'; diff --git a/packages/@aws-cdk/aws-codepipeline-api/lib/source-action.ts b/packages/@aws-cdk/aws-codepipeline-api/lib/source-action.ts new file mode 100644 index 0000000000000..d836e2d1f5fec --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline-api/lib/source-action.ts @@ -0,0 +1,66 @@ +import cdk = require("@aws-cdk/cdk"); +import { CommonActionProps, Action, ActionCategory } from "./action"; +import { Artifact } from "./artifact"; + +/** + * Construction properties of the low-level {@link SourceAction source Action}. + */ +export interface SourceActionProps extends CommonActionProps { + /** + * The source action owner (could be "AWS", "ThirdParty" or "Custom"). + * + * @default "AWS" + */ + owner?: string; + + /** + * The source action verison. + * + * @default "1" + */ + version?: string; + + /** + * The name of the source's output artifact. + * Output artifacts are used by CodePipeline as inputs into other actions. + */ + artifactName: string; + + /** + * The service provider that the action calls. + * For example, a valid provider for Source actions is "S3". + */ + provider: string; + + /** + * The action's configuration. These are key-value pairs that specify input values for an action. + * For more information, see the AWS CodePipeline User Guide. + * + * http://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#action-requirements + */ + configuration?: any; +} + +/** + * Low-level class for source actions. + * It is recommended that concrete types are used instead, + * such as {@link codepipeline.AmazonS3Source} or + * {@link codecommit.PipelineSource}. + */ +export abstract class SourceAction extends Action { + public readonly artifact: Artifact; + + constructor(parent: cdk.Construct, name: string, props: SourceActionProps) { + super(parent, name, { + stage: props.stage, + category: ActionCategory.Source, + owner: props.owner, + provider: props.provider, + version: props.version, + artifactBounds: { minInputs: 0, maxInputs: 0, minOutputs: 1, maxOutputs: 1 }, + configuration: props.configuration + }); + + this.artifact = this.addOutputArtifact(props.artifactName); + } +} diff --git a/packages/@aws-cdk/aws-codepipeline/lib/validation.ts b/packages/@aws-cdk/aws-codepipeline-api/lib/validation.ts similarity index 97% rename from packages/@aws-cdk/aws-codepipeline/lib/validation.ts rename to packages/@aws-cdk/aws-codepipeline-api/lib/validation.ts index 9769851bed353..2859cb833156d 100644 --- a/packages/@aws-cdk/aws-codepipeline/lib/validation.ts +++ b/packages/@aws-cdk/aws-codepipeline-api/lib/validation.ts @@ -1,4 +1,4 @@ -import { ActionCategory } from "./actions"; +import { ActionCategory } from "./action"; import { Artifact } from "./artifact"; /** @@ -47,4 +47,4 @@ export function validateName(thing: string, name: string | undefined) { if (name !== undefined && !VALID_IDENTIFIER_REGEX.test(name)) { throw new Error(`${thing} name must match regular expression: ${VALID_IDENTIFIER_REGEX.toString()}, got '${name}'`); } -} \ No newline at end of file +} diff --git a/packages/@aws-cdk/aws-codecommit-codepipeline/package.json b/packages/@aws-cdk/aws-codepipeline-api/package.json similarity index 68% rename from packages/@aws-cdk/aws-codecommit-codepipeline/package.json rename to packages/@aws-cdk/aws-codepipeline-api/package.json index ed18e206254de..72ce83307739f 100644 --- a/packages/@aws-cdk/aws-codecommit-codepipeline/package.json +++ b/packages/@aws-cdk/aws-codepipeline-api/package.json @@ -1,17 +1,17 @@ { - "name": "@aws-cdk/aws-codecommit-codepipeline", + "name": "@aws-cdk/aws-codepipeline-api", "version": "0.8.1", - "description": "AWS CodePipline Actions for AWS CodeCommit", + "description": "Actions API for AWS Code Pipeline", "main": "lib/index.js", "types": "lib/index.d.ts", "jsii": { "outdir": "dist", "targets": { "java": { - "package": "software.amazon.awscdk.services.codecommit.codepipeline", + "package": "software.amazon.awscdk.services.codepipeline.api", "maven": { "groupId": "software.amazon.awscdk", - "artifactId": "codecommit-codepipeline" + "artifactId": "codepipeline-api" } }, "sphinx": {} @@ -30,16 +30,14 @@ "pkglint": "pkglint -f", "package": "cdk-package" }, - "nyc": { - "lines": 60, - "branches": 30 - }, "keywords": [ "aws", + "aws-clib", + "aws-cloudlib", "cdk", - "codecommit", + "cloudlib", "codepipeline", - "constructs" + "pipeline" ], "author": { "name": "Amazon Web Services", @@ -54,9 +52,13 @@ "pkglint": "^0.8.1" }, "dependencies": { - "@aws-cdk/aws-codecommit": "^0.8.1", - "@aws-cdk/aws-codepipeline": "^0.8.1", - "@aws-cdk/cdk": "^0.8.1" + "@aws-cdk/aws-events": "^0.8.1", + "@aws-cdk/aws-iam": "^0.8.1", + "@aws-cdk/cdk": "^0.8.1", + "@aws-cdk/util": "^0.8.1" }, + "bundledDependencies": [ + "@aws-cdk/util" + ], "homepage": "https://github.com/awslabs/aws-cdk" } diff --git a/packages/@aws-cdk/aws-codepipeline/README.md b/packages/@aws-cdk/aws-codepipeline/README.md index c89bf4a6f6351..e37b61d115e03 100644 --- a/packages/@aws-cdk/aws-codepipeline/README.md +++ b/packages/@aws-cdk/aws-codepipeline/README.md @@ -3,7 +3,9 @@ Construct an empty pipeline: ```ts -const pipeline = new Pipeline(this, 'MyFirstPipeline'); +const pipeline = new Pipeline(this, 'MyFirstPipeline', { + pipelineName: 'MyFirstPipeline', +}); ``` All of the components of a pipeline are modeled as constructs. @@ -17,7 +19,8 @@ const sourceStage = new Stage(pipeline, 'Source'); Add an action to a stage: ```ts -new codecommit.PipelineSource(sourceStage, 'source', { +new codecommit.PipelineSource(this, 'Source', { + stage: sourceStage, artifactName: 'MyPackageSourceArtifact', repository: codecommit.RepositoryRef.import(this, 'MyExistingRepository', { repositoryName: new codecommit.RepositoryName('MyExistingRepository'), diff --git a/packages/@aws-cdk/aws-codepipeline/lib/actions.ts b/packages/@aws-cdk/aws-codepipeline/lib/actions.ts deleted file mode 100644 index 5b89af927f753..0000000000000 --- a/packages/@aws-cdk/aws-codepipeline/lib/actions.ts +++ /dev/null @@ -1,562 +0,0 @@ -import events = require('@aws-cdk/aws-events'); -import s3 = require('@aws-cdk/aws-s3'); -import cdk = require('@aws-cdk/cdk'); -import { Artifact } from './artifact'; -import { cloudformation } from './codepipeline.generated'; -import { Stage } from './stage'; -import validation = require('./validation'); - -export enum ActionCategory { - Source = 'Source', - Build = 'Build', - Test = 'Test', - Approval = 'Approval', - Deploy = 'Deploy', - Invoke = 'Invoke' -} - -/** - * Specifies the constraints on the number of input and output - * artifacts an action can have. - * - * The constraints for each action type are documented on the - * {@link https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html Pipeline Structure Reference} page. - */ -export interface ActionArtifactBounds { - minInputs: number; - maxInputs: number; - minOutputs: number; - maxOutputs: number; -} - -export function defaultBounds(): ActionArtifactBounds { - return { - minInputs: 0, - maxInputs: 5, - minOutputs: 0, - maxOutputs: 5 - }; -} - -/** - * Construction properties of the low level {@link Action action type}. - */ -export interface ActionProps { - /** - * A category that defines which action type the owner (the entity that performs the action) performs. - * The category that you select determine the providers that you can specify for the {@link #provider} property. - */ - category: ActionCategory; - - /** - * The service provider that the action calls. The providers that you can specify are determined by - * the category that you select. For example, a valid provider for the Deploy category is AWS CodeDeploy, - * which you would specify as CodeDeploy. - */ - provider: string; - - /** - * The constraints to apply to the number of input and output artifacts used by this action. - */ - artifactBounds: ActionArtifactBounds; - - /** - * The action's configuration. These are key-value pairs that specify input values for an action. - * For more information, see the AWS CodePipeline User Guide. - * - * http://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#action-requirements - */ - configuration?: any; - - /** - * For all currently supported action types, the only valid version string is "1". - * - * @default 1 - */ - version?: string; - - /** - * For all currently supported action types, the only valid owner string is - * "AWS", "ThirdParty", or "Custom". For more information, see the AWS - * CodePipeline API Reference. - * - * @default 'AWS' - */ - owner?: string; -} - -/** - * Low level class for generically creating pipeline actions. - * It is recommended that concrete types are used instead, such as {@link codecommit.PipelineSource} or - * {@link codebuild.PipelineBuildAction}. - */ -export abstract class Action extends cdk.Construct { - /** - * The category of the action. The category defines which action type the owner (the entity that performs the action) performs. - */ - public readonly category: ActionCategory; - - /** - * The service provider that the action calls. - */ - public readonly provider: string; - - /** - * The action's configuration. These are key-value pairs that specify input values for an action. - * For more information, see the AWS CodePipeline User Guide. - * - * http://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#action-requirements - */ - public readonly configuration?: any; - - /** - * The order in which AWS CodePipeline runs this action. - * For more information, see the AWS CodePipeline User Guide. - * - * https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#action-requirements - */ - public runOrder: number; - - private readonly artifactBounds: ActionArtifactBounds; - private readonly inputArtifacts = new Array(); - private readonly outputArtifacts = new Array(); - private readonly owner: string; - private readonly version: string; - private readonly stage: Stage; - - constructor(parent: Stage, name: string, props: ActionProps) { - super(parent, name); - - validation.validateName('Action', name); - - this.owner = props.owner || 'AWS'; - this.version = props.version || '1'; - this.category = props.category; - this.provider = props.provider; - this.configuration = props.configuration; - this.artifactBounds = props.artifactBounds; - this.runOrder = 1; - this.stage = parent; - } - - public validate(): string[] { - return validation.validateArtifactBounds('input', this.inputArtifacts, this.artifactBounds.minInputs, - this.artifactBounds.maxInputs, this.category, this.provider) - .concat(validation.validateArtifactBounds('output', this.outputArtifacts, this.artifactBounds.minOutputs, - this.artifactBounds.maxOutputs, this.category, this.provider) - ); - } - - /** - * Render the Action to a CloudFormation struct - */ - public render(): cloudformation.PipelineResource.ActionDeclarationProperty { - return { - name: this.name, - inputArtifacts: this.inputArtifacts.map(a => ({ name: a.name })), - actionTypeId: { - category: this.category.toString(), - version: this.version, - owner: this.owner, - provider: this.provider, - }, - configuration: this.configuration, - outputArtifacts: this.outputArtifacts.map(a => ({ name: a.name })), - runOrder: this.runOrder - }; - } - - public onStateChange(name: string, target?: events.IEventRuleTarget, options?: events.EventRuleProps) { - const rule = new events.EventRule(this.stage.pipeline, name, options); - rule.addTarget(target); - rule.addEventPattern({ - detailType: [ 'CodePipeline Stage Execution State Change' ], - source: [ 'aws.codepipeline' ], - resources: [ this.stage.pipeline.pipelineArn ], - detail: { - stage: [ this.stage.name ], - action: [ this.name ], - }, - }); - return rule; - } - - /** - * If an Artifact is added as a child, add it to the list of output artifacts. - */ - protected addChild(child: cdk.Construct, name: string) { - super.addChild(child, name); - if (child instanceof Artifact) { - this.outputArtifacts.push(child); - } - } - - protected addOutputArtifact(name: string): Artifact { - const artifact = new Artifact(this, name); - return artifact; - } - - protected addInputArtifact(artifact: Artifact): Action { - this.inputArtifacts.push(artifact); - return this; - } -} - -/** - * Construction properties of the low level {@link Source source action} - */ -export interface SourceProps { - /** - * The source action owner (could e "AWS", "ThirdParty" or "Custom") - * - * @default AWS - */ - owner?: string; - - /** - * The source action verison. - * - * @default "1" - */ - version?: string; - - /** - * The name of the source's output artifact. Output artifacts are used by CodePipeline as - * inputs into other actions. - */ - artifactName: string; - - /** - * The service provider that the action calls. For example, a valid provider for Source actions is S3. - */ - provider: string; - - /** - * The action's configuration. These are key-value pairs that specify input values for an action. - * For more information, see the AWS CodePipeline User Guide. - * - * http://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#action-requirements - */ - configuration?: any; -} - -/** - * Low level class for source actions. - * It is recommended that concrete types are used instead, such as {@link AmazonS3Source} or - * {@link codecommit.PipelineSource}. - */ -export abstract class Source extends Action { - public readonly artifact: Artifact; - - constructor(parent: Stage, name: string, props: SourceProps) { - super(parent, name, { - category: ActionCategory.Source, - owner: props.owner, - provider: props.provider, - version: props.version, - artifactBounds: { minInputs: 0, maxInputs: 0, minOutputs: 1, maxOutputs: 1 }, - configuration: props.configuration - }); - - this.artifact = this.addOutputArtifact(props.artifactName); - } -} - -/** - * Construction properties of the {@link AmazonS3Source S3 source action} - */ -export interface AmazonS3SourceProps { - /** - * The name of the source's output artifact. Output artifacts are used by CodePipeline as - * inputs into other actions. - */ - artifactName: string; - - /** - * The Amazon S3 bucket that stores the source code - */ - bucket: s3.BucketRef; - - /** - * The key within the S3 bucket that stores the source code - */ - bucketKey: string; - - // TODO: use CloudWatch events instead - /** - * Whether or not AWS CodePipeline should poll for source changes - * - * @default true - */ - pollForSourceChanges?: boolean; -} - -/** - * Source that is provided by a specific Amazon S3 object - */ -export class AmazonS3Source extends Source { - constructor(parent: Stage, name: string, props: AmazonS3SourceProps) { - super(parent, name, { - provider: 'S3', - configuration: { - S3Bucket: props.bucket.bucketName, - S3ObjectKey: props.bucketKey, - PollForSourceChanges: props.pollForSourceChanges || true - }, - artifactName: props.artifactName - }); - - // pipeline needs permissions to read from the S3 bucket - props.bucket.grantRead(parent.pipeline.role); - } -} - -/** - * Construction properties of the {@link GitHubSource GitHub source action} - */ -export interface GithubSourceProps { - /** - * The name of the source's output artifact. Output artifacts are used by CodePipeline as - * inputs into other actions. - */ - artifactName: string; - - /** - * The GitHub account/user that owns the repo. - */ - owner: string; - - /** - * The name of the repo, without the username. - */ - repo: string; - - /** - * The branch to use. - * - * @default "master" - */ - branch?: string; - - /** - * A GitHub OAuth token to use for authentication. - * - * It is recommended to use a `SecretParameter` to obtain the token from the SSM - * Parameter Store: - * - * const oauth = new SecretParameter(this, 'GitHubOAuthToken', { ssmParameter: 'my-github-token }); - * new GitHubSource(stage, 'GH' { oauthToken: oauth }); - * - */ - oauthToken: cdk.Secret; - - /** - * Whether or not AWS CodePipeline should poll for source changes - * - * @default true - */ - pollForSourceChanges?: boolean; -} - -/** - * Source that is provided by a GitHub repository - */ -export class GitHubSource extends Source { - constructor(parent: Stage, name: string, props: GithubSourceProps) { - super(parent, name, { - owner: 'ThirdParty', - provider: 'GitHub', - configuration: { - Owner: props.owner, - Repo: props.repo, - Branch: props.branch || "master", - OAuthToken: props.oauthToken, - PollForSourceChanges: props.pollForSourceChanges || true - }, - artifactName: props.artifactName - }); - } -} - -/** - * Construction properties of the low level {@link BuildAction build action} - */ -export interface BuildActionProps { - /** - * The source to use as input for this build - */ - inputArtifact: Artifact; - - /** - * The service provider that the action calls. For example, a valid provider for Source actions is CodeBuild. - */ - provider: string; - - /** - * The name of the build's output artifact - */ - artifactName?: string; - - /** - * The action's configuration. These are key-value pairs that specify input values for an action. - * For more information, see the AWS CodePipeline User Guide. - * - * http://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#action-requirements - */ - configuration?: any; -} - -/** - * Low level class for build actions. - * It is recommended that concrete types are used instead, such as {@link codebuild.PipelineBuildAction}. - */ -export abstract class BuildAction extends Action { - public readonly artifact?: Artifact; - - constructor(parent: Stage, name: string, props: BuildActionProps) { - super(parent, name, { - artifactBounds: { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 1 }, - category: ActionCategory.Build, - provider: props.provider, - configuration: props.configuration - }); - - this.addInputArtifact(props.inputArtifact); - if (props.artifactName) { - this.artifact = this.addOutputArtifact(props.artifactName); - } - } -} - -/** - * Manual approval action - */ -export class ApprovalAction extends Action { - constructor(parent: Stage, name: string) { - super(parent, name, { - category: ActionCategory.Approval, - provider: 'Manual', - artifactBounds: { minInputs: 0, maxInputs: 0, minOutputs: 0, maxOutputs: 0 } - }); - } -} - -// export class TestAction extends Action { -// constructor(parent: Stage, name: string, provider: string, artifactBounds: ActionArtifactBounds, configuration?: any) { -// super(parent, name, { -// category: ActionCategory.Test, -// provider, -// artifactBounds, -// configuration -// }); -// } -// } - -// export class CodeBuildTest extends TestAction { -// constructor(parent: Stage, name: string, project: codebuild.ProjectArnAttribute) { -// super(parent, name, 'CodeBuild', { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 1 }, { -// ProjectName: project -// }); -// } -// } - -export class DeployAction extends Action { - constructor(parent: Stage, name: string, provider: string, artifactBounds: ActionArtifactBounds, configuration?: any) { - super(parent, name, { - category: ActionCategory.Deploy, - provider, - artifactBounds, - configuration - }); - } -} - -// export class CodeDeploy extends DeployAction { -// constructor(parent: Stage, name: string, applicationName: string, deploymentGroupName: string) { -// super(parent, name, 'CodeDeploy', { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 0 }, { -// ApplicationName: applicationName, -// DeploymentGroupName: deploymentGroupName -// }); -// } -// } - -// export class ElasticBeanstalkDeploy extends DeployAction { -// constructor(parent: Stage, name: string, applicationName: string, environmentName: string) { -// super(parent, name, 'ElasticBeanstalk', { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 0 }, { -// ApplicationName: applicationName, -// EnvironmentName: environmentName -// }); -// } -// } - -// export class OpsWorksDeploy extends DeployAction { -// constructor(parent: Stage, name: string, app: string, stack: string, layer?: string) { -// super(parent, name, 'OpsWorks', { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 0 }, { -// Stack: stack, -// App: app, -// Layer: layer, -// }); -// } -// } - -// export class ECSDeploy extends DeployAction { -// constructor(parent: Stage, name: string, clusterName: string, serviceName: string, fileName?: string) { -// super(parent, name, 'ECS', { minInputs: 1, maxInputs: 1, minOutputs: 0, maxOutputs: 0 }, { -// ClusterName: clusterName, -// ServiceName: serviceName, -// FileName: fileName, -// }); -// } -// } - -/* - TODO: A Jenkins build needs a corresponding custom action for each "Jenkins provider". - This should be created automatically. - - Example custom action created to execute Jenkins: - { - "id": { - "category": "Test", - "provider": "", - "owner": "Custom", - "version": "1" - }, - "outputArtifactDetails": { - "minimumCount": 0, - "maximumCount": 5 - }, - "settings": { - "executionUrlTemplate": "https://www.google.com/job/{Config:ProjectName}/{ExternalExecutionId}", - "entityUrlTemplate": "https://www.google.com/job/{Config:ProjectName}" - }, - "actionConfigurationProperties": [ - { - "queryable": true, - "key": true, - "name": "ProjectName", - "required": true, - "secret": false - } - ], - "inputArtifactDetails": { - "minimumCount": 0, - "maximumCount": 5 - } - } -*/ - -// export class JenkinsBuild extends BuildAction { -// constructor(parent: Stage, name: string, jenkinsProvider: string, project: string) { -// super(parent, name, jenkinsProvider, DefaultBounds(), { -// ProjectName: project -// }); -// } -// } - -// export class JenkinsTest extends TestAction { -// constructor(parent: Stage, name: string, jenkinsProvider: string, project: string) { -// super(parent, name, jenkinsProvider, DefaultBounds(), { -// ProjectName: project -// }); -// } -// } diff --git a/packages/@aws-cdk/aws-codepipeline/lib/github-source-action.ts b/packages/@aws-cdk/aws-codepipeline/lib/github-source-action.ts new file mode 100644 index 0000000000000..037991d92b0a6 --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline/lib/github-source-action.ts @@ -0,0 +1,70 @@ +import actions = require('@aws-cdk/aws-codepipeline-api'); +import cdk = require('@aws-cdk/cdk'); + +/** + * Construction properties of the {@link GitHubSource GitHub source action}. + */ +export interface GitHubSourceProps extends actions.CommonActionProps { + /** + * The name of the source's output artifact. Output artifacts are used by CodePipeline as + * inputs into other actions. + */ + artifactName: string; + + /** + * The GitHub account/user that owns the repo. + */ + owner: string; + + /** + * The name of the repo, without the username. + */ + repo: string; + + /** + * The branch to use. + * + * @default "master" + */ + branch?: string; + + /** + * A GitHub OAuth token to use for authentication. + * + * It is recommended to use a `SecretParameter` to obtain the token from the SSM + * Parameter Store: + * + * const oauth = new SecretParameter(this, 'GitHubOAuthToken', { ssmParameter: 'my-github-token }); + * new GitHubSource(stage, 'GH' { oauthToken: oauth }); + * + */ + oauthToken: cdk.Secret; + + /** + * Whether or not AWS CodePipeline should poll for source changes + * + * @default true + */ + pollForSourceChanges?: boolean; +} + +/** + * Source that is provided by a GitHub repository. + */ +export class GitHubSource extends actions.SourceAction { + constructor(parent: cdk.Construct, name: string, props: GitHubSourceProps) { + super(parent, name, { + stage: props.stage, + owner: 'ThirdParty', + provider: 'GitHub', + configuration: { + Owner: props.owner, + Repo: props.repo, + Branch: props.branch || "master", + OAuthToken: props.oauthToken, + PollForSourceChanges: props.pollForSourceChanges || true + }, + artifactName: props.artifactName + }); + } +} diff --git a/packages/@aws-cdk/aws-codepipeline/lib/index.ts b/packages/@aws-cdk/aws-codepipeline/lib/index.ts index afa10c509b913..98b314f4f59aa 100644 --- a/packages/@aws-cdk/aws-codepipeline/lib/index.ts +++ b/packages/@aws-cdk/aws-codepipeline/lib/index.ts @@ -1,6 +1,7 @@ -export * from './actions'; -export * from './artifact'; +export * from './github-source-action'; +export * from './manual-approval-action'; export * from './pipeline'; +export * from './s3-source-action'; export * from './stage'; // AWS::CodePipeline CloudFormation Resources: diff --git a/packages/@aws-cdk/aws-codepipeline/lib/manual-approval-action.ts b/packages/@aws-cdk/aws-codepipeline/lib/manual-approval-action.ts new file mode 100644 index 0000000000000..f40043d9d05b0 --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline/lib/manual-approval-action.ts @@ -0,0 +1,20 @@ +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 { +} + +/** + * Manual approval action. + */ +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 } + }); + } +} diff --git a/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts b/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts index fe226459edb8e..7517226e98694 100644 --- a/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts +++ b/packages/@aws-cdk/aws-codepipeline/lib/pipeline.ts @@ -1,3 +1,4 @@ +import actions = require('@aws-cdk/aws-codepipeline-api'); import events = require('@aws-cdk/aws-events'); import iam = require('@aws-cdk/aws-iam'); import s3 = require('@aws-cdk/aws-s3'); @@ -5,7 +6,6 @@ import cdk = require('@aws-cdk/cdk'); import util = require('@aws-cdk/util'); import { cloudformation } from './codepipeline.generated'; import { Stage } from './stage'; -import validation = require('./validation'); /** * The ARN of a pipeline @@ -93,7 +93,7 @@ export class Pipeline extends cdk.Construct implements events.IEventRuleTarget { super(parent, name); props = props || {}; - validation.validateName('Pipeline', props.pipelineName); + actions.validateName('Pipeline', props.pipelineName); // If a bucket has been provided, use it - otherwise, create a bucket. let propsBucket = props.artifactBucket; @@ -235,7 +235,7 @@ export class Pipeline extends cdk.Construct implements events.IEventRuleTarget { return util.flatMap(this.stages, (stage, i) => { const onlySourceActionsPermitted = i === 0; return util.flatMap(stage.actions, (action, _) => - validation.validateSourceAction(onlySourceActionsPermitted, action.category, action.name, stage.name) + actions.validateSourceAction(onlySourceActionsPermitted, action.category, action.name, stage.name) ); }); } diff --git a/packages/@aws-cdk/aws-codepipeline/lib/s3-source-action.ts b/packages/@aws-cdk/aws-codepipeline/lib/s3-source-action.ts new file mode 100644 index 0000000000000..d134810d76794 --- /dev/null +++ b/packages/@aws-cdk/aws-codepipeline/lib/s3-source-action.ts @@ -0,0 +1,53 @@ +import actions = require('@aws-cdk/aws-codepipeline-api'); +import s3 = require('@aws-cdk/aws-s3'); +import cdk = require('@aws-cdk/cdk'); + +/** + * Construction properties of the {@link AmazonS3Source S3 source action}. + */ +export interface AmazonS3SourceProps extends actions.CommonActionProps { + /** + * The name of the source's output artifact. Output artifacts are used by CodePipeline as + * inputs into other actions. + */ + artifactName: string; + + /** + * The Amazon S3 bucket that stores the source code + */ + bucket: s3.BucketRef; + + /** + * The key within the S3 bucket that stores the source code + */ + bucketKey: string; + + // TODO: use CloudWatch events instead + /** + * Whether or not AWS CodePipeline should poll for source changes + * + * @default true + */ + pollForSourceChanges?: boolean; +} + +/** + * Source that is provided by a specific Amazon S3 object. + */ +export class AmazonS3Source extends actions.SourceAction { + constructor(parent: cdk.Construct, name: string, props: AmazonS3SourceProps) { + super(parent, name, { + stage: props.stage, + provider: 'S3', + configuration: { + S3Bucket: props.bucket.bucketName, + S3ObjectKey: props.bucketKey, + PollForSourceChanges: props.pollForSourceChanges || true + }, + artifactName: props.artifactName + }); + + // pipeline needs permissions to read from the S3 bucket + props.bucket.grantRead(props.stage.pipelineRole); + } +} diff --git a/packages/@aws-cdk/aws-codepipeline/lib/stage.ts b/packages/@aws-cdk/aws-codepipeline/lib/stage.ts index 3f74cf9db9985..763e805d28445 100644 --- a/packages/@aws-cdk/aws-codepipeline/lib/stage.ts +++ b/packages/@aws-cdk/aws-codepipeline/lib/stage.ts @@ -1,9 +1,9 @@ +import actions = 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 { Action } from './actions'; import { cloudformation } from './codepipeline.generated'; import { Pipeline } from './pipeline'; -import validation = require('./validation'); /** * A stage in a pipeline. Stages are added to a pipeline by constructing a Stage with @@ -13,12 +13,14 @@ import validation = require('./validation'); * // add a stage to a pipeline * new Stage(pipeline, 'MyStage'); */ -export class Stage extends cdk.Construct { +export class Stage extends cdk.Construct implements actions.IStage { /** * The Pipeline this stage is a member of */ public readonly pipeline: Pipeline; - private readonly _actions = new Array(); + public readonly name: string; + + private readonly _actions = new Array(); /** * Append a new stage to the pipeline @@ -29,14 +31,15 @@ export class Stage extends cdk.Construct { */ constructor(parent: Pipeline, name: string) { super(parent, name); + this.name = name; this.pipeline = parent; - validation.validateName('Stage', name); + actions.validateName('Stage', name); } /** * Get a duplicate of this stage's list of actions. */ - public get actions(): Action[] { + public get actions(): actions.Action[] { return this._actions.slice(); } @@ -44,10 +47,14 @@ export class Stage extends cdk.Construct { return this.validateHasActions(); } + public grantPipelineBucketReadWrite(identity?: iam.IPrincipal): void { + this.pipeline.artifactBucket.grantReadWrite(identity); + } + public render(): cloudformation.PipelineResource.StageDeclarationProperty { return { name: this.name, - actions: this._actions.map(action => action.render()) + actions: this._actions.map(action => this.renderAction(action)) }; } @@ -65,23 +72,37 @@ export class Stage extends cdk.Construct { return rule; } - /** - * If an action is added as a child, add it to the list of actions. - * TODO: This is a hack that should be removed once the CDK has an - * onChildAdded type hook. - * @override - * @param child - * @param name - */ - protected addChild(child: cdk.Construct, name: string) { - super.addChild(child, name); - if (child instanceof Action) { - this._actions.push(child); - } else { - throw new Error('Only Actions can be added as children to a Stage'); + public get pipelineArn(): cdk.Arn { + return this.pipeline.pipelineArn; + } + + public get pipelineRole(): iam.Role { + return this.pipeline.role; + } + + public _addAction(action: actions.Action): void { + // _addAction should be idempotent in case a customer ever calls it directly + if (!this._actions.includes(action)) { + this._actions.push(action); } } + private renderAction(action: actions.Action): cloudformation.PipelineResource.ActionDeclarationProperty { + return { + name: action.name, + inputArtifacts: action.inputArtifacts.map(a => ({ name: a.name })), + actionTypeId: { + category: action.category.toString(), + version: action.version, + owner: action.owner, + provider: action.provider, + }, + configuration: action.configuration, + outputArtifacts: action.outputArtifacts.map(a => ({ name: a.name })), + runOrder: action.runOrder, + }; + } + private validateHasActions(): string[] { if (this._actions.length === 0) { return [`Stage '${this.name}' must have at least one action`]; diff --git a/packages/@aws-cdk/aws-codepipeline/package.json b/packages/@aws-cdk/aws-codepipeline/package.json index 2f602631be6be..ebc15faf11afc 100644 --- a/packages/@aws-cdk/aws-codepipeline/package.json +++ b/packages/@aws-cdk/aws-codepipeline/package.json @@ -38,10 +38,12 @@ }, "keywords": [ "aws", + "aws-clib", + "aws-cloudlib", "cdk", "cloudlib", - "aws-cloudlib", - "aws-clib" + "codepipeline", + "pipeline" ], "author": { "name": "Amazon Web Services", @@ -51,6 +53,10 @@ "license": "Apache-2.0", "devDependencies": { "@aws-cdk/assert": "^0.8.1", + "@aws-cdk/aws-cloudformation": "^0.8.1", + "@aws-cdk/aws-codebuild": "^0.8.1", + "@aws-cdk/aws-codecommit": "^0.8.1", + "@aws-cdk/aws-lambda": "^0.8.1", "@aws-cdk/aws-sns": "^0.8.1", "cdk-build-tools": "^0.8.1", "cdk-integ-tools": "^0.8.1", @@ -58,6 +64,7 @@ "pkglint": "^0.8.1" }, "dependencies": { + "@aws-cdk/aws-codepipeline-api": "^0.8.1", "@aws-cdk/aws-events": "^0.8.1", "@aws-cdk/aws-iam": "^0.8.1", "@aws-cdk/aws-s3": "^0.8.1", diff --git a/packages/@aws-cdk/aws-cloudformation-codepipeline/test/integ.template-from-repo.lit.expected.json b/packages/@aws-cdk/aws-codepipeline/test/integ.cfn-template-from-repo.lit.expected.json similarity index 100% rename from packages/@aws-cdk/aws-cloudformation-codepipeline/test/integ.template-from-repo.lit.expected.json rename to packages/@aws-cdk/aws-codepipeline/test/integ.cfn-template-from-repo.lit.expected.json diff --git a/packages/@aws-cdk/aws-cloudformation-codepipeline/test/integ.template-from-repo.lit.ts b/packages/@aws-cdk/aws-codepipeline/test/integ.cfn-template-from-repo.lit.ts similarity index 66% rename from packages/@aws-cdk/aws-cloudformation-codepipeline/test/integ.template-from-repo.lit.ts rename to packages/@aws-cdk/aws-codepipeline/test/integ.cfn-template-from-repo.lit.ts index 033c4143c4210..d6587bf2e50a3 100644 --- a/packages/@aws-cdk/aws-cloudformation-codepipeline/test/integ.template-from-repo.lit.ts +++ b/packages/@aws-cdk/aws-codepipeline/test/integ.cfn-template-from-repo.lit.ts @@ -1,8 +1,7 @@ +import cfn = require('@aws-cdk/aws-cloudformation'); import codecommit = require('@aws-cdk/aws-codecommit'); -import codecommitpl = require('@aws-cdk/aws-codecommit-codepipeline'); -import codepipeline = require('@aws-cdk/aws-codepipeline'); import cdk = require('@aws-cdk/cdk'); -import cfnpl = require('../lib'); +import codepipeline = require('../lib'); const app = new cdk.App(process.argv); const stack = new cdk.Stack(app, 'aws-cdk-codepipeline-cloudformation'); @@ -15,7 +14,8 @@ const repo = new codecommit.Repository(stack, 'TemplateRepo', { repositoryName: 'template-repo' }); const sourceStage = new codepipeline.Stage(pipeline, 'Source'); -const source = new codecommitpl.PipelineSource(sourceStage, 'Source', { +const source = new codecommit.PipelineSource(stack, 'Source', { + stage: sourceStage, repository: repo, artifactName: 'SourceArtifact', }); @@ -25,19 +25,23 @@ const prodStage = new codepipeline.Stage(pipeline, 'Deploy'); const stackName = 'OurStack'; const changeSetName = 'StagedChangeSet'; -new cfnpl.CreateReplaceChangeSet(prodStage, 'PrepareChanges', { +new cfn.CreateReplaceChangeSet(prodStage, 'PrepareChanges', { + stage: prodStage, stackName, changeSetName, fullPermissions: true, templatePath: source.artifact.subartifact('template.yaml'), }); -new codepipeline.ApprovalAction(prodStage, 'ApproveChanges'); +new codepipeline.ManualApprovalAction(stack, 'ApproveChanges', { + stage: prodStage, +}); -new cfnpl.ExecuteChangeSet(prodStage, 'ExecuteChanges', { +new cfn.ExecuteChangeSet(stack, 'ExecuteChanges', { + stage: prodStage, stackName, changeSetName, }); /// !hide -process.stdout.write(app.run()); \ No newline at end of file +process.stdout.write(app.run()); diff --git a/packages/@aws-cdk/aws-lambda-codepipeline/test/integ.pipeline.expected.json b/packages/@aws-cdk/aws-codepipeline/test/integ.lambda-pipeline.expected.json similarity index 100% rename from packages/@aws-cdk/aws-lambda-codepipeline/test/integ.pipeline.expected.json rename to packages/@aws-cdk/aws-codepipeline/test/integ.lambda-pipeline.expected.json diff --git a/packages/@aws-cdk/aws-lambda-codepipeline/test/integ.pipeline.ts b/packages/@aws-cdk/aws-codepipeline/test/integ.lambda-pipeline.ts similarity index 79% rename from packages/@aws-cdk/aws-lambda-codepipeline/test/integ.pipeline.ts rename to packages/@aws-cdk/aws-codepipeline/test/integ.lambda-pipeline.ts index bdc7199b033f2..2ec41e9e8a5a9 100644 --- a/packages/@aws-cdk/aws-lambda-codepipeline/test/integ.pipeline.ts +++ b/packages/@aws-cdk/aws-codepipeline/test/integ.lambda-pipeline.ts @@ -1,8 +1,7 @@ -import codepipeline = require('@aws-cdk/aws-codepipeline'); import lambda = require('@aws-cdk/aws-lambda'); import s3 = require('@aws-cdk/aws-s3'); import cdk = require('@aws-cdk/cdk'); -import lambda_codepipeline = require('../lib'); +import codepipeline = require('../lib'); const app = new cdk.App(process.argv); @@ -14,7 +13,8 @@ const sourceStage = new codepipeline.Stage(pipeline, 'Source'); const bucket = new s3.Bucket(stack, 'PipelineBucket', { versioned: true, }); -new codepipeline.AmazonS3Source(sourceStage, 'Source', { +new codepipeline.AmazonS3Source(stack, 'Source', { + stage: sourceStage, artifactName: 'SourceArtifact', bucket, bucketKey: 'key', @@ -30,7 +30,8 @@ const lambdaFun = new lambda.Function(stack, 'LambdaFun', { runtime: lambda.Runtime.NodeJS610, }); const lambdaStage = new codepipeline.Stage(pipeline, 'Lambda'); -new lambda_codepipeline.PipelineInvokeAction(lambdaStage, 'Lambda', { +new lambda.PipelineInvokeAction(stack, 'Lambda', { + stage: lambdaStage, lambda: lambdaFun, }); diff --git a/packages/@aws-cdk/aws-cloudformation-codepipeline/test/integ.pipeline.expected.json b/packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-cfn.expected.json similarity index 100% rename from packages/@aws-cdk/aws-cloudformation-codepipeline/test/integ.pipeline.expected.json rename to packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-cfn.expected.json diff --git a/packages/@aws-cdk/aws-cloudformation-codepipeline/test/integ.pipeline.ts b/packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-cfn.ts similarity index 67% rename from packages/@aws-cdk/aws-cloudformation-codepipeline/test/integ.pipeline.ts rename to packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-cfn.ts index cceeb7f2a45a6..6ff220dfc3fe5 100644 --- a/packages/@aws-cdk/aws-cloudformation-codepipeline/test/integ.pipeline.ts +++ b/packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-cfn.ts @@ -1,11 +1,10 @@ -import codepipeline = require('@aws-cdk/aws-codepipeline'); -import { ArtifactPath } from '@aws-cdk/aws-codepipeline'; +import cfn = require('@aws-cdk/aws-cloudformation'); +import { ArtifactPath } from '@aws-cdk/aws-codepipeline-api'; import { Role } from '@aws-cdk/aws-iam'; import s3 = require('@aws-cdk/aws-s3'); import cdk = require('@aws-cdk/cdk'); import { ServicePrincipal } from '@aws-cdk/cdk'; - -import cfn_codepipeline = require('../lib'); +import codepipeline = require('../lib'); const app = new cdk.App(process.argv); @@ -17,7 +16,8 @@ const sourceStage = new codepipeline.Stage(pipeline, 'Source'); const bucket = new s3.Bucket(stack, 'PipelineBucket', { versioned: true, }); -const source = new codepipeline.AmazonS3Source(sourceStage, 'Source', { +const source = new codepipeline.AmazonS3Source(stack, 'Source', { + stage: sourceStage, artifactName: 'SourceArtifact', bucket, bucketKey: 'key', @@ -32,11 +32,12 @@ const role = new Role(stack, 'CfnChangeSetRole', { assumedBy: new ServicePrincipal('cloudformation.amazonaws.com'), }); -new cfn_codepipeline.CreateReplaceChangeSet(cfnStage, 'DeployCFN', { - changeSetName, - stackName, - role, - templatePath: new ArtifactPath(source.artifact, 'test.yaml') +new cfn.CreateReplaceChangeSet(stack, 'DeployCFN', { + stage: cfnStage, + changeSetName, + stackName, + role, + templatePath: new ArtifactPath(source.artifact, 'test.yaml') }); process.stdout.write(app.run()); diff --git a/packages/@aws-cdk/aws-codebuild-codepipeline/test/integ.pipeline-code-commit-build.expected.json b/packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-code-commit-build.expected.json similarity index 100% rename from packages/@aws-cdk/aws-codebuild-codepipeline/test/integ.pipeline-code-commit-build.expected.json rename to packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-code-commit-build.expected.json diff --git a/packages/@aws-cdk/aws-codebuild-codepipeline/test/integ.pipeline-code-commit-build.ts b/packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-code-commit-build.ts similarity index 58% rename from packages/@aws-cdk/aws-codebuild-codepipeline/test/integ.pipeline-code-commit-build.ts rename to packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-code-commit-build.ts index d7f40b1f7399b..a1d7a202d6cbc 100644 --- a/packages/@aws-cdk/aws-codebuild-codepipeline/test/integ.pipeline-code-commit-build.ts +++ b/packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-code-commit-build.ts @@ -1,32 +1,34 @@ import codebuild = require('@aws-cdk/aws-codebuild'); import codecommit = require('@aws-cdk/aws-codecommit'); -import codecommitPipeline = require('@aws-cdk/aws-codecommit-codepipeline'); -import codepipeline = require('@aws-cdk/aws-codepipeline'); import cdk = require('@aws-cdk/cdk'); -import codebuildPipeline = require('../lib'); +import codepipeline = require('../lib'); const app = new cdk.App(process.argv); const stack = new cdk.Stack(app, 'aws-cdk-codepipeline-codecommit-codebuild'); -const repo = new codecommit.Repository(stack, 'MyRepo', { repositoryName: 'my-repo' }); +const repository = new codecommit.Repository(stack, 'MyRepo', { + repositoryName: 'my-repo', +}); const pipeline = new codepipeline.Pipeline(stack, 'Pipeline'); const sourceStage = new codepipeline.Stage(pipeline, 'source'); -const source = new codecommitPipeline.PipelineSource(sourceStage, 'source', { +const source = new codecommit.PipelineSource(stack, 'source', { + stage: sourceStage, artifactName: 'SourceArtifact', - repository: repo, + repository, }); -const buildStage = new codepipeline.Stage(pipeline, 'build'); const project = new codebuild.Project(stack, 'MyBuildProject', { source: new codebuild.CodePipelineSource(), }); -new codebuildPipeline.PipelineBuildAction(buildStage, 'build', { +const buildStage = new codepipeline.Stage(pipeline, 'build'); +new codebuild.PipelineBuildAction(buildStage, 'build', { + stage: buildStage, + inputArtifact: source.artifact, project, - inputArtifact: source.artifact }); process.stdout.write(app.run()); diff --git a/packages/@aws-cdk/aws-codecommit-codepipeline/test/integ.pipeline-code-commit.expected.json b/packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-code-commit.expected.json similarity index 100% rename from packages/@aws-cdk/aws-codecommit-codepipeline/test/integ.pipeline-code-commit.expected.json rename to packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-code-commit.expected.json diff --git a/packages/@aws-cdk/aws-codecommit-codepipeline/test/integ.pipeline-code-commit.ts b/packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-code-commit.ts similarity index 72% rename from packages/@aws-cdk/aws-codecommit-codepipeline/test/integ.pipeline-code-commit.ts rename to packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-code-commit.ts index 2ad5b30f01948..967e2acfaad2d 100644 --- a/packages/@aws-cdk/aws-codecommit-codepipeline/test/integ.pipeline-code-commit.ts +++ b/packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-code-commit.ts @@ -1,7 +1,6 @@ import codecommit = require('@aws-cdk/aws-codecommit'); -import codepipeline = require('@aws-cdk/aws-codepipeline'); import cdk = require('@aws-cdk/cdk'); -import { PipelineSource } from '../lib/pipeline-action'; +import codepipeline = require('../lib'); const app = new cdk.App(process.argv); @@ -12,12 +11,15 @@ const repo = new codecommit.Repository(stack, 'MyRepo', { repositoryName: 'my-re const pipeline = new codepipeline.Pipeline(stack, 'Pipeline'); const sourceStage = new codepipeline.Stage(pipeline, 'source'); -new PipelineSource(sourceStage, 'source', { +new codecommit.PipelineSource(stack, 'source', { + stage: sourceStage, artifactName: 'SourceArtifact', repository: repo, }); const buildStage = new codepipeline.Stage(pipeline, 'build'); -new codepipeline.ApprovalAction(buildStage, 'manual'); +new codepipeline.ManualApprovalAction(stack, 'manual', { + stage: buildStage, +}); process.stdout.write(app.run()); diff --git a/packages/@aws-cdk/aws-codebuild-codepipeline/test/integ.pipeline-events.expected.json b/packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-events.expected.json similarity index 100% rename from packages/@aws-cdk/aws-codebuild-codepipeline/test/integ.pipeline-events.expected.json rename to packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-events.expected.json diff --git a/packages/@aws-cdk/aws-codebuild-codepipeline/test/integ.pipeline-events.ts b/packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-events.ts similarity index 66% rename from packages/@aws-cdk/aws-codebuild-codepipeline/test/integ.pipeline-events.ts rename to packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-events.ts index 19bbe822cc0d5..281517ff303f5 100644 --- a/packages/@aws-cdk/aws-codebuild-codepipeline/test/integ.pipeline-events.ts +++ b/packages/@aws-cdk/aws-codepipeline/test/integ.pipeline-events.ts @@ -1,11 +1,10 @@ // Use pipeline as CloudWAtch event target +import codebuild = require('@aws-cdk/aws-codebuild'); import codecommit = require('@aws-cdk/aws-codecommit'); -import codecommitPipeline = require('@aws-cdk/aws-codecommit-codepipeline'); -import codepipeline = require('@aws-cdk/aws-codepipeline'); import sns = require('@aws-cdk/aws-sns'); import cdk = require('@aws-cdk/cdk'); -import codebuildPipeline = require('../lib'); +import codepipeline = require('../lib'); const app = new cdk.App(process.argv); @@ -15,11 +14,21 @@ const pipeline = new codepipeline.Pipeline(stack, 'MyPipeline'); const sourceStage = new codepipeline.Stage(pipeline, 'Source'); const buildStage = new codepipeline.Stage(pipeline, 'Build'); -const repository = new codecommit.Repository(stack, 'CodeCommitRepo', { repositoryName: 'foo' }); -const project = new codebuildPipeline.PipelineProject(stack, 'BuildProject'); +const repository = new codecommit.Repository(stack, 'CodeCommitRepo', { + repositoryName: 'foo' +}); +const project = new codebuild.PipelineProject(stack, 'BuildProject'); -const sourceAction = new codecommitPipeline.PipelineSource(sourceStage, 'CodeCommitSource', { artifactName: 'Source', repository }); -new codebuildPipeline.PipelineBuildAction(buildStage, 'CodeBuildAction', { inputArtifact: sourceAction.artifact, project }); +const sourceAction = new codecommit.PipelineSource(pipeline, 'CodeCommitSource', { + stage: sourceStage, + artifactName: 'Source', + repository, +}); +new codebuild.PipelineBuildAction(stack, 'CodeBuildAction', { + stage: buildStage, + inputArtifact: sourceAction.artifact, + project +}); const topic = new sns.Topic(stack, 'MyTopic'); topic.subscribeEmail('benisrae', 'benisrae@amazon.com'); diff --git a/packages/@aws-cdk/aws-codepipeline/test/test.action.ts b/packages/@aws-cdk/aws-codepipeline/test/test.action.ts index f85d83cade9d6..e1943e9973ec8 100644 --- a/packages/@aws-cdk/aws-codepipeline/test/test.action.ts +++ b/packages/@aws-cdk/aws-codepipeline/test/test.action.ts @@ -1,11 +1,12 @@ +// import { validateArtifactBounds, validateSourceAction } from '../lib/validation'; +import actions = require('@aws-cdk/aws-codepipeline-api'); import cdk = require('@aws-cdk/cdk'); import { Test } from 'nodeunit'; import codepipeline = require('../lib'); -import { validateArtifactBounds, validateSourceAction } from '../lib/validation'; // tslint:disable:object-literal-key-quotes -class TestAction extends codepipeline.Action {} +class TestAction extends actions.Action {} export = { 'artifact bounds validation': { @@ -34,43 +35,46 @@ export = { 'action type validation': { 'must be source and is source'(test: Test) { - const result = validateSourceAction(true, codepipeline.ActionCategory.Source, 'test action', 'test stage'); + const result = actions.validateSourceAction(true, actions.ActionCategory.Source, 'test action', 'test stage'); test.deepEqual(result.length, 0); test.done(); }, 'must be source and is not source'(test: Test) { - const result = validateSourceAction(true, codepipeline.ActionCategory.Deploy, 'test action', 'test stage'); + const result = actions.validateSourceAction(true, actions.ActionCategory.Deploy, 'test action', 'test stage'); test.deepEqual(result.length, 1); test.ok(result[0].match(/may only contain Source actions/), 'the validation should have failed'); test.done(); }, 'cannot be source and is source'(test: Test) { - const result = validateSourceAction(false, codepipeline.ActionCategory.Source, 'test action', 'test stage'); + const result = actions.validateSourceAction(false, actions.ActionCategory.Source, 'test action', 'test stage'); test.deepEqual(result.length, 1); test.ok(result[0].match(/may only occur in first stage/), 'the validation should have failed'); test.done(); }, 'cannot be source and is not source'(test: Test) { - const result = validateSourceAction(false, codepipeline.ActionCategory.Deploy, 'test action', 'test stage'); + const result = actions.validateSourceAction(false, actions.ActionCategory.Deploy, 'test action', 'test stage'); test.deepEqual(result.length, 0); test.done(); }, }, 'standard action with artifacts'(test: Test) { - const stage = stageForTesting(); - const action = new TestAction(stage, 'TestAction', { - artifactBounds: defaultBounds(), - category: codepipeline.ActionCategory.Source, + const stack = new cdk.Stack(); + const pipeline = new codepipeline.Pipeline(stack, 'pipeline'); + const stage = new codepipeline.Stage(pipeline, 'stage'); + const action = new TestAction(stack, 'TestAction', { + stage, + artifactBounds: actions.defaultBounds(), + category: actions.ActionCategory.Source, provider: 'test provider', configuration: { blah: 'bleep' } }); - new codepipeline.Artifact(action, 'TestOutput'); + new actions.Artifact(action, 'TestOutput'); - test.deepEqual(action.render(), { + test.deepEqual((stage.render().actions as any)[0], { name: 'TestAction', inputArtifacts: [], actionTypeId: @@ -89,30 +93,18 @@ export = { }; function boundsValidationResult(numberOfArtifacts: number, min: number, max: number): string[] { - const stage = stageForTesting(); - const action = new TestAction(stage, 'TestAction', { - artifactBounds: defaultBounds(), - category: codepipeline.ActionCategory.Test, + const stack = new cdk.Stack(); + const pipeline = new codepipeline.Pipeline(stack, 'pipeline'); + const stage = new codepipeline.Stage(pipeline, 'stage'); + const action = new TestAction(stack, 'TestAction', { + stage, + artifactBounds: actions.defaultBounds(), + category: actions.ActionCategory.Test, provider: 'test provider' }); - const artifacts: codepipeline.Artifact[] = []; + const artifacts: actions.Artifact[] = []; for (let i = 0; i < numberOfArtifacts; i++) { - artifacts.push(new codepipeline.Artifact(action, `TestArtifact${i}`)); + artifacts.push(new actions.Artifact(action, `TestArtifact${i}`)); } - return validateArtifactBounds('output', artifacts, min, max, 'testCategory', 'testProvider'); -} - -function stageForTesting(): codepipeline.Stage { - const stack = new cdk.Stack(); - const pipeline = new codepipeline.Pipeline(stack, 'pipeline'); - return new codepipeline.Stage(pipeline, 'stage'); -} - -function defaultBounds(): codepipeline.ActionArtifactBounds { - return { - minInputs: 0, - maxInputs: 5, - minOutputs: 0, - maxOutputs: 5 - }; + return actions.validateArtifactBounds('output', artifacts, min, max, 'testCategory', 'testProvider'); } diff --git a/packages/@aws-cdk/aws-cloudformation-codepipeline/test/test.pipeline-actions.ts b/packages/@aws-cdk/aws-codepipeline/test/test.cloudformation-pipeline-actions.ts similarity index 90% rename from packages/@aws-cdk/aws-cloudformation-codepipeline/test/test.pipeline-actions.ts rename to packages/@aws-cdk/aws-codepipeline/test/test.cloudformation-pipeline-actions.ts index 51d6f0bfc41d6..3ce276d0f9542 100644 --- a/packages/@aws-cdk/aws-cloudformation-codepipeline/test/test.pipeline-actions.ts +++ b/packages/@aws-cdk/aws-codepipeline/test/test.cloudformation-pipeline-actions.ts @@ -1,14 +1,13 @@ import { expect, haveResource } from '@aws-cdk/assert'; -import { CodePipelineBuildArtifacts, CodePipelineSource, Project } from '@aws-cdk/aws-codebuild'; -import { PipelineBuildAction } from '@aws-cdk/aws-codebuild-codepipeline'; -import { Repository } from '@aws-cdk/aws-codecommit'; -import { PipelineSource } from '@aws-cdk/aws-codecommit-codepipeline'; -import { ArtifactPath, Pipeline, Stage } from '@aws-cdk/aws-codepipeline'; +import { CreateReplaceChangeSet, CreateUpdateStack, ExecuteChangeSet } from '@aws-cdk/aws-cloudformation'; +import { CodePipelineBuildArtifacts, CodePipelineSource, PipelineBuildAction, Project } from '@aws-cdk/aws-codebuild'; +import { PipelineSource, Repository } from '@aws-cdk/aws-codecommit'; +import { ArtifactPath } from '@aws-cdk/aws-codepipeline-api'; import { Role } from '@aws-cdk/aws-iam'; import cdk = require('@aws-cdk/cdk'); import { PolicyStatement, ServicePrincipal } from '@aws-cdk/cdk'; import { Test } from 'nodeunit'; -import { CreateReplaceChangeSet, CreateUpdateStack, ExecuteChangeSet } from '../lib/pipeline-actions'; +import { Pipeline, Stage } from '../lib'; // tslint:disable:object-literal-key-quotes @@ -27,7 +26,8 @@ export = { const sourceStage = new Stage(pipeline, 'source'); - const source = new PipelineSource(sourceStage, 'source', { + const source = new PipelineSource(stack, 'source', { + stage: sourceStage, artifactName: 'SourceArtifact', repository: repo, }); @@ -41,7 +41,8 @@ export = { artifacts: buildArtifacts, }); - const buildAction = new PipelineBuildAction(buildStage, 'build', { + const buildAction = new PipelineBuildAction(stack, 'build', { + stage: buildStage, project, inputArtifact: source.artifact, artifactName: "OutputYo" @@ -56,14 +57,16 @@ export = { const stackName = 'BrelandsStack'; const changeSetName = 'MyMagicalChangeSet'; - new CreateReplaceChangeSet(prodStage, 'BuildChangeSetProd', { + new CreateReplaceChangeSet(stack, 'BuildChangeSetProd', { + stage: prodStage, stackName, changeSetName, role: changeSetExecRole, templatePath: new ArtifactPath(buildAction.artifact!, 'template.yaml'), }); - new ExecuteChangeSet(prodStage, 'ExecuteChangeSetProd', { + new ExecuteChangeSet(stack, 'ExecuteChangeSetProd', { + stage: prodStage, stackName, changeSetName, }); @@ -196,6 +199,7 @@ export = { // WHEN new CreateUpdateStack(stack.deployStage, 'CreateUpdate', { + stage: stack.deployStage, stackName: 'MyStack', templatePath: stack.source.artifact.subartifact('template.yaml'), fullPermissions: true, @@ -247,7 +251,8 @@ export = { const stack = new TestFixture(); // WHEN - new CreateUpdateStack(stack.deployStage, 'CreateUpdate', { + new CreateUpdateStack(stack, 'CreateUpdate', { + stage: stack.deployStage, stackName: 'MyStack', templatePath: stack.source.artifact.subartifact('template.yaml'), outputFileName: 'CreateResponse.json', @@ -277,7 +282,8 @@ export = { const stack = new TestFixture(); // WHEN - new CreateUpdateStack(stack.deployStage, 'CreateUpdate', { + new CreateUpdateStack(stack, 'CreateUpdate', { + stage: stack.deployStage, stackName: 'MyStack', templatePath: stack.source.artifact.subartifact('template.yaml'), replaceOnFailure: true, @@ -322,7 +328,8 @@ class TestFixture extends cdk.Stack { this.sourceStage = new Stage(this.pipeline, 'Source'); this.deployStage = new Stage(this.pipeline, 'Deploy'); this.repo = new Repository(this, 'MyVeryImportantRepo', { repositoryName: 'my-very-important-repo' }); - this.source = new PipelineSource(this.sourceStage, 'Source', { + this.source = new PipelineSource(this, 'Source', { + stage: this.sourceStage, artifactName: 'SourceArtifact', repository: this.repo, }); diff --git a/packages/@aws-cdk/aws-codepipeline/test/test.general-validation.ts b/packages/@aws-cdk/aws-codepipeline/test/test.general-validation.ts index 04c1bb610729e..655cc7d555792 100644 --- a/packages/@aws-cdk/aws-codepipeline/test/test.general-validation.ts +++ b/packages/@aws-cdk/aws-codepipeline/test/test.general-validation.ts @@ -1,10 +1,10 @@ +import actions = require('@aws-cdk/aws-codepipeline-api'); import s3 = require('@aws-cdk/aws-s3'); import cdk = require('@aws-cdk/cdk'); import { Test } from 'nodeunit'; -import { AmazonS3Source } from '../lib/actions'; import { Pipeline } from '../lib/pipeline'; +import { AmazonS3Source } from '../lib/s3-source-action'; import { Stage } from '../lib/stage'; -import { validateName } from '../lib/validation'; interface NameValidationTestCase { name: string; @@ -23,7 +23,7 @@ export = { cases.forEach(testCase => { const name = testCase.name; - const validationBlock = () => { validateName('test thing', name); }; + const validationBlock = () => { actions.validateName('test thing', name); }; if (testCase.shouldPassValidation) { test.doesNotThrow(validationBlock, Error, `${name} failed validation but ${testCase.explanation}`); } else { @@ -61,12 +61,14 @@ export = { const secondStage = new Stage(pipeline, 'SecondStage'); const bucket = new s3.Bucket(stack, 'PipelineBucket'); - new AmazonS3Source(firstStage, 'FirstAction', { + new AmazonS3Source(stack, 'FirstAction', { + stage: firstStage, artifactName: 'FirstArtifact', bucket, bucketKey: 'key', }); - new AmazonS3Source(secondStage, 'SecondAction', { + new AmazonS3Source(stack, 'SecondAction', { + stage: secondStage, artifactName: 'SecondAction', bucket, bucketKey: 'key', diff --git a/packages/@aws-cdk/aws-codebuild-codepipeline/test/test.pipeline.ts b/packages/@aws-cdk/aws-codepipeline/test/test.pipeline.ts similarity index 56% rename from packages/@aws-cdk/aws-codebuild-codepipeline/test/test.pipeline.ts rename to packages/@aws-cdk/aws-codepipeline/test/test.pipeline.ts index 7ddcfa8b706f8..71606d3ca6df1 100644 --- a/packages/@aws-cdk/aws-codebuild-codepipeline/test/test.pipeline.ts +++ b/packages/@aws-cdk/aws-codepipeline/test/test.pipeline.ts @@ -1,38 +1,39 @@ import { expect, haveResource } from '@aws-cdk/assert'; import codebuild = require('@aws-cdk/aws-codebuild'); import codecommit = require('@aws-cdk/aws-codecommit'); -import codecommitPipeline = require('@aws-cdk/aws-codecommit-codepipeline'); -import codepipeline = require('@aws-cdk/aws-codepipeline'); +import lambda = require('@aws-cdk/aws-lambda'); import s3 = require('@aws-cdk/aws-s3'); import sns = require('@aws-cdk/aws-sns'); import cdk = require('@aws-cdk/cdk'); import { Test } from 'nodeunit'; -import codebuildPipeline = require('../lib'); +import codepipeline = require('../lib'); // tslint:disable:object-literal-key-quotes export = { 'basic pipeline'(test: Test) { - const stack = new cdk.Stack(); - const repo = new codecommit.Repository(stack, 'MyRepo', { repositoryName: 'my-repo' }); + const repository = new codecommit.Repository(stack, 'MyRepo', { + repositoryName: 'my-repo', + }); const pipeline = new codepipeline.Pipeline(stack, 'Pipeline'); const sourceStage = new codepipeline.Stage(pipeline, 'source'); - const source = new codecommitPipeline.PipelineSource(sourceStage, 'source', { + const source = new codecommit.PipelineSource(stack, 'source', { + stage: sourceStage, artifactName: 'SourceArtifact', - repository: repo, + repository, }); const buildStage = new codepipeline.Stage(pipeline, 'build'); const project = new codebuild.Project(stack, 'MyBuildProject', { source: new codebuild.CodePipelineSource() }); - - new codebuildPipeline.PipelineBuildAction(buildStage, 'build', { + new codebuild.PipelineBuildAction(stack, 'build', { + stage: buildStage, + inputArtifact: source.artifact, project, - inputArtifact: source.artifact }); test.notDeepEqual(stack.toCloudFormation(), {}); @@ -47,7 +48,9 @@ export = { const p = new codepipeline.Pipeline(stack, 'P'); - new codepipeline.GitHubSource(new codepipeline.Stage(p, 'Source'), 'GH', { + const s1 = new codepipeline.Stage(p, 'Source'); + new codepipeline.GitHubSource(stack, 'GH', { + stage: s1, artifactName: 'A', branch: 'branch', oauthToken: secret, @@ -55,7 +58,8 @@ export = { repo: 'bar' }); - new codepipeline.ApprovalAction(new codepipeline.Stage(p, 'Two'), 'Boo'); + const s2 = new codepipeline.Stage(p, 'Two'); + new codepipeline.ManualApprovalAction(stack, 'Boo', { stage: s2 }); expect(stack).to(haveResource('AWS::CodePipeline::Pipeline', { "ArtifactStore": { @@ -132,12 +136,16 @@ export = { const pipeline = new codepipeline.Pipeline(stack, 'PL'); - new codepipeline.AmazonS3Source(new codepipeline.Stage(pipeline, 'S1'), 'A1', { + const stage1 = new codepipeline.Stage(pipeline, 'S1'); + new codepipeline.AmazonS3Source(stack, 'A1', { + stage: stage1, artifactName: 'Artifact', bucket: new s3.Bucket(stack, 'Bucket'), bucketKey: 'Key' }); - new codepipeline.ApprovalAction(new codepipeline.Stage(pipeline, 'S2'), 'A2'); + + const stage2 = new codepipeline.Stage(pipeline, 'S2'); + new codepipeline.ManualApprovalAction(stack, 'A2', { stage: stage2 }); pipeline.onStateChange('OnStateChange', topic, { description: 'desc', @@ -213,7 +221,7 @@ export = { 'sets the source and artifacts to CodePipeline'(test: Test) { const stack = new cdk.Stack(); - new codebuildPipeline.PipelineProject(stack, 'MyProject', { + new codebuild.PipelineProject(stack, 'MyProject', { projectName: 'MyProject', }); @@ -243,4 +251,125 @@ export = { } } }, + + 'Lambda PipelineInvokeAction can be used to invoke Lambda functions from a CodePipeline'(test: Test) { + const stack = new cdk.Stack(); + + const lambdaFun = new lambda.Function(stack, 'Function', { + code: new lambda.InlineCode('bla'), + handler: 'index.handler', + runtime: lambda.Runtime.NodeJS43, + }); + + const pipeline = new codepipeline.Pipeline(stack, 'Pipeline'); + const stage = new codepipeline.Stage(pipeline, 'Stage'); + new lambda.PipelineInvokeAction(stack, 'InvokeAction', { + stage, + lambda: lambdaFun, + userParameters: 'foo-bar/42' + }); + + expect(stack).to(haveResource('AWS::CodePipeline::Pipeline', { + "ArtifactStore": { + "Location": { + "Ref": "PipelineArtifactsBucket22248F97" + }, + "Type": "S3" + }, + "RoleArn": { + "Fn::GetAtt": [ + "PipelineRoleD68726F7", + "Arn" + ] + }, + "Stages": [ + { + "Actions": [ + { + "ActionTypeId": { + "Category": "Invoke", + "Owner": "AWS", + "Provider": "Lambda", + "Version": "1" + }, + "Configuration": { + "FunctionName": { + "Ref": "Function76856677" + }, + "UserParameters": "foo-bar/42" + }, + "InputArtifacts": [], + "Name": "InvokeAction", + "OutputArtifacts": [], + "RunOrder": 1 + } + ], + "Name": "Stage" + } + ] + })); + + expect(stack).to(haveResource('AWS::IAM::Policy', { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "codepipeline:PutJobSuccessResult", + "codepipeline:PutJobFailureResult" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "FunctionServiceRoleDefaultPolicy2F49994A", + "Roles": [ + { + "Ref": "FunctionServiceRole675BB04A" + } + ] + })); + + test.done(); + }, + + 'polling for changes': { + 'does not poll for changes'(test: Test) { + const stack = new cdk.Stack(); + + const result = new codecommit.PipelineSource(stack, 'stage', { + stage: stageForTesting(stack), + artifactName: 'SomeArtifact', + repository: repositoryForTesting(stack), + pollForSourceChanges: false, + }); + test.equal(result.configuration.PollForSourceChanges, false); + test.done(); + }, + + 'polls for changes'(test: Test) { + const stack = new cdk.Stack(); + + const result = new codecommit.PipelineSource(stack, 'stage', { + stage: stageForTesting(stack), + artifactName: 'SomeArtifact', + repository: repositoryForTesting(stack), + pollForSourceChanges: true, + }); + test.equal(result.configuration.PollForSourceChanges, true); + test.done(); + } + } }; + +function stageForTesting(stack: cdk.Stack): codepipeline.Stage { + const pipeline = new codepipeline.Pipeline(stack, 'pipeline'); + return new codepipeline.Stage(pipeline, 'stage'); +} + +function repositoryForTesting(stack: cdk.Stack): codecommit.Repository { + return new codecommit.Repository(stack, 'Repository', { + repositoryName: 'Repository' + }); +} diff --git a/packages/@aws-cdk/aws-lambda-codepipeline/.gitignore b/packages/@aws-cdk/aws-lambda-codepipeline/.gitignore deleted file mode 100644 index 95b285093bf48..0000000000000 --- a/packages/@aws-cdk/aws-lambda-codepipeline/.gitignore +++ /dev/null @@ -1,16 +0,0 @@ -*.js -*.js.map -*.d.ts -node_modules -*.generated.ts -dist -tsconfig.json -tslint.json - -.jsii - -.LAST_BUILD -.nyc_output -coverage -.nycrc -.LAST_PACKAGE \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-codepipeline/.npmignore b/packages/@aws-cdk/aws-lambda-codepipeline/.npmignore deleted file mode 100644 index e511c5acc268d..0000000000000 --- a/packages/@aws-cdk/aws-lambda-codepipeline/.npmignore +++ /dev/null @@ -1,14 +0,0 @@ -# Don't include original .ts files when doing `npm pack` -*.ts -!*.d.ts -coverage -.nyc_output -*.tgz - -dist -.LAST_PACKAGE -.LAST_BUILD -!*.js - -# Include .jsii -!.jsii diff --git a/packages/@aws-cdk/aws-lambda-codepipeline/LICENSE b/packages/@aws-cdk/aws-lambda-codepipeline/LICENSE deleted file mode 100644 index 1739faaebb745..0000000000000 --- a/packages/@aws-cdk/aws-lambda-codepipeline/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2018-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/packages/@aws-cdk/aws-lambda-codepipeline/NOTICE b/packages/@aws-cdk/aws-lambda-codepipeline/NOTICE deleted file mode 100644 index 95fd48569c743..0000000000000 --- a/packages/@aws-cdk/aws-lambda-codepipeline/NOTICE +++ /dev/null @@ -1,2 +0,0 @@ -AWS Cloud Development Kit (AWS CDK) -Copyright 2018-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/packages/@aws-cdk/aws-lambda-codepipeline/README.md b/packages/@aws-cdk/aws-lambda-codepipeline/README.md deleted file mode 100644 index 1a16b93ca42a0..0000000000000 --- a/packages/@aws-cdk/aws-lambda-codepipeline/README.md +++ /dev/null @@ -1,24 +0,0 @@ -## AWS CodePipline Actions for AWS Lambda - -This module contains an Action that allows you to invoke a Lambda function from CodePipeline. - -Example usage: - -```ts -import codepipeline = require('@aws-cdk/aws-codepipeline'); -import lambda = require('@aws-cdk/aws-lambda'); -import lambdaCodepipeline = require('@aws-cdk/aws-lambda-codepipeline'); - -// see the @aws-cdk/aws-lambda module for more documentation on how to create Lamda functions -const lambdaFun = new lambda.Lambda(// ... -); - -const pipeline = new codepipeline.Pipeline(this, 'MyPipeline'); -const lambdaStage = new codepipeline.Stage(pipeline, 'Lambda'); -new lambdaCodepipeline.PipelineInvokeAction(lambdaStage, 'Lambda', { - lambda: lambdaFun, -}); -``` - -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-codepipeline/lib/index.ts b/packages/@aws-cdk/aws-lambda-codepipeline/lib/index.ts deleted file mode 100644 index 890162998e10d..0000000000000 --- a/packages/@aws-cdk/aws-lambda-codepipeline/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './pipeline-action'; diff --git a/packages/@aws-cdk/aws-lambda-codepipeline/package.json b/packages/@aws-cdk/aws-lambda-codepipeline/package.json deleted file mode 100644 index b041462565908..0000000000000 --- a/packages/@aws-cdk/aws-lambda-codepipeline/package.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "name": "@aws-cdk/aws-lambda-codepipeline", - "version": "0.8.1", - "description": "AWS CodePipline Actions for AWS Lambda", - "main": "lib/index.js", - "types": "lib/index.d.ts", - "jsii": { - "outdir": "dist", - "targets": { - "java": { - "package": "software.amazon.awscdk.services.lambda.codepipeline", - "maven": { - "groupId": "software.amazon.awscdk", - "artifactId": "lambda-codepipeline" - } - }, - "sphinx": {} - } - }, - "repository": { - "type": "git", - "url": "https://github.com/awslabs/aws-cdk.git" - }, - "scripts": { - "build": "cdk-build", - "watch": "cdk-watch", - "lint": "cdk-lint", - "test": "cdk-test", - "integ": "cdk-integ", - "pkglint": "pkglint -f", - "package": "cdk-package" - }, - "nyc": { - "lines": 60, - "branches": 30 - }, - "keywords": [ - "aws", - "cdk", - "codepipeline", - "constructs", - "lambda" - ], - "author": { - "name": "Amazon Web Services", - "url": "https://aws.amazon.com", - "organization": true - }, - "license": "Apache-2.0", - "devDependencies": { - "@aws-cdk/assert": "^0.8.1", - "cdk-build-tools": "^0.8.1", - "cdk-integ-tools": "^0.8.1", - "pkglint": "^0.8.1" - }, - "dependencies": { - "@aws-cdk/aws-codepipeline": "^0.8.1", - "@aws-cdk/aws-lambda": "^0.8.1", - "@aws-cdk/aws-s3": "^0.8.1", - "@aws-cdk/cdk": "^0.8.1" - }, - "homepage": "https://github.com/awslabs/aws-cdk" -} diff --git a/packages/@aws-cdk/aws-lambda-codepipeline/test/test.pipeline-action.ts b/packages/@aws-cdk/aws-lambda-codepipeline/test/test.pipeline-action.ts deleted file mode 100644 index b9513222f8827..0000000000000 --- a/packages/@aws-cdk/aws-lambda-codepipeline/test/test.pipeline-action.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { expect, haveResource } from '@aws-cdk/assert'; -import codepipeline = require('@aws-cdk/aws-codepipeline'); -import lambda = require('@aws-cdk/aws-lambda'); -import cdk = require('@aws-cdk/cdk'); -import { Test } from 'nodeunit'; -import { PipelineInvokeAction } from '../lib/pipeline-action'; - -// tslint:disable:object-literal-key-quotes - -export = { - 'PipelineInvokeAction can be used to invoke lambda functions from a CodePipeline'(test: Test) { - const stack = new cdk.Stack(); - - const lambdaFun = new lambda.Function(stack, 'Function', { - code: new lambda.InlineCode('bla'), - handler: 'index.handler', - runtime: lambda.Runtime.NodeJS43, - }); - - const pipeline = new codepipeline.Pipeline(stack, 'Pipeline'); - - new PipelineInvokeAction(new codepipeline.Stage(pipeline, 'Stage'), 'InvokeAction', { - lambda: lambdaFun, - userParameters: 'foo-bar/42' - }); - - expect(stack).to(haveResource('AWS::CodePipeline::Pipeline', { - "ArtifactStore": { - "Location": { - "Ref": "PipelineArtifactsBucket22248F97" - }, - "Type": "S3" - }, - "RoleArn": { - "Fn::GetAtt": [ - "PipelineRoleD68726F7", - "Arn" - ] - }, - "Stages": [ - { - "Actions": [ - { - "ActionTypeId": { - "Category": "Invoke", - "Owner": "AWS", - "Provider": "Lambda", - "Version": "1" - }, - "Configuration": { - "FunctionName": { - "Ref": "Function76856677" - }, - "UserParameters": "foo-bar/42" - }, - "InputArtifacts": [], - "Name": "InvokeAction", - "OutputArtifacts": [], - "RunOrder": 1 - } - ], - "Name": "Stage" - } - ] - })); - - expect(stack).to(haveResource('AWS::IAM::Policy', { - "PolicyDocument": { - "Statement": [ - { - "Action": [ - "codepipeline:PutJobSuccessResult", - "codepipeline:PutJobFailureResult" - ], - "Effect": "Allow", - "Resource": "*" - } - ], - "Version": "2012-10-17" - }, - "PolicyName": "FunctionServiceRoleDefaultPolicy2F49994A", - "Roles": [ - { - "Ref": "FunctionServiceRole675BB04A" - } - ] - })); - - test.done(); - } -}; diff --git a/packages/@aws-cdk/aws-lambda/README.md b/packages/@aws-cdk/aws-lambda/README.md index 78d22f32f2cc5..759f22beadf86 100644 --- a/packages/@aws-cdk/aws-lambda/README.md +++ b/packages/@aws-cdk/aws-lambda/README.md @@ -35,3 +35,26 @@ local directory `my-lambda-handler` to it: When deploying a stack that contains this code, the directory will be zip archived and then uploaded to an S3 bucket, then the exact location of the S3 objects will be passed when the stack is deployed. + +### Lambda in CodePipeline + +This module also contains an Action that allows you to invoke a Lambda function from CodePipeline: + +```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(pipeline, 'Lambda'); +new lambda.PipelineInvokeAction(this, 'Lambda', { + stage: lambdaStage, + lambda: lambdaFun, +}); +``` + +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/index.ts b/packages/@aws-cdk/aws-lambda/lib/index.ts index 3593e78c670f8..c512f7fc0c1ef 100644 --- a/packages/@aws-cdk/aws-lambda/lib/index.ts +++ b/packages/@aws-cdk/aws-lambda/lib/index.ts @@ -2,6 +2,7 @@ export * from './alias'; export * from './lambda-ref'; export * from './lambda'; export * from './permission'; +export * from './pipeline-action'; export * from './runtime'; export * from './code'; export * from './inline'; diff --git a/packages/@aws-cdk/aws-lambda-codepipeline/lib/pipeline-action.ts b/packages/@aws-cdk/aws-lambda/lib/pipeline-action.ts similarity index 85% rename from packages/@aws-cdk/aws-lambda-codepipeline/lib/pipeline-action.ts rename to packages/@aws-cdk/aws-lambda/lib/pipeline-action.ts index a2088ecf6c308..fa3789bd719eb 100644 --- a/packages/@aws-cdk/aws-lambda-codepipeline/lib/pipeline-action.ts +++ b/packages/@aws-cdk/aws-lambda/lib/pipeline-action.ts @@ -1,15 +1,15 @@ -import codepipeline = require('@aws-cdk/aws-codepipeline'); -import lambda = require('@aws-cdk/aws-lambda'); +import codepipeline = require('@aws-cdk/aws-codepipeline-api'); import cdk = require('@aws-cdk/cdk'); +import { FunctionRef } from './lambda-ref'; /** * Construction properties of the {@link PipelineInvokeAction Lambda invoke CodePipeline Action}. */ -export interface PipelineInvokeActionProps { +export interface PipelineInvokeActionProps extends codepipeline.CommonActionProps { /** * The lambda function to invoke. */ - lambda: lambda.FunctionRef; + lambda: FunctionRef; /** * String to be used in the event data parameter passed to the Lambda @@ -45,8 +45,9 @@ export interface PipelineInvokeActionProps { * @see https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-invoke-lambda-function.html */ export class PipelineInvokeAction extends codepipeline.Action { - constructor(parent: codepipeline.Stage, name: string, props: PipelineInvokeActionProps) { + constructor(parent: cdk.Construct, name: string, props: PipelineInvokeActionProps) { super(parent, name, { + stage: props.stage, category: codepipeline.ActionCategory.Invoke, provider: 'Lambda', artifactBounds: codepipeline.defaultBounds(), @@ -57,12 +58,12 @@ export class PipelineInvokeAction extends codepipeline.Action { }); // allow pipeline to list functions - parent.pipeline.addToRolePolicy(new cdk.PolicyStatement() + props.stage.pipelineRole.addToPolicy(new cdk.PolicyStatement() .addAction('lambda:ListFunctions') .addResource('*')); // allow pipeline to invoke this lambda functionn - parent.pipeline.addToRolePolicy(new cdk.PolicyStatement() + props.stage.pipelineRole.addToPolicy(new cdk.PolicyStatement() .addAction('lambda:InvokeFunction') .addResource(props.lambda.functionArn)); diff --git a/packages/@aws-cdk/aws-lambda/package.json b/packages/@aws-cdk/aws-lambda/package.json index ab0f3b247c9e7..e4c358ae21357 100644 --- a/packages/@aws-cdk/aws-lambda/package.json +++ b/packages/@aws-cdk/aws-lambda/package.json @@ -55,6 +55,7 @@ "dependencies": { "@aws-cdk/assets": "^0.8.1", "@aws-cdk/aws-cloudwatch": "^0.8.1", + "@aws-cdk/aws-codepipeline-api": "^0.8.1", "@aws-cdk/aws-events": "^0.8.1", "@aws-cdk/aws-iam": "^0.8.1", "@aws-cdk/aws-logs": "^0.8.1",