React app CI/CD pipeline using Azure Devops

React app CI/CD pipeline using Azure Devops

Published on: 22 October 2020

Author: Ramesh Kanjinghat

Recently I have created a simple React app. This is a simple single page application with no server back end.
It was quite simple to convert this pure react app to ASP.Net Core React app. Please check my post https://dhrutara.net/2020/06/12/react-app-to-asp-net-react-app/, if you are interested to know how I did it.
I am basically a Microsoft .Net Developer. I use Azure Devops for scrum process, Git repository and CI/CD pipeline. In my current company I setup and maintain CI/CD pipelines for all the projects.
So, naturally, Azure Devops was my primary choise for this project too. Azure Devops has node.js task that can be used, but I like to use powershell tasks instead. I feel you can achieve much more with powershell scripts than node.js tasks. It is just my personal opinion and I would like to know your thoughts.

Setup

  • Azure Devops pipelines using yaml is the recommended way to setup CI/CD pipelines. I personally like this approach too.
  • I like to break the process into individual units so that units can be reused in multiple pipelines like pull request, ci and master. Each unit is called stage in Azure Devops.
  • Each stage has steps to achieve a specific task like build the solution, run unit tests, publish build artifacts to temporary location, deploy web sites to IIS etc.
  • Each stage is like a function/method that takes arguments from the pipelines. For instance ci pipeline, staging and production/master pipelines pass different folder locations to deploy the code to.
The stages I have are
  • Build : Builds the code to check for any compilation errors.
  • Test: Run all the unit tests to check for any functionality errors.
  • Publish: Builds the code for given configuration and uploads the build artifacts to Azure Pipelines, TFS, or a file share.
  • Deploy: Downloads the published artifacts and deploy to different environments.
One of the disadvantages of having these stages separated is duplicate steps. For instance all the three stages, Build, Test and Publish, pulls the code, installs app dependencies and build. But the ability to reuse stages in multiple pipelines out weighs this duplicity.
Don’t mistake publish stage for dotnet publish command. dotnet publish command builds and actually deploys the binaries, static files to deployment location.
Other hand publish task zips up and stores the build artifacts in a temporary location which can be downloaded and deployed multiple times, if required.
Check https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish to learn more about dotnet publish command
  • Pull request: This pipeline will be triggered every time a pull request is created on the configured branch, mostly ci and master branches. The purpose if this pipeline is to make sure there are no compilation errors and all unit tests are passed, code coverage etc. So, this pipeline needs only Build and Test stages.
  • CI: This triggers when new code is merged into ci branch. This pipeline builds, tests and publishes build artifacts. It also includes Deploy pipeline.
  • Master: This triggers when new code is merged into master branch. This pipeline builds, tests and publishes build artifacts. It also includes Deploy pipeline and it can be deployed to multiple environments based on your requirement.
Before we delve into each stages and pipelines it is important to check the package.json file and see how I have configured the settings for each environment.
The package.json file have some custom scripts that helps use build, test and deploy the code to multiple environments. So, lets check the scripts section in the package.json.
1"scripts": {
2"install-dependencies": "npm install --save-dev",
3"start": "npm-run-all -p watch-css start-js",
4"build:ci": "env-cmd -f .env.ci react-scripts build",
5"build:staging": "env-cmd -f .env.staging react-scripts build",
6"build:production": "env-cmd -f .env.production react-scripts build",
7"test": "react-scripts test",
8"eject": "react-scripts eject",
9"start-js": "react-scripts start",
10}
The script commands we will be using in our pipeline stages are install-dependencies, build:ci, build:production and test.
I am using an open source npm package https://www.npmjs.com/package/env-cmd to read and apply environment specific configurations.
I have
1"env-cmd": "10.1.0",
in my package.json file under dependencies section.
Check https://create-react-app.dev/docs/adding-custom-environment-variables/ to learn more about settings up environment configurations.
Now lets look at each and very stages first and then the pipelines.

Build

Build stage in Azure CI/CD pipeline
Build stage in Azure CI/CD pipeline

Test

Test stage in Azure CI/CD pipeline
Test stage in Azure CI/CD pipeline
Publish
Publish stage in Azure CI/CD pipeline
Publish stage in Azure CI/CD pipeline

Deploy

Deploy stage in Azure CI/CD pipeline
Deploy stage in Azure CI/CD pipeline
Now that we have our stages defined lets see how our pipelines look

Pull Request Pipeline

Azure CI/CD pull request pipeline
Azure CI/CD pull request pipeline
As of writing this Azure Devops doesn’t support pull request triggers defined in yaml files if the repository is Azure Devops Git. We have to use branch policies to trigger pull request pipelines instead.

CI Pipeline

Azure CI/CD CI pipeline
Azure CI/CD CI pipeline

Master Pipeline

Azure CI/CD Master/Production pipeline
Azure CI/CD Master/Production pipeline
If you compare both CI and Master pipelines you can notice that the differences between these 2 pipelines are the buildConfiguration (‘ci’ for CI and ‘production’ for Master) and environmentName (‘CI’ for CI and ‘Production’ for Master)values.
If you want to deploy the code staging before production, you can add another deploy stage and change buildConfiguration and environmentName to, lest say, ‘staging’ and ‘Staging’ or what ever make sense to you.