diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00a9709b..9b7da194 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -282,3 +282,62 @@ jobs: env: NDI_REQUIRE_SONPIPE: "1" run: pytest tests/test_cedspike2_integration.py tests/test_cedspike2_sonpipe.py -v --tb=short + + install-without-git: + # Guards the git-free install. The double-click installer is built on + # `uv tool install`, and uv shells out to a system `git` for every + # `git+` dependency URL -- which many end users (Windows and macOS in + # particular) do not have. Every runtime dependency is therefore pulled + # from a GitHub archive (zip) URL, fetched over plain HTTPS. This job + # installs NDI with `git` made unusable, so a `git+` URL sneaking back + # into pyproject.toml (here, or through an extra we install) fails CI + # instead of failing on a user's machine. + name: Install without git + runs-on: ubuntu-latest + concurrency: + group: ci-install-without-git-${{ github.ref }} + cancel-in-progress: true + steps: + # The checkout itself uses git; that is fine -- the user's installer + # ships the source too. Only the install step below must not need it. + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v6 + with: + version: "0.11.32" + # No cache: a warm cache could satisfy a dependency without ever + # reaching the code path that would call git. + enable-cache: false + + - name: Install NDI with git unavailable + run: | + # Shadow git with a script that always fails, ahead of the real one + # on PATH. (Removing /usr/bin from PATH would also remove most of + # the toolchain, so shadowing is the cleaner way to hide it.) + mkdir -p "$RUNNER_TEMP/nogit" + printf '#!/bin/sh\necho "git is deliberately unavailable in this job" >&2\nexit 127\n' \ + > "$RUNNER_TEMP/nogit/git" + chmod +x "$RUNNER_TEMP/nogit/git" + export PATH="$RUNNER_TEMP/nogit:$PATH" + + # Prove the shadow works before trusting the install below. + if git --version; then + echo "::error::git is still usable; this job would prove nothing" + exit 1 + fi + + uv venv --python 3.12 "$RUNNER_TEMP/venv" + # [tutorials] brings pandas and matplotlib, which `ndi check` checks. + uv pip install --python "$RUNNER_TEMP/venv/bin/python" ".[tutorials]" + + - name: Import NDI and its sibling packages + run: | + "$RUNNER_TEMP/venv/bin/python" -c "import ndi, did, ndr, vlt, vhlib, ndicompress, ndi_ontology" + + - name: Validate installation + # Run from outside the checkout so `import ndi` resolves to the + # installed wheel, not the source tree. + working-directory: ${{ runner.temp }} + run: | + "$RUNNER_TEMP/venv/bin/python" -m ndi check diff --git a/pyproject.toml b/pyproject.toml index cbf761c4..86233e02 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,19 +35,19 @@ classifiers = [ ] requires-python = ">=3.10" dependencies = [ - "did @ git+https://github.com/VH-Lab/DID-python.git@main", - "ndr[formats] @ git+https://github.com/VH-lab/NDR-python.git@main", + "did @ https://github.com/VH-Lab/DID-python/archive/refs/heads/main.zip", + "ndr[formats] @ https://github.com/VH-lab/NDR-python/archive/refs/heads/main.zip", "vhlab-toolbox-python @ https://github.com/VH-Lab/vhlab-toolbox-python/archive/refs/heads/main.zip", # ndi.app.oridirtuning needs vhlib.response_stats.neural_response_significance, # mirroring NDI-matlab, which calls vhlab-library-matlab directly (see # NDI-matlab/src/ndi/docs/developer_notes/vhlabLibraryMatlab.md). "vhlab-library-python @ https://github.com/VH-Lab/vhlab-library-python/archive/refs/heads/main.zip", - "ndi-compress @ git+https://github.com/Waltham-Data-Science/NDI-compress-python.git@main", + "ndi-compress @ https://github.com/Waltham-Data-Science/NDI-compress-python/archive/refs/heads/main.zip", # ndi.ontology is a re-export of this package -- see src/ndi/ontology.py. # It tracks ndi-ontology-matlab, which is where NDI-matlab's ontology code # now lives; NDI-matlab pulls the MATLAB half in the same way, through its # requirements.txt. - "ndi-ontology @ git+https://github.com/Waltham-Data-Science/ndi-ontology-python.git@main", + "ndi-ontology @ https://github.com/Waltham-Data-Science/ndi-ontology-python/archive/refs/heads/main.zip", "numpy>=1.20.0", "networkx>=2.6", "jsonschema>=4.0.0", diff --git a/tests/test_intan_blockinfo_arity.py b/tests/test_intan_blockinfo_arity.py index e35cb3f4..6eb0a256 100644 --- a/tests/test_intan_blockinfo_arity.py +++ b/tests/test_intan_blockinfo_arity.py @@ -1,6 +1,6 @@ """The Intan reader survives NDR growing a return value. -``pyproject.toml`` pins ``ndr[formats] @ git+...NDR-python.git@main``, so +``pyproject.toml`` pins ``ndr[formats] @ .../NDR-python/archive/refs/heads/main.zip``, so CI installs NDR from its tip on every run and an arity change upstream reaches this repo the moment it merges -- with no version bump to notice and no local reproduction, because a developer's installed NDR is