Deploy SAM python lambda with Github actions
by Afanasy Barbarov
Continuous integration ideas for Terraform and AWS SAM
Amazon has an excellent framework https://aws.amazon.com/serverless/sam/ to build serverless applications. But there was a problem: one day I spend some time with Terraform to provision infrastructure on AWS. SAM itself allows publishing the lambda from the command line, but having a lot of lambdas and deploying each of it from localhost is not the best idea. Thus I needed to configure builds from a centralized place from one side, and from another - to develop lambda locally using the SAM framework, because of the ability of debugging locally.
I researched the Internet, found a great article - https://mechanicalrock.github.io/2020/01/06/github-actions-for-sam.html. Maybe I'll use it one day:) But I ended up with a very simple build pipeline. The idea is to use SAM CLI to build artifacts and put them to the S3 bucket.
- Create a new python app with
sam init. Сhose python 3.8 (the script below relates on python 3.8). - Configure github actions like so:
name: CI
on:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
checkout:
name: Checkout
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: SAM Build
run: sam build -u
env:
SAM_CLI_TELEMETRY: 0
- name: Zip lambda output
run: zip -r ${{ github.sha }}.zip ./*
working-directory: .aws-sam/build/HelloWorldFunction
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-1
- name: Copy to S3
run: aws s3 cp ${{ github.sha }}.zip
s3://YOUR-S3-BUCKET-NAME/${{ github.sha }}.zip
working-directory: .aws-sam/build/HelloWorldFunctionThe script above will compile lambda inside a docker container and copy the produced output to an S3 bucket. That assumes, that the bucket is already created. The script will run each time you push a commit in an open PR or on push to master branch. Configuring the lambda is out the scope, but you can refer to this Terraform script to get the idea:
provider "aws" {
profile = "defaul"
}
resource "aws_s3_bucket" "s3_lambda_src" {
bucket = "YOUR-S3-BUCKET-NAME"
}
resource "aws_lambda_function" "lambda_function" {
s3_bucket = "YOUR-S3-BUCKET-NAME"
s3_key = "SHA-OF-THE-COMMIT.zip"
function_name = "lambda-function"
handler = "app.lambda_handler"
runtime = "python3.8"
timeout = 180
role = aws_iam_role.iam_role_lambda.arn
}
resource "aws_iam_role" "iam_role_lambda" {
name = "iam_role_lambda"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}That's all, folks!