From 6920e9cdd6ec26b286282807e3b24674f856767c Mon Sep 17 00:00:00 2001 From: Martin Schuerrer Date: Thu, 19 Jun 2025 19:48:18 +0200 Subject: [PATCH 1/5] Add integration tests to CI workflow for pull requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Separate unit tests from integration tests in CI - Add new integration-test job that runs only on PRs - Use Python 3.12 specifically for integration tests - Decrypt NUTRIENT_DWS_API_KEY secret and create integration_config.py - Run integration tests against live Nutrient DWS API 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .github/workflows/ci.yml | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c932e57..0566c39 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,8 +43,8 @@ jobs: - name: Run type checking with mypy run: python -m mypy --python-version=${{ matrix.python-version }} src tests - - name: Run tests with pytest - run: python -m pytest -v --cov=nutrient_dws --cov-report=xml --cov-report=term + - name: Run unit tests with pytest + run: python -m pytest tests/unit/ -v --cov=nutrient_dws --cov-report=xml --cov-report=term - name: Upload coverage to Codecov uses: codecov/codecov-action@v4 @@ -55,6 +55,40 @@ jobs: name: codecov-umbrella fail_ci_if_error: false + integration-test: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Cache pip dependencies + uses: actions/cache@v4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -e ".[dev]" + + - name: Create integration config with API key + run: | + echo 'API_KEY = "${{ secrets.NUTRIENT_DWS_API_KEY }}"' > tests/integration/integration_config.py + env: + NUTRIENT_DWS_API_KEY: ${{ secrets.NUTRIENT_DWS_API_KEY }} + + - name: Run integration tests + run: python -m pytest tests/integration/ -v + build: runs-on: ubuntu-latest needs: test From 06f62f71312acc7cb76cd9a4d23509f43f962514 Mon Sep 17 00:00:00 2001 From: Martin Schuerrer Date: Thu, 19 Jun 2025 19:50:08 +0200 Subject: [PATCH 2/5] Fix secret exposure in GitHub Actions logs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use Python to write integration config instead of echo to prevent API key from being visible in build logs. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .github/workflows/ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0566c39..b9de6ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,7 +82,11 @@ jobs: - name: Create integration config with API key run: | - echo 'API_KEY = "${{ secrets.NUTRIENT_DWS_API_KEY }}"' > tests/integration/integration_config.py + python -c " + import os + with open('tests/integration/integration_config.py', 'w') as f: + f.write(f'API_KEY = \"{os.environ[\"NUTRIENT_DWS_API_KEY\"]}\"\n') + " env: NUTRIENT_DWS_API_KEY: ${{ secrets.NUTRIENT_DWS_API_KEY }} From fb960265f224ffad125880c378b845c296b653fb Mon Sep 17 00:00:00 2001 From: Jonathan Rhyne Date: Fri, 20 Jun 2025 11:52:28 -0400 Subject: [PATCH 3/5] feat: enhance integration test workflow --- .github/workflows/ci.yml | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9de6ef..293a912 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,14 +58,17 @@ jobs: integration-test: runs-on: ubuntu-latest if: github.event_name == 'pull_request' + strategy: + matrix: + python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] steps: - uses: actions/checkout@v4 - - name: Set up Python 3.12 + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: ${{ matrix.python-version }} - name: Cache pip dependencies uses: actions/cache@v4 @@ -80,7 +83,17 @@ jobs: python -m pip install --upgrade pip pip install -e ".[dev]" + - name: Check for API key availability + run: | + if [ -z "${{ secrets.NUTRIENT_DWS_API_KEY }}" ]; then + echo "::warning::NUTRIENT_DWS_API_KEY secret not found, skipping integration tests" + echo "skip_tests=true" >> $GITHUB_ENV + else + echo "skip_tests=false" >> $GITHUB_ENV + fi + - name: Create integration config with API key + if: env.skip_tests != 'true' run: | python -c " import os @@ -91,8 +104,13 @@ jobs: NUTRIENT_DWS_API_KEY: ${{ secrets.NUTRIENT_DWS_API_KEY }} - name: Run integration tests + if: env.skip_tests != 'true' run: python -m pytest tests/integration/ -v + - name: Cleanup integration config + if: always() + run: rm -f tests/integration/integration_config.py + build: runs-on: ubuntu-latest needs: test @@ -120,4 +138,4 @@ jobs: uses: actions/upload-artifact@v4 with: name: dist - path: dist/ \ No newline at end of file + path: dist/ From 7e6e9d1707d7797fa87260e1d75800b70c683c6d Mon Sep 17 00:00:00 2001 From: Jonathan Rhyne Date: Fri, 20 Jun 2025 11:53:38 -0400 Subject: [PATCH 4/5] Add basic smoke test for integration setup --- tests/integration/test_smoke.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/integration/test_smoke.py diff --git a/tests/integration/test_smoke.py b/tests/integration/test_smoke.py new file mode 100644 index 0000000..bec1e81 --- /dev/null +++ b/tests/integration/test_smoke.py @@ -0,0 +1,22 @@ +"""Basic smoke test to validate integration test setup.""" + +import pytest + +from nutrient_dws import NutrientClient + +try: + from . import integration_config + + API_KEY = integration_config.API_KEY +except (ImportError, AttributeError): + API_KEY = None + + +@pytest.mark.skipif(not API_KEY, reason="No API key available") +def test_api_connection(): + """Test that we can connect to the API.""" + client = NutrientClient(api_key=API_KEY) + # Just verify client initialization works + assert client._api_key == API_KEY + assert hasattr(client, "convert_to_pdf") + assert hasattr(client, "build") From cd9ba08ed780272f482744ab90cb71714b171d17 Mon Sep 17 00:00:00 2001 From: Jonathan Rhyne Date: Fri, 20 Jun 2025 11:58:55 -0400 Subject: [PATCH 5/5] feat: enhance integration test workflow --- tests/integration/test_smoke.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/integration/test_smoke.py b/tests/integration/test_smoke.py index bec1e81..59800ce 100644 --- a/tests/integration/test_smoke.py +++ b/tests/integration/test_smoke.py @@ -1,11 +1,16 @@ """Basic smoke test to validate integration test setup.""" +from typing import Optional + import pytest from nutrient_dws import NutrientClient +# Type annotation for mypy +API_KEY: Optional[str] = None + try: - from . import integration_config + from . import integration_config # type: ignore[attr-defined] API_KEY = integration_config.API_KEY except (ImportError, AttributeError):