8000 Install dicom3tools from PyPI instead of GitHub release assets by fedorov · Pull Request #561 · QIICR/dcmqi · GitHub
[go: up one dir, main page]

Skip to content

Install dicom3tools from PyPI instead of GitHub release assets - #561

Merged
fedorov merged 3 commits into
masterfrom
ci/dicom3tools-from-pypi
Sep 11, 2026
Merged

fedorov merged 3 commits into
masterfrom
ci/dicom3tools-from-pypi

Conversation

@fedorov
@fedorov fedorov commented Sep 10, 2026
Copy link
Copy Markdown
Member

dciodvfy was obtained two different ways, and one of them had never worked.

The composite action

.github/actions/install-dicom3tools downloaded per-platform tarballs from a GitHub release, verifying three SHA-256 digests because a release asset can be replaced in place under an unchanged tag. It now installs dicom3tools from PyPI, pinned to 20260901 (the current latest) and overridable via a version: input.

This drops the download, the per-OS archive handling (tar / 7z / unzip) and the digests: PyPI filenames are immutable, so the exact version pin is itself a pin on the bytes CI executes. The programs are located through the distribution's own bin_dir(), which puts the native executables on PATH rather than the Python console-script shims.

The Linux/x86_64 job

docker/Makefile's prereq.build_dicom3tools fetched the Windows .zip, unpacked it with tar xjf, and cd'd into a directory the flat archive does not contain — with the whole && chain swallowed by || echo "Reusing ". It reported success while find_program() found nothing, so the conformance tests were silently dropped from this job.

It is replaced by prereq.install_dicom3tools, which installs the same PyPI package inside the dockcross container, where the tests actually run (the composite action installs on the runner and would never reach them). manylinux_2_17_x86_64 matches that image's glibc 2.17.

The Linux/arm64 job

The wheels also close the gap that kept dciodvfy off arm64: the published manylinux_2_28_aarch64 build matches that job's container exactly, so it now uses the action too. This is what the existing TODO in the workflow asked for once manylinux assets existed.

Both Linux jobs now assert the tests were registered before running the suite, as macOS and Windows already did.

Verification

Done locally before pushing:

  • The pip binary is a drop-in for the release binary it replaces: byte-identical stdout, stderr and exit codes across all 19 DICOM files in data/.
  • The action's script body was run end-to-end in a simulated runner (fresh venv, RUNNER_TEMP, GITHUB_PATH); dciodvfy resolves on PATH exactly as find_program() would.
  • Failure modes fail loudly with nothing written to PATH: nonexistent version, and --only-binary refusing the sdist stub on a platform with no wheel.
  • Makefile recipes were executed against a stub dockcross, and the registration guard was tested across the registered / zero / no-match cases.

Two bugs surfaced during that checking and are fixed in this branch: the bin_dir() command substitution was being evaluated by the host shell (where the venv does not exist) instead of the container, and two dockcross invocations would have mounted docker/ instead of the repo root.

What CI needs to confirm

Docker was not available locally, so the dockcross path was verified only by expansion and stub execution, not against the real container. Specifically:

  • the dockcross image must have a CPython >= 3.10 under /opt/python/ (the wheels require it; the Makefile still pins cp38 for the build itself). The recipe picks the newest cp31[0-9]-cp31[0-9] and fails with a clear message if there is none.
  • the arm64 job's dciodvfy tests have never run before, so they may surface genuine conformance failures on first run.

ð 8000 Ÿ¤– Generated with Claude Code

fedorov and others added 3 commits September 10, 2026 13:02
dciodvfy was obtained two different ways, and one of them had never worked.

The composite action downloaded per-platform tarballs from a GitHub release,
verifying three SHA-256 digests because a release asset can be replaced in
place under an unchanged tag. Installing from PyPI removes that concern along
with the download, unpacking and per-OS archive handling: PyPI filenames are
immutable, so the exact version pin is itself a pin on the bytes CI executes.
The packaged programs are located through the distribution's own bin_dir(),
which gives CMake the native executables rather than the console-script shims.

docker/Makefile's prereq.build_dicom3tools fetched the *Windows* .zip, unpacked
it with `tar xjf` and cd'd into a directory the flat archive does not contain,
with the whole && chain swallowed by `|| echo "Reusing "`. It reported success
while find_program() found nothing, so the conformance tests were silently
dropped from the Linux/x86_64 job. It now installs the same PyPI package inside
the dockcross container, where the tests actually run; manylinux_2_17_x86_64
matches that image's glibc 2.17.

The wheels also close the gap that kept dciodvfy off Linux/arm64: the published
manylinux_2_28_aarch64 build matches that job's container exactly, so it uses
the action too. Both Linux jobs now assert the tests were registered before
running the suite, as macOS and Windows already did.

Verified locally that the pip-installed dciodvfy produces byte-identical output
and exit codes to the release binary it replaces, across all 19 DICOM files in
data/.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Python terminates lines with CRLF on Windows and `read -r` keeps the CR, so the
captured path carried a trailing carriage return: the file test missed dciodvfy
and the step failed with

  ls: cannot access '.../dicom3tools/bin'$'\r': No such file or directory

The install itself was fine -- the win_amd64 wheel downloaded and unpacked -- so
this only ever affected the path capture. No-op on macOS and Linux, where the
same output is LF-terminated.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Matches docker/Makefile's dicom3tools_version and the DICOM3TOOLS_VERSION
environment variable, and follows the convention of the setup-* actions
(python-version, node-version) rather than a bare `version`. All three callers
use the default, so nothing else changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

@fedorov
fedorov merged commit 0ed03e9 into master Sep 11, 2026
9 checks passed
@fedorov
fedorov deleted the ci/dicom3tools-from-pypi branch September 11, 2026 14:34
fedorov added a commit that referenced this pull request Sep 11, 2026
The dciodvfy tests for the three multiframe source variants derived both
the name of the test they depend on and the file they verify from one
loop variable, but the producing tests and their output files used
different suffixes: the tests are named after the full variant
(_2frames_per_plane, _shared_plane_position) while the files were
abbreviated (_2frames, _shared). Two of the three TEST_DEPENDS therefore
named tests that do not exist. CTest ignores an unknown DEPENDS silently,
so nothing failed - but under ctest -j the dciodvfy test could run before
the conversion that writes its input.

This stayed invisible because CI had no dciodvfy until #559/#561, which
install dicom3tools from PyPI on all platforms; the tests are created and
run there now.

Name the output files after the variants as well, so a single identifier
drives the test name, the file and the dependency.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0