diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 0536c7e5..39f7a2c9 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -44,6 +44,10 @@ jobs: run: | poetry run mypy landingai - name: Test with pytest + env: + # Not available to pull requests from forks; the integration tests that + # need it skip themselves when it is empty. + LANDINGAI_API_KEY: ${{ secrets.LANDINGAI_API_KEY }} run: | poetry run pytest -v tests diff --git a/tests/integration/landingai/test_predict_e2e.py b/tests/integration/landingai/test_predict_e2e.py index 0b320a94..aedaacf9 100644 --- a/tests/integration/landingai/test_predict_e2e.py +++ b/tests/integration/landingai/test_predict_e2e.py @@ -1,4 +1,5 @@ import logging +import os from pathlib import Path import numpy as np @@ -9,7 +10,17 @@ from landingai.predict import OcrPredictor, Predictor from landingai.visualize import overlay_predictions -_API_KEY = "land_sk_aMemWbpd41yXnQ0tXvZMh59ISgRuKNRKjJEIUHnkiH32NBJAwf" +# These tests call live LandingLens endpoints, so they need a real API key. +# It is read from the LANDINGAI_API_KEY environment variable, which CI populates +# from the repository secret of the same name. Secrets are not exposed to +# workflow runs triggered by pull requests from forks, so skip instead of +# failing when the key is absent. +_API_KEY = os.environ.get("LANDINGAI_API_KEY", "") + +pytestmark = pytest.mark.skipif( + not _API_KEY, + reason="LANDINGAI_API_KEY is not set; skipping tests that call live endpoints.", +) _EXPECTED_VP_PREDS = [ { diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py new file mode 100644 index 00000000..fafda79b --- /dev/null +++ b/tests/unit/conftest.py @@ -0,0 +1,26 @@ +import pytest + +# Both cases are cleared because pydantic-settings matches env vars +# case-insensitively, and the tests below set the lowercase spelling. +_API_CREDENTIAL_ENV_VARS = ( + "LANDINGAI_API_KEY", + "landingai_api_key", + "LANDINGAI_API_SECRET", + "landingai_api_secret", +) + + +@pytest.fixture(autouse=True) +def unset_api_credential_env_vars(monkeypatch): + """Isolate unit tests from API credentials in the ambient environment. + + CI exports LANDINGAI_API_KEY so the integration tests can call live + endpoints. Environment variables take precedence over .env files, so + without this the credential-loading tests would read the real key instead + of the one they set up, and the tests asserting that an invalid or missing + key raises would silently find a valid one. + + Tests that need a credential set it themselves after this fixture runs. + """ + for var in _API_CREDENTIAL_ENV_VARS: + monkeypatch.delenv(var, raising=False)