Freestyle vs Pipeline
| Freestyle | Pipeline |
|---|---|
| Configured in the Jenkins UI | Defined as code in a Jenkinsfile |
| Hard to review / version | Versioned in Git with the app |
| Fine for learning | Preferred for real projects |
| Limited reuse | Stages, shared libraries, when, parallel |
Freestyle jobs are great for learning. In real-world projects you use Pipelines — CI/CD logic in a Jenkinsfile at the root of (or path inside) your repository.
What is a Jenkinsfile?
A Jenkinsfile is a text file written in a Groovy-based DSL that defines your entire pipeline. Because it lives in the repo, pipeline changes are tracked in Git like any other change.
Two syntax styles:
- Declarative (recommended) — structured, easier to read
- Scripted — more flexible, raw Groovy
This course uses Declarative.
Jenkinsfile structure
pipeline {
agent any
environment {
APP_NAME = "my-app"
}
stages {
stage('Build') {
steps {
sh 'npm install'
}
}
}
post {
always {
echo 'Cleanup or notify'
}
}
}pipeline
Top-level block for a Declarative pipeline. Everything else nests inside it.
agent
Where the pipeline (or a stage) runs:
agent any // any available node
agent none // each stage picks its own agent
agent { label 'linux' } // node with label
agent {
docker { image 'node:18-alpine' } // clean Node environment per build
}Docker agents eliminate "works on my machine" Node version mismatches. You will use them heavily on Day 3.
environment
Variables available globally or per stage — including credentials bindings (Day 3–4).
stages / stage
Logical phases: Checkout, Install, Test, Build, Deploy. Stages run sequentially by default. If one fails, Jenkins stops and marks the build failed.
Parallel example:
stage('Parallel Tests') {
parallel {
stage('Unit') {
steps { sh 'npm run test:unit' }
}
stage('Integration') {
steps { sh 'npm run test:integration' }
}
}
}steps
Commands that actually run:
steps {
sh 'npm install'
echo 'Installing...'
checkout scm
script {
def out = sh(script: 'npm test', returnStdout: true)
echo out.trim()
}
}sh 'npm install' && sh 'npm test' is wrong thinking — each sh is a separate step. For one shell session, use a multiline block:
sh '''
npm install
npm test
'''post
Runs after the pipeline (or stage) finishes:
post {
always { echo 'Always runs' }
success { echo 'Only on success' }
failure { echo 'Only on failure' }
unstable { echo 'Tests unstable' }
changed { echo 'Result changed vs previous build' }
}Next: Project 2 puts this structure into a real Node.js Express pipeline with PM2 deploy and email.