Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding support for CodeCommit events #5397

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@ services:
image: node:6.10.3
volumes:
- ./tmp/serverless-integration-test-aws-alexa-typescript:/app
aws-codecommit-nodejs:
image: node:6.10.3
volumes:
- ./tmp/serverless-integration-test-aws-codecommit-nodejs:/app
aws-git-client-nodejs:
image: node:6.10.3
volumes:
- ./tmp/serverless-integration-test-aws-git-client-nodejs:/app
aws-nodejs-ecma-script:
image: node:6.10.3
volumes:
Expand Down
2 changes: 2 additions & 0 deletions docs/providers/aws/cli-reference/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ Most commonly used templates:
- aws-nodejs
- aws-nodejs-typescript
- aws-alexa-typescript
- aws-codecommit-nodejs
- aws-git-client-nodejs
- aws-nodejs-ecma-script
- aws-python
- aws-python3
Expand Down
209 changes: 209 additions & 0 deletions docs/providers/aws/events/codecommit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
<!--
title: Serverless Framework - AWS Lambda Events - CodeCommit
menuText: CodeCommit
menuOrder: 13
description: Setting up AWS CodeCommit Events with AWS Lambda via the Serverless Framework
layout: Doc
-->

<!-- DOCS-SITE-LINK:START automatically generated -->
### [Read this on the main serverless docs site](https://www.serverless.com/framework/docs/providers/aws/events/codecommit)
<!-- DOCS-SITE-LINK:END -->

# CodeCommit

In the following example we create a new CodeCommit repository with the name `MyRepo` which is bound to the `git` function. The function will be called every time a change (e.g. create or delete a branch / tag, or push to an existing branch) happens to the `MyRepo` repository.

```yml
functions:
git:
handler: git.handler
events:
- git: MyRepo
```

Note that in this example you were not required to explicitly create a trigger. The framework created a default trigger which will call the function for all changes to any of `MyRepo` branches.

You're also able to add the same CodeCommit repository to multiple functions:

```yml
functions:
git:
handler: git.handler
events:
- git: MyRepo
git2:
handler: git2.handler
events:
- git: MyRepo
```

This will run both functions for any changes to any branches of repository `MyRepo`.

**Note:** Every repository trigger created by the framework assigns the `arn` of the function where the event is defined to the trigger's `destinationArn` property. Check the [CodeCommit API reference](https://docs.aws.amazon.com/codecommit/latest/APIReference/API_RepositoryTrigger.html) for details.

## Using a pre-existing repository

If an `arn:` is specified, the framework will give permission to the repository to invoke the function.

**Note:** The repository trigger to invoke the function will not be created by the framework.

```yml
functions:
git:
handler: git.handler
events:
- git: arn:xxx
```

```yml
functions:
git:
handler: git.handler
events:
- git:
arn: arn:xxx
```

Or with intrinsic CloudFormation function like `Fn::Join` or `Fn::GetAtt`.

```yml
functions:
git:
handler: git.handler
events:
- git:
arn:
Fn::Join:
- ""
- - "arn:aws:codecommit:"
- Ref: "AWS::Region"
- ":"
- Ref: "AWS::AccountId"
- ":MyRepo"
repositoryName: MyRepo
```

**Note:** It is important to know that the repository `arn` must contain the value given in the `repositoryName` property.

## Using custom triggers

We can customize our triggers as well. In the following example we explicitly create a trigger named `MyTrigger` which will call the function `git` for every push to `MyRepo` repository branches `MyBranch1` or `MyBranch2`.

```yml
functions:
git:
handler: git.handler
events:
- git:
repositoryName: MyRepo
triggers:
- name: MyTrigger
events:
- updateReference
branches:
- MyBranch1
- MyBranch2
```

## Adding custom data to a trigger

Now we create a trigger named `MyTrigger` which will call the function `git` for every change to any `MyRepo` repository branches and any `customData` defined in the trigger will be included in the information sent to the function.

```yml
functions:
git:
handler: git.handler
events:
- git:
repositoryName: MyRepo
triggers:
- name: MyTrigger
customData: MyCustomData
```

## Note About CodeCommit Users & Roles

