fix: squash all requirement handling bugs #3113
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Run test suite | |
| on: | |
| pull_request: | |
| push: | |
| branches: | |
| - main | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| tests-base: | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest, windows-latest, macos-latest] | |
| # test with oldest and latest supported Python versions | |
| # NOTE: If bumping the minimum Python version here, also do it in | |
| # ruff.toml, setup.py and other CI files as well. | |
| python-version: ["3.10", "3.14"] | |
| runtime-deps: ["latest"] | |
| include: | |
| - os: ubuntu-latest | |
| python-version: "3.10" | |
| runtime-deps: "oldest" | |
| fail-fast: false | |
| runs-on: ${{ matrix.os }} | |
| defaults: | |
| run: | |
| shell: bash -el {0} | |
| steps: | |
| - name: Set up Git repository | |
| uses: actions/checkout@v7 | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| enable-cache: true | |
| - name: Install package | |
| run: | | |
| cp production.uv.lock uv.lock | |
| uv sync --python ${{ matrix.python-version }} --extra dev --frozen | |
| if [ "${{ matrix.runtime-deps }}" == "oldest" ]; then | |
| # replace >= with == in runtime deps section of pyproject.toml to install oldest runtime deps | |
| sed -i '/^runtime = \[$/,/^]$/s/>=/==/g' ./pyproject.toml | |
| uv pip install -e .[runtime] | |
| fi | |
| - name: Run test suite | |
| run: | | |
| uv run --no-sync pytest \ | |
| -v \ | |
| --skip-endtoend \ | |
| --timeout=300 \ | |
| --cov-report=term-missing:skip-covered \ | |
| --cov-report=xml:coverage.xml \ | |
| --cov=tesseract_core \ | |
| --cov-branch | |
| - name: Upload coverage reports to Codecov | |
| uses: codecov/codecov-action@v7.0.0 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| slug: pasteurlabs/tesseract-core | |
| files: coverage*.xml | |
| fail_ci_if_error: true | |
| get-e2e-matrix: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| matrix: ${{ steps.get-matrix.outputs.matrix }} | |
| demos: ${{ steps.get-matrix.outputs.demos }} | |
| steps: | |
| - name: Set up Git repository | |
| uses: actions/checkout@v7 | |
| - name: Get available test matrix | |
| id: get-matrix | |
| env: | |
| EXAMPLES_DIR: examples | |
| DEMO_DIR: demo | |
| run: | | |
| # get JSON array of directories in EXAMPLES_DIR, except ones that start with _ | |
| subjobs=$( | |
| find "${{ env.EXAMPLES_DIR }}" -type d -maxdepth 1 -mindepth 1 -exec basename {} \; \ | |
| | grep -v '^_' \ | |
| | jq -R -s -c 'split("\n")[:-1]' | |
| ) | |
| # add "base" to subjobs | |
| subjobs=$(echo "$subjobs" | jq -c -r '. + ["base"]') | |
| printf 'matrix=%s\n' "$subjobs" >> $GITHUB_OUTPUT | |
| # get JSON array of directories in DEMO_DIR, except ones that start with _ | |
| demos=$( | |
| find "${{ env.DEMO_DIR }}" -type d -maxdepth 1 -mindepth 1 -exec basename {} \; \ | |
| | grep -v '^_' \ | |
| | jq -R -s -c 'split("\n")[:-1]' | |
| ) | |
| printf 'demos=%s\n' "$demos" >> $GITHUB_OUTPUT | |
| tests-e2e: | |
| needs: [get-e2e-matrix] | |
| if: needs.get-e2e-matrix.outputs.matrix != '[]' | |
| strategy: | |
| matrix: | |
| os: [ubuntu-24.04] | |
| python-version: ["3.14"] | |
| arch: ["x64"] | |
| docker-engine: ["docker"] | |
| unit-tesseract: ${{ fromJson(needs.get-e2e-matrix.outputs.matrix) }} | |
| exclude: | |
| - arch: x64 | |
| unit-tesseract: "pyvista-arm64" | |
| include: | |
| # Test on arm to ensure compatibility with Apple M1 chips | |
| # (OSX runners don't have access to Docker so we use Linux ARM runners instead) | |
| - os: "ubuntu-24.04" | |
| python-version: "3.14" | |
| arch: "arm" | |
| docker-engine: "docker" | |
| unit-tesseract: "base" | |
| - os: "ubuntu-24.04" | |
| python-version: "3.14" | |
| arch: "arm" | |
| docker-engine: "docker" | |
| unit-tesseract: "pyvista-arm64" | |
| # Run tests using Podman | |
| - os: "ubuntu-24.04" | |
| python-version: "3.14" | |
| arch: "x64" | |
| docker-engine: "podman" | |
| unit-tesseract: "base" | |
| fail-fast: false | |
| runs-on: ${{ matrix.arch == 'x64' && matrix.os == 'ubuntu-24.04' && 'ubuntu-24.04' || matrix.arch == 'arm' && matrix.os == 'ubuntu-24.04' && 'ubuntu-24.04-arm'}} | |
| defaults: | |
| run: | |
| shell: bash -el {0} | |
| steps: | |
| - name: Set up Git repository | |
| uses: actions/checkout@v7 | |
| # Use Conda to install Python (setup-python action doesn't support ARM) | |
| - uses: conda-incubator/setup-miniconda@v4 | |
| with: | |
| auto-update-conda: true | |
| python-version: ${{ matrix.python-version }} | |
| channels: defaults | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| enable-cache: true | |
| - name: Restore UV environment | |
| run: cp production.uv.lock uv.lock | |
| - name: Install package | |
| run: | | |
| uv sync --extra dev --frozen | |
| - name: Set up Podman | |
| if: matrix.docker-engine == 'podman' | |
| run: | | |
| systemctl start --user podman.socket | |
| systemctl status --user podman.socket | |
| podman --version | |
| export DOCKER_HOST=unix:///run/user/1001/podman/podman.sock | |
| echo "DOCKER_HOST=${DOCKER_HOST}" >> $GITHUB_ENV | |
| echo "TESSERACT_DOCKER_EXECUTABLE=podman" >> $GITHUB_ENV | |
| - name: Run test suite | |
| run: | | |
| if [ "${{ matrix.unit-tesseract }}" == "base" ]; then | |
| uv run --no-sync pytest \ | |
| --always-run-endtoend \ | |
| --timeout=300 \ | |
| --cov-branch \ | |
| --cov-report=term-missing:skip-covered \ | |
| --cov-report=xml:coverage.xml \ | |
| --cov=tesseract_core \ | |
| tests/endtoend_tests \ | |
| -k "not test_examples" | |
| else | |
| uv run --no-sync pytest \ | |
| --always-run-endtoend \ | |
| --timeout=300 \ | |
| --cov-branch \ | |
| --cov-report=term-missing:skip-covered \ | |
| --cov-report=xml:coverage.xml \ | |
| --cov=tesseract_core \ | |
| tests/endtoend_tests/test_examples.py \ | |
| -k "[${{ matrix.unit-tesseract }}]" | |
| fi | |
| - name: Upload coverage reports to Codecov | |
| uses: codecov/codecov-action@v7.0.0 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| slug: pasteurlabs/tesseract-core | |
| files: coverage*.xml | |
| fail_ci_if_error: true | |
| tests-demos: | |
| needs: [get-e2e-matrix] | |
| if: needs.get-e2e-matrix.outputs.demos != '[]' | |
| strategy: | |
| matrix: | |
| os: [ubuntu-latest] | |
| # test with oldest supported Python version only (for slow tests) | |
| python-version: ["3.10"] | |
| demo: ${{ fromJson(needs.get-e2e-matrix.outputs.demos) }} | |
| fail-fast: false | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Set up Git repository | |
| uses: actions/checkout@v7 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| with: | |
| enable-cache: true | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Restore UV environment | |
| run: cp production.uv.lock uv.lock | |
| - name: Install dev requirements | |
| run: | | |
| uv sync --extra dev --frozen | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update -qq | |
| sudo apt-get install -y -qq xvfb libgl1 libosmesa6 | |
| - name: Install demo requirements | |
| working-directory: demo/${{matrix.demo}} | |
| run: | | |
| uv pip install -r requirements.txt | |
| - name: Run demos | |
| working-directory: demo/${{matrix.demo}} | |
| env: | |
| DISPLAY: ":99" | |
| PYVISTA_OFF_SCREEN: "true" | |
| run: | | |
| Xvfb :99 -screen 0 1024x768x24 & | |
| uv pip install jupyter | |
| uv run --no-sync jupyter nbconvert --to notebook --execute demo.ipynb | |
| all-ok: | |
| if: always() | |
| needs: [tests-base, tests-e2e, tests-demos] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Check for errors | |
| run: | | |
| if [[ "${{ needs.tests-base.result }}" != "success" && "${{ needs.tests-base.result }}" != "skipped" ]]; then | |
| echo "Base tests failed" | |
| exit 1 | |
| fi | |
| if [[ "${{ needs.tests-e2e.result }}" != "success" && "${{ needs.tests-e2e.result }}" != "skipped" ]]; then | |
| echo "E2E tests failed" | |
| exit 1 | |
| fi | |
| if [[ "${{ needs.tests-demos.result }}" != "success" && "${{ needs.tests-demos.result }}" != "skipped" ]]; then | |
| echo "Demo tests failed" | |
| exit 1 | |
| fi | |
| echo "All tests passed!" |