DevOpsInterviewPrep logo
CI/CD, Release Engineering & GitOps / 02
easyNewTCSInfosysAccenture

What is a Jenkinsfile, and what is the difference between declarative and scripted pipelines?

Pipeline as code moved the build definition into the repository, where it is reviewed and versioned with the thing it builds. Declarative is the default answer, and knowing when scripted still earns its place is the follow-up.

Updated Sep 2026 · Grounded in researched DevOps, SRE and platform engineering interview loops, written to a senior-engineer editorial bar, and never padded to hit a word count.

TL;DR: A Jenkinsfile is the pipeline definition committed alongside the code, so the build changes with the branch it builds. Declarative syntax is structured, validated before it runs and readable; scripted is Groovy with full control. Start declarative, drop into a script block for the rare piece that needs logic.

How to approach it

Say why pipeline as code matters before covering syntax, because the reason is the interesting half: the build definition is versioned, reviewed and branch-specific instead of living in a form somebody edited in the UI. Then pick declarative and say when you would not.

A strong answer

Before Jenkinsfiles, a job was configured through the web interface. The configuration lived in Jenkins, not in git, so there was no history of who changed the build, no review, no way for a branch to build differently from main, and restoring a lost job meant rebuilding it by hand. A Jenkinsfile at the repository root fixes all of that at once: the pipeline is reviewed in the same pull request as the code, and a feature branch that needs an extra step just has it. The image the publish stage pushes is the one that later moves through environments, so the file also records how that artifact was made.

Declarative is the structured form, and it is what you should write:

pipeline {
  agent { label 'linux' }
  options { timeout(time: 20, unit: 'MINUTES') }
  environment { REGISTRY = 'registry.internal' }
  stages {
    stage('Build') {
      steps { sh './gradlew clean build' }
    }
    stage('Test') {
      steps { sh './gradlew test' }
      post { always { junit 'build/test-results/**/*.xml' } }
    }
    stage('Publish') {
      when { branch 'main' }
      steps { sh 'docker push $REGISTRY/checkout:$GIT_COMMIT' }
    }
  }
  post {
    failure { slackSend channel: '#builds', message: "Failed: ${env.JOB_NAME}" }
  }
}

The structure is fixed, which is the point. It is validated before execution, so a syntax error fails immediately rather than halfway through. The blocks are named and predictable: agent picks where it runs, options sets timeouts and retention, when gates a stage, and post runs on success, failure or always, which is where you put test publishing and notifications so they happen even when the build fails.

Scripted is Groovy with a node { } block and no imposed structure. Full loops, conditionals, try/catch, method definitions. It is more powerful and considerably easier to make unreadable, and a 600-line Groovy pipeline that only one person understands is a common and unhappy outcome.

The practical rule: declarative, with a script { } block inside a step for the specific piece that needs real logic. That keeps the shape readable and the complexity contained.

Two things worth mentioning because they show experience. Shared libraries let common steps live in one repository that many Jenkinsfiles import, which is how you stop forty teams copy-pasting the same deploy stage. And agent matters more than it looks: agent none at the top with a per-stage agent means stages can run on different executors, and a heavyweight pipeline that pins one agent for its whole duration wastes capacity during approvals.

What interviewers probe next

"How do you handle credentials?" The credentials plugin, injected with withCredentials or environment { FOO = credentials('id') }, so the value is masked in logs and never in the file. Never a plaintext secret in a Jenkinsfile, which is in git forever.

"What does Multibranch Pipeline do?" Scans a repository, finds branches and pull requests containing a Jenkinsfile, and creates and removes jobs automatically. It is how you avoid maintaining a job per branch by hand.

"How do you make a stage run in parallel?" A parallel block containing named stages, which is the cheapest large win on a slow pipeline. Each branch can have its own agent.

Common mistakes

Configuring jobs in the UI and treating the Jenkinsfile as optional, which loses history and review.

Writing everything scripted because it felt more flexible, ending with a Groovy program nobody wants to touch.

Putting test result publishing in a normal step, so it is skipped when the build fails, which is the exact run you needed the results for.

Secrets as plain environment variables or committed into the Jenkinsfile.

That one was free, and so are 18 answers per topic without an account. Signing in doubles that to 28, keeps your bookmarks, and tracks which topics you keep getting wrong.one Google click · no card · nothing to cancel
HOW DID IT GO?
0
UP NEXT ON YOUR JOURNEY
DISCUSSION · 0

Nothing here yet. Say how you would answer it.