Repository navigation
586 lines (536 loc) · 25.9 KB
/
Copy pathci.yml
File metadata and controls
586 lines (536 loc) · 25.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
name: CI
on:
push:
branches: [main]
# No branch filter: a PR targeting a feature branch needs lint and tests
# just as much as one targeting main.
pull_request:
jobs:
lint:
runs-on: ubuntu-latest
# Only the lint job gets cancel-in-progress. The test job talks to the
# live cloud, and cancelling it mid-run strands the datasets it created.
concurrency:
group: ci-lint-${{ github.ref }}
cancel-in-progress: true
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install linting tools
run: |
python -m pip install --upgrade pip
pip install ruff black
- name: Check formatting with black
run: black --check src/ tests/
- name: Lint with ruff
run: ruff check src/ tests/
bridge:
name: MATLAB/Python bridge completeness
runs-on: ubuntu-latest
concurrency:
group: ci-bridge-${{ github.ref }}
cancel-in-progress: true
steps:
# Two checkouts, laid out as siblings, because the check compares
# NDI-matlab's +ndi/+cloud tree against this repo's bridge YAMLs.
# No MATLAB runtime is needed -- it only reads the source tree --
# so this stays a fast job rather than joining test-symmetry.yml.
- uses: actions/checkout@v4
with:
path: NDI-python
# TestAHashChangeIsJustified diffs this branch against its
# merge-base, and a shallow clone has no merge-base -- the check
# would then skip in the one job that is supposed to run it.
fetch-depth: 0
- name: Check out NDI-matlab (matching branch, fall back to main)
uses: actions/checkout@v4
with:
repository: VH-Lab/NDI-matlab
# Same pairing rule as test-symmetry.yml: a bridge entry usually
# lands in the same feature branch as the MATLAB function it
# records, so check that branch when it exists.
ref: ${{ github.head_ref || github.ref_name }}
path: NDI-matlab
# Full history: the sync-hash check resolves recorded commits with
# `git cat-file -t`, and the default shallow clone has only HEAD --
# every commit hash would come back "missing".
fetch-depth: 0
continue-on-error: true
id: matlab_checkout_branch
- name: Check out NDI-matlab (main fallback)
if: steps.matlab_checkout_branch.outcome == 'failure'
uses: actions/checkout@v4
with:
repository: VH-Lab/NDI-matlab
ref: main
path: NDI-matlab
# See the note on the step above.
fetch-depth: 0
- name: Set up Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install pytest and PyYAML
run: |
python -m pip install --upgrade pip
pip install pytest pyyaml
- name: Check bridge completeness
working-directory: NDI-python
env:
# Both repos are checked out above, so an absent MATLAB tree
# means the checkout step broke. Fail instead of skipping --
# a check that could not run must not report a pass (see #77).
NDI_BRIDGE_CHECK_STRICT: "1"
run: pytest tests/test_matlab_bridge_completeness.py -v --tb=short
- name: Check bridge sync hashes are commits
working-directory: NDI-python
env:
# Same reasoning as the step above: this job checks NDI-matlab out,
# so an absent tree is a broken checkout rather than a local
# developer without one. Fail rather than skip (#77).
NDI_BRIDGE_CHECK_STRICT: "1"
run: pytest tests/test_matlab_bridge_hashes.py -v --tb=short
- name: Check public MATLAB properties are public in Python
working-directory: NDI-python
env:
# Both repos are checked out above, so an absent MATLAB tree means
# the checkout step broke. Fail instead of skipping -- a check that
# could not run must not report a pass (see #77).
NDI_BRIDGE_CHECK_STRICT: "1"
run: pytest tests/test_matlab_bridge_properties.py -v --tb=short
- name: Check every python_path resolves
working-directory: NDI-python
env:
# Reads only this repo, so it needs no MATLAB tree -- but it is
# named here as well as running in the matrix, because a check no
# job names runs nowhere (section 7).
NDI_BRIDGE_CHECK_STRICT: "1"
run: pytest tests/test_matlab_bridge_python_paths.py -v --tb=short
- name: Check ndi_common sync with NDI-matlab
working-directory: NDI-python
env:
# Both repos are checked out above, so an absent MATLAB tree
# means the checkout step broke. Fail instead of skipping --
# same reasoning as NDI_BRIDGE_CHECK_STRICT above (see #77).
NDI_COMMON_SYNC_STRICT: "1"
NDI_MATLAB_PATH: ${{ github.workspace }}/NDI-matlab
run: pytest tests/test_ndi_common_matlab_sync.py -v --tb=short
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12"]
steps:
- uses: actions/checkout@v4
with:
# Same reason as the bridge job: the hash-justification check
# needs a merge-base, and it reads only this repo, so it is
# supposed to run here too rather than only where NDI-matlab is.
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install with ndi_install.py
run: |
python -m pip install --upgrade pip
python ndi_install.py --dev --no-validate --verbose
- name: Validate installation
run: python -m ndi check
- name: Run tests with coverage
env:
NDI_CLOUD_USERNAME: ${{ secrets.TEST_USER_2_USERNAME }}
NDI_CLOUD_PASSWORD: ${{ secrets.TEST_USER_2_PASSWORD }}
# The CI test account does not have a registered MATLAB
# license, so the destructive BYOL tests (DELETE
# /users/me/matlab-license) are allowed to run; they will
# clean up after themselves. The license guard in
# tests/_matlab_license_guard.py enforces this at module-import
# time and refuses to run if this variable is unset.
NDI_CLOUD_TEST_USER_HAS_MATLAB_LICENSE: "false"
run: |
# Use sys.monitoring (PEP 669) on Python 3.12+ for faster coverage.
# CTracer (sys.settrace) is catastrophically slow on 3.12 when
# importing large packages like openminds (~6 min vs ~2 sec).
COVERAGE_CORE=$(python -c "import sys; print('sysmon' if sys.version_info >= (3,12) else 'ctrace')")
export COVERAGE_CORE
pytest tests/ -v --tb=short --cov=src/ndi --cov-report=term-missing
windows-smoke:
# Windows import-and-smoke leg (#160). The main `test` job cannot add
# Windows as it stands: it injects NDI_CLOUD_USERNAME / NDI_CLOUD_PASSWORD
# and runs the destructive live-cloud suite, so a second OS would double
# the load on the shared test account for no Windows-specific signal.
# This job installs, runs `python -m ndi check`, and then runs the suite
# WITHOUT NDI_CLOUD_* in the environment, so the cloud tests skip
# themselves via their _has_creds gate. That is enough to catch the two
# import-fatal bugs Windows has already shipped (pathSafeName carving
# forbidden characters, and `import fcntl` at module scope).
name: Windows import and smoke
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install with ndi_install.py
run: |
python -m pip install --upgrade pip
python ndi_install.py --dev --no-validate --verbose
- name: Validate installation
run: python -m ndi check
- name: Run offline test suite (advisory)
# No NDI_CLOUD_USERNAME / NDI_CLOUD_PASSWORD are set here on purpose:
# every cloud test gates on `_has_creds` and skips when they are
# absent, so this run stays offline while still importing every
# module in `src/ndi` and exercising the local-only tests -- the
# cheap first step the issue asks for. No coverage upload: this job
# is here to catch import and path bugs on Windows, not to be a
# second source of coverage numbers.
#
# `continue-on-error: true` (#160): the two required steps above --
# `ndi_install.py` and `python -m ndi check` -- cover the class of
# bug the issue named (an import-fatal like `fcntl`, or a broken
# smoke path). Running the whole suite is the "then the offline
# portion of the suite" the issue asks for on top of that, and the
# first run surfaced 23 pre-existing Windows bugs across seven
# categories (see the PR thread). Fixing them exceeds this PR's
# scope; the step stays running here so those failures are visible
# on every push, and a follow-up removes this flag once the count
# drops to zero.
continue-on-error: true
env:
# The MATLAB BYOL license guard in `tests/_matlab_license_guard.py`
# fatal-checks this env var at MODULE IMPORT time -- before the
# `_has_creds` skip gate can decide to skip the destructive tests
# -- so its absence turns two test files into collection errors
# even when no cloud credentials are set. Mirror the linux `test`
# job's value: "false" says the account has no registered license
# and destructive tests may run, and without NDI_CLOUD_USERNAME
# they will still skip through `_has_creds` and never fire.
NDI_CLOUD_TEST_USER_HAS_MATLAB_LICENSE: "false"
run: pytest tests/ -v --tb=short
ced-integration:
name: CED integration (real sonpipe)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.14
uses: actions/setup-python@v5
with:
# CED ships sonpy only for CPython 3.14 on Linux, so the real CLI
# cannot run on the main test matrix. This job is the one place the
# cedspike2 wrapper is exercised end-to-end against a real .smr; the
# fake CLI in tests/_fake_sonpipe.py covers it on every other
# version. Mirrors NDR-python's ced-integration job by design.
python-version: "3.14"
- name: Install NDI-python
run: |
python -m pip install --upgrade pip
python ndi_install.py --dev --no-validate --verbose
- name: Install sonpipe (pulls CED's sonpy)
# Uses the entry point NDR-python exposes for this purpose so the git
# URL only lives in NDR-python's [ced] extra. --check afterwards
# fails the job if the CLI is still not reachable through the bridge.
run: |
python -m ndr.setup.sonpipe
python -m ndr.setup.sonpipe --check
- name: Run CED integration tests against the real CLI
# NDI_REQUIRE_SONPIPE turns "sonpipe missing" from skip to failure so
# this job cannot pass by quietly reading nothing.
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, compiler-free install on every platform the
# double-click installer targets.
#
# git: the 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 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.
#
# Pyraview: not on PyPI, and a C++ build from its sdist. It must come from
# the pre-built wheels on its GitHub release, found through the committed
# flat index install/pyraview-wheels.html, with hashes enforced through
# install/pyraview-constraints.txt. `--only-binary pyraview` makes a
# missing wheel an error rather than a compile, CMake and the C/C++
# compilers are hidden as well, and tools/check_pyraview_wheel.py then
# proves the installed WHEEL tags are exactly those of a release wheel.
#
# The Linux x86_64 leg keeps the job's original check name, so a branch
# rule that requires "Install without git" still finds it.
name: ${{ matrix.check_name }}
runs-on: ${{ matrix.os }}
# Bounds a hung install. (It does not bound time spent QUEUED for a
# runner label: if macos-15-intel is ever retired, drop that leg.)
timeout-minutes: 45
concurrency:
group: ci-install-without-git-${{ matrix.leg }}-${{ github.ref }}
cancel-in-progress: true
strategy:
fail-fast: false
matrix:
include:
- leg: linux-x86_64
check_name: Install without git
os: ubuntu-latest
python: "3.12"
machine: x86_64
tags: "manylinux_ x86_64"
- leg: linux-aarch64
check_name: Install without git (linux-aarch64)
os: ubuntu-24.04-arm
python: "3.12"
machine: aarch64
tags: "manylinux_ aarch64"
- leg: windows-amd64
check_name: Install without git (windows-amd64)
os: windows-latest
python: "3.12"
machine: AMD64
tags: "win_amd64"
- leg: macos-arm64
check_name: Install without git (macos-arm64)
os: macos-latest
python: "3.12"
machine: arm64
tags: "macosx_ arm64"
- leg: macos-intel
check_name: Install without git (macos-intel)
os: macos-15-intel
python: "3.12"
machine: x86_64
tags: "macosx_ x86_64"
# An Intel Mac, as Apple Silicon sees one: an x86_64 CPython under
# Rosetta 2. uv picks wheels for the interpreter it installs into,
# so this resolves exactly what an Intel Mac would.
- leg: macos-rosetta-x86_64
check_name: Install without git (macos-rosetta-x86_64)
os: macos-latest
python: cpython-3.12-macos-x86_64
rosetta: true
machine: x86_64
tags: "macosx_ x86_64"
defaults:
run:
shell: bash
env:
# Raw URL of THIS commit's index: uv reads --find-links only from a URL
# or a directory (a local .html file is refused), and the raw URL is
# what the double-click installer will use on main.
PYRAVIEW_FIND_LINKS: https://raw.githubusercontent.com/${{ github.event.pull_request.head.repo.full_name || github.repository }}/${{ github.event.pull_request.head.sha || github.sha }}/install/pyraview-wheels.html
steps:
# The checkout itself uses git; that is fine -- the user's installer
# ships the source too. Only the install steps 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, or skip a download
# whose hash we mean to check.
enable-cache: false
- name: Make sure Rosetta 2 is available
if: matrix.rosetta
run: |
/usr/bin/pgrep -q oahd || sudo softwareupdate --install-rosetta --agree-to-license
arch -x86_64 /usr/bin/true
- name: Create the Python ${{ matrix.python }} environment
run: |
uv python install "${{ matrix.python }}"
uv venv --python "${{ matrix.python }}" "$RUNNER_TEMP/venv"
if [ "$RUNNER_OS" = Windows ]; then
PY="$RUNNER_TEMP/venv/Scripts/python.exe"
else
PY="$RUNNER_TEMP/venv/bin/python"
fi
echo "PY=$PY" >> "$GITHUB_ENV"
"$PY" -c "import platform, sys; print(sys.version); print('machine:', platform.machine())"
"$PY" -c "import platform, sys; m = platform.machine(); sys.exit(0 if m == '${{ matrix.machine }}' else f'machine is {m}, expected ${{ matrix.machine }}')"
- name: Hide git, CMake and the C/C++ compilers
run: |
# Writes a script the install steps source. On Linux and macOS it
# SHADOWS each tool with one that always fails, ahead of the real
# one on PATH (removing /usr/bin would remove the whole toolchain).
# On Windows a shadow script would be ignored -- native programs
# look for git.exe, not a shell script -- so every PATH directory
# holding one of these tools is dropped instead.
tools="git cmake cc c++ gcc g++ clang clang++ cl"
hide="$RUNNER_TEMP/hide-tools.sh"
if [ "$RUNNER_OS" = Windows ]; then
cat > "$hide" <<EOF
newpath=""
IFS=':' read -ra dirs <<< "\$PATH"
for d in "\${dirs[@]}"; do
drop=""
for t in $tools; do if [ -e "\$d/\$t.exe" ]; then drop=1; fi; done
if [ -z "\$drop" ]; then newpath="\${newpath:+\$newpath:}\$d"; fi
done
export PATH="\$newpath"
EOF
else
mkdir -p "$RUNNER_TEMP/notools"
for t in $tools; do
printf '#!/bin/sh\necho "%s is deliberately unavailable in this job" >&2\nexit 127\n' "$t" \
> "$RUNNER_TEMP/notools/$t"
chmod +x "$RUNNER_TEMP/notools/$t"
done
echo "export PATH=\"$RUNNER_TEMP/notools:\$PATH\"" > "$hide"
fi
echo "HIDE_TOOLS=$hide" >> "$GITHUB_ENV"
# Prove the hiding works before trusting the steps that rely on it.
source "$hide"
for t in git cmake c++ gcc; do
if "$t" --version >/dev/null 2>&1; then
echo "::error::$t is still usable; this job would prove nothing"
exit 1
fi
done
echo "git, cmake, c++ and gcc are all unusable"
- name: "Negative check: no find-links means no pyraview (and no compile)"
run: |
source "$HIDE_TOOLS"
# pyraview is not on PyPI, and the sdist is in no index we name, so
# without --find-links this has nothing to install and must say so.
# It must not fall back to building anything.
if uv pip install --python "$PY" --only-binary pyraview \
--dry-run ".[pyraview]" > "$RUNNER_TEMP/neg.log" 2>&1; then
cat "$RUNNER_TEMP/neg.log"
echo "::error::installing .[pyraview] without --find-links succeeded"
exit 1
fi
cat "$RUNNER_TEMP/neg.log"
grep -q "pyraview" "$RUNNER_TEMP/neg.log"
if grep -qiE "building pyraview|cmake" "$RUNNER_TEMP/neg.log"; then
echo "::error::the failed install tried to build pyraview"
exit 1
fi
- name: "Negative check: a wrong hash is refused"
run: |
source "$HIDE_TOOLS"
# uv does NOT check the #sha256 fragments in a find-links page; the
# constraints file is what makes it verify. Prove that it does by
# corrupting every hash in a copy and expecting a refusal.
sed -E 's/sha256:[0-9a-f]{64}/sha256:0000000000000000000000000000000000000000000000000000000000000000/' \
install/pyraview-constraints.txt > "$RUNNER_TEMP/bad-constraints.txt"
uv venv --python "${{ matrix.python }}" "$RUNNER_TEMP/hashcheck"
if uv pip install --python "$RUNNER_TEMP/hashcheck" --only-binary pyraview \
-f "$PYRAVIEW_FIND_LINKS" -c "$RUNNER_TEMP/bad-constraints.txt" \
"pyraview==0.4.2" > "$RUNNER_TEMP/hash.log" 2>&1; then
cat "$RUNNER_TEMP/hash.log"
echo "::error::a pyraview wheel with the wrong sha256 was installed"
exit 1
fi
cat "$RUNNER_TEMP/hash.log"
grep -qi "hash mismatch" "$RUNNER_TEMP/hash.log"
- name: Install NDI with git and compilers unavailable
run: |
source "$HIDE_TOOLS"
# [tutorials] brings pandas and matplotlib, which `ndi check` checks.
# [pyraview] is the extra the double-click installer will request.
# -v so the log names the wheel uv selected; only those lines are
# printed, the whole log only if the install fails.
if ! uv pip install -v --python "$PY" \
-f "$PYRAVIEW_FIND_LINKS" \
-c install/pyraview-constraints.txt \
--only-binary pyraview \
".[tutorials,pyraview]" > "$RUNNER_TEMP/install.log" 2>&1; then
tail -n 200 "$RUNNER_TEMP/install.log"
exit 1
fi
grep -m 20 -E "Selecting: pyraview|/pyraview-[0-9.]+-[^ ]*\.whl|\+ pyraview" "$RUNNER_TEMP/install.log" \
|| echo "(no pyraview lines in the uv log; the next step is the proof)"
if grep -qiE "building pyraview|pyraview-[0-9.]+\.tar\.gz" "$RUNNER_TEMP/install.log"; then
echo "::error::pyraview was built from source"
exit 1
fi
- name: Prove pyraview is a release wheel for this platform
# From outside the checkout, so imports resolve to the installed tree.
working-directory: ${{ runner.temp }}
run: |
"$PY" -c "import pyraview, os; print(pyraview.__file__, pyraview._lib_path)"
tag_args=()
for t in ${{ matrix.tags }}; do tag_args+=(--expect-tag "$t"); done
"$PY" "$GITHUB_WORKSPACE/tools/check_pyraview_wheel.py" \
--expect-machine "${{ matrix.machine }}" "${tag_args[@]}"
- name: The pip path (ndi_install.py's) also takes the wheel
run: |
source "$HIDE_TOOLS"
# pip, unlike uv, reads a local find-links .html file and checks the
# #sha256 fragment on each link -- which is how ndi_install.py uses
# the index. A seeded venv gives this interpreter its own pip.
uv venv --seed --python "${{ matrix.python }}" "$RUNNER_TEMP/pipvenv"
if [ "$RUNNER_OS" = Windows ]; then PIPPY="$RUNNER_TEMP/pipvenv/Scripts/python.exe"
else PIPPY="$RUNNER_TEMP/pipvenv/bin/python"; fi
"$PIPPY" -m pip install --no-cache-dir --only-binary pyraview \
--find-links install/pyraview-wheels.html "pyraview==0.4.2"
cd "$RUNNER_TEMP"
tag_args=()
for t in ${{ matrix.tags }}; do tag_args+=(--expect-tag "$t"); done
"$PIPPY" "$GITHUB_WORKSPACE/tools/check_pyraview_wheel.py" \
--expect-machine "${{ matrix.machine }}" "${tag_args[@]}"
- name: The installer's command form (uv tool install) also takes the wheel
if: matrix.leg == 'linux-x86_64'
run: |
source "$HIDE_TOOLS"
# What the double-click installer runs, against this checkout.
# uv tool install does not verify hashes (neither the #sha256
# fragments nor a constraints file's), so this leg proves only the
# wheel-not-sdist half; the steps above prove the hash half.
export UV_TOOL_DIR="$RUNNER_TEMP/uvtools" UV_TOOL_BIN_DIR="$RUNNER_TEMP/uvbin"
uv tool install --python 3.12 -f "$PYRAVIEW_FIND_LINKS" \
--no-build-package pyraview "$GITHUB_WORKSPACE[pyraview]"
cd "$RUNNER_TEMP"
"$UV_TOOL_DIR/ndi/bin/python" "$GITHUB_WORKSPACE/tools/check_pyraview_wheel.py" \
--expect-machine x86_64 --expect-tag manylinux_
- name: The committed index matches the GitHub release
if: matrix.leg == 'linux-x86_64'
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
# Regenerates both install/ files from the GitHub API in memory and
# compares: the committed sha256s are GitHub's own asset digests.
tag="v$(sed -nE 's/^ *"pyraview==([^"]+)",/\1/p' pyproject.toml)"
python3 tools/make_pyraview_index.py "$tag" --check
- name: Import NDI and its sibling packages
run: |
"$PY" -c "import ndi, did, ndr, vlt, vhlib, ndicompress, ndi_ontology, ndicalc_vis_matlab, pyraview"
- 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: |
"$PY" -m ndi check
- name: Resolve an NDIcalc document definition
# NDIcalc-vis-matlab's definitions are not in this repo: they come
# from the ndicalc-vis-matlab package, found through its `ndi.calc`
# entry point (ndi_common_PathConstants.CalcDoc). Prove a plain
# install finds one, both directly and through DID's
# $NDICALCDOCUMENTPATH placeholder. Run from outside the checkout for
# the same reason as the step above.
working-directory: ${{ runner.temp }}
run: |
"$PY" - <<'PY'
from did.validate import resolve_definition_path
from ndi.common import ndi_common_PathConstants
from ndi.document import ndi_document
print("CalcDoc:", ndi_common_PathConstants.CalcDoc)
doc = ndi_document("vision/contrast_tuning")
assert "contrast_tuning" in doc.document_properties, doc.document_properties
path = resolve_definition_path("$NDICALCDOCUMENTPATH/vision/contrast_tuning.json")
assert path, "DID could not resolve $NDICALCDOCUMENTPATH/vision/contrast_tuning.json"
print("vision/contrast_tuning resolved from", path)
PY