YAML Linter: Fast Config Validation Without External Dependencies
Validating YAML configuration files is a common task in CI/CD pipelines—checking for required fields, empty values, or structure issues. The YAML Linter is a lightweight Python tool that performs basic validation without installing PyYAML or other external dependencies. It uses simple regex patterns to detect missing fields, undefined values, and consistency issues across your configuration files.
What Does It Do?
The YAML Linter checks for:
- Missing required fields — Variables that should exist based on a requirements list
- Empty/undefined values — Keys referenced but with no value assigned
- Numeric key conflicts — Numbered keys vs non-numeric key types
- Pattern validation — Basic consistency checks across nested structures
Unlike full YAML parsers, it uses simple pattern matching for speed—ideal when you want lightweight validation without package overhead.
Why Use This Tool?
Common config mistakes break deployments:
# Common issues that cause deployment failures
export API_URL="http://${API_HOST}:${API_PORT}" # Missing vars fail
# production.yml has required fields missing
# DATABASE_URL='' empty value ignored in some contexts
Env Checker catches these before they hit production—without installing PyYAML.
Installation
Add to your PATH with zero dependencies:
cp ~/env-checker/yaml-lint.py /usr/local/bin/
yaml-lint.sh config.yml # Basic validation
yaml-lint.sh < config.txt # Pipeline-ready, use for scripts
Or via pip if you prefer packages:
git clone https://github.com/Poolion/env-checker.git
cd env-checker
pip install . # Optional wrapper for package distribution
python yaml-lint.sh myconfig.yml
No pip install pyyaml needed—uses only the Python standard library.
Usage Examples
Basic Validation
Run a quick check on your configs:
$ python yaml-lint.sh app/configs/production.yml
* YAML Linter Report
Source: production.yml
Fields found: 14
* No issues detected.
Enforce Required Fields
Specify which fields must exist in every config file:
python yaml-lint.sh configs/*.yml --required-fields name,url,sslCertFile
# or with shorter flag:
yaml-lint.sh myapp.json -r "name,url,version"
Output when missing:
$ python3 env-checker/yaml-lint.py app/configs/production.yml -r "apiVersion,namespace,replicas,version"
* YAML Linter Report
Source: production.yml
Fields found: 12
* Missing required fields:
Missing required field: VERSION (referenced but never defined)
Show Empty Values
Find keys that exist with empty or undefined values:
$ python3 env-checker/yaml-lint.sh config.yml --show-empty
* Issues found: 2
• KeyError at line 5: DATABASE_URL
Empty value found: API_KEY (empty on line 10)
# Empty key found at line 8: LOGGING_LEVEL
The --show-empty flag helps catch configs where variables are referenced but never populated.
Command Line Interface
Basic syntax:
python yaml-lint.py <content> [OPTIONS]
Options:
--required-fields LIST, -r LIST Comma-separated list of required fields (e.g., "name,url,version")
--show-empty Also report empty/undefined values (default: off)
--help Show this help message
Examples:
python yaml-lint.sh config.yml # Basic validation with zero deps
python env-checker/yaml-lint.sh -r "apiVersion" config.yml
yaml-lint.sh myapp.json # Run from PATH
Help menu:
python3 env-checker/yaml-lint.py --help
# Usage: python yaml-lint.py [OPTIONS] [file]
# Options:
# -h, --help Show help message and exit
# --required-fields LIST, -r LIST
Comma-separated list of required fields (e.g. "name,url,loggingLevel")
Configuration File Example
Here is a typical app config with validation checks:
# production.yml
apiVersion: v2
name: MyApp
version: 1.0.0 # Required by pipeline script
sslCertFile: /etc/ssl/certs/myapp.crt
DATABASE_URL='${DATABASE}' # Must be populated or check fails
API_HOST=${API_HOST} # External service reference
logging: # Nested structure (checked for empty values)
level: DEBUG
format: "%(asctime)s - %(message)s"
Run validation against your config file:
$ python3 env-checker/yaml-lint.sh production.yml --required-fields "apiVersion,version,namesp ace"
* YAML Linter Report
Source: production.yml
Fields found: 7
* No issues detected.
With a missing field:
python yaml-lint.py configs/*.yml -r "apiVersion,namespace"
# Missing required field: NAMESPACE (in nested structure?)
# Check line where it should be defined in production/config.yml
Output Differences
| Scenario | Simple validation output | Advanced PyYAML validation output |
|---|---|---|
| Missing required fields | Lists each missing field with source reference | Fails immediately if critical field absent |
| Empty values | Shows which keys are empty without parsing anchors | Validates entire YAML structure including complex nested patterns |
| Comments in file | Preserves and shows for documentation | Often stripped during validation processing |
| Nested configs | Basic key-level checks per level | Full graph traversal of nested structures |
For CI/CD validation tasks, the simple approach is sufficient—no overhead from full parsing. Add PyYAML only if you need deep analysis like anchor validation or complex schema enforcement.
Integration Examples
GitHub Actions Pipeline Step
Validate configs before building Docker images:
name: Validate Environment Variables
- uses: actions/setup-node@v3
- run: pip install pyyaml # Optional deep validation (not required for basic)
- name: Validate YAML configs
run: |
for config in app/configs/*.json; do \
python yaml-lint.sh "$config" -r "apiVersion,namespace" || exit 1; \
done
name: Build Docker image
uses: docker/build-push-action@v3
Dockerfile Check Step
Ensure configs are valid before container build:
COPY app/configs/*.yml /app/
# Validate YAML before finalization
RUN python yaml-lint.sh /app/production.yml -r "apiVersion,name" || echo "* YAML linting failed—fix missing fields and rebuild" && make build-docker-image
Or with shellcheck for comprehensive validation:
name: Shell linting
uses: docker/build-push-action@v3
shellcheck myscript.sh # Validate syntax
python yaml-lint.sh configs/*.yml || exit 1
CMD bash /app/script.sh
Makefile Linting Target
Include config validation in your project's CI workflow:
.PHONY: validate-config
validate-config:
@echo "Validating all YAML configs..."
for config in app/configs/*.yml; do \
python yaml-lint.sh $$config -r name,url || exit 1; \
done
build: validate-config
make build-docker-production
Run validation as part of your pre-commit hook:
#!/bin/bash
# .pre-commit-config.yaml or manual check script
validate_all_configs() {
for f in config/*.yml configs/*.json; do \
if [[ -f $f ]]; then \
python yaml-lint.sh "$f" --required-fields apiVersion || exit 1; \
fi
done
return $?
}
validate_all_configs || (echo "* Config validation failed"; exit 1)
pre-commit: validate-all-configs
This runs before each commit—ensuring configs meet requirements.
How to Extend the Tool
The code is intentionally minimal and modifiable for custom rules!
Example: Add logging level hints with a simple check:
#!/bin/bash
# .pre-commit-hooks/log-level-check.sh
find_config_files() {
find . -name "*.yml" -o -name "config.json" 2>/dev/null | grep -v node_modules
}
check_log_level() {
level_value = $(grep -i log-level "$@" || true)
if echo "$level_value" | grep -qiE '^[Dd][Ii][Ee]B[bB]|W[Ww][Aa][Rr|i*Ng|C[Cc]*[Rr]*|[Nn]*[Oo]*$'; then
return 0; fi
echo "* Invalid log level: $level_value — use DEBUG|INFO|WARNING|ERROR|CRITICAL"
return 1
}
for config in $(find_config_files); do
check_log_level "$config" || exit 1; done
This adds custom rule enforcement to your CI/CD without external packages.
Custom validators for specific fields:
# Check numeric keys are consistently used
def find_mixed_numeric_keys(content):
"""Track numeric key usage consistency."""
import re
number_patterns = [
r'^\d+\s*:', # "1:" or "01:" style keys
r'^[0-9]+\w*\s*:.*$',
]
issues = []
for line in content.splitlines():
if ':' in line:
num_match = re.search(r'^(?:\"?\d+)??\.\.\.[a-z]*$|^'\s*[0-9][a-zA-Z]+\.?$', line, re.IGNORECASE)
if num_match and not any(p for p in number_patterns):
issues.append({line: content.splitlines()[num_match.start()].strip()})
if issues:
print(f'* Mismatch detected at line {issues[0]}')
return True
return False
Add this to your validation workflow if needed—no external dependencies required.
Limitations to Know
The YAML Linter prioritizes speed and zero-dependency design over full parsing:
- Basic key matching — Handles standard key-value patterns but doesn't validate anchors, aliases, or complex nested structures
- Simple type checks — Reports on numeric vs text key conflicts only—doesn't perform type inference like PyYAML does
- Regex-based parsing — Uses pattern matching rather than full YAML grammar for efficiency
For most CI/CD validation tasks—this approach is sufficient. Install PyYAML if you need:
- Anchors/alias validation ($$ref)
# Full syntax verification including complex nested structures
pip install pyyaml
python3 env-checker/yaml-lint.py --strict config.yml # Advanced mode with full parsing
But for quick checks in pipelines, docs validation, or template checks—Env Checker is fast and minimal.
When To Use This Tool vs PyYAML
| Use Case | Env Checker Appropriate | Full PyYAML Required? |
|---|---|---|
| Quick CI validation | ✅ Yes — fast boolean result | ❌ No overhead needed |
| Documentation examples | ✅ Yes — ensure example configs don't break | ❌ Optional complexity |
| Template generation | ✅ Yes — validate generated files meet schema | ❌ Overkill unless deep parsing needed |
| Production deployment check | ✅ Yes — minimal deps | ❌ PyYAML adds unnecessary overhead |
Env Checker is your lightweight validation companion. Use PyYAML for deep analysis when needed—but most tasks don't require the full parser.
Comparison: Tools Overview
| Tool | Dependency | Validation Depth | CI/CD Speed | Best For |
|---|---|---|---|---|
| Env Checker | None (stdlib) | Basic field checks | Instant | Pipelines, docs, templates |
| PyYAML | pip install pyyaml |
Full syntax + anchors | 200–400ms per file | Deep schema enforcement |
| Shellcheck | External (apt/yum/npm etc.) | Script-specific | Varies | Shell script validation |
Env Checker fills the gap when you want fast, dependency-free boolean validation without waiting for package downloads. For CI/CD pipelines—every 100ms matters, so minimal tools make faster builds.
Conclusion
The YAML Linter is a lightweight Python utility for basic config validation without external dependencies. It detects missing required fields and empty values using simple pattern matching—ideal for CI/CD workflows that need fast boolean checks before build steps. Add it to your toolkit when you want rapid validation without PyYAML overhead, documentation maintainers who need example configs validated, or projects that prioritize minimal dependencies over deep parsing capabilities.
For most configuration files—Env Checker's basic field matching catches issues quickly without the complexity of installing packages or waiting for parsers. Install PyYAML only if you need full YAML schema enforcement or complex nesting validation beyond what this lightweight tool provides.
Project: https://github.com/Poolion/yaml-lint
If you find this useful, you can support development: https://www.buymeacoffee.com/poolion
Top comments (0)