Skip to content

๐Ÿงญ Tool Comparison โ€” CI/CD Recommendations

!!! abstract "Document Purpose" This document summarizes recommended tooling for FastAPI projects using UV, covering linting, formatting, type checking, testing, and security scanning. The goal is a pragmatic stack that works well locally (fast hooks) and in CI (strict checks).


โšก Quick Recommendations

!!! success "Recommended Stack at a Glance"

| Category | Tool | Why? |
|----------|------|------|
| ๐Ÿ” **Linting** | Ruff + isort | Blazing fast, comprehensive rules |
| ๐ŸŽจ **Formatting** | Black or Ruff Format | Consistent, opinionated styling |
| ๐Ÿ”Ž **Type Checking** | Mypy (CI) + Pyright (IDE) | Best of both worlds |
| ๐Ÿงช **Testing** | pytest + Hypothesis | Industry standard + property testing |
| ๐Ÿ” **Security** | Bandit + Semgrep + Safety + Trivy | Multi-layered protection |

๐Ÿ” Linters โ€” Speed, Rules & Ergonomics

Comparing tools for code quality and style enforcement.

Tool Category Pros Cons Score Status
Ruff Linter โšก Very fast (Rust-based)
๐Ÿ“ฆ Combines linting, fixing & formatting
โš™๏ธ Supports pyproject.toml
โš ๏ธ Fewer deep analysis rules than Pylint for legacy code 9/10 โœ… Recommended
Flake8 Linter ๐Ÿ”Œ Mature ecosystem with many plugins
๐Ÿ“š bugbear, docstrings, etc.
๐ŸŒ Slower on large codebases
๐Ÿ”Œ Relies heavily on plugins
7/10 โš ๏ธ Specific contexts
Pylint Linter ๐Ÿ”ฌ Deep static analysis
๐Ÿ“Š Code smells & complexity metrics
๐Ÿ—ฃ๏ธ Verbose and slow by default
โš™๏ธ Requires extensive tuning
7/10 โš ๏ธ Audits/legacy code
Pyflakes Linter โšก Fast execution
๐ŸŽฏ Detects undefined names/unused vars
โŒ No stylistic checks (PEP8) 6/10 โš ๏ธ Component use only
Semgrep SAST/Linter โšก Fast rule-based checks
๐Ÿ” Security policy enforcement
๐Ÿ”’ More SAST-oriented
โš ๏ธ May overlap with other tools
8/10 โœ… Security policies

๐Ÿ’ก Why Choose Ruff?

!!! tip "Ruff: The Pragmatic Default" Ruff's speed and wide coverage make it ideal for:

- โœ… Pre-commit hooks with instant feedback
- โœ… Large codebases requiring fast linting
- โœ… Teams wanting unified tooling

**Use Pylint only when you need deep, opinionated code audits.**

๐ŸŽจ Formatters โ€” Speed, Configurability & Adoption

Ensuring consistent code style across your project.

Tool Category Pros Cons Score Status
Black Formatter ๐ŸŽฏ Opinionated & stable
๐ŸŒ Widely adopted
๐Ÿ“‰ Small, consistent diffs
โš™๏ธ Limited customization 9/10 โœ… Recommended
Ruff Format Formatter โšก Very fast & lightweight
๐Ÿ”— Integrates with Ruff toolchain
๐Ÿšง Still evolving feature set 9/10 โœ… Great alternative
autopep8 Formatter ๐Ÿ“ PEP8-focused fixes
โš™๏ธ Configurable
๐Ÿคท Less opinionated
๐Ÿ“ˆ Larger diffs
6/10 โš ๏ธ Legacy use
YAPF Formatter โš™๏ธ Highly configurable ๐Ÿ“‰ Less adoption
โš ๏ธ Results vary across versions
6/10 โš ๏ธ Not recommended
isort Import Sorter ๐Ÿ† Industry standard
๐Ÿค Black-compatible
๐Ÿ“ฆ Imports only (not full formatter) 8/10 โœ… Use alongside

