$npx -y skills add MLOps-Courses/mlops-coding-skills --skill mlops-validationGuide to implement rigorous validation layers including static analysis, automated testing, structured logging, and security scanning.
| 1 | # MLOps Validation |
| 2 | |
| 3 | ## Goal |
| 4 | |
| 5 | To ensure software quality, reliability, and security through automated validation layers. This skill enforces **Strict Typing** (`ty`), **Unified Linting** (`ruff`), **Comprehensive Testing** (`pytest`), and **Structured Logging** (`loguru`). |
| 6 | |
| 7 | ## Prerequisites |
| 8 | |
| 9 | - **Language**: Python |
| 10 | - **Manager**: `uv` |
| 11 | - **Context**: Ensuring code quality before merge/deploy. |
| 12 | |
| 13 | ## Instructions |
| 14 | |
| 15 | ### 1. Static Analysis (Typing & Linting) |
| 16 | |
| 17 | Catch errors before they run. |
| 18 | |
| 19 | 1. **Typing**: |
| 20 | - **Tool**: `ty` (Astral type checker; pre-1.0, pin a compatible range). The mandated checker — do not use `mypy`. |
| 21 | - **Rule**: No `Any` (unless absolutely necessary). Fully typed function signatures. |
| 22 | - **DataFrames**: Use `pandera` schemas to validate DataFrame structures/types. |
| 23 | - **Classes**: Use `pydantic` for data modeling and runtime validation. |
| 24 | 2. **Linting & Formatting**: |
| 25 | - **Tool**: `ruff` (replaces black, isort, pylint, flake8). |
| 26 | - **Rule**: Zero tolerance for linter errors. Use `noqa` sparingly and with justification. |
| 27 | - **Config**: Centralize in `pyproject.toml`. |
| 28 | |
| 29 | ### 2. Testing Strategy |
| 30 | |
| 31 | Verify behavior and prevent regressions. |
| 32 | |
| 33 | 1. **Tool**: `pytest`. |
| 34 | 2. **Structure**: Mirror `src/` in `tests/`. |
| 35 | |
| 36 | ```text |
| 37 | src/pkg/mod.py -> tests/test_mod.py |
| 38 | ``` |
| 39 | |
| 40 | 3. **Fixtures**: Use `tests/conftest.py` for shared setup (mock data, temp paths). |
| 41 | 4. **Coverage**: Aim for high coverage (>80%) on core business logic. Use `pytest-cov`. |
| 42 | 5. **Pattern**: Use **Given-When-Then** in comments. |
| 43 | |
| 44 | ```python |
| 45 | def test_pipeline_execution(input_data): |
| 46 | # Given: Valid input data |
| 47 | # When: The pipeline processes the data |
| 48 | # Then: The output content matches expectations |
| 49 | ``` |
| 50 | |
| 51 | ### 3. Structured Logging |
| 52 | |
| 53 | Enable observability and debugging. |
| 54 | |
| 55 | 1. **Tool**: `loguru` (replacing stdlib `logging`). |
| 56 | 2. **Format**: Use structured logging (JSON) in production for queryability. |
| 57 | 3. **Levels**: |
| 58 | - `DEBUG`: Low-level tracing (payloads, internal state). |
| 59 | - `INFO`: Key business events (Job started, Model saved). |
| 60 | - `ERROR`: Actionable failures (with stack traces). |
| 61 | 4. **Context**: Include context (Job ID, Model Version) in logs. |
| 62 | |
| 63 | ### 4. Security |
| 64 | |
| 65 | Protect the supply chain and runtime. |
| 66 | |
| 67 | 1. **Code Scanning**: Enable Ruff `S` (flake8-bandit) rules to detect unsafe patterns (e.g., `eval`, `yaml.load`) — this replaces standalone `bandit`. |
| 68 | 1. **Dependencies**: Run `pip-audit` (and/or `GitHub Dependabot`) to patch vulnerable packages. |
| 69 | 1. **Secret Scanning**: Run `gitleaks` to keep credentials out of the code and git history. |
| 70 | 1. **Secrets**: **NEVER** log secrets. Sanitize outputs. |
| 71 | |
| 72 | ## Self-Correction Checklist |
| 73 | |
| 74 | - [ ] **Type Safety**: Does `ty` pass without errors? |
| 75 | - [ ] **Lint Cleanliness**: Does `ruff check` pass? |
| 76 | - [ ] **Test Discovery**: Does `pytest` successfully find modules in `src/`? |
| 77 | - [ ] **Log Format**: Are production logs serializing to JSON? |
| 78 | - [ ] **Security**: Do Ruff `S` rules, `pip-audit`, and `gitleaks` pass? |