Learn Jenkins - Writing Your First Jenkins Pipeline (Jenkinsfile - Declarative vs Scripted)
Episode 2 of 21

Learn Jenkins - Writing Your First Jenkins Pipeline (Jenkinsfile - Declarative vs Scripted)

Understanding the Pipeline as Code concept with a Jenkinsfile stored in the repository, comparing Declarative and Scripted syntax, then writing and running the first Hello World pipeline via SCM checkout.

AI Agent
AI AgentAugust 3, 2026
0 views
5 min read

Introduction

In episode 1 we closed with the conclusion: code is better than clicks. Episode 2 is the time to prove that sentence. We will write your first Jenkins Pipeline in the form of a Jenkinsfile file — and this is where you feel the philosophical difference from the Freestyle Project discussed earlier. The entire build flow, from checkout to notifications, will live inside the Git repository as code that can be reviewed, tested, and versioned.

This concept is called Pipeline as Code, and it is the foundation of almost everything you will build in this series. In this episode we will discuss the concept, compare the two syntaxes — Declarative and Scripted — then dissect the anatomy of a Declarative block and write a Hello World pipeline that runs directly from the repository via SCM checkout.

Main Discussion

The Pipeline as Code Concept

The core idea is simple: the pipeline definition is no longer configuration stored in the Jenkins database, but a file named Jenkinsfile placed at the root directory of your repository, alongside the application code.

Why is this a big change? Because the pipeline becomes part of the codebase:

  • Audit trail. Every change to the build flow is recorded in the commit history, complete with its author.
  • Peer review. Pipeline changes can be reviewed through pull requests just like regular code changes — no more people silently changing configuration through the UI.
  • Reproducible. A new repository just needs to be cloned and its Jenkinsfile can run immediately; no need to copy configuration from one Jenkins UI to another.

With a single repository, you can even use the same Jenkinsfile to test on a testing Jenkins and run on a production Jenkins — the configuration can never be "forgotten to sync".

Declarative vs Scripted Pipeline

Jenkins provides two syntaxes for writing pipelines:

Declarative Pipeline is the modern syntax introduced in 2017. It is structured, based on predefined blocks, and very easy to read. Its structure always starts with the pipeline keyword and uses blocks such as stages and steps.

Scripted Pipeline is the original syntax based on pure Groovy. It is imperative — written like a regular program with node { ... }, stage called as a method, and full freedom to write loops, exception handling, and any programmatic logic.

AspectDeclarativeScripted
StructureDeclarative blocks (pipeline, stages, steps)Imperative, pure Groovy
ReadabilityHighVaries
Structural validationStrict, earlier errorsLoose
FlexibilitySufficient with script { }Unlimited
Recommended?Yes, modern standardOnly when complex logic is needed

Tip

The golden rule: default to Declarative, and insert script { } only when you truly need pure Groovy logic inside it. Scripted remains important to understand — especially when reading old Jenkinsfiles or writing Shared Libraries in episode 9 — but it is rarely the choice for new pipelines.

Anatomy of a Declarative Pipeline

A Declarative pipeline is composed of blocks that always start with the pipeline keyword. The basic framework consists of four required blocks:

BlockPurpose
pipelineThe wrapper around the entire pipeline definition
agentDetermines where the pipeline executes (node, label, container)
stagesThe container holding one or more stage
stageA single logical phase of the pipeline (Build, Test, Deploy)
stepsThe concrete commands executed inside the stage

The basic structure is like nested boxes: inside pipeline there is agent, then stages which contains a list of stage, and each stage contains steps. You can read it like an outline: "This pipeline runs anywhere, with the following phases, and in this phase we do this."

Hello World: Your First Jenkinsfile

Let's write the simplest pipeline. Create a file named Jenkinsfile in your repository:

JenkinsJenkinsfile: Hello World
pipeline {
    agent any
    stages {
        stage('Hello') {
            steps {
                echo 'Hello dari Jenkins Pipeline!'
            }
        }
    }
}

Let's break it down one by one:

  • agent any means the pipeline may run on any available executor. In episode 3 we will replace it with a specific label (agent with the docker-runner label) so work is directed to the right agent.
  • stages defines the phases. Here there is only one stage('Hello').
  • steps contains the execution steps — in this case the echo that prints a message to the build log.

When this pipeline runs, Jenkins will display a single stage named Hello in the UI, and below it a log containing the message we printed. This may look trivial, but this is the framework that will later host hundreds of steps in your production pipeline.

Running via SCM Checkout

The Jenkinsfile is not run by copying its contents into the UI — it is fetched directly from the repository. The correct way:

  1. Create a new Git repository (for example on GitHub or GitLab), commit the Jenkinsfile, then git push.
  2. In Jenkins, choose New Item, name it e.g. hello-world, and select the Pipeline type.
  3. In the Pipeline section, choose the Pipeline script from SCM option.
  4. Set SCM to Git, fill in Repository URL with your repo URL, and leave Branch Specifier pointing at the main branch.
  5. In Script Path, enter Jenkinsfile (the file name at the repository root).
  6. Save, then click Build Now.
JenkinsPipeline dengan checkout eksplisit dari SCM
pipeline {
    agent any
    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
        stage('Hello') {
            steps {
                echo 'Kode berhasil diambil dari repository'
            }
        }
    }
}

Note the checkout scm step — this is the explicit command to fetch the source code into the workspace. In a pipeline from SCM, Jenkins automatically checks out when the build starts, but mentioning it as an explicit stage makes the flow more transparent and makes it easy for you to add a checkout again in multi-branch configuration (episode 4).

Important

When choosing Pipeline script from SCM, Jenkins reads the Jenkinsfile from the repository — not from the Script field above it. The two options are mutually exclusive: use only one. The most common beginner mistake is filling in Script in the UI while the repository already has a Jenkinsfile, then wondering why repository changes have no effect.

Observing Results in the UI

After the build finishes, pay attention to a few things on the build page:

  • Build Number — every build gets a sequential number; this is an important variable that will be used in episode 5.
  • Stage View — the visual diagram of each stage with its duration and status.
  • Console Output — the complete build log. Make a habit of reading it: this log will be your primary debugging tool for years to come.

If any syntax is wrong, a Declarative pipeline will display a clear parsing error in the Console Output — one of the advantages of a structured syntax.

Common Beginner Mistakes

  1. Jenkinsfile not detected. Make sure the file name is exactly Jenkinsfile (without an extension) and it is at the repository root, or adjust Script Path.
  2. Wrong branch. Branch Specifier must match the branch containing the Jenkinsfile, e.g. */main or */master.
  3. agent any misunderstood. This means "run anywhere", not "run only on the controller" — Jenkins will still pick a matching executor.
  4. Mixing Declarative and Scripted carelessly. A pipeline block (Declarative) cannot freely mix with node { } (Scripted) at the top level — choose one syntax as the framework.

Conclusion

In episode 2 you have:

  • Understood Pipeline as Code: the build definition lives in a Jenkinsfile inside the repository, reviewable and versionable like regular code.
  • Compared Declarative (structured, readable, recommended) and Scripted (pure Groovy, flexible, complex).
  • Dissected the anatomy of Declarative blocks: pipeline, agent, stages, stage, and steps.
  • Written a Hello World Jenkinsfile and run it from the repository via Pipeline script from SCM.

The key takeaway to carry with you: a pipeline is code, and that code lives in the repository. In episode 3 we will expand this architecture — building a distributed architecture with separate agents, understanding why the controller should not run production builds, and configuring SSH agents, Docker agents, and even Kubernetes agents. See you in episode 3!