CI/CD for Swift AWS Lambda on an M1 SoC

if you are a software developer that is experimenting with containers using macOS M1 and Docker. You are not the only one! people are working and talking about it on Swift Vapor Discord Channel

Disclaimer: You will deploy the lambda using an AmazonLinux2 agent as your work from your new M1 Pro 😅

Serverless, is a transferable concept across tooling-🛠 cloud providers-☁️ and programming languages-{}. It is/has become the new architecture. As the nature of my work implies, things change, how quickly and for how long they stayed? Sometimes is both read more


I have been developing Swift lambda intending to work with it more. I did this using the AWS Serverless Application Model. I suggest readers get started with Fabian’s tutorial. Then, progressively jump to GitHub’s discussions. Lastly, there is the documentation and how to work with AWS CDK.


I’ll showcase parts of the code where things can be more clear:


Part I: Developing

  • Use the latest/experimental branch of the Swift AWS runtime, including the new Swift concurrency features

.package(name: "swift-aws-lambda-runtime", 
         url: "https://github.com/swift-server/swift-aws-lambda-runtime", 
         branch: "main")
  • Write your swift lambda code 📦

@main
struct PushNotificationHandler: LambdaHandler {
	typealias Event = APIGatewayV2Request
	typealias Output = APIGatewayV2Response
	...
}
  • Make sure your Lambda will take the APIGateway payload. read more

{"routeKey": "POST /send_apns","version": "2.0","rawPath": "/send_apns","stageVariables": {},"body": "{\"body\":\"dummy test\"}","isBase64Encoded": false,"rawQueryString": "","headers": {"host": "hello.test.com","user-agent": "Paw/3.1.10 (Macintosh; OS X/10.15.4) GCDHTTPRequest","content-length": "0"}}

Part II: CI/CD

  • Edit the Dockerfile to use FROM swift:5.5.2-amazonlinux2

  • Edit the provided script from the repo to the one below, the original it assumes it’s running from your Intel Mac. Just set the passing arguments for the commands within the script:

... 
s3_bucket="<INSERT_NAME>" aws s3 cp ".build/lambda/$executable/lambda.zip" "s3://$s3_bucket"echo "-------------------------------------------------------------------------"echo "updating to latest \"$executable\""echo "-------------------------------------------------------------------------"lambda_name="<INSERT_NAME>" aws lambda update-function-code --function $lambda_name --s3-bucket $s3_bucket --s3-key lambda.zip 
  • Adapt the SAM (CloudFormation) template to what you need:

...
Resources:
    APNSServiceFunction:
    Type: AWS::Serverless::Function
    Properties:
        CodeUri: ../../lambda.zip
        Handler: xyz
        Runtime: provided.al2
        AutoPublishAlias: live
        FunctionName: send_apns_notification
        Events:
            NotifyUsers:
            Type: HttpApi
            Properties:
                Path: /staging/send_apns
                Method: POST
...
  • Configure a Github Action (CI) to run the build, packaging, and deployment scripts with the AWS OIDC trusted provider and using Docker action

...
permissions: # important
	id-token: write
	contents: read
jobs:
	deployment:
	runs-on: ubuntu-latest
	environment: staging
	steps:
		- name: Checkout
		uses: actions/checkout@v2
		- name: Configure AWS Credentials
		uses: aws-actions/configure-aws-credentials@v1
		with:
			role-to-assume: ${{ env.ROLE_TO_ASSUME }}
			aws-region: ${{ env.ROLE_TO_ASSUME }}
...

Come back here when things are starting to look more familiar. I hope the above was helpfull. Comments, feedback, questions @idelfonsoGM