Freestyle projects are powerful and have been the status quo for many years. However, it is found lacking in several areas:
- When Hudson, Jenkins' predecessor, was written, using a UI for configuration was the norm. However, in the last few years, the ecosystem has moved towards Configuration-as-Code (CaC), where the configuration can be tracked in source control.
- Jenkins saves the configurations files for freestyle projects on the Jenkins server under /var/lib/jenkins/jobs/. This means if the Jenkins server is destroyed, all the configuration settings would be lost. Furthermore, the configuration file is written in XML and is hard to read.
- While it is possible to chain multiple freestyle projects together using post-build actions, you are likely to end up with a lot of duplicate projects, each with different post-build action steps.
To address these issues, Jenkins 2.0 came with a feature called Pipeline, which allow you to do the following:
- Instead of linking multiple freestyle projects together via post-action build steps, you can, with Pipeline, specify many sequential steps, which can optionally be grouped into stages. In a Pipeline, the execution of a downstream step/stage depends on the outcome of the previous step/stage in the chain. Only when the previous steps are successful will the subsequent steps be run. For example, if the tests did not pass, then the deployment step would not run.
- Allows you to specify steps using a Jenkinsfile: A configuration file that is part of your codebase. This CaC (or "pipeline as code") approach means all changes made to the pipeline can be tracked in Git, Pipelines can be branched and merged, and any broken pipelines can be reverted back to the last-known-good version. Furthermore, even if the Jenkins server is corrupt, the configuration will still survive as the Jenkinsfile is stored in the repository, not the Jenkins server; this also means that you can build the project using any Jenkins server that has access to the repository.
Note that you can still define your Pipeline using the Jenkins web UI, although using a Jenkinsfile checked into your Git repository is the recommended approach.
The pipeline feature is enabled by the pipeline plugin, which is installed by default. To define a pipeline, you have to write in a pipeline Domain Specific Language (DSL) syntax and save it inside a text file named Jenkinsfile. A simple Jenkinsfile looks like this:
pipeline {
agent { docker 'node:6.3' }
stages {
stage('build') {
steps {
sh 'npm --version'
}
}
}
}
For the remainder of this chapter, we will focus on using Jenkins to replicate the functions of Travis CI, specifically the following:
- Integrate with GitHub so that a message will be sent to our Jenkins server whenever changes are pushed to our project repository
- Whenever Jenkins receives that message, it will check out the source code and run the tests inside a clean and isolated environment