Following on my previous post #1 about creating a blog infrastructure with GitHub Issues, GitHub Actions, and AWS Services, I’m moving on writing a Lambda function in Swift, to consume the messages from the SQS queue.

2 sqs-to-lambda

Making a Swift Lambda function

My plan is to use this repo as the source for any code needed for publishing articles. For Lambda, I will use the following:

Going to get started with the package and will update the post as I go.

Package Configuration

Package with targets and dependencies:

// swift-tools-version:5.2
import PackageDescription

let package = Package(
    name: "Blog",
    dependencies: [
        .package(url: "https://github.com/swift-server/swift-aws-lambda-runtime", from: "0.3.0"),
        .package(url: "https://github.com/eneko/GitHub", from: "0.1.0")
    ],
    targets: [
        .target(name: "IssueProcessorLambda", dependencies: [
            .product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"),
            .product(name: "AWSLambdaEvents", package: "swift-aws-lambda-runtime"),
        ])
    ]
)

Lambda Code

The following code will listen to an SQS event, and dump the received event to CloudWatch (after prepending “Hello world” to it):

import AWSLambdaRuntime
import AWSLambdaEvents
import NIO

struct Handler: EventLoopLambdaHandler {
    typealias In = SQS.Event // One or more messages
    typealias Out = String // Response type

    func handle(context: Lambda.Context, event: In) -> EventLoopFuture<Out> {
        let response = """
        Hello world
        \(event)

        """
        context.logger.debug("\(response)")
        return context.eventLoop.makeSucceededFuture(response)
    }
}

Lambda.run(Handler())

This should be enough for now, to check the integration is working.

AWS SAM template

For deployment, I like using AWS SAM, since it handles creation of the infrastructure, code updates, IAM roles and trigger event configuration. All with a few configuration lines.

This SAM template has the definition for the Issue Processor lambda function, and the trigger event from the inbound SQS queue (see Triggering lambdas with SQS.

AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: SAM template

Resources:
  IssueProcessorLambda:
    Type: AWS::Serverless::Function
    Properties:
      Handler: Provided
      Runtime: provided
      CodeUri: .build/lambda/IssueProcessorLambda/lambda.zip
      Environment:
        Variables:
          LOG_LEVEL: debug
      Events:
        SQSEvent:
            Type: SQS
            Properties:
              Queue: arn:aws:sqs:us-west-2:<account_number>:blog-issue-updates
              BatchSize: 10
              Enabled: true

Dockerfile & Makefile

I’ve set up a couple of scripts, from the Swift Lambda Runtime examples, together with a Dockerfile and a Makefile to make it easy to build and package the Lambda binary on Amazon Linux 2. The files are located at the root of the Swift Package repo. The build and package scripts are in the Scripts folder.

FROM swift:5.2-amazonlinux2

RUN yum -y install zip
build:
	./scripts/build-and-package.sh IssueProcessorLambda

To build and package the lambda we just run make (or make build).

Deploying with SAM

The first time, we will do a guided deploy, to properly configure SAM for further deployments. We do this with:

$ sam deploy --guided

Configuring SAM deploy
======================

	Looking for config file [samconfig.toml] :  Not found

	Setting default arguments for 'sam deploy'
	=========================================
	Stack Name [sam-app]: blog-engine
	AWS Region [us-east-1]: us-west-2
	#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
	Confirm changes before deploy [y/N]: 
	#SAM needs permission to be able to create roles to connect to the resources in your template
	Allow SAM CLI IAM role creation [Y/n]: 
	Save arguments to configuration file [Y/n]: 
	SAM configuration file [samconfig.toml]: 
	SAM configuration environment [default]: 

        ...

Reading logs from CloudWatch

If all goes well, we should see our Lambda function being invoked when issues are updated on GitHub, and logs with the events dumped on CloudWatch.

And here it is, the JSON with the Issue Number in the body property of the SQS Message:

Screen Shot 2020-12-21 at 4 35 51 PM

On to the next step!

Next steps

  • Configure GitHub action to push Issue updates to Amazon SQS (#1) ✅
  • Configure an AWS Lambda to process the incoming messages (#2) ✅
  • Retrieve entire issue details via GitHub Graph API, or embed in message (#3 & #4) ✅
  • Automate creation of blog post on GitHub pages (via direct commit, or pull request) (#7 & #9) ✅
  • Send me a notification via email or SMS with the url of the new blog post (using AWS SNS)
  • Potentially store a mapping of GitHub issues to blog URLs (and file paths) on a DynamoDB table

This article was written as an issue on my Blog repository on GitHub (see Issue #2)