Write a Jenkinsfile
In this tutorial, I explain: - What a Jenkinsfile is and why it’s important - Where the Jenkinsfile should be stored - Basic structure of a Jenkinsfile - How stages and steps are defined - Why Jenkinsfile is preferred over UI-based configuration
What is a Jenkinsfile?¶
Jenkinsfile is a text file that contains the definition of a Jenkins Pipeline and is checked into version control (SCM).
It implements the concept of Pipeline-as-Code, treating the CD pipeline as a part of the application to be versioned and reviewed like any other code.
Why use Jenkinsfile (vs UI)?¶
Creating a Jenkinsfile and storing it in Source Control offers several advantages over the UI-based "Pipeline Script":
- Code Review/Iteration: Changes to the pipeline can be reviewed by the team.
- Audit Trail: You can track who changed what and when (via Git history).
- Single Source of Truth: The code dictates the build process, reducing manual configuration drift.
In the Jenkins pipeline, we have two ways of writing Jenkinsfile,
-
Scripted - The Older way of writing Jenkinsfile, we have to write a lot of logic using Groovy
-
Declarative - Newer and easier way, comes with a lot of inbuilt functions (also called steps)
Scripted¶
In the Scripted way, the Jenkinsfile starts with the node block
node {
}
Declarative¶
In the Declarative way, the Jenkinsfile starts with the pipeline block (Mandatory)
pipeline {
}
Declarative Jenkinsfile in detail¶
Basic Structure¶
-
Inside the pipeline block, we have an agent block
(Mandatory)and stages block(Mandatory) -
Inside the stages block, we should have at least one stage block
-
Inside the stage block, we should have steps block
-
Inside the steps block, we should have at least one step (inbuild function name)
E.g.-
sh step to execute any shell commands
-
echo step to print some data
-
pipeline {
agent any
stages {
stage ('Print') {
steps {
echo "Hello Devops Engineers"
}
}
}
}
-
agent block is used to tell Jenkins where to execute this Pipeline. It executes in the same Jenkins server ( Controller ) by default.
If we have configured agents for Jenkins ( additional servers only for building the pipelines ), then we can use this agent block to tell Jenkins where to execute this pipeline. -
stage block is used to group the set of tasks and visualize in the Pipeline Dashboard
-
steps block is used to group the step
-
step is the basic unit that executes the command.
In the above Jenkinsfile, we have created the Print stage which uses the echo step to print Hello Devops Engineers
Post block in Jenkinsfile¶
The post block is inside a pipeline block. This block is executed once all stages are completed
pipeline {
agent any
stages {
stage ('Print') {
steps {
echo "Hello Devops Engineers"
}
}
}
post {
always {
echo 'I will always say Hello again!'
}
success {
echo 'I will say Hello only if job is success'
}
failure {
echo 'I will say Hello only if job is failure'
}
}
}
In post block, we have three subblocks always, success and failure
-
always - If we trigger a job, whether the stage is success or failure, this block will always be executed.
-
success - This block will be executed only if all the stages are passed.
-
failure - This block will be executed if any one of the stages is failed.
Triggers block in Jenkinsfile¶
The triggers block is inside a pipeline block. Which is used to define how the pipeline should be triggered
These are some options for triggers cron, pollSCM, upstream, and githubPush
cron¶
Accepts a cron-style string to define a regular interval at which the Pipeline should be triggered
triggers {
cron('H/15 * * * *')
}
This will trigger the pipeline every fifteen minutes
pollSCM¶
Accepts a cron-style string to define a regular interval at which Jenkins should check for new source code changes.
If any new changes exist, the Pipeline will be triggered else skipped.
triggers {
pollSCM('* * * * *')
}
This will check for new source code changes in the Git repository every minute.
upstream¶
Accepts a comma-separated string of jobs and a threshold. When any job in the string finishes with the minimum threshold, the Pipeline will be triggered.
triggers {
upstream(upstreamProjects: 'Pipeline-1,Pipeline-2', threshold: hudson.model.Result.SUCCESS)
}
This will trigger the pipeline if Pipeline-1 or Pipeline-2 is finished with SUCCESS status.
Jenkinsfile with cron triggers
pipeline {
agent any
triggers {
cron('H/15 * * * *')
}
stages {
stage ('Print') {
steps {
echo "Hello Devops Engineers"
}
}
}
post {
always {
echo 'I will always say Hello again!'
}
success {
echo 'I will say Hello only if job is success'
}
failure {
echo 'I will say Hello only if job is failure'
}
}
}
Parameters block in Jenkinsfile¶
The parameters block is inside a pipeline block.
The parameters block is used to pass dynamic parameters/variables to the Pipeline.
It has the following types
-
string
-
text
-
booleanParam
-
choice
-
password
string¶
A parameter of a string type
parameters {
string(name: 'ENVIRONMENT', defaultValue: 'dev', description: 'Type Environment name to deploy')
}
text¶
A text parameter can contain multiple lines
parameters {
text(name: 'DEPLOY_TEXT', defaultValue: 'One\nTwo\nThree\n', description: 'Multi line string')
}
booleanParam¶
A boolean parameter
parameters {
booleanParam(name: 'ENABLE_DEBUG', defaultValue: true, description: 'Enable debugging logs')
}
choice¶
A choice parameter
parameters {
choice(name: 'ENVIRONMENT', choices: ['dev', 'qa', 'prod'], description: 'Choose Environment to deploy')
}
password¶
A password parameter
parameters {
password(name: 'SERVER_PASSWORD', defaultValue: '***', description: 'Server SSH password')
}
Jenkinsfile with parameters
pipeline {
agent any
triggers {
cron('H/15 * * * *')
}
parameters {
choice(name: 'ENVIRONMENT', choices: ['dev', 'qa', 'prod'], description: 'Select Environment to deploy')
}
stages {
stage ('Print') {
steps {
echo "Hello Devops Engineers"
}
}
}
post {
always {
echo 'I will always say Hello again!'
}
success {
echo 'I will say Hello only if job is success'
}
failure {
echo 'I will say Hello only if job is failure'
}
}
}
Environment block in Jenkinsfile¶
The environment block specifies a sequence of key-value pairs that will be available as environment variables inside the steps block
The environment block can be inside the pipeline block or inside the stage block
pipeline {
agent any
environment {
DESIGNATION = 'Devops Engineer'
}
triggers {
cron('H/15 * * * *')
}
parameters {
choice(name: 'ENVIRONMENT', choices: ['dev', 'qa', 'prod'], description: 'Select Environment to deploy')
}
stages {
stage ('Print') {
environment {
MESSAGE = 'Hello Devops Engineers'
}
steps {
echo "Your Designation is $DESIGNATION"
echo "$MESSAGE"
}
}
}
post {
always {
echo 'I will always say Hello again!'
}
success {
echo 'I will say Hello only if job is success'
}
failure {
echo 'I will say Hello only if job is failure'
}
}
}
If environment block is defined within the stage block, then those environment variables will be accessible only within that stage.
Important Tips¶
Tip
Linter: You can validate your Declarative Jenkinsfile syntax without running it by using the "Pipeline Linter" (SSHD or HTTP API) or the "Validate" button if you have the VS Code Jenkins Extension.
Note
Groovy: While Declarative Pipelines use a simplified syntax, they are still Groovy under the hood. You can use script { ... } blocks to write raw Groovy code for complex logic if needed.
🧠Quick Quiz — Jenkinsfile¶
Where should the Jenkinsfile be stored?