refactor: codebase optimization - module decomposition, test dedup, t… #89
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ============================================================================= | |
| # CI/CD Pipeline | |
| # ============================================================================= | |
| # Constitution: Reliability & Quality | |
| # Runs on every push and PR: lint → type check → unit → integration → E2E → coverage | |
| # | |
| # Quality Gates: | |
| # - All tests must pass | |
| # - Coverage must not regress | |
| # - Type checking must pass | |
| # - Linting must pass | |
| name: CI | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| branches: [main, develop] | |
| env: | |
| PYTHON_VERSION: "3.11" | |
| UV_CACHE_DIR: /tmp/.uv-cache | |
| jobs: | |
| # =========================================================================== | |
| # Lint & Type Check (Fast Feedback) | |
| # =========================================================================== | |
| lint: | |
| name: Lint & Type Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "uv.lock" | |
| - name: Restore uv cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: /tmp/.uv-cache | |
| key: uv-${{ runner.os }}-${{ hashFiles('uv.lock') }} | |
| restore-keys: | | |
| uv-${{ runner.os }}- | |
| - name: Install dependencies | |
| run: uv sync --frozen --dev | |
| - name: Run ruff (lint) | |
| run: uv run ruff check src/ tests/ | |
| - name: Run ruff (format check) | |
| run: uv run ruff format --check src/ tests/ | |
| - name: Run mypy | |
| run: uv run mypy src/ | |
| - name: Minimize uv cache | |
| run: uv cache prune --ci | |
| # =========================================================================== | |
| # Unit Tests (Fast, Isolated) | |
| # =========================================================================== | |
| unit-tests: | |
| name: Unit Tests | |
| runs-on: ubuntu-latest | |
| needs: lint | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "uv.lock" | |
| - name: Install dependencies | |
| run: uv sync --frozen --dev | |
| - name: Run unit tests | |
| run: | | |
| uv run pytest tests/unit \ | |
| -v \ | |
| --tb=short \ | |
| -m "unit or not (integration or e2e)" \ | |
| --cov=src \ | |
| --cov-report=xml:coverage-unit.xml \ | |
| --cov-report=term-missing | |
| mv .coverage .coverage.unit | |
| - name: Upload coverage | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-unit | |
| include-hidden-files: true | |
| path: | | |
| coverage-unit.xml | |
| .coverage.unit | |
| # =========================================================================== | |
| # Integration Tests (Require Services) | |
| # =========================================================================== | |
| integration-tests: | |
| name: Integration Tests | |
| runs-on: ubuntu-latest | |
| needs: unit-tests | |
| services: | |
| postgres: | |
| image: postgres:16-alpine | |
| env: | |
| POSTGRES_USER: test | |
| POSTGRES_PASSWORD: test | |
| POSTGRES_DB: aether_test | |
| ports: | |
| - 5432:5432 | |
| options: >- | |
| --health-cmd pg_isready | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 5 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "uv.lock" | |
| - name: Install dependencies | |
| run: uv sync --frozen --dev | |
| - name: Run integration tests | |
| env: | |
| DATABASE_URL: postgresql+asyncpg://test:test@localhost:5432/aether_test | |
| OPENAI_API_KEY: test-key | |
| HA_URL: http://localhost:8123 | |
| HA_TOKEN: test-token | |
| run: | | |
| uv run pytest tests/integration \ | |
| -v \ | |
| --tb=short \ | |
| -m "integration" \ | |
| --cov=src \ | |
| --cov-report=xml:coverage-integration.xml \ | |
| --cov-fail-under=0 | |
| mv .coverage .coverage.integration | |
| - name: Upload coverage | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-integration | |
| include-hidden-files: true | |
| path: | | |
| coverage-integration.xml | |
| .coverage.integration | |
| # =========================================================================== | |
| # E2E Tests (Full System) | |
| # =========================================================================== | |
| e2e-tests: | |
| name: E2E Tests | |
| runs-on: ubuntu-latest | |
| needs: integration-tests | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "uv.lock" | |
| - name: Install dependencies | |
| run: uv sync --frozen --dev | |
| - name: Start test services | |
| run: | | |
| docker compose -f infrastructure/test/docker-compose.test.yaml up -d | |
| # Wait for services | |
| sleep 10 | |
| - name: Run E2E tests | |
| env: | |
| DATABASE_URL: postgresql+asyncpg://test:test@localhost:5433/aether_test | |
| OPENAI_API_KEY: test-key | |
| HA_URL: http://localhost:8124 | |
| HA_TOKEN: test-token | |
| MLFLOW_TRACKING_URI: http://localhost:5001 | |
| run: | | |
| uv run pytest tests/e2e \ | |
| -v \ | |
| --tb=short \ | |
| -m "e2e" \ | |
| --cov=src \ | |
| --cov-report=xml:coverage-e2e.xml \ | |
| --cov-fail-under=0 | |
| mv .coverage .coverage.e2e || true | |
| - name: Stop test services | |
| if: always() | |
| run: docker compose -f infrastructure/test/docker-compose.test.yaml down -v | |
| - name: Upload coverage | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-e2e | |
| include-hidden-files: true | |
| path: | | |
| coverage-e2e.xml | |
| .coverage.e2e | |
| # =========================================================================== | |
| # Coverage Report | |
| # =========================================================================== | |
| coverage: | |
| name: Coverage Report | |
| runs-on: ubuntu-latest | |
| needs: [unit-tests, integration-tests, e2e-tests] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Download coverage artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: coverage-* | |
| merge-multiple: true | |
| - name: Upload to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| files: coverage-unit.xml,coverage-integration.xml,coverage-e2e.xml | |
| fail_ci_if_error: false | |
| verbose: true | |
| - name: Check coverage threshold | |
| run: | | |
| # Combine binary .coverage files from each test step and enforce threshold | |
| pip install coverage | |
| coverage combine .coverage.unit .coverage.integration .coverage.e2e || coverage combine .coverage.unit .coverage.integration || coverage combine .coverage.unit | |
| coverage report --fail-under=80 | |
| # =========================================================================== | |
| # Security Scan | |
| # =========================================================================== | |
| security: | |
| name: Security Scan | |
| runs-on: ubuntu-latest | |
| needs: lint | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v4 | |
| with: | |
| enable-cache: true | |
| cache-dependency-glob: "uv.lock" | |
| - name: Install dependencies | |
| run: uv sync --frozen --dev | |
| - name: Run bandit security scan | |
| run: uv run bandit -r src/ -c pyproject.toml | |
| - name: Check for vulnerabilities in dependencies | |
| run: | | |
| pip install pip-audit | |
| pip-audit --requirement <(uv pip compile pyproject.toml) || true |