A Jenkinsfile linter that validates Jenkinsfiles using Jenkins API
Project description
Jenkinsfile Lint
Catch Jenkinsfile syntax errors before they break your CI.
jenkinsfilelint validates your Declarative Pipeline syntax via Jenkins's
/pipeline-model-converter/validate
endpoint. It's primarily a pre-commit hook, but also
works as a standalone CLI tool.
📖 Read the official blog post for the story behind this tool.
Table of Contents
- Quick Start
- Pre-commit Hook
- CLI
- Filtering files
- Configuration
- Security
- How It Works
- Requirements
- Contributing
- License
Quick Start
pip install jenkinsfilelint
Then add the pre-commit hook (see below) or use the CLI directly.
Pre-commit Hook
Add the hook to your .pre-commit-config.yaml and install. Once configured,
every commit that touches a Jenkinsfile is automatically validated.
Remote mode (with a Jenkins server)
# .pre-commit-config.yaml
repos:
- repo: https://github.com/jenkinsci/jenkinsfilelint
rev: # use the latest or a specific version, e.g. v1.4.0
hooks:
- id: jenkinsfilelint
Set credentials via environment variables, then install:
export JENKINS_URL=https://jenkins.example.com
export JENKINS_USER=your-username
export JENKINS_TOKEN=your-api-token
pip install pre-commit
pre-commit install
Local mode (with Docker, no Jenkins server needed)
# .pre-commit-config.yaml
repos:
- repo: https://github.com/jenkinsci/jenkinsfilelint
rev: # use the latest or a specific version, e.g. v1.4.0
hooks:
- id: jenkinsfilelint
args: ["--local"]
Docker (or Podman) is the only requirement — no credentials needed:
pip install pre-commit
pre-commit install
The first commit pulls a minimal Jenkins container (~20–40s cold start). Subsequent commits reuse the running container and complete in milliseconds.
[!IMPORTANT] Local mode validates vanilla Declarative Pipeline syntax only. If your production Jenkins has plugins that provide custom options, agents, or steps (e.g., custom shared libraries), local mode may not catch errors related to those plugins. For authoritative validation, use remote mode pointing at your real Jenkins server.
In short:
--local= fast syntax gate, remote = authoritative validation.
When you're done, stop the container:
jenkinsfilelint server stop
What happens on commit
A valid file passes silently:
git commit -m "Update Jenkinsfile"
jenkinsfilelint..........................................................Passed
A syntax error blocks the commit with a clear message:
git commit -m "Update Jenkinsfile"
jenkinsfilelint..........................................................Failed
- hook id: jenkinsfilelint
- exit code: 1
Errors encountered validating Jenkinsfile:
WorkflowScript: 17: Expected a step @ line 17, column 11.
test
^
Fix the error and re-commit.
CLI
You can also run jenkinsfilelint directly on any file:
pip install jenkinsfilelint
jenkinsfilelint Jenkinsfile
jenkinsfilelint Jenkinsfile Jenkinsfile.prod tests/Jenkinsfile
jenkinsfilelint --local Jenkinsfile
Filtering files
Use --include (whitelist) and --skip (blacklist) to control which files are validated:
# Only validate Jenkinsfiles
jenkinsfilelint --include 'Jenkinsfile*' Jenkinsfile src/Utils.groovy
# Exclude shared-library helper classes
jenkinsfilelint --skip '*/src/*.groovy' --skip 'vars/*.groovy' Jenkinsfile src/Utils.groovy
These work in pre-commit too:
Exclude non-pipeline Groovy files (shared library helpers):
- id: jenkinsfilelint
args: ["--skip=*/src/*.groovy", "--skip=vars/*.groovy"]
Only validate files matching specific patterns:
- id: jenkinsfilelint
args: ["--include=Jenkinsfile*", "--include=pipelines/*.groovy"]
You can also combine both — --include narrows first, then --skip removes from that set:
- id: jenkinsfilelint
args: ["--include=Jenkinsfile*", "--skip=*/src/*.groovy"]
Configuration
Supply credentials via environment variables (recommended) or CLI flags:
| Env Variable | CLI Flag | Required |
|---|---|---|
JENKINS_URL |
--jenkins-url |
Yes * |
JENKINS_USER |
--username |
No ** |
JENKINS_TOKEN |
--token |
No ** |
JENKINSFILELINT_SERVER_IMAGE |
— | No |
* Not required in --local mode.
** Only required if your Jenkins requires authentication (not used in --local mode).
[!TIP] Even if your Jenkins allows anonymous access for validation, using an API token is recommended for production setups.
CLI flags override env vars. There is no config file.
Local Docker image
By default, --local mode uses the official image
ghcr.io/jenkinsci/jenkinsfilelint-server:latest. You can override this with
the JENKINSFILELINT_SERVER_IMAGE environment variable if you maintain a
custom build.
Security
[!WARNING] Never hardcode credentials in config files — use environment variables.
- Never put
--tokenor--usernamein.pre-commit-config.yaml— use environment variables. - Use an API token, not your password.
- A regular user token with read access is sufficient — no need for admin privileges.
How It Works
jenkinsfilelint POSTs your Jenkinsfile to Jenkins's
/pipeline-model-converter/validate endpoint and reports whether the syntax is
valid. That's it — it only answers: "Will Jenkins accept this syntax?"
- Remote mode: validates against your existing Jenkins server using the URL and credentials you configure.
- Local mode (
--local): automatically starts a lightweight Jenkins container (via Docker or Podman) and validates against it. The container is reused across runs for near-instant validation.
Requirements
- Python 3.10+
- For remote mode: a Jenkins server with the Pipeline plugin installed
- For
--localmode: Docker or Podman
Contributing
See CONTRIBUTING.md.
License
MIT — see LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jenkinsfilelint-1.5.0.tar.gz.
File metadata
- Download URL: jenkinsfilelint-1.5.0.tar.gz
- Upload date:
- Size: 147.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d6d108b8b256b76eb41bb80b68c370efa990e73c71241d62242cc4cedb68991
|
|
| MD5 |
4b76b7e0f3a927aba2e002d4fd7ce3a1
|
|
| BLAKE2b-256 |
6017cdc76d4a739f493908db14910a4b7751fd511f4cda5ba73cbd98827d1b32
|
Provenance
The following attestation bundles were made for jenkinsfilelint-1.5.0.tar.gz:
Publisher:
release.yml on jenkinsci/jenkinsfilelint
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jenkinsfilelint-1.5.0.tar.gz -
Subject digest:
9d6d108b8b256b76eb41bb80b68c370efa990e73c71241d62242cc4cedb68991 - Sigstore transparency entry: 2146745466
- Sigstore integration time:
-
Permalink:
jenkinsci/jenkinsfilelint@1bc30cfcd1ec68993b858737afcc7ff94b9f7633 -
Branch / Tag:
refs/tags/v1.5.0 - Owner: https://github.com/jenkinsci
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1bc30cfcd1ec68993b858737afcc7ff94b9f7633 -
Trigger Event:
release
-
Statement type:
File details
Details for the file jenkinsfilelint-1.5.0-py3-none-any.whl.
File metadata
- Download URL: jenkinsfilelint-1.5.0-py3-none-any.whl
- Upload date:
- Size: 14.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
982a8ff7678617a2beda7ff2c6f7a6552902b6d37fb076fcf0a79d572032eb70
|
|
| MD5 |
04e8f164d742d49c86666dd08ecf7e08
|
|
| BLAKE2b-256 |
d30fbbaf5873558f27a874e601ecbf5935d9c22555fb2568edff5e52a01cf884
|
Provenance
The following attestation bundles were made for jenkinsfilelint-1.5.0-py3-none-any.whl:
Publisher:
release.yml on jenkinsci/jenkinsfilelint
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jenkinsfilelint-1.5.0-py3-none-any.whl -
Subject digest:
982a8ff7678617a2beda7ff2c6f7a6552902b6d37fb076fcf0a79d572032eb70 - Sigstore transparency entry: 2146745498
- Sigstore integration time:
-
Permalink:
jenkinsci/jenkinsfilelint@1bc30cfcd1ec68993b858737afcc7ff94b9f7633 -
Branch / Tag:
refs/tags/v1.5.0 - Owner: https://github.com/jenkinsci
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1bc30cfcd1ec68993b858737afcc7ff94b9f7633 -
Trigger Event:
release
-
Statement type: