What is CI/CD? And how to create CI/CD pipelines using GitHub Actions

Johnson Tito
Towards AWS
Published in
7 min readMay 24, 2021

--

Why should I do CI/CD for my application? Being a developer you would have definitely came across the terms CI/CD, DevOps, Workflows in your daily routine, but have you ever felt like, why is it so special and why do teams go for it?

What is continuous integration & delivery(CI/CD)?

The ultimate goal of any software development team is to roll out new features to the customers regularly. But doing this not so easy as it sounds, for each new feature, we have to ensure that the below things are ok

  1. Make sure that we haven’t introduced any new bugs
  2. Maintain the code quality of the application for each PR that has been raised
  3. Back up and deploy the code in the various environment that the team may have i.e Staging, UAT, and then finally the production environment.

And this takes a lot of time, to ensure that nothing is broken, analyze code quality, then merge the PR’s and finally manually deploy them to each environment. Automating this whole process is called CI/CD.

In simple terms, whenever a developer raises a PR, then that code will be tested against the existing test-cases, and the code quality will be analyzed and vulnerabilities will be detected and reported even before merging the PR, this saves a lot of time in reviewing the PR and also ensures the code quality and all functionalities are intact.

Once all the checks have passed and the PR has been merged then based on the target branch to which the code was merged, the entire app will be deployed to the specific environment. For example, we can configure so that merging to develop will deploy the code to Staging env, and merging to master will deploy to the Production env.

TL;DR

Build → PR(Auto Test) → Merge(Auto deploy) → Repeat

How can I implement CI/CD?

Well for starters we don’t have to start writing a full set of code to do this automation, there are lots of readily available tools out there in the market with which we can just do some configuration and have our own CI/CD pipelines set up for our projects in minutes.

Some of the popular tools are:

  1. Jenkins
  2. CircleCI
  3. TravisCI
  4. GitHub Actions
  5. Bitbucket Pipelines & a lot of other tools on the list.

Why GitHub Actions?

The major benefit of using GitHub Actions is that it comes along with your version control system and also they provide around 2000 free build minutes for private projects and totally free for public projects. If you are already using GitHub for your version control then I would recommend you to go for GitHub Actions as your CI/CD platform.

Additionally, they have a decent amount of readily available action(More like libraries we use in our code) for almost everything that we might need to build a clean CI/CD pipeline.

This doesn’t mean that other tools are not performing well, each has its own use cases where they shine. Say for example most people prefer using Jenkins for their DevOps work as it is open-source and provides lot’s of flexibility in terms of customizing your flow and Jenkins is not cloud-based, so you will have the entire code for yours to do more customization and build secure pipelines, but that being said you have to host your Jenkins application in a separate instance this involves cost and maintenance that will turn out to be another headache that you have to handle eventually.

Similarly with CircleCI you can either do CI or CD but not both at the same time. And if you are using Bitbucket as your version control you can also try using that for your CI/CD platform.

Getting started with GitHub Actions

Before starting with building our own pipeline, it good to be familiar with some of the terminologies that will be used.

  1. Actions →Small sets of building blocks that are used to perform some task.
  2. Jobs →Collection of steps and action which are run on the instance. Jobs can be run sequentially or parallelly.
  3. ON → The Main event on which the Workflow has to be triggered(PR / Merge).
  4. Runs_on → The operating systems type on which we run the jobs(Cost varies based on the OS we select).
  5. Steps → Commands that need to be executed, multiple commands can also be grouped as a single step.
  6. Workflow → A file which contains jobs, and the order that they have to be executed.

There are two way’s to add the GitHub workflow into your application, One is to directly configure it from your GitHub portal like below.

Adding workflow through the GitHub editor

You can add actions, preview them and finalize your flow and once you save it, it will be added to your codebase automatically under the folder .github/workflows/

Additionally, you can search for Actions that you need to complete your workflow and add them directly from the workflow editor.

PS: For a complete list of actions visit https://github.com/marketplace?type=actions

Adding a workflow manually

To start using GitHub Action, first, we need to create the folder .github/ at the root of your project and within that .github folder create a new folder called workflows/

Within this workflows/ folder, you can have as many workflows as you want. Also, you can create separate workflows for different branches. The below is an example workflow that will be triggered only when a pull request is raised against the master branch. You can also add multiple branches in the array if you want the same to be executed for those branches

Adding a workflow manaually
name: continuous Integration

This is the display name that will be shown under the actions tabs.

on:
pull_request:
branches: [ master ]

As already mentioned this is the place where we define when to start the workflow, it could either be on a pull request or when a pull request is merged. To trigger the workflow when the PR is merged or the code it pushed use the below code.

on:
push:
branches: [ master ]

The next section is the “jobs” section which is a collection of steps and actions that has to be done to complete the workflow.

jobs: 
build_and_test:
name: Build and run test:
runs-on: ubuntu-latest

Here we specify the name of the job and the environment in which the job will be run. if you want to specify a specific version of OS you can also do that, and if you want to test the integration across different OS you could also do that with a matrix configuration.

Generally, the jobs specified in a workflow will be executed parallel, and will not wait for one job to complete. But if you want we can make the job started after its parent job is completed like below

jobs:
job1:
steps:
....
job2:
needs: job1
steps:
....

Example:

Running jobs dependant on each other

In the above example, the deployment job will start only after completing the integration job, because we have mentioned that ‘Deployment’ needs ‘Integration’ as needs: Integration

Using steps in a workflow

With steps, you can do anything that you do in your computer terminal, like fetching the latest code, creating a zip file and moving it to the server, or even connecting with the cloud and perform some tasks.

steps:      - name: Checkout code from GitHub
uses: actions/checkout@v2
- name: Setup Node.js environment
uses: actions/setup-node@v2.1.2
with:
node-version: '12'
- name: Install dependencies
run: npm install
- name: Run test cases
run: npm run test

To perform any operation in our code, we need to first check the code to the new environment that we have created in the “jobs” section, and for that, we can use the Action “actions/checkout@v2” provided by GitHub marketplace like above example

You can provide a user-friendly name for each step that you have in your job, but it’s completely optional.

Apart from using Actions in our steps, we can also do some normal shell commands as well using the keyword run.

You can also do an SCP or SSH to your server with the help of available Actions, also we can enable the cache layer to speed up the build time and also utilize the docker containers as well in our workflow.

That’s it with this you can start building your own CI/CD pipeline and reduce all your mundane works.

All set, now if you push code to your master branch, then you can see that the workflow is triggered in the Actions tab of your repository like below

Workflows in GitHub Actions

You can click on the workflow to view its details of each step.

Ref: https://github.com/dev-johnson/nodejs-github-actions

Bonus:

Secrets: GitHub provides a way to store your confidential information that you might want to use in your workflow like, your environmental variables, SSH keys or it could be anything.

Creating secrets in GitHub

All you have to do is go to your “settings” and then select “Secrets” click on “New Repository Secret” and start adding your secrets there, and you can access these secrets in your workflow like below.

steps:
-name: Using my first secret
run: echo ${{ secrets.MY_SECRET_NAME }}

This will come in handy when we try to connect our workflow to the cloud and perform actions.

Happy Coding! 👍

--

--

Polystack developer currently in love with JavaScript, who is excited to learn new stuff and share them as well. Currently associated with Ideas2It Technologies