{"id":50766949,"url":"https://github.com/jenkinsci/jenkinsfilelint","last_synced_at":"2026-06-11T14:31:52.099Z","repository":{"id":325917481,"uuid":"1104248799","full_name":"jenkinsci/jenkinsfilelint","owner":"jenkinsci","description":"Validate Jenkinsfile syntax locally using pre-commit","archived":false,"fork":false,"pushed_at":"2026-06-06T16:36:14.000Z","size":187,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-06T18:07:24.915Z","etag":null,"topics":["jenkins","jenkinsfile","jenkinsfile-linter","jenkinsfile-syntax","jenkinsfilelint","pre-commit"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jenkinsci.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"community_bridge":"jenkins","custom":["https://www.jenkins.io/donate/#why-donate"]}},"created_at":"2025-11-26T00:42:48.000Z","updated_at":"2026-06-06T16:36:17.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jenkinsci/jenkinsfilelint","commit_stats":null,"previous_names":["shenxianpeng/jenkinsfilelint","jenkinsci/jenkinsfilelint"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/jenkinsci/jenkinsfilelint","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenkinsci%2Fjenkinsfilelint","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenkinsci%2Fjenkinsfilelint/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenkinsci%2Fjenkinsfilelint/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenkinsci%2Fjenkinsfilelint/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jenkinsci","download_url":"https://codeload.github.com/jenkinsci/jenkinsfilelint/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jenkinsci%2Fjenkinsfilelint/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34204178,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-11T02:00:06.485Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["jenkins","jenkinsfile","jenkinsfile-linter","jenkinsfile-syntax","jenkinsfilelint","pre-commit"],"created_at":"2026-06-11T14:31:52.012Z","updated_at":"2026-06-11T14:31:52.089Z","avatar_url":"https://github.com/jenkinsci.png","language":"Python","funding_links":["https://funding.communitybridge.org/projects/jenkins","https://www.jenkins.io/donate/#why-donate"],"categories":[],"sub_categories":[],"readme":"# Jenkinsfile Lint\n\n[![CI](https://github.com/jenkinsci/jenkinsfilelint/actions/workflows/main.yml/badge.svg)](https://github.com/jenkinsci/jenkinsfilelint/actions/workflows/main.yml)\n[![codecov](https://codecov.io/gh/jenkinsci/jenkinsfilelint/graph/badge.svg?token=nGrwXORFtI)](https://codecov.io/gh/jenkinsci/jenkinsfilelint)\n[![PyPI version](https://img.shields.io/pypi/v/jenkinsfilelint)](https://pypi.org/project/jenkinsfilelint/)\n\nCatch Jenkinsfile syntax errors before they break your CI.\n\n`jenkinsfilelint` sends your Jenkinsfiles to your Jenkins server's `/pipeline-model-converter/validate` endpoint for real syntax validation. It's primarily a [pre-commit](https://pre-commit.com/) hook, but also works as a CLI tool.\n\n\u003e 📖 Read the [official blog post](https://www.jenkins.io/blog/2026/06/08/jenkinsfilelint-pre-commit/) for the story behind this tool.\n\n![demo](demo.gif)\n\n## Table of Contents\n\n- [Quick Start](#quick-start)\n- [Usage](#usage)\n  - [Pre-commit Hook](#pre-commit-hook)\n  - [CLI](#cli)\n  - [Filtering files](#filtering-files)\n- [Configuration](#configuration)\n- [Security](#security)\n- [How It Works](#how-it-works)\n- [Requirements](#requirements)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Quick Start\n\n```yaml\n# .pre-commit-config.yaml\nrepos:\n  - repo: https://github.com/jenkinsci/jenkinsfilelint\n    rev: # use the latest or a specific version, e.g. v1.4.0\n    hooks:\n      - id: jenkinsfilelint\n```\n\n```bash\nexport JENKINS_URL=https://jenkins.example.com\nexport JENKINS_USER=your-username\nexport JENKINS_TOKEN=your-api-token\n\npip install pre-commit\npre-commit install\n```\n\n## Usage\n\n### Pre-commit Hook\n\nOnce installed, every commit that touches a Jenkinsfile is validated:\n\n```bash\ngit commit -m \"Update Jenkinsfile\"\njenkinsfilelint..........................................................Passed\n```\n\nIf the file has a syntax error the commit is blocked:\n\n```bash\ngit commit -m \"Update Jenkinsfile\"\njenkinsfilelint..........................................................Failed\n- hook id: jenkinsfilelint\n- exit code: 1\n\nErrors encountered validating Jenkinsfile:\nWorkflowScript: 17: Expected a step @ line 17, column 11.\n             test\n             ^\n```\n\nFix the error, re-commit, and it passes.\n\n### CLI\n\n```bash\npip install jenkinsfilelint\n\njenkinsfilelint Jenkinsfile\njenkinsfilelint Jenkinsfile Jenkinsfile.prod tests/Jenkinsfile\n```\n\n### Filtering files\n\nUse `--include` (whitelist) and `--skip` (blacklist) to control which files are validated:\n\n```bash\n# Only validate Jenkinsfiles\njenkinsfilelint --include 'Jenkinsfile*' Jenkinsfile src/Utils.groovy\n\n# Exclude shared-library helper classes\njenkinsfilelint --skip '*/src/*.groovy' --skip 'vars/*.groovy' Jenkinsfile src/Utils.groovy\n```\n\nThese work in pre-commit too:\n\n**Exclude non-pipeline Groovy files (shared library helpers):**\n\n```yaml\n- id: jenkinsfilelint\n  args: [\"--skip=*/src/*.groovy\", \"--skip=vars/*.groovy\"]\n```\n\n**Only validate files matching specific patterns:**\n\n```yaml\n- id: jenkinsfilelint\n  args: [\"--include=Jenkinsfile*\", \"--include=pipelines/*.groovy\"]\n```\n\nYou can also combine both — `--include` narrows first, then `--skip` removes from that set:\n\n```yaml\n- id: jenkinsfilelint\n  args: [\"--include=Jenkinsfile*\", \"--skip=*/src/*.groovy\"]\n```\n\n## Configuration\n\nSupply credentials via environment variables (recommended) or CLI flags:\n\n| Env Variable    | CLI Flag       | Required |\n|-----------------|----------------|----------|\n| `JENKINS_URL`   | `--jenkins-url`| Yes      |\n| `JENKINS_USER`  | `--username`   | No *     |\n| `JENKINS_TOKEN` | `--token`      | No *     |\n\n\\* Only required if your Jenkins requires authentication.\n\n\u003e [!TIP]\n\u003e Even if your Jenkins allows anonymous access for validation, using an API token is recommended for production setups.\n\nCLI flags override env vars. There is no config file.\n\n## Security\n\n\u003e [!WARNING]\n\u003e Never hardcode credentials in config files — use environment variables.\n\n- **Never** put `--token` or `--username` in `.pre-commit-config.yaml` — use environment variables.\n- Use an API token, not your password.\n- A regular user token with read access is sufficient — no need for admin privileges.\n\n## How It Works\n\n`jenkinsfilelint` is a **syntax gate** — it checks that your Declarative Pipeline syntax is valid.\n\n1. Reads the local Jenkinsfile.\n2. POSTs it to `\u003cJENKINS_URL\u003e/pipeline-model-converter/validate`.\n3. Jenkins parses the Pipeline and returns `\"ok\"` or errors.\n4. Errors are printed and the tool exits non-zero.\n\nIt only answers: **\"Will Jenkins accept this syntax?\"**\n\n## Requirements\n\n- Python 3.10+\n- Jenkins server with the Pipeline plugin\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjenkinsci%2Fjenkinsfilelint","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjenkinsci%2Fjenkinsfilelint","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjenkinsci%2Fjenkinsfilelint/lists"}