Building Lambdas with GitHub Actions
Building a Lambda Function
More often than not, project dependencies must be built and bundled in an environment matching AWS Lambda for code to be deployed to the service. Python, for example, often requires binaries to match the architecture of the platform.
The LambCI project makes this easy. The project publishes Docker images for each of the Lambda runtimes. In this case, we’re using python3.8
but the same general approach works for any runtime.
GitHub Actions makes it easy to run parts of the build in specific Docker images, using the uses tag. In this case, we’re installing the dependencies within the Docker image lambci/lambda:build-python3.8
:
- uses: actions/checkout@v2
- 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: ${{ secrets.AWS_REGION }}
- name: Install dependencies with LambCI
uses: docker://lambci/lambda:build-python3.8
with:
entrypoint: pip
args: install -r requirements.txt --target .
- name: Bundle function with dependencies
run: |
zip -r build.zip .
- name: Copy function zip file to S3
run: |
aws s3 cp build.zip s3://<bucket-name>/function.zip
- name: Update function from S3
run: |
aws lambda update-function-code --function-name function --s3-bucket <bucket-name> --s3-key function.zip
Building a Lambda Layer
Once a project reaches a certain scale, it’s easy to exceed the 50mb function size limit with bundled dependencies. To solve this, large dependencies can be published in a layer and then excluded from the function bundle.
When building both a layer and a function from the same GitHub repo, dependencies can be separated in two sets. For example with Python, two requirements files can be used: requirements-layer.txt
and requirements-function.txt
.
- uses: actions/checkout@v2
- 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: ${{ secrets.AWS_REGION }}
- name: Install dependencies with LambCI
uses: docker://lambci/lambda:build-python3.8
with:
entrypoint: pip
args: install -r requirements.txt --target .
- name: Bundle layer with dependencies
run: |
zip -r build.zip .
- name: Copy layer zip file to S3
run: |
aws s3 cp build.zip s3://<bucket-name>/layer.zip
- name: Publish layer from S3
run: |
aws lambda publish-layer-version --layer-name layer --content S3Bucket=<bucket-name>,S3Key=layer.zip
IAM Policy for GitHub Actions
For GitHub to interact with AWS, create an IAM user and attach the policy below. Generate an access key for the new user and store the credentials in the repo’s GitHub Secrets.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "0",
"Effect": "Allow",
"Action": [
"iam:ListRoles",
"lambda:CreateFunction",
"lambda:UpdateFunctionCode",
"lambda:PublishLayerVersion",
"lambda:UpdateFunctionConfiguration",
"s3:PutObject",
"s3:GetObject",
"s3:PutObjectAcl"
],
"Resource": "*"
}
]
}
Stay in touch
The next post will be about mapping Bosnia & Herzegovina's minefields and minimizing risk while hiking and mountaineering. Subscribe to the email list to get notified when it's published. No spam, ever.