Comprehensive toolkit for validating, linting, testing, and automating Jenkinsfile pipelines (both Declarative and Scripted). Use this skill when working with Jenkins pipeline files, validating pipeline syntax, checking best practices, debugging pipeline issues, or working with custom plugins.
Overall
score
93%
Does it follow best practices?
Validation for skill structure
Documentation for frequently used Jenkins plugins in pipelines.
Provides Git repository access for Jenkins jobs.
Declarative:
pipeline {
agent any
stages {
stage('Checkout') {
steps {
checkout scm
}
}
}
}Scripted:
node {
checkout scm
}checkout([
$class: 'GitSCM',
branches: [[name: '*/main']],
userRemoteConfigs: [[
url: 'https://github.com/user/repo.git',
credentialsId: 'github-credentials'
]]
])
// With multiple remotes
checkout([
$class: 'GitSCM',
branches: [[name: '*/develop']],
userRemoteConfigs: [
[url: 'https://github.com/user/repo.git', name: 'origin'],
[url: 'https://github.com/upstream/repo.git', name: 'upstream']
]
])// Get commit hash
def commit = sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
// Get short commit hash
def shortCommit = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
// Get current branch
def branch = sh(script: 'git rev-parse --abbrev-ref HEAD', returnStdout: true).trim()
// Get commit author
def author = sh(script: 'git log -1 --pretty=%an', returnStdout: true).trim()
// Get commit message
def message = sh(script: 'git log -1 --pretty=%B', returnStdout: true).trim()
// Tag commit
sh "git tag -a v${env.BUILD_NUMBER} -m 'Release ${env.BUILD_NUMBER}'"
sh 'git push origin --tags'GIT_COMMIT - Current commit hashGIT_BRANCH - Branch nameGIT_PREVIOUS_COMMIT - Previous commitGIT_PREVIOUS_SUCCESSFUL_COMMIT - Last successful build commitGIT_URL - Repository URLGIT_AUTHOR_NAME - Commit author nameGIT_AUTHOR_EMAIL - Commit author emailJenkins plugin for running builds in Docker containers.
Declarative:
pipeline {
agent {
docker {
image 'maven:3.8.1-adoptopenjdk-11'
args '-v /tmp:/tmp'
label 'docker-agent'
}
}
stages {
stage('Build') {
steps {
sh 'mvn --version'
}
}
}
}node {
// Run inside container
docker.image('maven:3.8.1').inside {
sh 'mvn clean package'
}
// With additional arguments
docker.image('node:14').inside('-v /tmp:/tmp -e NODE_ENV=production') {
sh 'npm install'
sh 'npm test'
}
// Build Docker image
def image = docker.build("myapp:${env.BUILD_NUMBER}")
// Build with custom Dockerfile
def image2 = docker.build("myapp:latest", "-f Dockerfile.prod .")
// Push to registry
docker.withRegistry('https://registry.example.com', 'registry-credentials') {
image.push()
image.push('latest')
}
// Run container
def container = docker.image('nginx:latest').run('-p 8080:80')
try {
sh 'curl http://localhost:8080'
} finally {
container.stop()
}
}sh 'docker-compose up -d'
try {
sh 'run-integration-tests.sh'
} finally {
sh 'docker-compose down'
}Run Jenkins agents as Kubernetes pods.
Declarative:
pipeline {
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
metadata:
labels:
jenkins: agent
spec:
containers:
- name: maven
image: maven:3.8.1-adoptopenjdk-11
command:
- cat
tty: true
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "1000m"
- name: docker
image: docker:latest
command:
- cat
tty: true
volumeMounts:
- name: docker-sock
mountPath: /var/run/docker.sock
volumes:
- name: docker-sock
hostPath:
path: /var/run/docker.sock
'''
}
}
stages {
stage('Build') {
steps {
container('maven') {
sh 'mvn clean package'
}
}
}
stage('Docker Build') {
steps {
container('docker') {
sh 'docker build -t myapp:latest .'
}
}
}
}
}podTemplate(
label: 'my-pod',
containers: [
containerTemplate(name: 'maven', image: 'maven:3.8.1', ttyEnabled: true, command: 'cat'),
containerTemplate(name: 'kubectl', image: 'bitnami/kubectl:latest', ttyEnabled: true, command: 'cat')
],
volumes: [
secretVolume(secretName: 'kubeconfig', mountPath: '/home/jenkins/.kube')
]
) {
node('my-pod') {
stage('Build') {
container('maven') {
sh 'mvn clean package'
}
}
stage('Deploy') {
container('kubectl') {
sh 'kubectl apply -f deployment.yaml'
}
}
}
}Securely store and use credentials in pipelines.
withCredentials([usernamePassword(
credentialsId: 'my-credentials',
usernameVariable: 'USERNAME',
passwordVariable: 'PASSWORD'
)]) {
sh 'echo "User: $USERNAME"'
// Use $PASSWORD
}withCredentials([string(
credentialsId: 'api-token',
variable: 'API_TOKEN'
)]) {
sh 'curl -H "Authorization: Bearer $API_TOKEN" https://api.example.com'
}withCredentials([sshUserPrivateKey(
credentialsId: 'ssh-key',
keyFileVariable: 'SSH_KEY',
usernameVariable: 'SSH_USER'
)]) {
sh 'ssh -i $SSH_KEY $SSH_USER@server.example.com "deploy.sh"'
}withCredentials([file(
credentialsId: 'kubeconfig',
variable: 'KUBECONFIG'
)]) {
sh 'kubectl --kubeconfig=$KUBECONFIG get pods'
}withCredentials([certificate(
credentialsId: 'cert-id',
keystoreVariable: 'KEYSTORE',
passwordVariable: 'KEYSTORE_PASSWORD'
)]) {
sh 'sign-app.sh $KEYSTORE $KEYSTORE_PASSWORD'
}Declarative:
environment {
DOCKER_CREDENTIALS = credentials('docker-hub-credentials')
// Creates DOCKER_CREDENTIALS_USR and DOCKER_CREDENTIALS_PSW
API_KEY = credentials('api-key') // Secret text
}Common utility steps for pipelines.
// Read file
def content = readFile(file: 'version.txt')
// Write file
writeFile(file: 'output.txt', text: 'Hello World')
// Read JSON
def json = readJSON(file: 'config.json')
// Or from text
def data = readJSON(text: '{"key": "value"}')
// Write JSON
writeJSON(file: 'output.json', json: [name: 'Jenkins', version: '2.0'])
// Read YAML
def yaml = readYAML(file: 'config.yaml')
// Write YAML
writeYAML(file: 'output.yaml', data: [name: 'Jenkins', version: '2.0'])
// Read CSV
def csv = readCSV(file: 'data.csv')
// Read properties
def props = readProperties(file: 'config.properties')// Check if file exists
if (fileExists('path/to/file')) {
echo 'File exists'
}
// Find files
def files = findFiles(glob: '**/*.jar')
files.each { file ->
echo "Found: ${file.path}"
}
// Touch file
touch(file: 'marker.txt')
// ZIP files
zip(zipFile: 'archive.zip', dir: 'target')
// Unzip
unzip(zipFile: 'archive.zip', dir: 'output')Publish JUnit test results.
post {
always {
junit '**/target/test-results/*.xml'
}
}
// With options
junit(
testResults: '**/target/surefire-reports/*.xml',
allowEmptyResults: true,
keepLongStdio: true,
healthScaleFactor: 1.0
)Publish HTML reports.
publishHTML([
reportDir: 'coverage',
reportFiles: 'index.html',
reportName: 'Coverage Report',
keepAll: true,
alwaysLinkToLastBuild: true,
allowMissing: false
])
// Multiple reports
publishHTML([
reportDir: 'test-results',
reportFiles: 'index.html',
reportName: 'Test Results'
])
publishHTML([
reportDir: 'coverage',
reportFiles: 'index.html',
reportName: 'Code Coverage'
])Send notifications to Slack.
// Simple notification
slackSend(
color: 'good',
message: 'Build succeeded!'
)
// With details
slackSend(
color: currentBuild.result == 'SUCCESS' ? 'good' : 'danger',
message: """
Build: ${env.JOB_NAME} #${env.BUILD_NUMBER}
Status: ${currentBuild.result}
Duration: ${currentBuild.durationString}
URL: ${env.BUILD_URL}
""",
channel: '#builds',
teamDomain: 'myteam',
tokenCredentialId: 'slack-token'
)
// Conditional notifications
post {
success {
slackSend color: 'good', message: "Build ${env.BUILD_NUMBER} succeeded"
}
failure {
slackSend color: 'danger', message: "Build ${env.BUILD_NUMBER} failed"
}
fixed {
slackSend color: 'good', message: "Build ${env.BUILD_NUMBER} fixed!"
}
}Send detailed email notifications.
emailext(
subject: "Build ${currentBuild.result}: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: """
<h2>Build ${currentBuild.result}</h2>
<p><strong>Job:</strong> ${env.JOB_NAME}</p>
<p><strong>Build Number:</strong> ${env.BUILD_NUMBER}</p>
<p><strong>Build URL:</strong> <a href="${env.BUILD_URL}">${env.BUILD_URL}</a></p>
<p><strong>Duration:</strong> ${currentBuild.durationString}</p>
""",
to: 'team@example.com',
from: 'jenkins@example.com',
replyTo: 'noreply@example.com',
mimeType: 'text/html',
attachLog: true,
compressLog: true,
attachmentsPattern: '**/target/*.jar'
)
// Conditional emails
post {
failure {
emailext(
subject: "Build Failed: ${env.JOB_NAME}",
body: "Check ${env.BUILD_URL}",
to: 'team@example.com',
recipientProviders: [
developers(), // Send to developers who made changes
culprits(), // Send to developers who broke the build
requestor() // Send to user who triggered the build
]
)
}
}Set timeouts for builds.
Declarative:
options {
timeout(time: 1, unit: 'HOURS')
}Scripted:
timeout(time: 30, unit: 'MINUTES') {
node {
// steps
}
}
// Activity timeout (no console output)
timeout(time: 10, unit: 'MINUTES', activity: true) {
node {
// steps
}
}Add timestamps to console output.
Declarative:
options {
timestamps()
}Scripted:
timestamps {
node {
echo 'This will have timestamps'
}
}Add color to console output.
Declarative:
options {
ansiColor('xterm')
}Scripted:
ansiColor('xterm') {
node {
sh 'ls --color=always'
}
}Clean workspace before/after builds.
// Clean before build
cleanWs()
// Clean after build
post {
always {
cleanWs()
}
}
// Clean with options
cleanWs(
deleteDirs: true,
disableDeferredWipeout: true,
notFailBuild: true,
patterns: [
[pattern: 'target', type: 'INCLUDE'],
[pattern: '*.log', type: 'INCLUDE']
]
)
// Delete directory
deleteDir()archiveArtifacts(
artifacts: '**/*.jar',
allowEmptyArchive: false,
fingerprint: true,
onlyIfSuccessful: true
)// Stash files
stash(
name: 'build-artifacts',
includes: 'target/*.jar',
excludes: 'target/*-sources.jar'
)
// Unstash files
unstash 'build-artifacts'// Trigger another job
build(
job: 'downstream-job',
parameters: [
string(name: 'ENVIRONMENT', value: 'production'),
booleanParam(name: 'RUN_TESTS', value: true)
],
wait: true,
propagate: true
)def userInput = input(
message: 'Deploy to production?',
ok: 'Deploy',
parameters: [
choice(name: 'ENVIRONMENT', choices: ['staging', 'production'], description: 'Target environment'),
string(name: 'VERSION', defaultValue: '1.0', description: 'Version to deploy')
],
submitter: 'admin,ops',
submitterParameter: 'approver'
)
echo "Deploying ${userInput.VERSION} to ${userInput.ENVIRONMENT}"
echo "Approved by: ${userInput.approver}"retry(3) {
sh 'flaky-command'
}sleep(time: 30, unit: 'SECONDS')waitUntil {
def status = sh(script: 'check-status.sh', returnStatus: true)
return status == 0
}For unlisted plugins, use:
/jenkinsci/\<plugin-name\>-pluginInstall with Tessl CLI
npx tessl i pantheon-ai/jenkinsfile-validator@0.1.0