Lampros Papadimitriou
Posted on February 4, 2021
About
After working on developing the build pipelines for my company, I noticed how modern building tools can help with the automation of important tasks in frontend development.
I also migrated my personal website to use Jenkins for automatically building and deploying it. This guide explains how I was able to do it.
The technology stack I am using for my website is the following
- Vue.js
- Typescript
- NPM
- Eslint
- Jest
- Cypress
Why Jenkinsfile
I personally prefer to give freedom to developers and let them modify the building process as they need. Each git project also contains the Jenkinsfile in the root folder. We setup a Jenkins project as following:
- Add a Pipeline option to job
- Set "Pipeline Script from SCM"
I have worked in the past for projects where the building process and Jenkins were part of the admin team. As frontend developers we had difficulties to introduce new processes and steps in the pipeline and it constrained us to use new technologies we wanted.
Install dependencies
It is a common but wrong practice to install dependencies in CI pipelines using the following command:
npm install
This is actually wrong, since npm install may install a newer minor release for either your dependencies and/or sub-dependencies.
In a nutshell: This way it is possible that your build works on your developer laptop but it fails to compile in Jenkins, simply because npm install
installed a minor sub-dependency that had a breaking change.
In order to avoid this issue simple use:
npm ci
and add package-lock.json
in GIT. Believe me, this is a life savior! It will always install the exact package and versions listed in this file.
Audit dependencies
There is no need for anything else than:
npm audit --parseable --production
This way we are sure that main dependencies have no security issues. I am not checking for any vulnerabilities in dev packages since they are not directly used and it is not possible at the moment to define a threshold to exclude minor issues.
I am also checking if packages are outdated by executing the command:
npm outdated || exit 0
This way the pipeline won't fail if the packages are outdated. It is also not possible here to define a threshold here.
Check linting
Eslint is my favorite option for linting and format checks, since the
integration with IDEs and console command is almost perfect!
If you are using vue-cli to setup your project, we simply need to execute in Jenkinsfile:
npm run lint
Unit testing
A unit testing with coverage is another safety lock for capturing bugs before entering
production.
The following software has been used for this step:
- jest
- @vue/cli-plugin-unit-jest
- jest-junit
- Coberture jenkins plugin
Simple execute the following:
npm run test:unit -- --ci --coverage
After successfully integrating Jenkins with Jest you will get a nice overview of the test
results directly into Jenkins:
E2E testing
I used an end-to-end testing as a smoke test for my website. This way I am sure that the website was deployed successfully.
I chose for this case nightwatch and installed it using vue-cli:
vue add e2e-nightwatch
After building the application, I made the dist directory as the root directory for my web server.
Once it is successfully build, I can execute the smoke test as following:
npm run test:e2e -- --headless --url https://www.trelobifteki.com --config video=false
Some points there:
- I used
--headless
since this is an automated test (no interaction is required) - I am using the actual URL of my website for end-to-end testing
- I deactivated video recording (since I don't need it)
Complete example
This is the actual pipeline I am using in my project. Feel free to check it out and experiment with it!
pipeline {
agent any
stages {
stage('Check for vulnerabilities') {
steps {
sh 'npm audit --parseable --production'
sh 'npm outdated || exit 0'
}
}
stage('download dependencies') {
steps {
sh 'npm ci'
}
}
stage('Check linting') {
steps {
sh 'npm run lint'
}
}
stage('Check unit:test') {
steps {
sh 'npm run test:unit -- --ci --coverage'
}
post {
always {
junit 'junit.xml'
cobertura coberturaReportFile: 'coverage/cobertura-coverage.xml'
}
}
}
stage('Build') {
steps {
sh 'npm run build'
}
}
stage('Check unit:e2e') {
steps {
sh 'npm run test:e2e -- --headless --url https://www.trelobifteki.com --config video=false'
}
}
}
}
Posted on February 4, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.