Jenkins Pipeline (a plugin suite, ID workflow-aggregator) defines pipelines in a Jenkinsfile kept in the repo — reviewed through PRs, with history. Two syntaxes: Declarative (structured, readable, recommended) and Scripted (free-form Groovy, older).
pipeline {
agent any
parameters {
string(name: 'ENV', defaultValue: 'dev', description: 'Target env')
}
environment {
APP = 'my-app'
}
stages {
stage('Build') { steps { sh 'npm ci && npm run build' } }
stage('Test') { steps { sh 'npm test' } }
stage('Deploy') { steps { echo "Deploy ${env.APP} to ${params.ENV}" } }
}
}
flowchart LR PL["pipeline"] --> AG["agent any"] PL --> ST["stages"] ST --> S1["stage Build<br/>steps"] ST --> S2["stage Test<br/>steps"] ST --> S3["stage Deploy<br/>steps"]
| Block | Meaning |
|---|---|
agent |
Where to run: any, none, { label 'linux' }, { docker { image 'node:22-alpine' } } — required |
stages / stage / steps |
Each stage has a name and steps; steps must sit inside a stage |
environment |
Environment variables, read as env.APP or $APP in the shell |
parameters |
Parameters for "Build with Parameters", read as params.ENV |
- A Pipeline job → "Pipeline script from SCM" pointing at the repo; or a Multibranch Pipeline that creates a job per branch with a Jenkinsfile.
- Check the syntax before pushing with the CLI command
declarative-linter(reads the Jenkinsfile from stdin).
Traps: missing agent; putting steps outside a stage; reading a parameter as ${ENV} instead of params.ENV.
| Command | Meaning |
|---|---|
java -jar jenkins-cli.jar -s http://localhost:8080/ -auth @/home/fresher/.jenkins-cli-auth declarative-linter < Jenkinsfile |
Lint a Jenkinsfile |
java -jar jenkins-cli.jar -s http://localhost:8080/ -auth @/home/fresher/.jenkins-cli-auth build my-app-ci -s -v |
Run a job, wait, print the log |
Common steps
| Step | Purpose |
|---|---|
checkout scm |
Check out the commit that triggered the build |
sh 'make test' / bat / powershell |
Run commands on Linux or Windows agents |
echo "..." |
Print a message |
archiveArtifacts artifacts: 'dist/**', fingerprint: true |
Keep build outputs with the build |
junit 'reports/*.xml' |
Publish test results; failing tests mark the build unstable |
stash / unstash |
Pass files between stages on different agents |
dir('frontend') { ... } |
Run steps in a subdirectory |
retry(3) { ... } |
Retry flaky steps such as a network download |
A typical build-and-push pipeline
pipeline {
agent { label 'docker' }
environment { IMAGE = "registry.example.com/team/my-app:${env.GIT_COMMIT.take(7)}" }
stages {
stage('Test') { steps { sh 'npm ci && npm test' } }
stage('Build') { steps { sh 'docker build -t "$IMAGE" .' } }
stage('Push') {
when { branch 'main' }
steps {
withCredentials([usernamePassword(credentialsId: 'registry-cred', usernameVariable: 'U', passwordVariable: 'P')]) {
sh 'echo "$P" | docker login registry.example.com -u "$U" --password-stdin && docker push "$IMAGE"'
}
}
}
}
}
The image tag uses the commit SHA, so every image traces back to its source.
Built-in environment variables
env.BUILD_NUMBER, env.BUILD_URL, env.JOB_NAME, env.BRANCH_NAME (multibranch), env.GIT_COMMIT, and env.WORKSPACE are available in every build. The Pipeline Syntax page in the Jenkins UI (snippet generator) produces correct step syntax and lists all variables.
Keeping Jenkinsfiles maintainable
- Keep logic in scripts or Makefiles in the repo (
sh './scripts/test.sh') so developers can run the same steps locally. - Share common stages across repositories with a shared library (
@Library('ci-lib') _) instead of copying pipelines. - Replay a build with an edited Jenkinsfile from the UI to experiment without committing, then commit the fix.