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:
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!