| name: CI_CD | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: {} | |
| env: | |
| PYTHON_VERSION: "3.12" | |
| jobs: | |
| build_and_test: | |
| name: Build & Test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| lfs: true | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v8.1.0 | |
| with: | |
| version: "0.5.4" | |
| - name: Install dependencies | |
| run: uv sync --frozen | |
| - name: Lint (ruff) | |
| run: uv run ruff check api database feature_engineering tests | |
| - name: Ensure test table exists in Supabase | |
| if: env.TEST_DATABASE_URL != '' | |
| env: | |
| TEST_DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }} | |
| run: uv run python -m database.setup --create-test --database-url "$TEST_DATABASE_URL" | |
| - name: Run tests with coverage | |
| env: | |
| TEST_DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }} | |
| run: | | |
| uv run pytest \ | |
| --cov=api \ | |
| --cov-report=term-missing \ | |
| --cov-report=xml \ | |
| --cov-fail-under=80 | |
| - name: Truncate test table (cleanup) | |
| if: always() && env.TEST_DATABASE_URL != '' | |
| env: | |
| TEST_DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }} | |
| run: uv run python -m database.setup --truncate-test --database-url "$TEST_DATABASE_URL" | |
| - name: Upload coverage report | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: coverage-xml | |
| path: coverage.xml | |
| retention-days: 30 | |
| deploy: | |
| name: Deploy to Hugging Face Space | |
| needs: build_and_test | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| lfs: true | |
| - name: Push to Hugging Face Space | |
| env: | |
| HF_TOKEN: ${{ secrets.HF_TOKEN }} | |
| run: | | |
| pip install huggingface_hub | |
| python - <<'EOF' | |
| import os | |
| from huggingface_hub import HfApi | |
| api = HfApi(token=os.environ["HF_TOKEN"]) | |
| api.upload_folder( | |
| folder_path=".", | |
| repo_id="KLEB38/OC_P8", | |
| repo_type="space", | |
| ignore_patterns=[ | |
| ".git", ".github", ".venv", ".claude", | |
| "__pycache__", "*.pyc", | |
| "data/", "dashboard/", "database/.env", | |
| ], | |
| ) | |
| EOF | |