skip to Main Content

Automatic Deployment Using GitHub Actions

CICD

Software development is a continuous process, with regular code updates from time to time. Whether from adding new features, fixing bugs or just performing general chores like updating project dependencies now and then. One effective approach to easily push and preview these local development changes to a staging or production environment is to create a continuous integration and deployment workflow. In the next few steps, I will teach you how to automatically deploy your project from GitHub to cloud server using GitHub Actions.

Prerequisites:

GitHub Account

In order to use GitHub actions you should have a GitHub account.

Cloud Server

You will also need a cloud server on which we will deploy the React app. For this tutorial we are going to a React app to keep the process of deployment simple.

Let’s go through some fundamentals

What is CICD?


CI and CD stand for continuous integration and continuous delivery/continuous deployment. In very simple terms, CI is a modern software development practice in which incremental code changes are made frequently and reliably. Automated build-and-test steps triggered by CI ensure that code changes being merged into the repository are reliable. The code is then delivered quickly and seamlessly as a part of the CD process. In the software world, the CI/CD pipeline refers to the automation that enables incremental code changes from developers’ desktops to be delivered quickly and reliably to production.

Why CICD?

CI/CD allows organizations to ship software quickly and efficiently. CI/CD facilitates an effective process for getting products to market faster than ever before, continuously delivering code into production, and ensuring an ongoing flow of new features and bug fixes via the most efficient delivery method.

GitHub Actions

GitHub Actions helps you automate tasks within your software development life cycle. GitHub Actions are event-driven, meaning that you can run a series of commands after a specified event has occurred. For  example, every time someone creates a pull request for a repository, you can automatically run a command that executes a software testing script.
What can you do with GitHub Actions? The possibilities are limitless, you could do anything from:

  • Handling CI and CD (Build, test, and deploy applications)
  • Performance monitoring
  • Twilio voice call or SMS alerts

and much more!

Let’s Start

Our target here is to see how automatic deployment of a react project from GitHub to cloud server can be done using GitHub Actions.

Create Project Repo

For this project I used react-app-deployment-GitHub-action as the repo name.

Create React Project

Step 1

Clone the empty repository.

git clone git@GitHub.com:vishnu-kyatannawar/react-app-deployment-GitHub-action.git

Step 2

Create the basic react app using create-react-app command.

npx create-react-app react-app-deployment-GitHub-action

Please checkout more about how to create a new react app here.

Step 3

Run the base app verify that there are no issues.

npm start
    

Step 4

Commit and push the code to GitHub.

// If you did not clone before then you can set the remote git remote origin
$ git remote add origin
git@GitHub.com:vishnu-kyatannawar/react-app-deployment-GitHub-action.git
$ git add .
$ git push origin HEAD

Add GitHub Action workflow

Now that we have the react app in the repository, we can go ahead and create the GitHub Action workflow for deployment.

Step 1

Go to Actions tab.

Step 2

Select Node.js workflow.

Step 3

Create the workflow file.

Let’s go back to our project file and make a small change to see how this workflow runs now.

Step 1

Make a dummy update to base react app.

import logo from "./logo.svg";
import "./App.css";
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
        <h1>Hello world!!! (testing auto deployment)</h1>
      </header>
    </div>
  );
}
export default App;

For now I added a h1 tag

<h1>Hello world!!! (testing auto deployment)</h1>

Step 2

Commit and push the code. Go to the Actions tab and you will find your workflow running

Firstly rename the file as react-app-deployment.yml (you can use any filename).Edit the new file and paste the following content.

# This workflow will do a clean install of node dependencies, cache/restore them, build the source
code and run tests across different versions of node
# For more information see:
https://help.GitHub.com/actions/language-and-framework-guides/using-nodejs-with-GitHub-actions

name: React app deployment

on:
 push:
  branches: [ master ]

jobs:
 build:
  
  runs-on: self-hosted

  strategy:
   matrix:
    node-version: [16.x]

  steps:
  - uses: actions/checkout@v2
  - name: Use Node.js ${{ matrix.node-version }}
    uses: actions/setup-node@v2
    
    with:
	 node-version: ${{ matrix.node-version }}
     cache: 'npm'
   - run: npm i
   - run: npm run build --if-present
   - run: npm tes

Commit the file to the repo with a commit message.

Let's break the above yml file and understand what we are trying to do.

name: React app deployment

This is the name of the workflow.

on:
 push:
  branches: [ master ]
 

Here we are telling when this workflow should trigger. In my example I want this workflow to trigger whenever someone pushes code to the master branch.

jobs:
 build:

