React, Github Actions and Google Cloud — Continuous Deployment
By: Lyubomir Stoykov
Tags: Github Actions, React, Google Cloud Platform, Continuous Delivery, Software Development

Important: Make sure you have signed up & received an invitation for the Github Actions beta here to be able to follow the article.

In this tutorial, we’ll look into how to integrate Github Actions with Google Cloud App Engine to continuously deliver a (React) web application.

Our main goal is to understand how Github Actions and Google Cloud work together, therefore familiarity with React and the ecosystem around it would be assumed.

Github Actions are executable tasks that can be triggered by events such as pushing to the repository. Multiple actions combined together form a workflow. An example of a workflow is one that builds and deploys your application on each push.

Part 1: React

The first step is to go ahead and create a React application. For the purposes of this write-up, we’ll use create-react-app. In your terminal, write

npx create-react-app my-app

Part 2: Google Cloud

Initial Setup

If you haven’t already, install the gcloud SDK. After that, go to the google console, create a Project and enable the App Engine as explained here.

Service Account

We’ll need a service account to later authenticate Github against Google Cloud. To create one, go to service accounts in the google console.

Then click on create service account, give it an appropriate description such as authenticate Github against Google Cloud, a name such as github-actions and click create. In the next step it’s important to assign the correct Roles:

App Engine Deployer

App Engine Service Admin

Storage Object Creator

Storage Object Viewer

Lastly, click create key and save it somewhere (you’ll need it later). Let’s name the key: github-app-engine-access.json. Here you can learn more about service accounts and what they’re typically used for.

Project Configuration

Add app.yaml and .gcloudignore config files in the root dir of your React App as follows:

app.yaml

runtime: python27

api_version: 1

threadsafe: true handlers:

- url: /

static_files: build/index.html

upload: build/index.html

expiration: 1s - url: /(.*)

static_files: build/\1

upload: build/(.*)

Indentations here are very important, otherwise, you’ll get an error.

ps. I haven’t figured out to set a Cache-Control: no-cache header, therefore it says expiration 1s. Let me know if you know how! I want to cache the assets only, but not index.html so new versions of the app are immediately visible.

.gcloudignore

Since we don’t want to push the node_modules folder to the cloud, we exclude it.

node_modules/

Manual Deployment

Before we introduce Github Actions, we’ll build & deploy our app manually.

Go to the folder of your React App and run: gcloud auth login. This will connect the app to your Google Cloud account so you can deploy. Run npm run build in order to build the React App. Lastly, run gcloud app deploy and follow the instructions.

In order to visit your app in the browser, you could run gcloud app browse.

Part 3: Github Actions

Our goal now is to automate the Manual Deployment above via Github Actions. Here are the steps

Create a Github repository Push your React App there Go to the Github repository and click Actions (top bar, next to Pull Requests. If you don’t have the button, sign up for the beta here). Click the create a new workflow button followed by another click on the create a new workflow link on the next page. Label the workflow as you wish. I have named mine: build & deploy and click done. Create the Actions

Before we start, each action has several attributes as documented here.

needs — the action the current action relies on

— the action the current action relies on uses — the package we’re going to use. Either a repository or a link to a docker image.

— the package we’re going to use. Either a repository or a link to a docker image. runs — what we want to run in the docker image. If not specified, the ENTRYPOINT command will be executed.

— what we want to run in the docker image. If not specified, the ENTRYPOINT command will be executed. args — CLI arguments (usually for the ENTRYPOINT command).

Don’t worry if you don’t fully grasp them yet. Follow the steps below and it will start making sense.

Now let’s finally create our Actions.

actions/bin/filter@master

The first action enables a workflow to be executed only when we push on the master, no other branch.

Use the blue connector in the visual editor to create the action. In the search field enter `actions/bin/filter@master` and select use.

You can name the label however you want, I’ve named mine filter master. Leave the field runs empty and for args field fill in branch master.

Now, any push to a non-master branch would be filtered out, therefore deployment of the React App won’t be triggered.

nuxt/actions-yarn@master

The second action installs node_modules. Go ahead and create it via the blue connector. In the search field look for nuxt/actions-yarn@master and select use.

The label is again personal preference, I’ve named mine install node_modules. For args the input is install. This action runs `yarn install` in order to install node_modules.

build static assets

The third action runs yarn build. Follow the same steps as above, but instead of install in the args field, fill in build.

GitHub Action for Google Cloud SDK auth

The goal of this fourth action is to grant permission to Github to connect to Google Cloud.

Create it via the blue connector and look for GitHub Action for Google Cloud SDK auth in the search field.

Leave both runs and args empty, but click on create new secret. Name the key as GCLOUD_AUTH and for value field, you have to find github-app-engine-access.json (the service account key that we’ve already created above in Part 2: Google Cloud) and encrypt it in base64.

In Unix-based systems, run base64 github-app-engine-access.json in the terminal. Now copy the string and paste it in the value field.

GitHub Action for Google Cloud

The last action is to finally deploy the application. You should look for GitHub Action for Google Cloud in the search field and in the field runs fill in: gcloud app deploy — project=<PROJECT-ID>.

You could find <PROJECT-ID> when you run gcloud app browse in the terminal and that would be the subdomain of appspot.com. For instance, something like https://core-123.appspot.com/ would have <PROJECT-ID> of core-123.



That’s it, we’re done! Now you can make changes to your application, push to master and the new version should be live within a few minutes.



The final main.workflow looks like this: