A CI/CD Solution That Scales To Zero With Actions And Cloud Run

Background

There’s a lot of overlap between the projects I work on in my own time, and when I am on the clock working with the team to develop solutions when it comes to two aspects. Due to my limited free time when developing on my own, and our team’s smaller size the solutions I will always favor are ones that are simple, and scale down to zero with no operational effort.

So when looking for a CI/CD solution that would support one of my favorite products that Google Cloud Platform (GCP) offers called Cloud Run I wanted to take a look at Github Actions. Github Actions is very similar to Cloud Run in this way as you are only charged for what you use.

Not only are these services fully managed, and scale down to zero, but they also have an added benefit that I love to take advantage of when experimenting on my own which is both of these services have a free tier 🙌

I was able to get these two services to play nice together after a little bit of effort. I stumbled a lot when it came to configuring the roles and permissions due to GCP’s unpredictable behavior behind their roles, but thankfully wrote down every step that I went through to get a workable solution so that you don’t need to do spend the hours of trial an error to accomplish an integration between Github Actions and Google Cloud Run.

Getting Started

The example I will be stepping you through will be a simple Flask server deployed via Github Actions to Google Cloud Run. Before I step through the example I have provided a number of concepts, and some requirements that are needed to run this locally.

Concepts

Github Actions — Github’s automation solution that allows you to supply a yaml configuration to automate tasks such as CI/CD operations.

Google Cloud Run— A managed serverless platform provided by Google that scales down to zero. The user just needs to provide a Dockerfile for the container to be run.

Flask — A Python micro web framework commonly used by Python developers.

Requirements

In the example I will be stepping you through you will need two things to run it locally: Python 3.9 and Flask. As with all of my examples your life will be a lot less painful if you install your requirements in a virtual environment via pip. If you are familiar with both of those I would also encourage using virtualenvwrapper which has some really nice extensions that simplify your development environment’s workflow even further.

Step 1: Enable Google Cloud Run

If you skip this step you will actually be presented with the following error which actually is pretty informative.

Image for post

Otherwise, just click on the link below, and enable the API.

You should see a screen that contains the following. Make sure that you have your the project you want to deploy to selected which you should see on the navigation bar near the left side.

Image for post

Step 2: Setup Google Authentication

In this step we will need to create a service account that has a set of permissions needed to deploy to Cloud Run from Github Actions. So navigate to your Google Project, and create this service account.

Once the service account is created you will need to select the following roles. I tried a number of different ways to remove the very permissive project viewer role, but at the time of this writing this your service account will need this role or the deployment will appear to fail in Github even if it is successfully deployed to Cloud Run.

Image for post

All that’s left is just to export a credential for your service account you will need to keep this handy because we will use this later to provide a credential that will allow the Github Action to deploy our web server to Cloud Run.

Step 3: Create or Clone Sample Code to Deploy

Now we could have lead with this step, but since the code really isn’t the valuable part of our process I am planning on focusing more on the integration between Google Cloud Run and Github Actions.

For this step, you can do one of two things. Create your own Github repository from scratch or clone the repository below.

After you have done that note or create a simple hello world endpoint. The example below is from our Github repo, and just provides a simple example that will allow us to see if our integration was successful.

import os

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def hello_world():
    name = request.args.get('name', 'World')
    return f'Hello {name}!'

if __name__ == "__main__":
    app.run(debug=True, host='0.0.0.0', port=int(os.environ.get('PORT', 8080)))

The requirements needed to run the project locally, and in the Docker container we will be spinning up are as followed.

Flask
gunicorn

A requirements.txt file will need to be created at the base level of your project with those permissions so that we can easily install them in our container.

#cloud #github #flask #developer #python

Deploy To Google Cloud Run Using Github Actions
5.10 GEEK