!!! success "Winning Formula" Black (or Ruff Format) + isort

- Black/Ruff Format provides stable, opinionated formatting
- isort manages import organization
- Ruff can consolidate both if you want a single fast binary

=== "Option A: Classic" yaml # .pre-commit-config.yaml - repo: https://github.com/psf/black hooks: - id: black - repo: https://github.com/pycqa/isort hooks: - id: isort

=== "Option B: Unified" yaml # .pre-commit-config.yaml - repo: https://github.com/astral-sh/ruff-pre-commit hooks: - id: ruff - id: ruff-format - repo: https://github.com/pycqa/isort hooks: - id: isort


๐Ÿ”Ž Type Checkers โ€” Precision, Speed & IDE Integration

Static type checking for Python codebases.

Tool Category Pros Cons Score Status
Mypy Static Type Checker ๐Ÿ“š Reference implementation
๐Ÿ”’ Strict checks available
๐Ÿ”Œ Plugin support (SQLModel, FastAPI)
๐ŸŒ Can be slower
๐Ÿ“– Configuration learning curve
9/10 โœ… CI-focused
Pyright Static Type Checker โšก Very fast
๐Ÿ’ป Excellent editor integration (Pylance)
๐ŸŽฏ Great developer experience
โš ๏ธ Less strict by default vs Mypy 8/10 โœ… IDE-focused
Pyre Static Type Checker โšก Fast & scalable
๐Ÿ”ฌ Advanced analysis (Pysa)
๐Ÿข Less common outside Meta
โš™๏ธ Heavier setup
7/10 โš ๏ธ Large codebases
Pytype Static Type Checker ๐Ÿ”„ Good inference for migrations ๐Ÿ“‰ Less mainstream adoption 7/10 โš ๏ธ Alternative
Typeguard Runtime Checker ๐Ÿงช Runtime validation in tests โš ๏ธ Runtime overhead
โŒ Not for production
7/10 โš ๏ธ Test-only

!!! tip "Best of Both Worlds" Mypy in CI (strict mode) + Pyright for IDE (developer feedback)

This combination provides:

- โœ… Strict enforcement in CI pipeline
- โœ… Fast, real-time feedback during development
- โœ… Best tooling integration for both contexts

Configuration Example:

# pyproject.toml
[tool.mypy]
python_version = "3.11"
strict = true
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true

