From 7d2a68acb6f9fc8b88687a001dbb6a0c9c7bbb3f Mon Sep 17 00:00:00 2001 From: hrnn Date: Thu, 13 Aug 2026 14:30:52 -0400 Subject: [PATCH 1/2] fix(tests): read integration test API key from LANDINGAI_API_KEY The e2e predict tests carried a hardcoded LandingLens API key. Read it from the LANDINGAI_API_KEY environment variable instead, populated in CI from the repository secret of the same name. Secrets are not exposed to workflow runs triggered by pull requests from forks, so the tests skip themselves when the key is absent rather than failing with a 401. --- .github/workflows/ci_cd.yml | 4 ++++ tests/integration/landingai/test_predict_e2e.py | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) 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 = [ { From 6b53cb60f25c0c254d704382534b402ef117d85a Mon Sep 17 00:00:00 2001 From: hrnn Date: Thu, 13 Aug 2026 14:43:27 -0400 Subject: [PATCH 2/2] fix(tests): isolate unit tests from LANDINGAI_API_KEY in the environment Exporting LANDINGAI_API_KEY for the whole pytest run leaks it into the unit tests that cover credential loading. Environment variables take precedence over .env files, so those tests read the real key instead of the one they set up, and the tests asserting that a missing or invalid key raises found a valid one instead. Clear the credential env vars before each unit test. Tests that need a credential still set it themselves. --- tests/unit/conftest.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/unit/conftest.py 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)