Running multiple steps
Pipelines are made up of multiple steps that allow you to build, test and deploy applications. Jenkins Pipeline allows you to compose multiple steps in an easy way that can help you model any sort of automation process.
Think of a “step” like a single command which performs a single action. When a step succeeds it moves onto the next step. When a step fails to execute correctly the Pipeline will fail.
When all the steps in the Pipeline have successfully completed, the Pipeline is considered to have successfully executed.
Linux, BSD, and Mac OS
On Linux, BSD, and Mac OS (Unix-like) systems, the sh
step is used to execute a shell command in a Pipeline.
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'echo "Hello World"'
sh '''
echo "Multiline shell steps works too"
ls -lah
'''
}
}
}
}
Jenkinsfile (Scripted Pipeline)
node {
stage('Build') {
sh 'echo "Hello World"'
sh '''
echo "Multiline shell steps works too"
ls -lah
'''
}
}
Windows
Windows-based systems should use the bat
step for executing batch commands.
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage('Build') {
steps {
bat 'set'
}
}
}
}
Jenkinsfile (Scripted Pipeline)
node {
stage('Build') {
bat 'set'
}
}
Timeouts, retries and more
There are some powerful steps that “wrap” other steps which can easily solve problems like retrying (retry
) steps until successful or exiting if a step takes too long (timeout
).
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage(‘Deploy’) {
steps {
retry(3) {
sh ‘./flakey-deploy.sh’
}
timeout(time: 3, unit: 'MINUTES') {
sh './health-check.sh'
}
}
}
}
}
Jenkinsfile (Scripted Pipeline)
node {
stage('Deploy') {
retry(3) {
sh './flakey-deploy.sh'
}
timeout(time: 3, unit: 'MINUTES') {
sh './health-check.sh'
}
}
}
The “Deploy” stage retries the flakey-deploy.sh
script 3 times, and then waits for up to 3 minutes for the health-check.sh
script to execute. If the health check script does not complete in 3 minutes, the Pipeline will be marked as having failed in the “Deploy” stage.
“Wrapper” steps such as timeout
and retry
may contain other steps, including timeout
or retry
.
We can compose these steps together. For example, if we wanted to retry our deployment 5 times, but never want to spend more than 3 minutes in total before failing the stage:
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage(‘Deploy’) {
steps {
timeout(time: 3, unit: ‘MINUTES’) {
retry(5) {
sh ‘./flakey-deploy.sh’
}
}
}
}
}
}
Jenkinsfile (Scripted Pipeline)
node {
stage(‘Deploy’) {
timeout(time: 3, unit: ‘MINUTES’) {
retry(5) {
sh ‘./flakey-deploy.sh’
}
}
}
}
Finishing up
When the Pipeline has finished executing, you may need to run clean-up steps or perform some actions based on the outcome of the Pipeline. These actions can be performed in the post
section.
Jenkinsfile (Declarative Pipeline)
pipeline {
agent any
stages {
stage(‘Test’) {
steps {
sh ‘echo “Fail!”; exit 1’
}
}
}
post {
always {
echo ‘This will always run’
}
success {
echo ‘This will run only if successful’
}
failure {
echo ‘This will run only if failed’
}
unstable {
echo ‘This will run only if the run was marked as unstable’
}
changed {
echo ‘This will run only if the state of the Pipeline has changed’
echo ‘For example, if the Pipeline was previously failing but is now successful’
}
}
}
Jenkinsfile (Scripted Pipeline)
node {
try {
stage('Test') {
sh 'echo "Fail!"; exit 1'
}
echo 'This will run only if successful'
} catch (e) {
echo 'This will run only if failed'
// Since we're catching the exception in order to report on it,
// we need to re-throw it, to ensure that the build is marked as failed
throw e
} finally {
def currentResult = currentBuild.result ?: 'SUCCESS'
if (currentResult == 'UNSTABLE') {
echo 'This will run only if the run was marked as unstable'
}
def previousResult = currentBuild.previousBuild?.result
if (previousResult != null && previousResult != currentResult) {
echo 'This will run only if the state of the Pipeline has changed'
echo 'For example, if the Pipeline was previously failing but is now successful'
}
echo 'This will always run'
}
}