Lambda with CodePipeline
Introduction
Building a continuous delivery pipeline for a Lambda application with AWS CodePipeline.
Using the steps available from the AWS Lambda developer guide.
The CDK helped define the following AWS resources.
- CodeCommit repository
- CodePipeline
- S3 Bucket
Assets
The following assets are required for this example.
index.js
A Lambda function that returns the current time.
var time = require('time');
exports.handler = (event, context, callback) => {
var currentTime = new time.Date();
currentTime.setTimezone("America/Los_Angeles");
callback(null, {
statusCode: '200',
body: 'The time in Los Angeles is: ' + currentTime.toString(),
});
};
template.yml
The AWS SAM (Server-less Application Model) template that defines the application
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Outputs the time
Resources:
TimeFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs10.x
CodeUri: ./
Events:
MyTimeApi:
Type: Api
Properties:
Path: /TimeResource
Method: GET
buildspec.yml
An AWS CodeBuild build specification that installs required packages and uploads the deployment package to Amazon S3.
Replace lambda-deployment-artifacts-123456789012
with the name of your bucket.
version: 0.2
phases:
install:
runtime-versions:
nodejs: 10
build:
commands:
- npm install time
- export BUCKET=lambda-deployment-artifacts-123456789012
- aws cloudformation package --template-file template.yml --s3-bucket $BUCKET --output-template-file outputtemplate.yml
artifacts:
type: zip
files:
- template.yml
- outputtemplate.yml
Defining the code pipeline resources
App
#!/usr/bin/env python3
from aws_cdk import core
from lambda_code_pipeline.LambdaCodePipelineStack import LambdaCodePipelineStack
props = {
'namespace' : 'LambdaCodePipeline',
'repositoryName' : 'lambda-pipeline-repo',
'codeBuildProjectName' : 'lambda-pipeline-build'
}
app = core.App()
LambdaCodePipelineStack(app, f"{props['namespace']}-Pipeline",props)
app.synth()
LambdaCodePipelineStack
from aws_cdk import (
core,
aws_codecommit as code_commit,
aws_codepipeline as codepipeline,
aws_codepipeline_actions as codepipeline_actions,
aws_codebuild as code_build,
aws_s3 as s3,
aws_cloudformation as cloudformation,
aws_iam as iam
)
class LambdaCodePipelineStack(core.Stack):
def __init__(self, scope: core.Construct, id: str,props, **kwargs) -> None:
super().__init__(scope, id, **kwargs)
# The code that defines your stack goes here
# Pipeline requires a bucket for versioning
artifact_bucket = s3.Bucket(
self,
"SourceBucket",
bucket_name=f"lambda-deployment-artifacts-{core.Aws.ACCOUNT_ID}",
versioned=True,
removal_policy=core.RemovalPolicy.DESTROY
)
# Create a CodeCommit repository
repository = code_commit.Repository(self, "CodeCommitRepository",repository_name=props['repositoryName'])
# Create a CodePipline
pipeline = codepipeline.Pipeline(
self, "code-pipeline",
pipeline_name="MyFirstPipeline",
artifact_bucket=artifact_bucket,
)
# Create pipeline stages
source_stage = pipeline.add_stage(stage_name="Source")
build_stage = pipeline.add_stage(stage_name="Build")
deploy_stage = pipeline.add_stage(stage_name="Deploy")
source_output = codepipeline.Artifact(artifact_name='source')
source_stage.add_action(
codepipeline_actions.CodeCommitSourceAction(
action_name="Source",
repository=repository,
run_order=1,
output=source_output,
trigger=codepipeline_actions.CodeCommitTrigger.EVENTS,
branch="master"
)
)
# create a Pipeline project
code_build_project = code_build.PipelineProject(
self,
"CodeBuildProject",
project_name=props['codeBuildProjectName'],
build_spec=code_build.BuildSpec.from_source_filename(
filename="buildspec.yml"
),
environment=code_build.BuildEnvironment(
build_image=code_build.LinuxBuildImage.UBUNTU_14_04_BASE,
compute_type=code_build.ComputeType.SMALL
)
)
# define a build action
build_stage.add_action(
codepipeline_actions.CodeBuildAction(
action_name="CodeBuild",
input=source_output,
project=code_build_project
)
)
# define deploy action
deploy_stage.add_action(
codepipeline_actions.CloudFormationCreateReplaceChangeSetAction(
stack_name="lambda-pipeline-stack",
change_set_name="lambda-pipeline-changeset",
template_path=source_output.at_path("outputtemplate.yml"),
capabilities=[
core.CfnCapabilities.AUTO_EXPAND,
core.CfnCapabilities.NAMED_IAM
],
admin_permissions=False,
action_name="execute-changeset",
)
)
Commit assets to code repository
Once the code repository is setup.
Checkout the code repository and then commit the assets defined earlier into the repository.
~/lambda-pipeline-repo$ git add .
~/lambda-pipeline-repo$ git commit -m "project files"
~/lambda-pipeline-repo$ git push
Test the application
The application includes an API Gateway API with a public endpoint that returns the current time. Use the Lambda console to view the application and access the API.
To test the application
Open the Lambda console Applications page
Choose lambda-pipeline-stack.
Under Resources, expand ServerlessRestApi.
Choose Prod API endpoint.
Add /TimeResource to the end of the URL. For example, https://l193nqxdjj.execute-api.us-east-2.amazonaws.com/Prod/TimeResource.
Open the URL.
The API returns the current time in the following format.
The time in Los Angeles is: Thu Jun 27 2019 16:07:20 GMT-0700 (PDT)