Skip to main content

Jenkinsfile Lint

CI codecov PyPI version

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.

demo

Table of Contents

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.

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).

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, which includes the following plugins to cover common Declarative Pipeline constructs:

Plugin Common pattern enabled
docker-workflow agent { docker '…' }, docker.image('…')
git git url: '…'
credentials-binding withCredentials([…]) { … }
timestamper options { timestamps() }
ws-cleanup post { always { cleanWs() } }
pipeline-utility-steps readJSON, readYAML, findFiles

This list is a curated starting point — not exhaustive. If your Jenkinsfile uses a plugin not listed here (e.g. kubernetes, pipeline-github-lib), please open an issue to propose adding it, or use a custom image (see below).

Custom image

Build a custom image matching your production Jenkins setup and point to it via JENKINSFILELINT_SERVER_IMAGE:

# Export plugin list from your Jenkins (Script Console or Jenkins CLI)
# and generate plugins.txt + a Dockerfile, then:
docker build -t my-company/jenkinsfilelint-server:custom .
JENKINSFILELINT_SERVER_IMAGE=my-company/jenkinsfilelint-server:custom \
  jenkinsfilelint --local Jenkinsfile

The existing Dockerfile and plugins.txt are a good starting template — fork them and adjust the plugin list to match your production Jenkins.

A full Jenkins plugin list can be 100+ entries, which increases build time and image size. Only add what you need.

Security

  • Never put --token or --username in .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.

Scripted Pipelines and other Groovy files. The endpoint only checks Declarative syntax. For a file with no pipeline { … } block (a Scripted Pipeline, a shared-library vars/*.groovy step, an empty file) Jenkins still parses the Groovy, so syntax errors such as an unclosed brace fail as usual. If it parses, the file is reported as skipped and does not fail the run (⊘ vars/notify.groovy: Skipped (not a Declarative Pipeline) with --verbose). To keep such files from being sent at all, use --skip / --include.

Requirements

  • Python 3.10+
  • For remote mode: a Jenkins server with the Pipeline plugin installed
  • For --local mode: Docker or Podman

Contributing

See CONTRIBUTING.md.

License

MIT — see LICENSE.

Metadata

Release files for jenkinsfilelint 1.5.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jenkinsfilelint 1.5.2
File Size Uploaded Provenance
jenkinsfilelint-1.5.2.tar.gz 402.9 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for jenkinsfilelint 1.5.2
File Interpreter ABI Platform
jenkinsfilelint-1.5.2-py3-none-any.whl Python 3 none any Details

Total release size: 417.7 kB

Release files / jenkinsfilelint-1.5.2.tar.gz

Download URL jenkinsfilelint-1.5.2.tar.gz
Size 402.9 kB
Tags Source
SHA-256 checksum
How to use checksums
d67abf76eba440b4bd332d3b07708c2ab64faceff68575a9d0d90d4b070b5473
BLAKE2b-256 checksum
How to use checksums
548e49237ed9b53a4b4e75fb91f2c251617770937d16340bbd8662c9bc8cec86
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / jenkinsfilelint-1.5.2-py3-none-any.whl

Download URL jenkinsfilelint-1.5.2-py3-none-any.whl
Size 14.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8a87dc482bf2d152d9555690a5c916a4c5271191afd1f780a4eb2b498aacc7cd
BLAKE2b-256 checksum
How to use checksums
cf250978e282193d979f7dfd0fe8b52a219afb82d3963c2df78098db0c307679
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Security for jenkinsfilelint 1.5.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for jenkinsfilelint-1.5.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page