diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f53da61..3c9486e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,9 +11,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 + with: + lfs: true - name: Set up Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.11" @@ -46,7 +48,7 @@ jobs: - uses: actions/checkout@v7 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: "20" cache: "npm" diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 2efa1c9..71a7cef 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,15 +9,15 @@ "version": "0.1.0", "dependencies": { "@react-google-maps/api": "^2.20.8", - "framer-motion": "^12.35.0", + "framer-motion": "^12.42.0", "lucide-react": "^1.17.0", - "react": "^18.2.0", + "react": "^19.2.7", "react-dom": "^18.2.0", "react-router-dom": "^7.16.0", "recharts": "^3.7.0" }, "devDependencies": { - "@types/react": "^18.2.55", + "@types/react": "^19.2.17", "@types/react-dom": "^18.2.19", "@vitejs/plugin-react": "^4.2.1", "autoprefixer": "^10.4.17", @@ -1373,21 +1373,13 @@ "integrity": "sha512-X9QTSvGJ0nCfMzYOnaVs/k6/4L+7F5uCS+4iUmkLEls6J9S/Phv+m/i3mDeyc49ZBgwab3EFO1HEoBY7k98EGQ==", "license": "MIT" }, - "node_modules/@types/prop-types": { - "version": "15.7.15", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", - "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "devOptional": true, - "license": "MIT" - }, "node_modules/@types/react": { - "version": "18.3.27", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz", - "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==", + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", "devOptional": true, "license": "MIT", "dependencies": { - "@types/prop-types": "*", "csstype": "^3.2.2" } }, @@ -1996,13 +1988,13 @@ } }, "node_modules/framer-motion": { - "version": "12.35.0", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.35.0.tgz", - "integrity": "sha512-w8hghCMQ4oq10j6aZh3U2yeEQv5K69O/seDI/41PK4HtgkLrcBovUNc0ayBC3UyyU7V1mrY2yLzvYdWJX9pGZQ==", + "version": "12.42.0", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.42.0.tgz", + "integrity": "sha512-wp7EJnfWaaEScVygKv3e20udoRz+LbtxScsuTkakAxfXmt+ReC6WyPW2nINRAGvd+hG9odwcjBLyOTPjH5pBRA==", "license": "MIT", "dependencies": { - "motion-dom": "^12.35.0", - "motion-utils": "^12.29.2", + "motion-dom": "^12.42.0", + "motion-utils": "^12.39.0", "tslib": "^2.4.0" }, "peerDependencies": { @@ -2297,18 +2289,18 @@ } }, "node_modules/motion-dom": { - "version": "12.35.0", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.35.0.tgz", - "integrity": "sha512-FFMLEnIejK/zDABn+vqGVAUN4T0+3fw+cVAY8MMT65yR+j5uMuvWdd4npACWhh94OVWQs79CrBBuwOwGRZAQiA==", + "version": "12.42.0", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.42.0.tgz", + "integrity": "sha512-M63h4n8R+quJdNhBwuLlgxM+OLYa9+I/T2pzDRboB9fLXRdbou+Gw7Zury+SkpaCyACP1JHSjHgZ1EgTkBr30w==", "license": "MIT", "dependencies": { - "motion-utils": "^12.29.2" + "motion-utils": "^12.39.0" } }, "node_modules/motion-utils": { - "version": "12.29.2", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.29.2.tgz", - "integrity": "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==", + "version": "12.39.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.39.0.tgz", + "integrity": "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==", "license": "MIT" }, "node_modules/ms": { @@ -2618,13 +2610,10 @@ "license": "MIT" }, "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, "engines": { "node": ">=0.10.0" } diff --git a/frontend/package.json b/frontend/package.json index 12b4698..62ba083 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,15 +10,15 @@ }, "dependencies": { "@react-google-maps/api": "^2.20.8", - "framer-motion": "^12.35.0", + "framer-motion": "^12.42.0", "lucide-react": "^1.17.0", - "react": "^18.2.0", + "react": "^19.2.7", "react-dom": "^18.2.0", "react-router-dom": "^7.16.0", "recharts": "^3.7.0" }, "devDependencies": { - "@types/react": "^18.2.55", + "@types/react": "^19.2.17", "@types/react-dom": "^18.2.19", "@vitejs/plugin-react": "^4.2.1", "autoprefixer": "^10.4.17", diff --git a/requirements-install.txt b/requirements-install.txt index 452bf49..8aa46f8 100644 --- a/requirements-install.txt +++ b/requirements-install.txt @@ -13,7 +13,7 @@ pyproj>=3.4.0 # Computer Vision opencv-python>=4.5.0 pillow>=9.0.0 -albumentations>=1.3.0 +albumentations>=2.0.8 # Visualization matplotlib>=3.5.0 diff --git a/requirements.txt b/requirements.txt index c404605..eee76a8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,7 +15,7 @@ fiona>=1.9.0 # Computer Vision opencv-python>=4.5.0 pillow>=9.0.0 -albumentations>=1.3.0 +albumentations>=2.0.8 # Visualization matplotlib>=3.5.0 @@ -39,7 +39,7 @@ dask[complete]>=2023.1.0 fastapi>=0.95.0 uvicorn[standard]>=0.20.0 pydantic>=2.0.0 -email-validator>=2.0.0 +email-validator>=2.3.0 python-multipart>=0.0.20 # MLOps (optional) diff --git a/tests/test_api.py b/tests/test_api.py index 1593b40..997f51a 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -25,8 +25,15 @@ def test_predict_json_rejects_missing_auth(client: TestClient) -> None: assert "API key required" in response.json()["detail"] -def test_predict_json_accepts_dev_key(client: TestClient) -> None: - """POST /api/predict should accept the cv_dev development key.""" +def test_predict_json_accepts_dev_key( + client: TestClient, monkeypatch: pytest.MonkeyPatch +) -> None: + """POST /api/predict should accept the cv_dev development key. + + The dev bypass is gated behind CLIMATEVISION_ALLOW_DEV_KEY, so enable it + explicitly for this test (production leaves it unset/disabled). + """ + monkeypatch.setenv("CLIMATEVISION_ALLOW_DEV_KEY", "1") payload = { "bbox": [-60.0, -15.0, -45.0, -5.0], "start_date": "2023-01-01",