# 🩺 yaml-doctor

**YAML Linter & Security Scanner for DevOps Engineers**

Validate and lint Kubernetes manifests, Docker Compose files, GitHub Actions workflows, GitLab CI pipelines, and generic YAML with **60+ built-in rules** covering security, reliability, and best practices.

[![PyPI version](https://img.shields.io/pypi/v/yaml-doctor.svg)](https://pypi.org/project/yaml-doctor/)
[![Python](https://img.shields.io/pypi/pyversions/yaml-doctor.svg)](https://pypi.org/project/yaml-doctor/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Tests](https://img.shields.io/badge/tests-188%20passing-brightgreen.svg)]()

---

## ✨ Features

- 🔍 **60+ Lint Rules** — Security, reliability, and best practice checks
- 🎯 **Auto-Detection** — Automatically identifies Kubernetes, Docker Compose, GitHub Actions, GitLab CI, and Helm files
- 📊 **Grading System** — A+ to F grades with detailed scoring
- 🌐 **HTML Dashboard** — Beautiful dark-theme HTML reports with severity charts
- 📋 **JSON Export** — Machine-readable reports for CI/CD integration
- 🔧 **Fix Suggestions** — Actionable remediation for every finding
- 🎮 **Demo Mode** — Try it instantly with built-in sample files
- 🚀 **Zero Config** — Works out of the box, no configuration needed

## 📦 Installation

```bash
pip install yaml-doctor
```

## 🚀 Quick Start

```bash
# Lint a single file
yaml-doctor lint deployment.yaml

# Scan a directory recursively
yaml-doctor scan ./k8s/

# Run demo with sample files
yaml-doctor demo

# Show all 60 rules
yaml-doctor rules

# Get fix suggestions
yaml-doctor fix deployment.yaml

# Export HTML dashboard
yaml-doctor scan . --html report.html

# Export JSON report
yaml-doctor lint config.yaml -j report.json
```

## 🎯 Supported File Types

| Type | Detection | Rules |
|------|-----------|-------|
| **Kubernetes** | `apiVersion` + `kind` | 20 rules (K8S001-K8S020) |
| **Docker Compose** | `services` + `image/build` | 12 rules (DC001-DC012) |
| **GitHub Actions** | `.github/workflows/` + `on/jobs` | 10 rules (GHA001-GHA010) |
| **GitLab CI** | `.gitlab-ci.yml` + `stages/script` | 10 rules (GL001-GL010) |
| **Helm** | `Chart.yaml` / `values.yaml` | K8s rules applied |
| **Generic YAML** | Any `.yml`/`.yaml` file | 8 rules (YML001-YML008) |

## 🔒 Security Rules

### Kubernetes (20 rules)

| Rule | Severity | Description |
|------|----------|-------------|
| K8S001 | 🔴 CRITICAL | Container running as root |
| K8S004 | 🔴 CRITICAL | Privileged container |
| K8S002 | 🟠 HIGH | Missing resource limits |
| K8S003 | 🟠 HIGH | Missing resource requests |
| K8S005 | 🟠 HIGH | Using `:latest` image tag |
| K8S006 | 🟠 HIGH | Missing liveness probe |
| K8S011 | 🟠 HIGH | Host network enabled |
| K8S012 | 🟠 HIGH | Host PID enabled |
| K8S016 | 🟠 HIGH | Secrets in environment variables |
| K8S007 | 🟡 MEDIUM | Missing readiness probe |
| K8S008 | 🟡 MEDIUM | Read-only filesystem not set |
| K8S013 | 🟡 MEDIUM | Single replica deployment |
| K8S014 | 🟡 MEDIUM | Privilege escalation allowed |
| K8S017 | 🟡 MEDIUM | Missing update strategy |
| K8S018 | 🟡 MEDIUM | Capabilities not dropped |
| K8S020 | 🟡 MEDIUM | Missing restart policy |
| K8S009 | 🔵 LOW | Missing recommended labels |
| K8S015 | 🔵 LOW | Missing PodDisruptionBudget |
| K8S019 | 🔵 LOW | No anti-affinity rules |
| K8S010 | ⚪ INFO | Missing namespace |

### Docker Compose (12 rules)

| Rule | Severity | Description |
|------|----------|-------------|
| DC002 | 🔴 CRITICAL | Privileged container |
| DC001 | 🟠 HIGH | Using `:latest` tag |
| DC005 | 🟠 HIGH | Secrets in environment |
| DC009 | 🟠 HIGH | Host volume with write access |
| DC012 | 🟡 MEDIUM | Host network mode |
| DC003 | 🟡 MEDIUM | No restart policy |
| DC004 | 🟡 MEDIUM | No healthcheck defined |
| DC007 | 🟡 MEDIUM | Exposed to all interfaces |
| DC011 | 🟡 MEDIUM | No depends_on |
| DC006 | 🔵 LOW | No resource limits |
| DC010 | 🔵 LOW | No logging configuration |
| DC008 | ⚪ INFO | Deprecated version key |

### GitHub Actions (10 rules)

| Rule | Severity | Description |
|------|----------|-------------|
| GHA001 | 🔴 CRITICAL | Mutable action reference (using @main) |
| GHA002 | 🟠 HIGH | Persist credentials enabled |
| GHA003 | 🟠 HIGH | Secrets in run commands |
| GHA009 | 🟠 HIGH | Script injection risk |
| GHA004 | 🟡 MEDIUM | Overly broad permissions |
| GHA005 | 🟡 MEDIUM | No job timeout |
| GHA006 | 🟡 MEDIUM | pull_request_target trigger |
| GHA007 | 🔵 LOW | No concurrency control |
| GHA008 | 🔵 LOW | Unversioned runner image |
| GHA010 | ⚪ INFO | Missing workflow name |

### GitLab CI (10 rules)

| Rule | Severity | Description |
|------|----------|-------------|
| GL001 | 🟠 HIGH | Secrets in script blocks |
| GL007 | 🟠 HIGH | allow_failure on security jobs |
| GL002 | 🟡 MEDIUM | No retry configuration |
| GL004 | 🟡 MEDIUM | Using `:latest` image |
| GL005 | 🟡 MEDIUM | No timeout set |
| GL009 | 🟡 MEDIUM | No rules/conditions |
| GL003 | 🔵 LOW | No cache defined |
| GL008 | 🔵 LOW | No artifacts defined |
| GL010 | 🔵 LOW | Missing job description |
| GL006 | ⚪ INFO | No stages defined |

### Generic YAML (8 rules)

| Rule | Severity | Description |
|------|----------|-------------|
| YML005 | 🟠 HIGH | Hardcoded credentials |
| YML001 | 🟡 MEDIUM | Inconsistent indentation |
| YML006 | 🟡 MEDIUM | Duplicate keys |
| YML002 | 🔵 LOW | Trailing whitespace |
| YML003 | 🔵 LOW | Line too long (>200 chars) |
| YML007 | 🔵 LOW | Empty values |
| YML004 | ⚪ INFO | Missing document start marker |
| YML008 | ⚪ INFO | File too long (>1000 lines) |

## 📊 Grading System

| Grade | Score | Description |
|-------|-------|-------------|
| A+ | 95-100 | Excellent — production ready |
| A | 85-94 | Great — minor improvements possible |
| B | 75-84 | Good — some issues to address |
| C | 65-74 | Fair — significant improvements needed |
| D | 50-64 | Poor — many issues found |
| F | 0-49 | Failing — critical issues present |

**Score deductions per finding:**
- 🔴 Critical: -15 points
- 🟠 High: -8 points
- 🟡 Medium: -3 points
- 🔵 Low: -1 point
- ⚪ Info: 0 points

## 🖥️ CLI Commands

### `yaml-doctor lint <file>`

Lint a single YAML file with auto-detection.

```bash
yaml-doctor lint deployment.yaml
yaml-doctor lint docker-compose.yml --html report.html
yaml-doctor lint .github/workflows/ci.yml -j report.json
```

### `yaml-doctor scan <directory>`

Scan all YAML files in a directory.

```bash
yaml-doctor scan ./k8s/
yaml-doctor scan . --html dashboard.html
yaml-doctor scan ./configs --no-recursive
```

### `yaml-doctor demo`

Run a demo with built-in sample files.

```bash
yaml-doctor demo
yaml-doctor demo --type kubernetes
yaml-doctor demo --type compose
yaml-doctor demo --html demo-report.html
```

### `yaml-doctor rules`

Display all 60 available lint rules.

```bash
yaml-doctor rules
```

### `yaml-doctor fix <file>`

Show fix suggestions for all findings.

```bash
yaml-doctor fix deployment.yaml
```

## 🔌 CI/CD Integration

### GitHub Actions

```yaml
- name: YAML Lint
  run: |
    pip install yaml-doctor
    yaml-doctor scan . --html report.html -j report.json
    
- name: Upload Report
  uses: actions/upload-artifact@v4
  with:
    name: yaml-doctor-report
    path: report.html
```

### GitLab CI

```yaml
yaml-lint:
  stage: test
  script:
    - pip install yaml-doctor
    - yaml-doctor scan . --html report.html -j report.json
  artifacts:
    paths:
      - report.html
      - report.json
```

### Pre-commit Hook

```yaml
# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: yaml-doctor
        name: yaml-doctor
        entry: yaml-doctor lint
        language: python
        types: [yaml]
        additional_dependencies: [yaml-doctor]
```

## 📁 Project Structure

```
yaml-doctor/
├── yaml_doctor/
│   ├── __init__.py          # Package version
│   ├── __main__.py          # python -m support
│   ├── cli.py               # Click CLI commands
│   ├── scanner.py           # Core scanning engine
│   ├── models.py            # Data models & enums
│   ├── rules.py             # Rule registry (60 rules)
│   ├── utils.py             # Helper utilities
│   ├── demo.py              # Demo sample data
│   ├── analyzers/
│   │   ├── __init__.py      # File type detection
│   │   ├── kubernetes.py    # 20 K8s rules
│   │   ├── compose.py       # 12 Docker Compose rules
│   │   ├── github_actions.py # 10 GitHub Actions rules
│   │   ├── gitlab_ci.py     # 10 GitLab CI rules
│   │   └── yaml_lint.py     # 8 generic YAML rules
│   └── output/
│       ├── console.py       # Rich terminal output
│       └── html_report.py   # HTML dashboard reports
├── tests/                   # 188 tests
├── pyproject.toml
├── LICENSE
└── README.md
```

## 🧪 Development

```bash
git clone https://github.com/SanjaySundarMurthy/yaml-doctor.git
cd yaml-doctor
pip install -e ".[dev]"
pytest
ruff check .
```

## 📄 License

MIT License — see [LICENSE](LICENSE) for details.

## 👨‍💻 Author

**Sanjay S** — [GitHub](https://github.com/SanjaySundarMurthy) · [Email](mailto:sanjaysundarmurthy@gmail.com)
