Previous posts:

In this tutorial, I gonna show you how to set up and CI/CD system which helps us to run automation tests, build and deploy automatically.

But firstly, we need to know why we need it and should use it?

Why we should use CI/CD system

In the traditioanal workflow, there is a code repository like GitHub, Bitbucket to store the codebase. Every individual developer will push there completed code to that repository as well as pull code from it if they want to keep their codebase always up-to-date. When a developer finishes their task and pushes code to the repository, they will run the automation test on their local machine to make sure everything still be ok. If nothing wrong with the test, they will build the project and deploy it to the production server and give that new feature to the user’s hand

But traditional workflow has many disadvantages:

  • If an individual developer forgets to pull the latest code from the repository and build their out-of-date code to the server, it will cause missing new features from other developers
  • Run the automaition test, build and deploy take time and resources in the developer’s local machine
  • The objectivity of the code is not guaranteed because the developer can change anything in their codebase which is not allowed in the production environment
  • Developer need to run build and deploy manually to make the production server run the same code with the repository
  • The last but not least, every single developer have the credential (username/password) to deploy their code to the server. It is not secure when we spread that information widely.

CI/CD workflow was born to help us avoid these problems:

CI/CI workflow

In CI/CD workflow, every developer only needs to interact with the repository, they don’t need to run tests, build or deploy on their local machine anymore because now these task belongs to external CD/CI server. That server will take responsibility to always make the production server reflects the same status with the repository by automatically run build and deploy whenever a change is made from the repository. In contrast with traditional workflow, developers must wait on building and deploy on their local machine, now with CD/CI workflow, developers now can take time to take care other in the meantime.

Advantage of CI/CD system:

  • The application on the server is always up-to-date automatically.
  • The objectivity of the code is guaranteed because it only gets the code from the repository, not by any individual developer.
  • The developer can spend their time on other tasks rather than running the build and deploy process.
  • Centralize the credential for deploy to a server, we can protect unwanted deploying and security leak.

How to set up a CI/CD system:

CI/CD requires a service which runs test and deploys for us automatically. There are several CD/CI service in the market such as CircleCI, Jenkins, TravisCI, GitLab, Buddy… In this tutorial, I’ll demonstrate with CircleCI service which is suitable for a small project and free.

Register CircleCI account

  1. Access https://circleci.com/
https://circleci.com/

2. Signup an account (if you haven’t had account yet) or Sign in with your account

3. Start a Project

4. Choose the GitHub project you want to apply here (You must push your current project to GitHub before)

5. Configuration for CircleCI

After this step, we must add some configuration to our “Toeic-learning” project in order to allow circleCI system can get the code, build and deploy it properly

Config project

Follow the guide of CIrcleCI:

  1. Create a folder named .circleci and add a fileconfig.yml.

In created .circle/config.yml, paste these code:

version: 2
jobs:
  build:
    docker:
      - image: circleci/node:10.15.0 #Because our project run on NodeJS, we need to define node as image docker
    working_directory: ~/repo

    steps:
      - checkout
      # Download and cache dependencies
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "package.json" }}
            # fallback to using the latest cache if no exact match is found
            - v1-dependencies-
      - run: npm install # Install dependencies:
      - save_cache:
          paths:
            - node_modules
          key: v1-dependencies-{{ checksum "package.json" }}

      - run: npm build # Run build

Explanation:

There are 2 main important properties in config.yml here: docker and steps .

  • Docker defined what kind of project structure our project we’re running on, in this case, we’re running on Nodejs.
  • Steps help us to defined how our application is built:
    • checkout: code first the get the lastest codebase
    • restore_cache : Help us to speed up the progress by caching installed dependencies. Because every time CircleCI build, it’ll wipe out the whole workspace that means it needs to reinstall dependencies any in the next build, with caching, it helps us to avoid redownloading dependencies.
    • run: npm install to download the new and uncached dependencies.
    • save_cache: cached the new dependencies which are not cached before
    • run: npm build: Build application, this command is defined in package.json
    • run: npm deploy: Deploy built application to Firebase Hosting, this command is defined in package.json