A job is a set of steps that execute on the same runner. By default, a workflow with multiple jobs will run those jobs in parallel. You can also configure a workflow to run jobs sequentially. For example, a workflow can have two sequential jobs: build and test code, where the test job is dependent on the status of the build job. If the build job fails, the test job will not run.

For our purpose we just want to do deployment so we just have 1 job.

runs-on: self-hosted

Configures the job to run on a self hosted server. Since we want to deploy the project on our cloud server.

strategy:
   matrix:
    node-version: [16.x]

For now we just want to use node version 16 for our react portal. But if you want to use GitHub actions for testing and you have a piece of code written in node and want to test it across different node versions then you can mention that in the node-version array.

For our purpose we just want to deploy on a server so we will go ahead with Node v16.

steps:

Groups together all the steps that run in the job. Each item nested under this section is a separate action or shell command.

steps:
  - uses: actions/checkout@v2

The uses keyword tells the job to retrieve v2 of the community action named actions/checkout@v2. This is an action that checks out your repository and downloads it to the runner, allowing you to run actions against your code (such as testing tools). You must use the checkout action any time your workflow will run against the repository’s code or you are using an action defined in the repository.

steps:
 uses: actions/setup-node@v2
  with:
   node-version: ${{ matrix.node-version }}
   cache: 'npm'
This step uses the actions/setup-node@v2 action to install the specified version of the node software package on the runner, which gives you access to the npm command.
- run: npm i
- run: npm run build --if-present
- run: npm test

Finally we would like to install the node dependencies and build the production files. Optionally you can even run the test cases.

Note that as soon as you commit the file the workflow will start. Since the workflow file is being pushed to the master branch.

This workflow will fail since we did not yet tell GitHub which server to use to run the workflow on.

Setup GitHub Runner

We have the workflow in place but we still did not specify which self hosted server to use. For this you need to add a GitHub Runner to the repo.

Step 1

Go to Settings tab.

Step 2

Go to Actions tab, and click on New self-hosted runner.

Step 3

Select the runner type. We are going to use a Linux server.

Step 4

You will see a bunch of commands which will guide you through the installation process.

Run the above download steps on your server.

Step 5

Please run all the commands in the same order in which they are shown to download.

Step 6

When you configure your runner please fill in the details which are asked.

You can give a name to your runner and also give a name for the work folder.

Step 7

Finally run the run script.

./run.sh

This will start your runner and it will start listening for the workflow events.

Step 8

Confirm that the runner is running.
Go to Settings > Actions > Runners

You will find that your runner is available and ready to take on any job.

Trigger workflow

Let’s go back to our project file and make a small change to see how this workflow runs now.

Step 1

Make a dummy update to base react app.

import logo from "./logo.svg";
import "./App.css";
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
        <h1>Hello world!!! (testing auto deployment)</h1>
      </header>
    </div>
  );
}
export default App;

For now I added a h1 tag

<h1>Hello world!!! (testing auto deployment)</h1>

Step 2

Commit and push the code. Go to the Actions tab and you will find your workflow running

Step 3

You can click on the latest workflow and check the details of the build job.
You will find all the steps and it will also show you the time it took for each step.

Step 4

Login to your server and you will find the build files inside actions-runner folder.

/home/vishnu/actions-runner/_work/react-app-deployment-GitHub-action/react-app-deployment
-GitHub-action/build

Here all the build files are there which can be served via apache or nginx.

Nginx Setup

I would like to keep this setup very simple.

Step 1

Install nginx

sudo apt update
sudo apt install nginx

Step 2

Update the default nginx file

sudo nano /etc/nginx/sites-available/default

Step 3

Update the root path to your build file.

root
/home/vishnu/actions-runner/_work/react-app-deployment-GitHub-action/react-app-deployment
-GitHub-action/build;

Here I am telling nginx to load the files from my react project.

Step 4

Restart nginx service

sudo systemctl restart nginx

Step 5

Open your server IP address and you will your react app.

Keep GitHub Runner running

You will find that after you close your server terminal where ./run.sh was running, your GitHub runner stopped.

What you can do instead is run the following command.

  1. Stop the self-hosted runner application if it is currently running.
  2. Install the service with the following command:
sudo ./svc.sh install
  1. Start the service with the following command:
sudo ./svc.sh start 

You can find more details about this here.

Conclusion

Overall, I very much enjoy the experience of using GitHub Actions. I think it’ll be the future standard of CI/CD platforms. Every time I use GitHub Actions I’m delighted by how fast I can create workflows to automate a manual task and find new patterns to use GitHub Actions.

References

Posted By: Vishnu Kyatannawar, Osmosee

This Post Has 0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Search