Ravindra BagaleCourses & study guides मराठी

Chapter 21: Jenkins Pipeline and Jenkinsfile

21.2 Declarative vs Scripted (pick Declarative)

Why: the problem

Jenkins gives you two ways to write a pipeline. Declarative and Scripted. Both run on the same engine. Think of a recipe at a restaurant like Haldiram's. Declarative is a printed form. It has fixed boxes: ingredients, steps, serving. Anyone in the kitchen can read it. Scripted is a free notebook. You can write anything, but a new cook may not understand it. In most companies, like Infosys or TCS project teams, the rule is simple. Use Declarative for normal builds. Use a small script block only when you really need a loop or a complex choice. Declarative also checks the file before running. A typo in a block name fails in one second, not after ten minutes of build. In this lesson you will write the same build both ways, run both, and see why teams pick Declarative.

What we will build

You will write one build in Declarative style and one in Scripted style. You will break each on purpose and compare the errors. Then you will add a small script block inside Declarative for a loop.

What: every term in plain English

  • Declarative pipeline — Starts with pipeline {. Has fixed blocks like agent, stages, post. Easy to read and checked early.
  • Scripted pipeline — Starts with node {. Plain Groovy code. Very flexible, harder to read.
  • node — In Scripted, asks for an executor and a workspace.
  • script block — A small piece of Scripted code allowed inside a Declarative step.
  • Validation — Declarative checks the shape of the file before any stage runs.
  • Sandbox — A safety layer that blocks dangerous Groovy methods.
  • DSL — Domain specific language. The set of words Jenkins adds, like sh and stage.
Write the Declarative file Write the Scripted file Make two jobs Run both Break Declarative Break Scripted
Declarative form and Scripted code, top to bottom

How: step by step

  1. Write the Declarative file

    nano Jenkinsfile
    

    What it does: Uses pipeline, agent, stages, steps.

    Output

    (file saved)
    
  2. Write the Scripted file

    nano Jenkinsfile.scripted
    

    What it does: Uses node and stage with plain Groovy.

    Output

    (file saved)
    
  3. Make two jobs

    New Item > badge-decl (Script Path Jenkinsfile)
    New Item > badge-scr (Script Path Jenkinsfile.scripted)
    

    What it does: Two Pipeline jobs, one per style.

    Output

    Saved
    
  4. Run both

    Build Now on each job
    

    What it does: Both show the same stages and output.

    Output

    Finished: SUCCESS
    
  5. Break Declarative

    Change steps to step in one stage and push
    

    What it does: Declarative fails before running.

    Output

    WorkflowScript: 5: Unknown stage section "step"
    
  6. Break Scripted

    Misspell sh as shh and push
    

    What it does: Scripted fails only when it reaches that line.

    Output

    No such DSL method shh found
    

Example 1: Declarative style

Stack. Jenkins Declarative

Goal. Declarative style.

Jenkinsfile

pipeline {
  agent any
  stages {
    stage('Build') {
      steps {
        sh 'npm ci'
        sh 'npm run build'
      }
    }
    stage('Test') {
      steps { sh 'npm test' }
    }
  }
  post {
    always { echo "Result: ${currentBuild.currentResult}" }
  }
}

What each line does

  • pipeline — Root block. Must be the first word.
  • agent any — Where to run.
  • stages / stage / steps — The fixed three levels. Steps hold the real work.
  • post always — Runs at the end, pass or fail.
  • currentBuild.currentResult — SUCCESS, UNSTABLE or FAILURE so far.

Green output

[Pipeline] stage (Build)
+ npm ci
+ npm run build
[Pipeline] stage (Test)
+ npm test
Tests: 9 passed, 9 total
Result: SUCCESS
Finished: SUCCESS

Expected result. A clean, fixed shape. A new team member can read it in a minute.

Example 2: Scripted style for the same build

Stack. Jenkins Scripted

Goal. Scripted style for the same build.

Jenkinsfile.scripted

node {
  try {
    stage('Checkout') { checkout scm }
    stage('Build') {
      sh 'npm ci'
      sh 'npm run build'
    }
    stage('Test') { sh 'npm test' }
  } catch (err) {
    currentBuild.result = 'FAILURE'
    throw err
  } finally {
    echo "Result: ${currentBuild.currentResult}"
  }
}

What each line does

  • node { — Takes an executor and a workspace.
  • stage('Checkout') { checkout scm } — Scripted does not clone by itself, you must ask.
  • try / catch / finally — Plain Groovy error handling. This replaces post.
  • throw err — Fails the build after marking it.

Green output

[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/badge-scr
[Pipeline] stage (Checkout)
[Pipeline] stage (Build)
+ npm ci
[Pipeline] stage (Test)
Tests: 9 passed, 9 total
Result: SUCCESS
Finished: SUCCESS

Expected result. Same result, but you wrote the error handling yourself. More code, more chances for mistakes.

Example 3: Declarative with a small script block for a loop

Stack. Jenkins Declarative with script

Goal. Declarative with a small script block for a loop.

Jenkinsfile

pipeline {
  agent any
  stages {
    stage('Smoke pages') {
      steps {
        script {
          def pages = ['index.html', 'about.html', 'contact.html']
          for (p in pages) {
            sh "test -f dist/${p} && echo OK ${p}"
          }
        }
      }
    }
  }
}

What each line does

  • script { — Opens a small Scripted area inside a Declarative step.
  • def pages = [...] — A Groovy list.
  • for (p in pages) — Loops over the list.
  • sh "...${p}" — Double quotes let Groovy put the value of p into the command.

Green output

[Pipeline] script
+ test -f dist/index.html
OK index.html
+ test -f dist/about.html
OK about.html
+ test -f dist/contact.html
OK contact.html
Finished: SUCCESS

Expected result. You kept the readable Declarative shape and used code only where you needed it.

Example 4: Convert a real Scripted job to Declarative

Stack. Jenkins

Goal. Convert a real Scripted job to Declarative.

old Jenkinsfile (Scripted)

node('linux') {
  stage('Build') {
    timeout(time: 10, unit: 'MINUTES') {
      sh 'npm ci && npm run build'
    }
  }
  stage('Archive') { archiveArtifacts 'dist/**' }
}

new Jenkinsfile (Declarative)

pipeline {
  agent { label 'linux' }
  options { timeout(time: 10, unit: 'MINUTES') }
  stages {
    stage('Build') { steps { sh 'npm ci && npm run build' } }
  }
  post { success { archiveArtifacts 'dist/**' } }
}

What each line does

  • node('linux') — Becomes agent label linux.
  • timeout around a step — Becomes options timeout for the whole pipeline.
  • Archive stage — Becomes post success, so it runs only on green.
  • Result — Same build, fewer lines, checked before it runs.

Green output

[Pipeline] stage (Build)
+ npm ci && npm run build
build done: dist/index.html
Archiving artifacts
Finished: SUCCESS

Expected result. You will do this kind of move often at work. Run both versions once and compare the logs.

Verify: did it work?

  1. Check the shape online

    Job > Pipeline Syntax > Declarative Directive Generator
    

    What it does: Builds correct blocks for you to copy.

    Output

    Generated: options { timeout(time: 10, unit: MINUTES) }
    
  2. Validate from the terminal

    curl -s -X POST -u admin:API_TOKEN -F "jenkinsfile=@Jenkinsfile" http://localhost:8080/pipeline-model-converter/validate
    

    What it does: Checks a Declarative file without running it.

    Output

    Jenkinsfile successfully validated.
    

When it is red 1

WorkflowScript: 5: Unknown stage section "step". Starting with version 0.5, steps in a stage must be in a steps block.

Cause. You wrote step instead of steps, or put sh straight inside stage.

Fix, step by step

  1. Wrap the commands in steps { }.
  2. Validate with the linter.

When it is red 2

No such DSL method 'shh' found among steps

Cause. A typo in a step name in Scripted code.

Fix, step by step

  1. Fix the spelling.
  2. Use the Snippet Generator to copy step names.

When it is red 3

Scripts not permitted to use method java.io.File

Cause. The sandbox blocked a Groovy method.

Fix, step by step

  1. Use a Jenkins step like readFile instead.
  2. Ask an admin before approving in In-process Script Approval.

Cleanup

  1. Delete the test jobs

    badge-decl > Delete Pipeline, badge-scr > Delete Pipeline
    

    What it does: Removes the practice jobs.

    Output

    Deleted
    
  2. Remove the scripted file

    git rm Jenkinsfile.scripted && git commit -m "remove scripted demo" && git push
    

    What it does: Keeps only one Jenkinsfile in the repo.

    Output

    1 file changed, 15 deletions(-)
    

Ravindra Bagale's Tip

Navin team sathi Declarative vapra. Loop lagla tarach script block. Sopa theva!

Practice tasks

Easy Name the blocks

Why: You must read both styles at work.

What to do: Label each block in both examples.

How:
  1. pipeline, agent, stages, steps, post.

Check: All blocks named.

Medium Convert Scripted to Declarative

Why: Old company jobs are often Scripted.

What to do: Rewrite example 2 in Declarative.

How:
  1. Replace try with post.

Check: Same output.

Hard Validate with curl

Why: Catch errors before push.

What to do: Run the validate URL on a broken file.

How:
  1. Make an API token.

Check: Error shown in the terminal.

Easy Say Declarative vs Scripted in two lines

Why: If you can say it simply, you understand it. Juniors and interviewers want the short version first.

What to do: Write two short lines about Declarative vs Scripted for a fresher who knows only Linux basics.

How:
  1. Write what problem it solves.
  2. Write the one command or menu you use for it.
  3. Read it aloud to a friend.

Check: A fresher understands it without asking a question.

Easy Start a fresh lab Jenkins

Why: Practice needs a throwaway Jenkins. If you break it, you delete it and start again.

What to do: Run Jenkins LTS in Docker with a named volume.

How:
  1. docker volume create jenkins_home
  2. docker run -d --name jenkins -p 8080:8080 -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts-jdk17
  3. docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword

Check: The Jenkins unlock page opens on localhost:8080.

Medium Break it on purpose

Why: You must know the red message by face. During an outage there is no time to read slowly.

What to do: Cause one error from the "When it is red" part of this lesson and fix it.

How:
  1. Follow the error section.
  2. Copy the exact message into your notes.
  3. Write the fix in one line.

Check: You fixed it using only the steps, without searching the web.

Medium Write a one-page runbook

Why: At 2 a.m. nobody remembers where a file lives. A short page saves the on-call person.

What to do: Write a runbook page for this lesson.

How:
  1. Title, when to use, exact command, how to check, how to undo.

Check: A teammate can follow it alone.

Medium Repeat it on a cloud VM

Why: A laptop is not a server. Real Jenkins runs on EC2 or a company VM.

What to do: Do the main steps of this lesson again on a small Ubuntu 22.04 EC2 instance.

How:
  1. Launch t3.small with 20 GB disk.
  2. Open port 22 only to your IP.
  3. Repeat the steps and compare the output.

Check: Same green output on the VM as on your laptop.

Hard Explain it like an interview

Why: Interviewers want real stories, not definitions.

What to do: Record a 60 second answer about this lesson.

How:
  1. Say the problem, the command you ran, and one error you hit.

Check: Your answer has a real command and a real error message.

Hard Draw the flow top to bottom

Why: A drawing shows who talks to whom and in what order.

What to do: Draw this lesson as boxes from top to bottom.

How:
  1. Start at the developer push, go through the controller and agent, end at the result.

Check: Each box matches a real thing you saw on screen.

Homework: try at home

Try at home

At home, write a two-stage build in both styles. Break each one with a typo and note how fast each error appears.

Recap

  • Declarative has a fixed shape and early checks.
  • Scripted is plain Groovy, flexible but harder.
  • Use Declarative by default.
  • Use script blocks only for loops or complex logic.
  • Validate files before push.

FAQ

Can I mix both styles?

Yes, by using script blocks inside Declarative steps.

Is Scripted faster?

No. Both run on the same engine.

Which style do interviews expect?

Declarative, with knowledge of what a script block is.

Why does the sandbox block some code?

To stop pipelines from reading files or running code on the controller.

Where do I find all step names?

Pipeline Syntax > Snippet Generator.

Interview questions

  1. Declarative vs Scripted?

    Declarative has a fixed, validated structure and is easy to read. Scripted is plain Groovy inside node blocks and is flexible. Use Declarative and add script blocks when needed.

  2. What is a script block?

    A block inside Declarative steps where you can write Scripted Groovy like loops.

  3. How do you handle errors in Scripted?

    With try, catch and finally, and by setting currentBuild.result.

  4. How do you validate a Jenkinsfile?

    With the pipeline-model-converter validate endpoint or the VS Code Jenkins linter.

  5. What is the Groovy sandbox?

    A security layer that only allows approved methods in pipeline code.

Quick quiz

Q1. Which word starts a Declarative pipeline?

pipeline.

Q2. Which word starts a Scripted pipeline?

node.

Q3. How do you add a loop in Declarative?

Use a script block inside steps.

Q4. Which style checks the file before running?

Declarative.

Q5. What replaces post in Scripted?

try, catch and finally.

Samajla ka?

Ravi Sir's Cards for this lesson

मराठी cards