A Jenkins Shared Library that provides a reusable, YAML-configured CI/CD pipeline for downstream repositories. Consuming repos get a full pipeline — checkout, build, unit test, scan, deploy, integration test, PR gate — from a two-line Jenkinsfile, and configure each stage declaratively in a workflow file, similar to GitHub Actions.
1. Register the library in Jenkins under Manage Jenkins → System → Global Pipeline Libraries with the name jenkins-pipelines, pointing at this repository.
2. Add a Jenkinsfile to your repo:
@Library('jenkins-pipelines') _
ciPipeline()3. (Optional) Add a workflow file at .jenkins/workflows/ci.yaml to override defaults. Every field is optional — with no file at all, the pipeline runs with sensible Gradle defaults (build + unit test + PR gate). See .jenkins/workflows/example.yaml for a fully annotated example.
name: my-service
stages:
build:
tool: gradle
gradle:
tasks: "clean build -x test"
jdkVersion: "17"
scan:
sonar:
enabled: true
projectKey: my-service
deploy:
enabled: true
environments:
- name: dev
branches: ["develop", "feature/*"]
tool: helm
helm:
chart: ./charts/my-service
namespace: devciPipeline() accepts parameters that take precedence over the YAML file:
ciPipeline(
agent: 'gradle-long-running', // pod-template/node label; without it, runs on any available node
workflowFile: 'custom.yaml', // file under .jenkins/workflows/ (default: ci.yaml)
overrides: [stages: [deploy: [enabled: false]]] // deep-merged over the loaded config
)The agent label can only be set here, not in the workflow YAML — the YAML lives in the repo, so it can only be read after a node is allocated and the workspace checked out. On a Kubernetes-cloud Jenkins the label must match a pod template label, or the build will queue forever.
Stages run in this order. Each is driven by its section under stages: in the workflow YAML.
| Stage | Enabled by default | What it does |
|---|---|---|
| Checkout | yes | checkout scm, optional submodules / Git LFS, prints commit info |
| Build | yes | Builds with the configured tool (gradle | maven | nodejs), optionally archives artifacts |
| Unit Test | yes | Runs tests with the same tool, always publishes JUnit results |
| Scan | no | SonarQube analysis (with quality-gate wait) and/or Trivy image scan; runs both in parallel when both are enabled |
| Deploy | no | Deploys to every environment whose branches patterns match the current branch, via helm or kustomize |
| Integration Test | no | Runs an arbitrary shell command with a timeout, publishes JUnit results |
| PR Gate | yes (PR builds only) | Reports build status back to GitHub or Bitbucket; final status is always sent, even on failure |
Notes on stage semantics:
- Most stages are opt-out (
enabled: falseto skip); Trivy, deploy, and integration-test are opt-in (enabled: trueto run). - The PR Gate only runs when
env.CHANGE_IDis set, i.e. on multibranch PR builds. - Deploy branch patterns support globs:
*matches within a path segment,**matches across segments (e.g.feature/*,release/**). - Environment variables like
${IMAGE_TAG}in the YAML are resolved byreadYaml/shell at runtime; make sure they are set on the build.
Configuration is resolved in three layers, later layers winning via deep merge:
- Library defaults —
PipelineConfig.DEFAULTS(mirrored inresources/default-workflow.yaml) - Repo workflow file —
.jenkins/workflows/ci.yamlin the consuming repo - Runtime
overrides— the map passed tociPipeline()
name: my-service # display name (default: jenkins-pipeline)
options:
timeout: 60 # whole-pipeline timeout, minutes
abortPreviousBuilds: false # cancel older builds of the same branch/PR
buildsToKeep: 20
artifactsToKeep: 5Set stages.build.tool and configure the matching block:
build:
tool: gradle # gradle | maven | nodejs
# container: jdk17 # legacy k8s sidecar only; omit for the all-in-one jnlp agent
gradle:
tasks: "clean build -x test"
jdkVersion: "17" # k8s all-in-one: JAVA17_HOME; classic: Jenkins JDK tool "jdk-17"
gradleOpts: "-Xmx2g"
proxy: # optional override; auto-detected from agent env by default
host: 192.168.0.89
port: 10809
noProxy: "localhost,127.0.0.1,.svc.cluster.local"
maven:
goals: "clean package -DskipTests" # runs ./mvnw when present, otherwise mvn
mavenOpts: "-Xmx2g"
profiles: ["ci"]
settingsId: my-settings # Config File Provider file id
nodejs:
nodeVersion: "22" # k8s all-in-one: NODE22_HOME; classic: NodeJS installation "NodeJS-22"
packageManager: npm # npm | yarn
buildScript: build
archiveArtifacts: "**/build/libs/*.jar"Unit-test commands are configured separately under stages.unit-test.<tool> (gradle.tasks, maven.goals, nodejs.testScript).
HTTP proxy. Plain http_proxy/no_proxy env vars are ignored by the JVM, so the library translates proxy settings into JVM flags (-Dhttp(s).proxyHost/Port, -Dhttp.nonProxyHosts) for build, unit-test, and Sonar steps. Gradle runs in two JVMs, so the flags are delivered on two channels: via the GRADLE_OPTS env var for the wrapper/launcher JVM (which downloads the Gradle distribution and ignores CLI -D args), and as CLI -D properties for the daemon JVM (which resolves dependencies). By default the library reads the standard HTTP(S)_PROXY / NO_PROXY env vars on the agent (set cluster-wide, e.g. in the pod template), so no per-repo config is needed; a gradle.proxy block overrides the env. NO_PROXY entries are converted (, → |, leading . → *.); CIDR ranges are dropped since the JVM cannot express them.
Note that gradle.gradleOpts is likewise passed via GRADLE_OPTS (JVM options like -Xmx2g are not valid Gradle CLI arguments).
Kubernetes vs classic agents. The preferred Kubernetes setup is an all-in-one inbound agent image on the pod template's jnlp container, for example ghcr.io/openprojectx/jenkins-build-agent:latest. With that setup, omit build.container; build, unit-test, and Sonar steps run in the agent container, jdkVersion: "17" selects JAVA17_HOME when the image provides it, and nodeVersion: "22" selects NODE22_HOME. build.container is still supported for older pod templates that use per-tool sidecars such as jdk17. On a classic agent, container is ignored and the library falls back to Jenkins tool installations: jdkVersion: "17" → JDK tool jdk-17, nodeVersion: "22" → NodeJS installation NodeJS-22.
scan:
sonar:
enabled: true
serverName: SonarQube # Jenkins SonarQube server name
projectKey: my-service # default: JOB_BASE_NAME
qualityGateWait: true # fail the build if the quality gate fails
timeout: 5 # quality-gate wait, minutes
extraProperties: "-Dsonar.coverage.exclusions=**/generated/**"
trivy:
enabled: true
image: "registry/my-service:${IMAGE_TAG}"
severity: "CRITICAL,HIGH"
exitCode: 1 # 0 = warn-only
ignoreFile: .trivyignoreSonar analysis uses the build tool's own plugin for Gradle/Maven and falls back to sonar-scanner for anything else. The Trivy report is archived as a build artifact.
Deploy is environment-driven: each entry in environments is matched against the current branch, and all matching environments are deployed.
deploy:
enabled: true
kubeCredentialsId: kube-config # file credential exported as KUBECONFIG (global fallback)
environments:
- name: dev
branches: ["develop", "feature/*"]
tool: helm # helm | kustomize
kubeCredentialsId: kube-dev # per-environment override
helm:
chart: ./charts/my-service
release: my-service-dev # default: environment name
namespace: dev
kubeContext: dev-cluster
values: [values.yaml, values-dev.yaml]
set:
image.tag: "${IMAGE_TAG}"
extraArgs: "--wait --timeout 5m"
- name: staging
branches: ["main"]
tool: kustomize
kustomize:
path: ./k8s/overlays/staging
namespace: staging
kubeContext: staging-clusterHelm deploys use helm upgrade --install --create-namespace; Kustomize uses kubectl apply -k followed by kubectl rollout status. Both deployers also implement rollback().
pr-gate:
enabled: true
provider: github # github | bitbucket
github:
credentialsId: github-token
statusContext: ci/jenkins
bitbucket:
credentialsId: bitbucket-token
buildKey: jenkins-ciAt the start of a PR build the gate posts a pending/in-progress status; in the pipeline's finally block it posts the terminal status (SUCCESS / FAILURE / ERROR), so the PR check is updated even when the build fails or aborts.
vars/ # Pipeline steps (the library's public API)
ciPipeline.groovy # Entry point: orchestrates all stages
checkoutStage.groovy # One step per stage, each takes the merged config
buildStage.groovy
unitTestStage.groovy
scanStage.groovy
deployStage.groovy
integrationTestStage.groovy
prGateStage.groovy
src/org/pipeline/
config/ # PipelineConfig (defaults) + YamlConfigLoader (load & deep-merge)
build/ # BuildTool interface, factory, Gradle/Maven/Nodejs builders
deploy/ # Deployer interface, factory, Helm/Kustomize deployers
scan/ # SonarScanner, TrivyScanner
prgate/ # PrGate interface, factory, GitHub/Bitbucket gates
utils/Logger.groovy # ANSI-colored log helper (debug gated on PIPELINE_DEBUG=true)
resources/default-workflow.yaml # Reference copy of the library defaults
.jenkins/workflows/example.yaml # Fully annotated example workflow for consumers
Jenkinsfile # Runs the library's own validation build
Each pluggable concern follows the same interface + factory pattern; to add a new implementation:
- Build tool — implement
org.pipeline.build.BuildTool(build/test), register it inBuildToolFactory. - Deployer — implement
org.pipeline.deploy.Deployer(deploy/rollback), register it inDeployerFactory. - PR gate provider — implement
org.pipeline.prgate.PrGate(check/notify), register it inPrGateFactory.
Then add the corresponding defaults to PipelineConfig.DEFAULTS and document the new YAML block in example.yaml.
All classes take the pipeline steps object in their constructor and must implement Serializable (Jenkins CPS requirement). Pure helper methods that use non-serializable iteration should be annotated @NonCPS.
Controller/agent tooling assumed by the stages you enable:
- Plugins: Pipeline Utility Steps (
readYaml), AnsiColor, JUnit, Workspace Cleanup; SonarQube Scanner (withSonarQubeEnv), GitHub Notify (githubNotify), Bitbucket Build Status Notifier (bitbucketStatusNotify), Config File Provider (MavensettingsId), NodeJS plugin — each only if the matching feature is used. - Agent tools:
git(plusgit-lfsif enabled), the selected build tool (./gradlewwrapper,./mvnwormvn, node/npm/yarn),trivy,helm,kubectlas applicable. For Kubernetes pod agents, the recommendedjnlpimage isghcr.io/openprojectx/jenkins-build-agent:latest. - Tool installations: JDKs named
jdk-<version>and NodeJS installations namedNodeJS-<version>whenjdkVersion/nodeVersionare set. - Credentials: kubeconfig file credentials for deploy; GitHub/Bitbucket tokens for the PR gate.