Comprehensive Azure DevOps YAML validator
Project description
Azure Pipeline Validator
azure-pipeline-validator is a batteries‑included Azure DevOps YAML inspector that runs the same validations you rely on in the service, but locally. It combines three feedback loops:
- yamllint – fast structural linting using a tuned configuration for Azure Pipelines quirks.
- JSON Schema – offline validation against Microsoft’s published schema (
/distributedtask/yamlschema). - Preview REST API – invokes
POST .../_apis/pipelines/{id}/previewwithyamlOverride, returning the realfinalYamland anyvalidationResultsthat Azure DevOps would produce.
The CLI understands both single files and whole repositories, wraps templates automatically (steps/jobs/stages), and mirrors the live API response schema (including continuation_token).
Table of contents
Features
- Template auto-wrapping – detects steps/jobs/stages templates, wrapping them into runnable pipelines before previewing.
- Schema caching – fetches the official schema once per run and reuses it for every file, keeping validation snappy.
- Rich reporting – console output shows pass/fail per file with the first offending message per stage.
- Toggleable stages – disable lint/schema/preview individually for quick iteration.
- Failure ergonomics –
--fail-faststops on first failure; exit codes are 0 (success) or 1 (any failures/API issues). - Selective scanning –
--exclude/-xlets you skip generated folders or files with glob patterns. - UV-native – built with uv, so you can run it via
uv run,uvx, or install it as a global tool.
Installation & invocation
Getting started (recommended)
-
Install uv (pick the command for your OS):
-
macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
-
Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
-
-
Pick the validations you need – nothing runs until you opt in:
-
Lint-only (no Azure creds needed):
uvx azure-pipeline-validator --lint .
-
Schema check (downloads the public schema anonymously):
uvx azure-pipeline-validator --schema workflows/ci.yml
-
Preview (requires
AZDO_*+AZDO_PATbecause it calls your org):uvx azure-pipeline-validator --preview --schema workflows/
-
Short flags -l, -s, and -p map to --lint, --schema, and --preview if you prefer brevity, and you can combine them as needed.
Global install with uv (install once, use anywhere):
uv tool install git+https://github.com/andrewmaspero/azure-pipeline-validator.git
azure-pipeline-validator --help
Once published to PyPI, you can also use:
uv tool install azure-pipeline-validator
azure-pipeline-validator --help
Pip install will also work once published (pip install azure-pipeline-validator).
Required environment
Environment variables (or their CLI equivalents) are only required when --preview/-p is enabled. Lint (--lint/-l) and schema (--schema/-s) checks run entirely offline using the public schema.
Export the same variables you would in an Azure Pipelines job, or pass them via the --azdo-* options:
| Variable | Description |
|---|---|
AZDO_ORG / --azdo-org |
Organization URL, e.g. https://dev.azure.com/contoso. (Falls back to az devops configure --defaults organization=....) |
AZDO_PROJECT / --azdo-project |
Project that owns the pipeline. (Falls back to az devops configure --defaults project=....) |
AZDO_PIPELINE_ID / --azdo-pipeline-id |
ID of an existing YAML pipeline (any pipeline is fine). |
AZDO_PAT / --azdo-pat |
PAT with Build (Read & Execute); use SYSTEM_ACCESSTOKEN inside CI. |
AZDO_REFNAME |
Optional ref used when expanding templates (default refs/heads/main). |
AZDO_TIMEOUT_SECONDS |
Optional HTTP timeout override (default 30). |
Tips:
- You can set variables inline without shell-specific syntax:
uvx azure-pipeline-validator AZDO_ORG=https://dev.azure.com/contoso AZDO_PROJECT=demo ...- Every Azure option also has a CLI flag, e.g.
uvx azure-pipeline-validator --azdo-org https://dev.azure.com/contoso --azdo-pat token workflows/.- Already signed in via
az devops login? The cached PAT from the Azure CLI DevOps extension (orAZURE_DEVOPS_EXT_PAT) is picked up automatically.- Defaults configured via
az devops configure --defaults organization=... project=...are used wheneverAZDO_ORG/AZDO_PROJECTare missing.- Inside Azure Pipelines you can skip
AZDO_PATby enabling “Allow scripts to access the OAuth token” and mapping it toSYSTEM_ACCESSTOKEN.
Discovering available projects
Need to remember project names? Run:
uvx azure-pipeline-validator projects --top 20
The command reuses the same credential discovery (env vars, az devops login, defaults configured via az devops configure).
Usage examples
Validate the entire repo with every check (requires AZDO_* + PAT):
uv run azure-pipeline-validator --lint --schema --preview . --repo-root $(pwd)
Validate a single template file using only the schema:
uv run azure-pipeline-validator --schema common/templates/steps/build.yml
Lint a directory quickly:
uv run azure-pipeline-validator --lint workflows/
Skip generated templates while linting:
uv run azure-pipeline-validator --lint workflows/ --exclude "workflows/generated"
CLI reference
Usage: azure-pipeline-validator [OPTIONS] [PATH]
Run yamllint, schema validation, and Azure preview against YAML files.
Arguments:
PATH File or directory to validate. Directories are scanned recursively for *.yml and *.yaml files. [default: .]
Options:
--repo-root PATH Base path used when resolving template references (defaults to CWD).
--azdo-org URL Organization URL (overrides AZDO_ORG).
--azdo-project NAME Project name (overrides AZDO_PROJECT).
--azdo-pipeline-id ID Pipeline ID used for preview (overrides AZDO_PIPELINE_ID).
--azdo-pat TOKEN PAT or OAuth token (overrides AZDO_PAT / SYSTEM_ACCESSTOKEN).
--azdo-ref-name REF Ref name for template expansion (overrides AZDO_REFNAME).
--azdo-timeout-seconds SECONDS HTTP timeout override (overrides AZDO_TIMEOUT_SECONDS).
--lint / --no-lint, -l / --no-l Run yamllint (aliases: --lint, -l). All checks are opt-in; lint is disabled by default.
--schema / --no-schema, -s / --no-s Validate against Microsoft's published YAML schema (aliases: --schema, -s).
--preview / --no-preview, -p / --no-p
Call the Azure DevOps preview endpoint (aliases: --preview, -p).
--fail-fast / --no-fail-fast Stop immediately after the first file that fails validation.
--exclude PATTERN Glob pattern or relative path to skip during scanning. Repeat the option to exclude multiple files/directories.
--help Show this message and exit.
Output format
Every file gets one row with three columns (yamllint / schema / preview). A passing stage prints pass; the first error message is shown otherwise (plus a “(+N more)” suffix when applicable). Example:
┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ File ┃ yamllint ┃ schema ┃ preview ┃
┣━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━╋━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
┃ workflows/ci.yml ┃ pass ┃ pass ┃ pass ┃
┃ workflows/deploy.yml ┃ L3 C5: … ┃ pass ┃ path not found (+2 more) ┃
┗━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
Validated 2 file(s). Failures: 1.
Exit code is non-zero whenever any file fails or when the preview/schema endpoints error.
CI integration
Add a job that installs uv, exports AZDO_*, and runs the command. When running inside Azure Pipelines you can reuse $(System.AccessToken) and the current pipeline id:
- job: Validate
pool:
vmImage: ubuntu-latest
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '3.12'
- script: |
uv tool install azure-pipeline-validator
azure-pipeline-validator --lint --schema --preview workflows/
env:
AZDO_ORG: $(System.TeamFoundationCollectionUri)
AZDO_PROJECT: $(System.TeamProject)
AZDO_PIPELINE_ID: $(System.DefinitionId)
AZDO_PAT: $(System.AccessToken)
AZDO_REFNAME: $(Build.SourceBranch)
The preview call runs with yamlOverride, so no build is queued.
Development workflow
Local development (inside this repo):
cd /path/to/azure-pipeline-validator
uv run azure-pipeline-validator --help
# Format and lint
uv run ruff format
uv run ruff check
# Run the test suite
uv run python -m pytest
pyproject.toml configures Ruff (line length 100, py313) and pytest/coverage. The tests include CLI help verification plus mock preview responses that mirror the real API payload captured from Azure DevOps.
Publishing the package
The package is published to PyPI automatically via GitHub Actions when a new tag is pushed using Trusted Publishing (OIDC) - no API tokens needed!
First-time Setup (Required Before First Publish)
Important: Trusted Publishing cannot create new projects on PyPI. You must create the project manually first:
-
Create the project on PyPI:
- Go to https://pypi.org/manage/projects/
- Click "Add new project"
- Enter project name:
azure-pipeline-validator(must matchnameinpyproject.toml)- Click "Create"
-
Set up Trusted Publishing:
- Go to https://pypi.org/manage/account/publishing/
- Click "Add a new trusted publisher"
- Fill in:
- PyPI project name:
azure-pipeline-validator - Owner:
andrewmaspero(your GitHub username) - Repository name:
azure-pipeline-validator - Workflow filename:
pipeline.yml - Environment name:
pypi(optional but recommended)
- PyPI project name:
- Click "Add trusted publisher"
Publishing a New Version
- Update
versioninpyproject.toml. - Commit and push the changes.
- Create and push a tag:
git tag v0.x.y && git push --tags.
The CI pipeline will automatically:
- Run all tests
- Build the package
- Publish to PyPI using Trusted Publishing (OIDC)
Once published, consumers can install and use it via:
# Using uvx (no installation needed)
uvx azure-pipeline-validator --help
# Or install globally
uv tool install azure-pipeline-validator
azure-pipeline-validator --help
# Or with pip
pip install azure-pipeline-validator
azure-pipeline-validator --help
For manual publishing, use uv directly:
uv build
uv publish
For manual publishing, you'll need to set UV_PUBLISH_USERNAME / UV_PUBLISH_PASSWORD environment variables, or use a PyPI API token.
Troubleshooting
| Symptom | Fix |
|---|---|
Set AZDO_PAT ... before running validation. |
Export AZDO_PAT or SYSTEM_ACCESSTOKEN so the preview call can authenticate. |
| Preview API returns 401/403 | Confirm AZDO_PIPELINE_ID is correct and the PAT has Build Read & Execute permissions. |
| Templates reference other repos/branches | Set AZDO_REFNAME appropriately; cross-repo templates may require additional repository resources in the payload. |
| yamllint errors but schema/preview pass | Temporarily omit --lint if you need to focus on schema/preview issues, but try to fix lint problems quickly. |
Feel free to fork, contribute improvements, or publish your own build. This README should give you everything you need to adopt the validator in local workflows, UV-based tooling, and CI/CD.
License
azure-pipeline-validator is open source software released under the MIT License. Contributions are welcome—just open an issue or pull request so we can review changes together.
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 azure_pipeline_validator-0.2.1.tar.gz.
File metadata
- Download URL: azure_pipeline_validator-0.2.1.tar.gz
- Upload date:
- Size: 63.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
96a17c4e3535b1d4dee48a000e65f303cda3f1dbe3851b580db192e3c1e071d9
|
|
| MD5 |
ee6f6f90fdef1a64b90a66a406909a90
|
|
| BLAKE2b-256 |
69e6919f3c283ae824ade06bb3d3743d0dd695e3d0422c9e7313909c3bb79a13
|
File details
Details for the file azure_pipeline_validator-0.2.1-py3-none-any.whl.
File metadata
- Download URL: azure_pipeline_validator-0.2.1-py3-none-any.whl
- Upload date:
- Size: 27.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1c8c31a81767f30d6be27ac10be84ee21ff81610eb7023c269001e3613875b0c
|
|
| MD5 |
8090b3cb1bd3a29d3f61f99d2ffaca02
|
|
| BLAKE2b-256 |
fc05800c44f7e90537815343fffa6faecc6eac75345427bc1a8525c10fd804e3
|