20
How To Set Up Continuous Integration and Delivery With Github Actions and Akka Serverless
CI/CD is one of those quintessential mindset shifts that helps developers automate away the toil of deploying apps. Especially in the realm of serverless, where the whole idea is to focus on the things that matter and let the undifferentiated heavy lifting be handled by others, automating as much as possible is paramount. It helps developers focus on what matters, code, and it helps business focus on what matters, getting quality software to market faster. So how does that work in Akka Serverless?
In the CI/CD I’ll use four different GitHub Actions:
- Docker Login so I can publish the resulting container to Docker Hub (or any other supported Docker registry)
- Docker Setup Buildx which uses BuildKit and makes it possible to create multi-platform images (which is out of scope for this blog post)
- Build and push Docker images to push the resulting image to Docker Hub
- Akka Serverless CLI for GitHub Actions to deploy to Akka Serverless
To make all the actions work, and to make it a little more secure, it’s best to set up usernames, passwords, and authentication tokens as secrets in GitHub. Under Settings -> Secrets
I’ve created four environment variables that have been encrypted:
- DOCKERHUB_TOKEN: the personal authentication token to log in to Docker Hub (while you could use a password too, it’s strongly recommended to use a personal access token)
- DOCKERHUB_USERNAME: the username to log in to Docker Hub
- PROJECT: the ID of the project I want to deploy to on Akka Serverless (
akkasls projects get <project name>
will show the ID of the project in the ID column) - TOKEN: the Akka Serverless authentication token that the action will use to connect to Akka Serverless (to create a token with “execution” scope, the command I need to run is
akkasls auth tokens create --type=refresh --scopes=execution --description="My CI/CD token"
)
After setting up the four secrets, the only thing left is to create the GitHub Actions YAML configuration. I’ll start with the complete file first, and break it into sections to explain what everything does. The file should be stored in the .github/workflows
folder of the repository.
In my case, I’ve named my file deploy.yaml
and stored it in the .github/workflows
folder of my repository.
name: akkasls-deployer
on:
push:
branches: [main]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push to Docker Hub
uses: docker/build-push-action@v2
with:
push: true
tags: retgits/myapp:1.0.0
- name: Deploy to Akka Serverless
uses: retgits/akkasls-action@v1
with:
cmd: "services deploy myapp retgits/myapp:1.0.0"
env:
token: ${{ secrets.TOKEN }}
project: ${{ secrets.PROJECT }}
Now that you can see the entire file, I’ll break it up into smaller sections to explain what they do.
name: akkasls-deployer
This basically determines the name of the workflow and this is how it shows up in the Actions section of the repository
on:
push:
branches: [main]
workflow_dispatch:
The on section of a workflow describes the triggers, or when the workflow is executed. In this case, the workflow is executed every time there is a push
to the main
branch or when it is triggered from the workflow (which is done by the workflow_dispatch
setting and is useful if you want to trigger the workflow without pushing to the main branch).
jobs:
build:
runs-on: ubuntu-latest
I run all my builds on Ubuntu, though you could opt to use different operating systems, or even use a self-hosted runner.
steps:
- name: Checkout
uses: actions/checkout@v2
This step checks out the code, so the other steps in this workflow can use it
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
This step sets up Buildx so I can build different images for different operating systems if I wanted (which is especially useful if you want to build containers that run on Apple Silicon chips)
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
As the name implies, this step logs in to Docker Hub so the resulting container image can be pushed there. It leverages two of the Secrets created earlier.
- name: Build and push to Docker Hub
uses: docker/build-push-action@v2
with:
push: true
tags: retgits/myapp:1.0.0
This step builds the container and pushes it to Docker Hub, calling it retgits/myapp:1.0.0
. This is obviously where you want to use some parameterization and use the name of the tag, the GitHub commit SHA, or something else to uniquely identify the container image.
- name: Deploy to Akka Serverless
uses: retgits/akkasls-action@v1
with:
cmd: "services deploy myapp retgits/myapp:1.0.0"
env:
token: ${{ secrets.TOKEN }}
project: ${{ secrets.PROJECT }}
The last step in the process is to deploy the container image to Akka Serverless. This step leverages the other two Secrets created earlier, and it uses the same tag as in the previous step.
As you can see, using CI/CD to deploy a service to Akka Serverless is pretty straight-forward and setting it up once saves a lot of hassle down the line. Let me know what you want to see next, or what you want us to build next!
Cover photo by Gerd Altmann from Pixabay
20