How to Continuously Deploy a Create-React-App Using GitHub Actions and Zeit Now
By: Leonhard Melzer
Tags: Create React App, Github, Continous Deployment, Now

Setup your CD workflow in less than 15 minutes and then stop worrying about it.

When we worked on our hackathon project jetztein.de, we wanted an easy way to immediately see the current state of our application. Ideally a new version should get deployed every time we push changes to the repository. This is commonly referred to as Continuous Deployment (CD). The GitLab blog has a nice introduction to the topic (and also how their tooling can help you implement CI/CD). They write:

Continuous Deployment is a software development practice in which every code change goes through the entire pipeline and is put into production automatically, resulting in many production deployments every day. It does everything that Continuous Delivery does, but the process is fully automated, there’s no human intervention at all.

Kicking off the process should only require this one easy step: running git push or hitting the Merge-button in the GitHub UI would automatically trigger the process to build and then deploy the application which would finally become accessible at some URL.

This sounds promising — less things to worry about and more time for the exciting stuff! 👍

We already had a GitHub repository with our app and an account with the zero-configuration app platform Zeit Now. So we had all the parts but were missing the tool to connect them. Enter GitHub Actions.

Unfortunately our GitHub Organization didn’t have the Actions feature enabled at the time so we had to do this process manually. But since we now do have access, we wanted to revisit the topic and see if it makes sense to consider this for future projects.

Requirements

You’ll need a couple things if you want to try it out yourself (but you can also just follow along):

An application you would like to deploy: We are working with a Create-React-App but any kind of app with a supported “builder” in Now will do. A GitHub repository with the app: Our hackathon repository is private but this will work with both public and private ones as long as you have… Access to the GitHub Actions feature: The feature is in beta at the time of writing. You may request access to it. You can confirm that you have it by checking the navigation of your GitHub repository: you should see a tab called Actions. A Now account: You’ll need to create a personal access token in your account settings which we’ll use as ZEIT_TOKEN to trigger commands from GitHub Actions.

Please note: We won’t be using the existing GitHub integration offered by Now in the following example. Instead we make use of the new GitHub Actions feature which gives us much greater power and flexibility. This also doesn’t require linking your entire GitHub Organization to Now.

Setup

There are three easy steps to Continuous Deployment (CD) with GitHub Actions and Now:

Adding a now.json to the repository Adding an NPM script called now-build to the package.json Adding a GitHub Actions workflow to the repository

Let’s get started! 🚀

1. Adding a now.json to the Repository

Now uses a configuration file, commonly called now.json . If the file is not present, the CLI will try its best to auto-discover some configuration values based on the given environment. We prefer configuration in code to make the behavior consistent and explicit.

The Now docs have an example for Create-React-App which we adapted for our needs:

now.json file with routing rules for a Create-React-App.

Let’s go through these options one-by-one to understand them a bit better:

Please consult the official configuration reference for further details.

2. Adding an NPM Script Called now-build to the package.json

The static-build builder runs a command to bundle the application as static files into an output folder. Now expects an NPM script called now-build which it will try to run automatically. Furthermore the builder expects the static files to be in a folder called dist . We'll need to move the generated files there:

Simplified package.json with the added now-build script.

3. Adding a GitHub Actions Workflow to the Repository

A GitHub Actions workflow can be described as a rooted directed graph. A failure at each step down the workflow will abort the execution and mark the action as failed ❌.

The workflow specification lives as a text-file with the .workflow extension in the well-known .github directory in the root of your repository.

GitHub provides both a visual editor UI as well as their classic text-editor. Here are both in comparison for the same workflow we’ll be using:

Visual editor UI with our CD workflow.

The textual representation of the workflow, main.workflow .

Which one do you prefer? 🤔

We think both have their place. The visual editor UI appeals to the idea of flow-based programming. Adding and connecting nodes (the actions) has a certain satisfaction you’ll have to experience yourself. The text version on the other hand makes it trivial to use with version control ( diff ) and is easily readable as well as parseable.

Let’s look at the specific nodes: Which actions do we need to implement our CD process?

We want to:

Run now to deploy the application. This is the default effect of the Zeit Now action. Continue only if the pushed branch was master . This is achieved with the GitHub Actions filter and passing branch master as arguments. Run now alias to have the alias point to the new deployment. We'll need to pass alias as an argument to the Zeit Now action for this.

Note: A common gotcha during our research was to miss the scope of Now resources. The ZEIT_TOKEN belongs to a specific user account but the alias domain most likely to an organization. We'll need to explicitly pass the relevant team scope to the CLI, like now --team peerigon to avoid permission errors. The same applies to secrets. You won't need this in a single-user setup.

Usage

Every time you push to your GitHub repository now, GitHub Actions will wake up automatically and do its job. It will run the workflow as we defined it in the previous step:

By running the command now the application will be deployed at a random (sub-)domain. If the pushed branch was master , the workflow continues and aliases the immutable deployment to the specified domain. Otherwise it stops here.

If all steps pass, the status icon of the repository will show the green checkmark ✅. All good!