CI CD Pipeline: How to Setup a CI CD Pipeline From Scratch with GitHub Actions.

Written by yuraabharian | Published 2022/06/16
Tech Story Tags: nodejs | javascript | github-actions | git-workflow | cicd | cicd-pipelines | debugging | getsentry

TLDRCI CD Pipeline: How to Setup a CI CD Pipeline From Scratch with GitHub Actions.via the TL;DR App

In software engineering, CI/CD or CICD is the combined practices of continuous integration and continuous delivery or continuous deployment. CI/CD bridges the gaps between development and operation activities and teams by enforcing automation in building, testing and deployment of applications.

What is CI CD Pipeline?

A CI/CD pipeline automates your software delivery process. The pipeline builds code, runs tests (CI), and deploys a new version of your application (CD) to the test or production environment.

How it works?

Let's assume that you have received the task of implementing some functionality. You split off from the main branch (mainly main or master) depending on the project, and then contribute your code, after you have completed writing for now, you make a Pull Request (there will be a abbreviation PR later in the article) and submit it for Code Review. Let's assume that your PR passed all the manual tests and got approved and can now be merged into the master. But there is one thing - ‘but‘ during the Code Review, we can only guarantee the quality of the code, and we can’t guarantee that the changes will not break your application.

How can we ensure that changes don’t break the application?

Options:

  • Build the application;
  • Run tests (run test);
  • Check code quality (eslint | prettier | type check);

As you can see, there are quite a few actions here, and it is very easy to forget or miss a step. And if this happens, then new changes can break your application. Especially on projects where there are a lot of checks. And, of course, it would be better to automate this process.

When should CI CD be run?

I think a good option would be to have the checks run when the PR is created, and that the developer who will conduct the Code Review would see if that PR passed the tests or not. And so that we can't merge our code into master if the code doesn't pass all the checks.

Note: We will see all the steps of the CI CD later in the article.

This has been a brief description of CI CD and now let’s set up our CI CD process.

The first thing to do is to initialize the project. Create an empty folder, then run npm init to initialize package.json and then run npm install express eslint prettier jest netlify-lambda serverless-http

Step 1: create src/api.js

const express = require('express')
const serverless = require('serverless-http')

const sum = require('../helper/sum')

const app = express()
const router = express.Router()

router.get('/test', (req, res) => {
  res.send('Hello World')
})

router.use(express.static('dist'))

router.get('/sum', (req, res) => {
  const { a, b } = req.query
  res.send(`RESULT: ${sum(a, b)}`)
})

app.use(`/.netlify/functions/api`, router)

module.exports = app
module.exports.handler = serverless(app)

Note: keep in mind that /.netlify/functions/api - /api stands for your application's entry point. In our case, this is the api.js file

Step 2: create helper/sum.js

function sum(a, b) {
  return Number(a) + Number(b)
}

module.exports = sum

Step 3: create test/sum.test.js

const sum = require('../helper/sum')

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3)
})

test('adds 2 + 2 to equal 4', () => {
  expect(sum(2, 2)).toBe(4)
})

test('adds 1 + 1 to equal 2', () => {
  expect(sum(1, 1)).toBe(2)
})

Step 4: create netlify.toml file in the root of your project

[build]
  functions = "functions"

[dev]
  publish = "dist"

Note: we need this for Netlify. We'll talk about it in Step 17

Step 5: create an empty dist/index.html file

Step 6: create scripts commands in the package.json

{
  "name": "cicd",
  "version": "1.0.0",
  "description": "CI/CD example",
  "main": "src/api.js",
  "scripts": {
    "lint": "./node_modules/.bin/eslint  . --ext .js",
    "lint:fix": "./node_modules/.bin/eslint --fix . --ext .js",
    "prettier": "./node_modules/.bin/prettier --check .",
    "prettier:fix": "./node_modules/.bin/prettier --write .",
    "test": "./node_modules/.bin/jest",
    "start": "NODE_ENV=development ./node_modules/.bin/netlify-lambda serve src",
    "build": "NODE_ENV=production ./node_modules/.bin/netlify-lambda build src"
  },
  "dependencies": {
    "express": "4.18.1",
    "prettier": "2.6.2",
    "eslint": "8.17.0",
    "jest": "28.1.1",
    "netlify-lambda": "2.0.15",
    "serverless-http": "3.0.1"
  }
}

Step 7: run the project npm start you should see in your terminal

Lambda server is listening on 9000

Project structure

your project/
--package.json
--.eslintrc
--netlify.toml
--.prettierrc
--jest.config.js
--test/
  --sum.test.js
--helper/
  --sum.js
--dist/
  --index.html
--src/
  --api.js

Step 8: after we init the project you have to create a new repository and push your project on GitHub

If you are not familiar with creating a GitHub repository, you can follow the GitHub tutorial

After you’ve pushed your project on GitHub you can see it on the GitHub

Step 9: create .yml config for the GitHub Actions

Step 10: create a .github folder in the root of your project

Step 11: create a workflows folder in the .github folder

Step 12: add github-actions-demo.yml file

name: CI/CD configure tutorial
on: [push]
jobs:
  Explore-GitHub-Actions:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [16.x]
    steps:
      - name: Check out repository code
        uses: actions/checkout@v3
      - name: installing node_modules
        run: npm install
      - name: building project
        run: npm run build
      - name: running prettier
        run: npm run prettier
      - name: running eslint
        run: npm run lint
      - name: running tests
        run: npm run test
      - run: echo "This job's status is ${{ job.status }}."

Note: *.yml file can have any name

Step 13: create a new commit and push it on the GitHub

Step 14: Open Actions tab

Note: your job name will be your latest commit

Step 15: click on this job, you should see how your job starts

Step 16: after your job is competed, you should see success status

Note: this is a very basic configuration, if you want to add some complex behaviour you can take a look at the official GitHub Actions documentation

At the current stage, we have dealt with CI and now we’ll set up CD. Continuous delivery is automatically deploys all code changes to a testing and/or production environment.

Note: as an example of hosting, I chose Netlify

Step 17: create a new account on Netlify, if you don’t have one

Step 18: connect Netlify’s account to the GitHub repository. Here is Netlify’s tutorial

Step 19: choose branch to deploy and click Customize build settings button

Step 20: after you click Customize build settings you should see additional settings. Add npm run build to the Build command row and dist to the Publish directory

Step 21: click Deploy site button

Step 22: wait while your site is deployed

Step 23: after your site is deployed, you should see a link to your application

Step 24: copy this link, open a new browser tab, paste this link into browser url and add /.netlify/functions/api/test to your link

Example: https://your app link.netlify.app/.netlify/functions/api/test

And finally your should see in the browser

Step 25: test /sum route, you should see RESULT: 5

Example: https://your app link.netlify.app/.netlify/functions/api/sum?a=2&b=2

Conclusion: As you can see CI CD is a very powerful and at the same time easily customizable tool. You can find my code sample by following this link. See you

P.S. Thanks for reading! More articles coming soon!


Written by yuraabharian | I am a Senior Software Engineer. If you have any questions, you can contact me via [email protected] or LinkedIn
Published by HackerNoon on 2022/06/16