Deploying AWS Lambdas with Custom GitHub Actions
The action built in this article is published in Marketplace/Actions/Deploy AWS Lambda
GitHub actions let us execute development and deployment workflows within the repo. Github Actions marketplace contains a lot of pre-defined actions that can be used as building blocks for our custom actions. In this article, we look at how to create a custom action that we can upload to the marketplace. Understanding how an action is built not only helps us build custom, reusable building blocks for workflows, but also help us better utilize the capabilities of actions available in the marketplace.
The objective
We’ll build a GitHub action that deploys packaged code in a repo into an AWS lambda function every time we commit code to the main
branch of the repo. There are a few actions in the marketplace that already does this. However, we are interested in building one on our own to understand how to build custom actions. This is also practical since we would want to build it ourselves instead of using one from an unknown third party – especially since we are passing AWS access keys into the action.
Since we want to share the action we build with others, we will keep the actions code in a separate repo. However, if we’re building it for use within our repo alone, we could have built it within the .github
folder of our repo.
GitHub actions can be built as docker
container, JavaScript
or composite
. We will be building a Docker container-based action here. Though they are slower than the JS-based ones, it is easier to understand as well as provide greater flexibility.
Action Creation
- We start by creating a GitHub Repo to host the action and clone it into your development machine. I have created embeddedinn/deploy_lambda
-
Create a
Dockerfile
that contains the primary OS and the executionENTRYPOINT
of the action that we are providing# Container image that runs your code FROM alpine:3.10 # Copies your code file from your action repository to the filesystem path `/` of the container COPY entrypoint.sh /entrypoint.sh # Install AWS CLI RUN apk add --no-cache \ python3 \ py3-pip \ && pip3 install --upgrade pip \ && pip3 install --no-cache-dir \ awscli \ && rm -rf /var/cache/apk/* # Just to make sure its installed alright RUN aws --version RUN chmod +x entrypoint.sh # Code file to execute when the docker container starts up (`entrypoint.sh`) ENTRYPOINT ["/entrypoint.sh"]
-
Next, we create an action metadata file (
action.yml
) that defines parameters like input, output, . Note that the function expects the lambda code to be deployed to be provided as aZip file
. This is designed to allow execution of pre-deployment steps in the code repo workflow file.# action.yml name: 'Deploy AWS Lambda' description: 'Deploys repo code into AWS Lambda' author: 'Vysakh P Pillai' branding: icon: 'upload-cloud' color: 'green' inputs: access-key-id: description: 'AWS Access Key ID' required: true access-key-secret: description: 'AWS Access Key Secret' required: true region: description: 'AWS region' required: true lambda-name: description: 'Lambda function name' required: true zip-file: description: 'Zip File to deploy' required: true runs: using: 'docker' image: 'Dockerfile' args: - ${{ inputs.access-key-id }} - ${{ inputs.access-key-secret }} - ${{ inputs.region }} - ${{ inputs.lambda-name }} - ${{ inputs.zip-file }}
-
Now, we add the entry point function that would use the user inputs and perform the actual deployment. Make sure that the file has execute permissions. Note that we are using
update-function-code
that expects the lambda function to be already available. Args are passed to teh script in the order defined in theaction.yml
file.#!/bin/sh -l AWS_ACCESS_KEY_ID=$1 AWS_SECRET_ACCESS_KEY=$2 AWS_DEFAULT_REGION=$3 \ aws lambda update-function-code --function-name $4 --zip-file fileb://$5
-
Update the readme file and commit, tag and push the changes we made to the repo.
git add action.yml entrypoint.sh Dockerfile README.md git commit -m "deploy_lambda action" git tag -a -m "deploy_lambda action V1" v1.0.0 git push --follow-tags
Testing the action
To test the deployment flow enabled by the action we created now, we will create a lambda function and a repo to host the code to be deployed.
- Create a lambda function in your AWS console.
- I created a temporary
python 3.9
lambda function with the default code and enabledfunction URL
to demonstrate changes being deployed quickly.
import json def lambda_handler(event, context): # TODO implement return { 'statusCode': 200, 'body': json.dumps('Hello from Lambda!') }
- I created a temporary
-
The function URL will return the
Hello from Lambda!
string
- Next I created a
deploy_test
repo in my GitHub account. This is where we will test the deployment workflow. - Clone the new repo into your development machine and create a file named
lambda_function.py
with the default code from the lambda function. -
Next create a workflow file in the path
.github/workflows/main.yml
This workflow will checkout main, compress the code into a zip file, and deploy it using the action that we created and deployedon: [push] jobs: lambda_deployment: runs-on: ubuntu-latest name: deploy code in repo into a lambda function steps: - name: Code checkout id: checkout uses: actions/checkout@master - name: Package code into zip id: Package run: zip -r package.zip lambda_function.py - name: Deploy Lambda id: Deploy uses: embeddedinn/deploy_lambda@v1.0.0 with: access-key-id: $ access-key-secret: $ region: $ lambda-name: $ zip-file: package.zip
- Commit and push the code
Creating Action Secrets
- Now we need to add the AWS key and secret that will be used by our Action to commit the code.
- From the AWS IAM console, create a Key and secret for a user with permissions limited to deploying code into the specific lambda function.
-
Go to the repo that hosts the lambda code and under settings, go to
secrets > actions
- Create the following secrets with corresponding values from your AWS account. The key names are self-explanatory.
AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_REGION
-
LAMBDA_NAME
Deploying Code
-
We will now edit the code in the repo to change the welcome message into something different. For demonstration, we are doing this from the GitHub web editor.
- Once the change is committed, we can now see that the workflow has been picked up under the
actons
tab of the code repo.
- Once the workflow is completed, you can see that the code has changed in the lambda console. It will also reflect in the URL base invocation.
Notes:
- The lambda deployment steps can also be integrated into the code repo’s workflow without relying on external action. However, the intention is to show the steps involved in creating an action that can be published on Marketplace.
- The process can be sped up using a JavaScript-based action instead of using a docker container.
- In case you want to package additional contents like python packages, resources, etc. into the zip file, the steps can be added in the source code action file before the packaging stage.
- Lambda deployment versioning is not considered here to keep the flow simple.
Leave a comment