fix: slight correction needed for "uv sync" to work #2958
Workflow file for this run
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: Smoke Tests | |
| on: | |
| push: | |
| branches: ["main", "release/*", "develop"] | |
| pull_request: | |
| branches: ["main", "release/*", "develop"] | |
| permissions: | |
| contents: read | |
| env: | |
| # UV_TORCH_BACKEND only works with 'uv pip' commands, not 'uv sync'. | |
| # Used by 'uv pip install torch torchvision' step to install CPU-only PyTorch. | |
| UV_TORCH_BACKEND: "cpu" | |
| jobs: | |
| try-all-models: | |
| runs-on: ${{ matrix.os }} | |
| concurrency: | |
| group: model-smoke-${{ matrix.os }}-${{ matrix.python-version }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: ["ubuntu-latest", "macos-latest", "windows-latest"] | |
| python-version: ["3.10", "3.13"] | |
| timeout-minutes: 15 | |
| steps: | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| - name: 🐍 Install uv and set Python version ${{ matrix.python-version }} | |
| uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 | |
| with: | |
| version: "0.9.26" | |
| python-version: ${{ matrix.python-version }} | |
| activate-environment: true | |
| - name: 🚀 Install Packages (plus extras) | |
| timeout-minutes: 5 | |
| # Install PyTorch CPU-only first (UV_TORCH_BACKEND=cpu works with 'uv pip') | |
| run: uv pip install -e .[plus] | |
| - name: 🔎 Smoke-test model instantiation, downloads, and inference | |
| run: python tests/run_smoke_all_models.py | |
| - name: Minimize uv cache | |
| run: uv cache prune --ci | |
| executorch-parity: | |
| name: ExecuTorch parity | |
| # The real numerical-parity test exports an RFDETRNano to .pte and asserts the | |
| # XNNPACK-delegated runtime matches eager PyTorch. XNNPACK is a plain-CPU backend, | |
| # so no special hardware/SDK is required — ubuntu-latest is sufficient. | |
| runs-on: ${{ matrix.os }} | |
| concurrency: | |
| group: pytest-executorch-${{ matrix.python-version }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| timeout-minutes: 25 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: ["ubuntu-latest"] | |
| # executorch 1.3.1 ships manylinux_2_28 x86_64 wheels for cp310–cp313 and | |
| # requires_python is >=3.10,<3.14. 3.10 (floor) and 3.13 (ceiling) bracket | |
| # the supported range; widen the matrix if the [executorch] pin changes. | |
| python-version: ["3.10", "3.13"] | |
| steps: | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| - name: 🐍 Install uv and set Python version ${{ matrix.python-version }} | |
| uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 | |
| with: | |
| version: "0.9.26" | |
| python-version: ${{ matrix.python-version }} | |
| activate-environment: true | |
| - name: 🚀 Install Packages (executorch extra) | |
| timeout-minutes: 8 | |
| # The end-to-end parity test builds and exports the full RFDETRNano stack, so | |
| # pull the same extras as the CPU test job plus the [executorch] backend. | |
| # --group ci-executorch-pin locks torch to a version whose C10 ABI matches | |
| # executorch 1.3.1's prebuilt wheel (see pyproject.toml for the empirically | |
| # validated range and removal condition). | |
| run: uv pip install -e ".[executorch,train,augment,cli,visual]" --group tests --group ci-executorch-pin | |
| - name: 🔎 Verify executorch runtime imports | |
| # Guard against a silently-skipped parity test: the test class is gated by a | |
| # skipif on executorch availability, so a broken/missing wheel would skip it | |
| # (false green). Fail here (red) instead if the runtime cannot be imported. | |
| # require_runtime=True also surfaces an actionable ABI-compatibility message | |
| # (rather than a bare "undefined symbol") if the pin above ever drifts stale. | |
| # shell: python — activate-environment: true (setup-uv, above) puts the venv's | |
| # python on PATH, so this runs the script through it directly (no uv run needed). | |
| run: | | |
| from rfdetr.export._executorch import _IS_EXECUTORCH_AVAILABLE | |
| from rfdetr.export._executorch.converter import _check_executorch_available | |
| _check_executorch_available(require_runtime=True) | |
| assert _IS_EXECUTORCH_AVAILABLE, "executorch installed but not detected as available" | |
| print("executorch runtime import OK") | |
| shell: python | |
| - name: 🧪 Run ExecuTorch parity tests | |
| # executorch export is heavy; run single-worker as advised for this suite. | |
| run: | | |
| uv run --no-sync pytest tests/export/test_executorch_export.py \ | |
| -m e2e_executorch -n 1 \ | |
| --timeout=600 \ | |
| --durations=20 | |
| - name: Minimize uv cache | |
| continue-on-error: true | |
| run: uv cache prune --ci | |
| coreml-parity: | |
| name: CoreML parity | |
| # coremltools + the CoreML runtime are macOS-only, so unlike executorch-parity (portable | |
| # XNNPACK, runs on ubuntu-latest) this job requires macos-latest. | |
| runs-on: macos-latest | |
| concurrency: | |
| group: pytest-coreml-${{ matrix.python-version }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| timeout-minutes: 25 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # 3.11 not 3.10 for this job specifically (bumped alongside the coreml extra's torch<2.12 | |
| # pin, see pyproject.toml) — other CI jobs keep testing 3.10 as the project floor. | |
| python-version: ["3.11", "3.13"] | |
| steps: | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| - name: 🐍 Install uv and set Python version ${{ matrix.python-version }} | |
| uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 | |
| with: | |
| version: "0.9.26" | |
| python-version: ${{ matrix.python-version }} | |
| activate-environment: true | |
| - name: 🚀 Install Packages (coreml extra) | |
| timeout-minutes: 8 | |
| run: uv pip install -e ".[coreml,train,augment,cli,visual]" --group tests | |
| - name: 🔎 Verify coremltools import | |
| # Guard against a silently-skipped parity test: TestCoreMLEndToEnd is gated by a | |
| # skipif on coremltools availability, so a broken/missing wheel would skip it (false | |
| # green) instead of failing red. | |
| run: | | |
| from rfdetr.export._coreml import _IS_COREMLTOOLS_AVAILABLE | |
| assert _IS_COREMLTOOLS_AVAILABLE, "coremltools installed but not detected as available" | |
| print("coremltools import OK") | |
| shell: python | |
| - name: 🧪 Run CoreML end-to-end parity tests | |
| # Real ct.convert + mlmodel.predict + download_assets is heavy/network; single-worker, | |
| # opt-in marker (see pyproject.toml `e2e_coreml`) — deliberately excluded from the | |
| # ci-tests-cpu.yml default filter (`and not e2e_coreml`) so it only runs here. | |
| run: | | |
| uv run --no-sync pytest tests/export/test_coreml_export.py \ | |
| -m e2e_coreml -n 1 \ | |
| --timeout=600 \ | |
| --durations=20 | |
| - name: Minimize uv cache | |
| continue-on-error: true | |
| run: uv cache prune --ci | |
| tensorrt-parity: | |
| name: TensorRT parity | |
| # TensorRT engine build + runtime inference need a real GPU + CUDA driver, so unlike the CPU | |
| # integration jobs this runs on the self-hosted GPU runner (same as ci-tests-gpu.yml). | |
| runs-on: Roboflow-GPU-VM-Runner | |
| timeout-minutes: 25 | |
| concurrency: | |
| group: pytest-tensorrt-${{ github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| env: | |
| # UV_TORCH_BACKEND=auto (GPU) works only with uv pip, not uv sync; overrides the workflow-level | |
| # "cpu" default which is wrong for this GPU job. | |
| UV_TORCH_BACKEND: "auto" | |
| steps: | |
| - name: 🖥️ Print GPU information | |
| run: nvidia-smi | |
| - name: 📥 Checkout the repository | |
| uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 | |
| - name: 🐍 Install uv and set Python version | |
| uses: astral-sh/setup-uv@61cb8a9741eeb8a550a1b8544337180c0fc8476b # v7.2.0 | |
| with: | |
| version: "0.9.26" | |
| python-version: "3.12" | |
| activate-environment: true | |
| - name: 🚀 Install Packages (tensorrt + onnx extras) | |
| timeout-minutes: 8 | |
| # [tensorrt] provides tensorrt/polygraphy for the engine build; [onnx] provides the ONNX | |
| # export toolchain (the e2e exports RFDETRNano to ONNX first). --group ci-gpu-pin matches the GPU | |
| # runner's CUDA driver (torch<2.11), same as ci-tests-gpu.yml. | |
| run: uv pip install -e ".[tensorrt,onnx,train,augment,cli,visual]" --group tests --group ci-gpu-pin | |
| - name: 🔎 Verify tensorrt import | |
| # Guard against a silently-skipped parity test: TestTensorRTEndToEnd is gated by a skipif on | |
| # tensorrt availability, so a broken/missing wheel would skip it (false green) instead of failing red. | |
| run: | | |
| from rfdetr.export._tensorrt import _IS_TENSORRT_AVAILABLE | |
| assert _IS_TENSORRT_AVAILABLE, "tensorrt/polygraphy installed but not detected as available" | |
| print("tensorrt import OK") | |
| shell: python | |
| - name: 🔗 Expose CUDA runtime (libcudart.so) to the loader | |
| # The engine build succeeds, but polygraphy's TrtRunner separately dlopen's the *unversioned* | |
| # `libcudart.so` for CUDA stream management. The GPU wheels ship it only as `libcudart.so.12` | |
| # (e.g. under torch/lib), which the dynamic loader does not resolve by bare name — hence | |
| # `OSError: libcudart.so: cannot open shared object file` at runtime. Symlink the versioned | |
| # library to `libcudart.so` in a job-local dir and prepend it to LD_LIBRARY_PATH. | |
| run: | | |
| import glob | |
| import os | |
| import pathlib | |
| import site | |
| roots = list(site.getsitepackages()) | |
| venv = os.environ.get("VIRTUAL_ENV") | |
| if venv: | |
| roots.append(os.path.join(venv, "lib")) | |
| candidates = [] | |
| for root in roots: | |
| candidates += glob.glob(os.path.join(root, "**", "libcudart.so*"), recursive=True) | |
| candidates += glob.glob("/usr/local/cuda*/lib64/libcudart.so*") | |
| candidates = sorted({c for c in candidates if os.path.exists(c)}, key=len) | |
| assert candidates, "libcudart.so* not found in installed wheels or system CUDA" | |
| source = candidates[0] | |
| lib_dir = pathlib.Path(os.environ["RUNNER_TEMP"]) / "cudalibs" | |
| lib_dir.mkdir(parents=True, exist_ok=True) | |
| link = lib_dir / "libcudart.so" | |
| if link.is_symlink() or link.exists(): | |
| link.unlink() | |
| link.symlink_to(source) | |
| print(f"linked {link} -> {source}") | |
| with open(os.environ["GITHUB_ENV"], "a", encoding="utf-8") as env_file: | |
| env_file.write(f"LD_LIBRARY_PATH={lib_dir}{os.pathsep}{os.environ.get('LD_LIBRARY_PATH', '')}\n") | |
| shell: python | |
| - name: 🧪 Run TensorRT end-to-end parity tests | |
| # Real ONNX->engine build + GPU inference is heavy; single-worker, opt-in marker (see pyproject.toml | |
| # `e2e_tensorrt`) — excluded from the ci-tests-gpu.yml default filter (`and not e2e_tensorrt`) so it | |
| # only runs here. | |
| run: | | |
| uv run --no-sync pytest tests/export/test_tensorrt_export.py \ | |
| -m e2e_tensorrt -n 1 \ | |
| --timeout=600 \ | |
| --durations=20 | |
| - name: Minimize uv cache | |
| continue-on-error: true | |
| run: uv cache prune --ci | |
| export-priority-guardian: | |
| runs-on: ubuntu-latest | |
| needs: [executorch-parity, coreml-parity, tensorrt-parity] | |
| if: always() | |
| steps: | |
| - name: 📋 Display parity job results | |
| run: | | |
| echo "executorch-parity: ${{ needs.executorch-parity.result }}" | |
| echo "coreml-parity: ${{ needs.coreml-parity.result }}" | |
| echo "tensorrt-parity: ${{ needs.tensorrt-parity.result }}" | |
| # Fail explicitly on any non-success result (failure, cancelled, or skipped) instead of | |
| # relying on timeout behavior, so a cancelled or skipped parity job still blocks the gate. | |
| - name: ❌ Fail guardian unless every parity job succeeded | |
| if: >- | |
| needs.executorch-parity.result != 'success' || | |
| needs.coreml-parity.result != 'success' || | |
| needs.tensorrt-parity.result != 'success' | |
| run: | | |
| echo "One or more export parity jobs did not succeed; failing explicitly." | |
| exit 1 | |
| - name: ✅ all parity jobs succeeded | |
| run: echo "All export parity jobs (executorch, coreml, tensorrt) completed successfully." |