[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_defs = false

๐Ÿงช Testing Frameworks โ€” Ease of Use, Plugins & Assertions

Building robust test suites for your application.

Tool Category Pros Cons Score Status
pytest Framework โœจ Simple syntax with assert introspection
๐Ÿ”Œ Modular fixtures
๐ŸŽฏ Vast plugin ecosystem
๐Ÿ“Š Parametrized tests
๐Ÿ“š Learning curve for advanced fixtures 10/10 โœ… Recommended
unittest Framework (stdlib) ๐Ÿ“ฆ Built into Python
๐Ÿ”’ Stable & mature
๐Ÿค unittest.mock integration
๐Ÿ“ Verbose syntax (assertEqual, etc.)
๐Ÿ˜• Less ergonomic
7/10 โš ๏ธ Compatibility use
nose2 Framework ๐Ÿ”Œ Easy plugins
๐Ÿ” Test discovery
๐Ÿ“‰ Less active development
๐Ÿ‘ฅ Smaller community
6/10 โš ๏ธ Not recommended
Hypothesis Property Testing ๐ŸŽฒ Generates random/priority tests
๐Ÿ” Finds edge cases
๐Ÿงฎ Great for algorithms
๐Ÿค” Different testing approach
๐Ÿ“š Requires different test design
9/10 โœ… Complementary
Robot Framework Acceptance/RPA ๐Ÿค– Robot syntax
๐ŸŒ Multi-language support
๐ŸŽฏ High-level tests & RPA
โš ๏ธ Overkill for simple API projects
๐ŸŽฏ Acceptance test focus
6/10 โš ๏ธ Specific use case

!!! success "Winning Combination" pytest as the foundation + Hypothesis for property testing

**Why pytest?**

- โœ… Industry standard with massive adoption
- โœ… Rich plugin ecosystem (coverage, markers, fixtures)
- โœ… Excellent ergonomics and readability

**When to add Hypothesis?**

- โœ… Parsers and data transformation logic
- โœ… Algorithm implementations
- โœ… Complex business rules
- โœ… Edge case discovery

Example Usage:

=== "pytest Basic" python # test_api.py def test_user_creation(client): response = client.post("/users", json={"name": "Alice"}) assert response.status_code == 201 assert response.json()["name"] == "Alice"

=== "pytest + Fixtures" ```python # conftest.py @pytest.fixture def client(): return TestClient(app)

# test_api.py
def test_user_creation(client):
    response = client.post("/users", json={"name": "Alice"})
    assert response.status_code == 201
```

=== "pytest + Hypothesis" ```python from hypothesis import given from hypothesis import strategies as st

@given(st.text(min_size=1, max_size=100))
def test_username_validation(username):
    result = validate_username(username)
    assert isinstance(result, bool)
```

๐Ÿ” Security Scanners โ€” Vulnerability Detection & False Positives

Multi-layered security scanning for applications and dependencies.

Tool Category Pros Cons Score Status
Bandit Static Code Security ๐Ÿ” AST analysis
โš ๏ธ Detects vulnerable patterns
๐Ÿ Python-specific (shell injection, unsafe eval)
โš ๏ธ False positives possible
โš™๏ธ Rule tuning required
8/10 โœ… Recommended
Safety SCA (Dependencies) ๐Ÿ” Known vulnerability detection
๐Ÿ“Š Vulnerability database
โœจ Simple to use
๐Ÿ’ฐ Advanced features paid (PyUp)
๐Ÿ“ฆ Limited to dependencies
8/10 โœ… Recommended
Trivy Container/Image ๐Ÿณ Scans images & OS packages
โšก Fast & comprehensive
๐Ÿ†“ Open source (Aqua)
๐Ÿ—๏ธ Requires built image artifact 9/10 โœ… Recommended
Semgrep SAST (Policy) ๐ŸŽฏ Flexible rule engine
๐Ÿ“ Code-like rules
๐Ÿ”„ Reusable patterns
๐Ÿ“‰ Low false positives
๐Ÿ’ฐ Advanced features paid (Pro)
โš™๏ธ Requires tuning
8/10 โœ… Recommended
Snyk SCA + Platform ๐Ÿ“Š SCA, SAST, container, IaC
๐Ÿ”ง Remediation guidance
๐Ÿ”— GitHub/GitLab integration
๐Ÿ“ˆ UI reporting
๐Ÿ’ฐ Paid (free tier limited)
๐Ÿ’ผ Enterprise features costly
9/10 โœ… Enterprise/org

๐Ÿ›ก๏ธ Defense in Depth Strategy

!!! warning "Security Requires Multiple Layers" No single tool catches everything. Build a comprehensive security strategy:

=== "Code Analysis" Static Application Security Testing (SAST)

- โœ… **Bandit** - Python-specific security issues
- โœ… **Semgrep** - Custom security policies

```yaml
# .github/workflows/security.yml
- name: Run Bandit
  run: bandit -r src/ -f json -o bandit-report.json

- name: Run Semgrep
  run: semgrep --config auto src/
```

=== "Dependency Analysis" Software Composition Analysis (SCA)

- โœ… **Safety** - Quick checks (open source)
- โœ… **Snyk** - Enterprise reporting & remediation

```yaml
- name: Check dependencies
  run: safety check --json

- name: Snyk test
  run: snyk test --severity-threshold=high
```

=== "Container Security" Image & Runtime Scanning

- โœ… **Trivy** - Container image vulnerabilities

```yaml
- name: Build image
  run: docker build -t myapp:latest .

- name: Scan with Trivy
  run: trivy image myapp:latest
```

!!! success "Comprehensive Coverage" Bandit + Semgrep (SAST) + Safety/Snyk (SCA) + Trivy (Containers)

This combination covers:

- ๐Ÿ” Static code vulnerabilities
- ๐Ÿ“ฆ Dependency vulnerabilities
- ๐Ÿณ Container security
- ๐Ÿ” Security policy enforcement

โœ… Pragmatic Stack Recommendation

๐Ÿ  Local Development & Pre-commit

!!! tip "Fast Feedback Loop" Keep local hooks lightweight for developer productivity:

# .pre-commit-config.yaml
repos:
  # Formatting & Linting
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.1.0
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format

  # Import sorting
  - repo: https://github.com/pycqa/isort
    rev: 5.12.0
    hooks:
      - id: isort
        args: [--atomic]

  # Type checking (optional - can be slow)
  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.7.0
    hooks:
      - id: mypy
        args: [--ignore-missing-imports]

  # Quick security checks
  - repo: https://github.com/PyCQA/bandit
    rev: 1.7.5
    hooks:
      - id: bandit
        args: [-c, pyproject.toml]

Local Tools:

  • โšก Ruff (lint + format)
  • ๐Ÿ“ฆ isort (imports)
  • ๐Ÿ”Ž Mypy/Pyright (type checking)
  • ๐Ÿงช pytest + Hypothesis (testing)
  • ๐Ÿ” Bandit + Semgrep (quick security)
  • ๐Ÿ“Š Safety (dependency scan)

โ˜๏ธ CI Pipeline Jobs

!!! info "Comprehensive CI Checks" Run parallel jobs for speed:

# .github/workflows/ci.yml
name: CI Pipeline

on: [push, pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v6
      - run: uv sync
      - run: uv run ruff check .
      - run: uv run ruff format --check .
      - run: uv run isort --check-only .

  type-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v6
      - run: uv sync
      - run: uv run mypy src/

  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v6
      - run: uv sync
      - run: uv run pytest --cov --cov-report=xml
      - uses: codecov/codecov-action@v3

  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v6
      - run: uv sync
      - run: uv run bandit -r src/
      - run: uv run semgrep --config auto src/
      - run: uv run safety check

  security-image:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build image
        run: docker build -t app:${{ github.sha }} .
      - name: Scan with Trivy
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: app:${{ github.sha }}
          format: sarif
          output: trivy-results.sarif

CI Jobs:

  1. ๐Ÿ” Lint - Ruff check + format check + isort check
  2. ๐Ÿ”Ž Type Check - Mypy (strict mode) or Pyright
  3. ๐Ÿงช Tests - pytest with coverage
  4. ๐Ÿ” Security - Bandit + Semgrep + Safety
  5. ๐Ÿณ Image Security - Trivy scan on Docker images

๐Ÿš€ CD/Release Pipeline

!!! success "Production-Ready Releases" Additional checks before deployment:

# .github/workflows/release.yml
name: Release

on:
  push:
    tags:
      - 'v*'

jobs:
  security-final:
    runs-on: ubuntu-latest
    steps:
      - name: Final Snyk scan
        run: snyk test --severity-threshold=critical

      - name: Final Trivy scan
        run: trivy image app:${{ github.ref_name }}

  publish:
    needs: security-final
    runs-on: ubuntu-latest
    steps:
      - run: uv build
      - run: uv publish

๐Ÿ’ก Detailed Recommendations & Adoption Tips

๐Ÿš€ Start Small & Iterate

!!! tip "Progressive Adoption Strategy"

**Phase 1: Foundation (Week 1)**

1. โœ… Set up Ruff + Black + isort in pre-commit โ†’ fast corrections
2. โœ… Add basic pytest tests
3. โœ… Configure pyproject.toml

**Phase 2: Quality Gates (Week 2-3)**

1. โœ… Add Mypy to CI with `--ignore-missing-imports`
2. โœ… Gradually increase strictness
3. โœ… Add coverage requirements

**Phase 3: Security (Week 3-4)**

1. โœ… Integrate Bandit + Safety
2. โœ… Add Semgrep rules
3. โœ… Set up Trivy for containers

๐Ÿ”ง Tool Complementarity

!!! success "Use Multiple Tools in Harmony" Each tool catches different issue classes:

- ๐Ÿ” **Ruff** - Quick fixes & common issues
- ๐Ÿ”Ž **Mypy** - Type safety & contracts
- ๐Ÿ” **Semgrep** - Security policies & patterns
- ๐Ÿ“ฆ **Safety** - Dependency vulnerabilities
- ๐Ÿณ **Trivy** - Container security

**Don't replace, complement!**

โšก CI Performance Optimization

!!! tip "Speed Up Your Pipeline"

**Caching Strategy:**

```yaml
- uses: astral-sh/setup-uv@v6
  with:
    enable-cache: true

- uses: actions/cache@v4
  with:
    path: |
      ~/.cache/pip
      ~/.cache/pre-commit
    key: ${{ runner.os }}-cache-${{ hashFiles('**/uv.lock') }}
```

**Parallelization:**

- โœ… Run lint, type-check, test, and security jobs in parallel
- โœ… Use matrix strategies for multi-version testing
- โœ… Cache UV dependencies and pre-commit environments

๐Ÿ” Security & False Positives

!!! warning "Managing Security Tool Noise"

**Configuration Best Practices:**

```toml
# pyproject.toml
[tool.bandit]
exclude_dirs = ["tests", "migrations"]
skips = ["B101"]  # Skip assert warnings in tests

[tool.semgrep]
paths.exclude = [
    "tests/",
    "*/migrations/",
]
```

**Progressive Refinement:**

1. โœ… Start with default rules
2. โœ… Create baseline of existing issues
3. โœ… Add suppressions for false positives
4. โœ… Document why suppressions exist
5. โœ… Use Snyk/Safety Pro for prioritized remediation

๐Ÿ‘จโ€๐Ÿ’ป Developer Workflow Optimization

!!! tip "Balance Speed and Quality"

**Local (Fast):**

- โšก Ruff `--fix` (instant)
- โšก isort `--atomic` (fast)
- โšก Quick formatting checks

**CI (Comprehensive):**

- ๐Ÿ” Full Bandit scan
- ๐Ÿณ Trivy image scan
- ๐Ÿ”Ž Mypy strict mode
- ๐Ÿ“Š Full test suite with coverage

๐Ÿ”— Official Resources & Documentation

๐Ÿ” Linting & Formatting

๐Ÿ”Ž Type Checking

๐Ÿงช Testing

๐Ÿ” Security


๐Ÿ“ Conclusion

!!! success "Modern CI/CD Pipeline for FastAPI + UV"

**Recommended Stack:**

=== "Code Quality"
    - ๐Ÿ” **Ruff** (lint + format) or **Black**
    - ๐Ÿ“ฆ **isort** (import sorting)
    - ๐Ÿ”Ž **Mypy** (CI) + **Pyright** (IDE)

=== "Testing"
    - ๐Ÿงช **pytest** (foundation)
    - ๐ŸŽฒ **Hypothesis** (property testing)
    - ๐Ÿ“Š Coverage reporting

=== "Security"
    - ๐Ÿ” **Bandit + Semgrep** (SAST)
    - ๐Ÿ“ฆ **Safety/Snyk** (SCA)
    - ๐Ÿณ **Trivy** (containers)

This combination provides:

โœ… **Fast local development** with instant feedback
โœ… **Comprehensive CI checks** catching issues early
โœ… **Multi-layered security** protecting production
โœ… **Developer-friendly** workflow with minimal friction

Ready to implement? Start with Phase 1 and iterate! ๐Ÿš€