As indicated in the [AWS CodeCommit FAQs](https://aws.amazon.com/codecommit/faqs/), CodeCommit charges per active user, which may lead to unnecessary charges if you create/delete CodeCommit related IAM users/roles along your services.

You may want to consider creating your CodeCommit related IAM users/roles in their own service file as follows.

Sample CodeCommit setup service:

```yml
service: setupCodeCommit

provider:
name: aws
runtime: nodejs8.10

resources:
Resources:
userCodeCommit:
# If using ssh create & upload ssh key to this user account
Type: AWS::IAM::User
Properties:
UserName: codeCommitUser
Policies:
- PolicyName: gitPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action: # actions below work for git clients, use other actions if using CodeCommit API
- codecommit:GitPull
- codecommit:GitPush
Resource:
- 'Fn::Join':
- ':'
- - 'arn:aws:codecommit'
- Ref: 'AWS::Region'
- Ref: 'AWS::AccountId'
- '*'

roleCodeCommit: # you will likely want to add permissions for CloudWatch logging
Type: AWS::IAM::Role
Properties:
RoleName: codeCommitRole
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- "sts:AssumeRole"
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/AWSCodeCommitFullAccess'

# The "Outputs" that your AWS CloudFormation Stack should produce. This allows references between services.
Outputs:
UserArn:
Description: The ARN for user codeCommitUser
Value:
'Fn::GetAtt': [ userCodeCommit, Arn ]
Export:
Name: ${self:service}:codeCommitUser

RoleArn:
Description: The ARN for user codeCommitRole
Value:
'Fn::GetAtt': [ roleCodeCommit, Arn ]
Export:
Name: setupCodeCommit-codeCommitRole
```

And then reference the role in your other service files, like so:

```yml
functions:
git:
handler: git.handler
role: 'Fn::ImportValue': 'setupCodeCommit-codeCommitRole'
events:
- git: MyRepo
```

The user is typically used indirectly, by referencing its CodeCommit keyId and key if using a git client through ssh.
19 changes: 19 additions & 0 deletions lib/plugins/aws/lib/naming.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,17 @@ module.exports = {
}`;
},

// CodeCommit
normalizeRepositoryName(repositoryName) {
return this.normalizeNameToAlphaNumericOnly(repositoryName);
},
getGitRepositoryId(repositoryName) {
return `GitRepository${this.normalizeRepositoryName(repositoryName)}`;
},
getGitRepositoryArn(repositoryName) {
return `GitRepository${this.normalizeRepositoryName(repositoryName)}Arn`;
},

// Permissions
getLambdaS3PermissionLogicalId(functionName, bucketName) {
return `${this.getNormalizedFunctionName(functionName)}LambdaPermission${this
Expand Down Expand Up @@ -330,4 +341,12 @@ module.exports = {
.getNormalizedFunctionName(functionName)}LambdaPermissionCognitoUserPool${
this.normalizeNameToAlphaNumericOnly(poolId)}TriggerSource${triggerSource}`;
},
getLambdaGitPermissionLogicalId(functionName, repositoryName) {
return `${this.getNormalizedFunctionName(functionName)}LambdaPermission${
this.normalizeRepositoryName(repositoryName)}GitRepository`;
},
getLambdaGitTriggerLogicalId(functionName, repositoryName) {
return `${this.getNormalizedFunctionName(functionName)}GitRepository${
this.normalizeRepositoryName(repositoryName)}Trigger`;
},
};
30 changes: 30 additions & 0 deletions lib/plugins/aws/lib/naming.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -529,4 +529,34 @@ describe('#naming()', () => {
.to.equal('FunctionNameEventSourceMappingSQSMyQueue');
});
});

describe('#getGitRepositoryId()', () => {
it('should normalize the repository name and add the standard prefix', () => {
expect(sdk.naming.getGitRepositoryId('repositoryName'))
.to.equal('GitRepositoryRepositoryName');
});
});

describe('#getGitRepositoryArn()', () => {
it('should normalize the repository name and add the standard prefix', () => {
expect(sdk.naming.getGitRepositoryArn('repositoryName'))
.to.equal('GitRepositoryRepositoryNameArn');
});
});

describe('#getLambdaGitPermissionLogicalId()', () => {
it('should normalize the function and repository names and add the standard suffix',
() => {
expect(sdk.naming.getLambdaGitPermissionLogicalId('functionName', 'repositoryName'))
.to.equal('FunctionNameLambdaPermissionRepositoryNameGitRepository');
});
});

describe('#getLambdaGitTriggerLogicalId()', () => {
it('should normalize the function and repository names and add the standard suffix',
() => {
expect(sdk.naming.getLambdaGitTriggerLogicalId('functionName', 'repositoryName'))
.to.equal('FunctionNameGitRepositoryRepositoryNameTrigger');
});
});
});
Loading