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?

The GitHub Actions

In the CI/CD I’ll use four different GitHub Actions:

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")

The YAML

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.

The full file

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 }}

Breaking up the file in parts

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.

What’s next?

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