Next step, we need to initialize package.json for our project, in this filre, we will define scripts to build and test our application as well as defined needed dependencies

Init package.json

Run $ npm init and follow the instruction to create package.json. After that we need to install firebase-tools via command $ npm install --save firebase-tools

package.json look like this

{
  "name": "toeic-learning",
  "version": "1.0.0",
  "description": "toeic-learning 1",
  "main": "App.js",
  "scripts": {
    "build": "echo \"Build\""
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/phuchieuct93abc/toeic-learning.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/phuchieuct93abc/toeic-learning/issues"
  },
  "homepage": "https://github.com/phuchieuct93abc/toeic-learning#readme",
  "dependencies": {
    "firebase-tools": "^7.1.0"
  }
}

Now we need to set up the script to build our application

Because our application contains submodules: one for React application and one for Firebase function backend. So we need to setup submodule for our application. It means when we run npm build, it’ll build both React module and functions module

Update script `build`

  "scripts": {
      "build": "npm install --prefix \"app\"  && npm run build --prefix \"app\" "
  },

The final step, we commit all of these change to GitHub

Trigger CircleCI

If you get the result like this, congratulation! You have set up a CD/CI system successfully

But it’s for the build process, we need one more step is automatically deploy to Firebase Hosting.

How to get Firebase token

Run

firebase login:ci

A tab browser will be opened to let user Firebase with your Google account

After login successfully, come back to their terminal and copy the generated token

Update config.yml with the new step to deploy:

version: 2
jobs:
  build:
    docker:
      - image: circleci/node:10.15.0 #Because our project run on NodeJS, we need to define node as image docker
    working_directory: ~/repo

    steps:
      - checkout
      # Download and cache dependencies
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "package.json" }}
            # fallback to using the latest cache if no exact match is found
            - v1-dependencies-
      - run: npm install # Install dependencies:
      - save_cache:
          paths:
            - node_modules
          key: v1-dependencies-{{ checksum "package.json" }}

      - run: npm run build # Run build
      - run: npm run deploy

Update new deploy script for package.json, remember to replace $FIREBASE_TOKEN by the one we got the step above.

{
  "name": "toeic-learning",
  "version": "1.0.0",
  "description": "toeic-learning 1",
  "main": "App.js",
  "scripts": {
    "build": "npm install --prefix \"app\"  && npm run build --prefix \"app\" ",
    "deploy":"firebase deploy --token \"$FIREBASE_TOKEN\""
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/phuchieuct93abc/toeic-learning.git"
  },
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/phuchieuct93abc/toeic-learning/issues"
  },
  "homepage": "https://github.com/phuchieuct93abc/toeic-learning#readme",
  "dependencies": {
    "firebase-tools": "^7.1.0"
  }
}

Commit and push the code to GitHub to trigger CircleCI

Check to see if it work

Open “app/src/App.js” and change something like this:

import React from 'react';
import './App.css';

function App() {

  let logo = "https://frontend.cloudaccess.host/wp-content/uploads/2019/03/010a9061-dcf4-4dd9-b879-ba1a7305280f-150x150.png"
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo}  alt="logo" />
        Welcome to        <a href="{blog}">Frontend        </a>
        Check to see if CircleCI works
      </header>
    </div>
  );
}

export default App;

Commit and push code to master branch, wait for a moment and check the result in our domain:

If our changes are applied in Firebase Hosting, it means our config for CD/CI workflow is working well.

We have done a good job to set up a CD/CI workflow by using CircleCI service. Now every time we change the code, we don’t need to build and deploy anymore, just enjoy coding, the rest will be taken care of by CircleCI

Final word

In this tutorial, I have just show you how to apply CD/CI workflow by using CircleCI service to automatically build and deploy application. This is also the last tutorial for setting up our application. In the next tutorials, we will focus on building React application for “TOEIC-learning” as well as building Firebase Function to server backend logic. Wait for the next one and don’t forget to put your comment if you have any question.

Leave a Reply

Your email address will not be published.