Generates Jenkinsfiles with stages, agents, parallel builds, post-build actions, and security scanning for Declarative and Scripted pipeline syntaxes. Use when creating a Jenkins pipeline script, Groovy pipeline, or build configuration; implementing CI/CD workflows, continuous integration, or build automation; adding Docker/Kubernetes deployments, matrix builds, parameterized pipelines, or DevSecOps security scanning to a Jenkins setup.
85%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Generate production-ready Jenkinsfiles following best practices. All generated files are validated using devops-skills:jenkinsfile-validator skill.
Process:
assets/templates/declarative/basic.Jenkinsfile and references/best_practices.mdparallelsAlwaysFailFast() in options when using parallel blocksfingerprint: true when using archiveArtifactsUse for complex conditional logic, dynamic generation, or full Groovy control.
Process:
assets/templates/scripted/basic.JenkinsfileUse parallel {} or matrix {} with axes {} for multi-dimensional builds. See Parallel & Matrix for failFast configuration.
Add SonarQube, OWASP Dependency-Check, Trivy stages with fail thresholds.
python3 scripts/generate_shared_library.py --name my-library --package org.exampleagent any // Any available agent
agent { label 'linux && docker' } // Label-based
agent { docker { image 'maven:3.9.11-eclipse-temurin-21' } }
agent { kubernetes { yaml '...' } } // K8s pod template
agent { kubernetes { yamlFile 'pod.yaml' } } // External YAMLenvironment {
VERSION = '1.0.0'
AWS_KEY = credentials('aws-key-id') // Creates _USR and _PSW vars
}options {
buildDiscarder(logRotator(numToKeepStr: '10'))
timeout(time: 1, unit: 'HOURS')
disableConcurrentBuilds()
timestamps()
parallelsAlwaysFailFast()
durabilityHint('PERFORMANCE_OPTIMIZED') // 2-6x faster for simple pipelines
}parameters {
string(name: 'VERSION', defaultValue: '1.0.0')
choice(name: 'ENV', choices: ['dev', 'staging', 'prod'])
booleanParam(name: 'SKIP_TESTS', defaultValue: false)
}| Condition | Example |
|---|---|
branch | branch 'main' or branch pattern: 'release/*', comparator: 'GLOB' |
tag | tag pattern: 'v*', comparator: 'GLOB' |
changeRequest | changeRequest target: 'main' |
changeset | changeset 'src/**/*.java' |
expression | expression { env.DEPLOY == 'true' } |
allOf/anyOf/not | Combine conditions |
Add beforeAgent true to skip agent allocation if condition fails.
catchError(buildResult: 'UNSTABLE', stageResult: 'FAILURE') { sh '...' }
warnError('msg') { sh '...' } // Mark UNSTABLE but continue
unstable(message: 'Coverage low') // Explicit UNSTABLE
error('Config missing') // Fail without stack tracepost {
always { junit '**/target/*.xml'; cleanWs() }
success { archiveArtifacts artifacts: '**/*.jar', fingerprint: true }
failure { slackSend color: 'danger', message: 'Build failed' }
fixed { echo 'Build fixed!' }
}Order: always → changed → fixed → regression → failure → success → unstable → cleanup
Always use fingerprint: true with archiveArtifacts for build traceability.
Always add parallelsAlwaysFailFast() to pipeline options {} block: covers all parallel/matrix blocks automatically. Use per-block failFast true only when options-level is not set:
// Per-block alternative (when options-level not set)
stage('Tests') {
failFast true
parallel {
stage('Unit') { steps { sh 'npm test:unit' } }
stage('E2E') { steps { sh 'npm test:e2e' } }
}
}stage('Matrix') {
matrix {
axes {
axis { name 'PLATFORM'; values 'linux', 'windows' }
axis { name 'BROWSER'; values 'chrome', 'firefox' }
}
excludes { exclude { axis { name 'PLATFORM'; values 'linux' }; axis { name 'BROWSER'; values 'safari' } } }
stages { stage('Test') { steps { echo "Testing ${PLATFORM}/${BROWSER}" } } }
}
}stage('Deploy') {
input { message 'Deploy?'; ok 'Deploy'; submitter 'admin,ops' }
steps { sh './deploy.sh' }
}Place input outside steps to avoid holding agents.
node('agent-label') {
try {
stage('Build') { sh 'make build' }
stage('Test') { sh 'make test' }
} catch (Exception e) {
currentBuild.result = 'FAILURE'
throw e
} finally {
deleteDir()
}
}
// Parallel
parallel(
'Unit': { node { sh 'npm test:unit' } },
'E2E': { node { sh 'npm test:e2e' } }
)
// Environment
withEnv(['VERSION=1.0.0']) { sh 'echo $VERSION' }
withCredentials([string(credentialsId: 'key', variable: 'KEY')]) { sh 'curl -H "Auth: $KEY" ...' }@NonCPS
def parseJson(String json) {
new groovy.json.JsonSlurper().parseText(json)
}Required for non-serializable operations (JsonSlurper, iterators, regex Matchers). No pipeline steps inside.
agent { docker { image 'maven:3.9.11'; args '-v $HOME/.m2:/root/.m2'; reuseNode true } }def img = docker.build("myapp:${BUILD_NUMBER}")
docker.withRegistry('https://registry.example.com', 'creds') { img.push(); img.push('latest') }agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:3.9.11-eclipse-temurin-21
command: [sleep, 99d]
'''
}
}
// Use: container('maven') { sh 'mvn package' }@Library('my-shared-library') _
// or dynamically: library 'my-library@1.0.0'
// vars/log.groovy
def info(msg) { echo "INFO: ${msg}" }
// Usage
log.info 'Starting build'ALWAYS validate using devops-skills:jenkinsfile-validator skill:
devops-skills:jenkinsfile-validator skillValidation commands:
# Full validation (syntax + security + best practices)
bash scripts/validate_jenkinsfile.sh Jenkinsfile
# Syntax only (fastest)
bash scripts/validate_jenkinsfile.sh --syntax-only JenkinsfileUse for simple, standard pipelines. Use manual generation for complex pipelines with custom logic or non-standard requirements.
# Declarative (simple pipelines)
python3 scripts/generate_declarative.py --output Jenkinsfile --stages build,test,deploy --agent docker
# Scripted (simple pipelines)
python3 scripts/generate_scripted.py --output Jenkinsfile --stages build,test --agent label:linux
# Shared Library (always use script for scaffolding)
python3 scripts/generate_shared_library.py --name my-library --package com.exampleAlways consult external docs for:
references/common_plugins.mdSkip external lookup when:
references/common_plugins.mdsh, checkout scm, junit)Covered plugins: Git, Docker, Kubernetes, Credentials, JUnit, Slack, SonarQube, OWASP Dependency-Check, Email, AWS, Azure, HTTP Request, Microsoft Teams, Nexus, Artifactory, GitHub
WHY: Declarative Pipeline syntax is the current standard with better tooling and cleaner validation; Scripted Pipeline should only be used to maintain existing files or when full Groovy control is required.
BAD: New pipelines starting with node { ... }.
GOOD: Start with pipeline { agent any stages { ... } } Declarative syntax.
WHY: Pipeline parameters are logged and visible in the Jenkins UI; credentials must go through the Jenkins Credentials Store.
BAD: parameters { string(name: 'API_KEY', ...) }
GOOD: withCredentials([string(credentialsId: 'api-key-prod', variable: 'API_KEY')]) { ... }
WHY: Sequential stages on a single executor waste build time; extract independent stages into parallel { } blocks.
BAD: Lint, unit-test, integration-test, and SAST in sequential stages.
GOOD: Wrap independent stages in parallel { stage('Lint') { ... } stage('Unit Test') { ... } }.
post { always { cleanWs() } }WHY: Without workspace cleanup, Jenkins agents fill disk with build artifacts from previous runs, causing disk-full build failures.
BAD: No post block in the pipeline.
GOOD: post { always { cleanWs() } } in every Declarative pipeline.
sh with inline secret variable expansionWHY: Shell substitution expands secrets into the command string where they appear in build logs and process lists.
BAD: sh "curl -H 'Authorization: Bearer ${API_KEY}'"
GOOD: withCredentials([...]) { sh 'curl -H "Authorization: Bearer $API_KEY"' } (single quotes prevent Groovy expansion; the credential is still available via the environment).
WHY: Without fail-fast, the remaining parallel branches keep running after one has failed, wasting agent time on a build that is already lost.
BAD: A parallel { ... } block with no parallelsAlwaysFailFast() in options and no failFast true.
GOOD: Add parallelsAlwaysFailFast() to the pipeline options {} block.
WHY: Fingerprints give build traceability, linking an artifact back to the build that produced it.
BAD: archiveArtifacts artifacts: '**/*.jar'
GOOD: archiveArtifacts artifacts: '**/*.jar', fingerprint: true
WHY: Generation can produce syntax errors or best-practice violations. The workflow requires validation with the Jenkinsfile validator skill and a re-run after fixes.
BAD: Generate a Jenkinsfile and hand it straight to the user.
GOOD: Run bash scripts/validate_jenkinsfile.sh Jenkinsfile, fix ERRORS and WARNINGS, re-validate, then present it.
WHY: Without a timeout a hung build occupies an executor indefinitely.
BAD: An options {} block with no timeout(...), or no options at all.
GOOD: options { timeout(time: 1, unit: 'HOURS') }
input inside stepsWHY: An input inside steps holds an agent while it waits for approval. Declaring it at stage level avoids that.
BAD: Calling input within a stage's steps block while an agent is allocated.
GOOD: stage('Deploy') { input { message 'Deploy?' } steps { sh './deploy.sh' } }
// Minimal Declarative Pipeline
pipeline {
agent any
stages {
stage('Build') { steps { sh 'make' } }
stage('Test') { steps { sh 'make test' } }
}
}
// Error-tolerant stage
stage('Flaky Tests') {
steps {
catchError(buildResult: 'SUCCESS', stageResult: 'UNSTABLE') {
sh 'run-flaky-tests.sh'
}
}
}
// Conditional deployment with approval
stage('Deploy') {
when { branch 'main'; beforeAgent true }
input { message 'Deploy to production?' }
steps { sh './deploy.sh' }
}| Option | Purpose |
|---|---|
timeout(time: 1, unit: 'HOURS') | Prevent hung builds |
buildDiscarder(logRotator(numToKeepStr: '10')) | Manage disk space |
disableConcurrentBuilds() | Prevent race conditions |
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') | Continue on error |
references/best_practices.md - Performance, security, reliability patternsreferences/common_plugins.md - Git, Docker, K8s, credentials, notificationsassets/templates/ - Declarative and scripted templatesdevops-skills:jenkinsfile-validator skill - Syntax and best practices validationAlways prefer Declarative unless scripted flexibility is required.
pantheon-org/tekhne
c8416e9
Also appears in
last in sync Aug 28, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.