deena-lad/climate-risk-quant
0
1# .github/workflows/ci.yml2# ─────────────────────────────────────────────────────────────────────────────3# Runs on every push and pull request to main.4# Jobs:5# lint — ruff + mypy static analysis6# test — pytest with coverage (synthetic data only, no network)7# docker — builds the Docker image to catch dependency/layer errors early8# (does NOT push; push is triggered by HuggingFace Spaces sync)9 10name: CI11 12on:13 push:14 branches: [main, develop]15 pull_request:16 branches: [main]17 18env:19 PYTHON_VERSION: "3.11"20 21jobs:22 # ── Lint ────────────────────────────────────────────────────────────────────23 lint:24 name: Lint & type-check25 runs-on: ubuntu-latest26 steps:27 - uses: actions/checkout@v428 29 - name: Set up Python30 uses: actions/setup-python@v531 with:32 python-version: ${{ env.PYTHON_VERSION }}33 cache: pip34 35 - name: Install lint deps36 run: pip install ruff mypy pydantic pydantic-settings37 38 - name: ruff check39 run: ruff check src/ app/ tests/40 continue-on-error: true41 42 - name: ruff format check43 run: ruff format --check src/ app/ tests/44 continue-on-error: true45 46 - name: mypy47 run: mypy src/ --ignore-missing-imports48 continue-on-error: true # mypy errors are warnings until stubs are complete49 50 # ── Test ────────────────────────────────────────────────────────────────────51 test:52 name: Unit tests53 runs-on: ubuntu-latest54 needs: lint55 56 steps:57 - uses: actions/checkout@v458 59 - name: Set up Python60 uses: actions/setup-python@v561 with:62 python-version: ${{ env.PYTHON_VERSION }}63 cache: pip64 65 - name: Install system geo deps66 run: |67 sudo apt-get update -qq68 sudo apt-get install -y --no-install-recommends \69 libgdal-dev libgeos-dev libproj-dev libspatialindex-dev libeccodes-dev70 71 - name: Install Python deps72 run: |73 pip install --upgrade pip74 pip install -r requirements.txt75 pip install -e .76 77 - name: Create .env for tests78 run: |79 cat > .env << 'EOF'80 CDS_API_KEY=00000:dummy-key-for-ci81 ERA5_YEAR_START=199082 ERA5_YEAR_END=202383 RISK_HAIRCUT_ALPHA=0.3084 WEIGHT_FLOOD=0.4085 WEIGHT_HEAT=0.3586 WEIGHT_CYCLONE=0.2587 LOG_LEVEL=WARNING88 EOF89 90 - name: Run tests with coverage91 run: |92 pytest tests/ \93 --cov=src \94 --cov-report=term-missing \95 --cov-report=xml \96 --cov-fail-under=65 \97 -v \98 --tb=short99 100 - name: Upload coverage report101 uses: codecov/codecov-action@v4102 if: always()103 with:104 file: coverage.xml105 fail_ci_if_error: false106 107 # ── Docker build check ───────────────────────────────────────────────────────108 docker:109 name: Docker build110 runs-on: ubuntu-latest111 needs: test112 # Only run on pushes to main (not PRs) to save minutes113 if: github.event_name == 'push' && github.ref == 'refs/heads/main'114 115 steps:116 - uses: actions/checkout@v4117 118 - name: Set up Docker Buildx119 uses: docker/setup-buildx-action@v3120 121 - name: Build Docker image (no push)122 uses: docker/build-push-action@v5123 with:124 context: .125 push: false126 tags: climate-risk-quant:ci127 cache-from: type=gha128 cache-to: type=gha,mode=max129 build-args: |130 BUILDKIT_INLINE_CACHE=1131 