Skip to content

Add in-memory handler overload of itkimage2dcmSegmentation. #263

Add in-memory handler overload of itkimage2dcmSegmentation.

Add in-memory handler overload of itkimage2dcmSegmentation. #263

Workflow file for this run

name: C/C++ CI macOS
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
release:
types: [ published ]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-macos:
runs-on: ${{ matrix.runner }}
# So far, a full superbuild (no caches) has always been complete in < 45 minutes.
timeout-minutes: 45
permissions:
contents: write
actions: write
packages: write
strategy:
matrix:
include:
- arch: x86_64
runner: macos-15-intel
cmake_arch: x86_64
- arch: arm64
runner: macos-15
cmake_arch: arm64
# Checkout and install python
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: '3.10.11'
# Install build tools (cmake and ninja) as well as jsondiff
- name: "Install jsondiff"
run: pip install jsondiff
- name: "Install cmake"
run: |
cmake --version
echo ${PATH}
wget --no-check-certificate https://github.com/ninja-build/ninja/releases/download/v1.12.1/ninja-mac.zip
unzip ninja-mac.zip && sudo cp ninja /usr/local/bin/
# Make sure all directories required for computing the hash actually exist
- name: "Prepare cache directories"
run: |
mkdir -p ${{ github.workspace }}/dcmqi-build/DCMTK-build
mkdir -p ${{ github.workspace }}/dcmqi-build/DCMTK
mkdir -p ${{ github.workspace }}/dcmqi-build/ITK
mkdir -p ${{ github.workspace }}/dcmqi-build/ITK-build
mkdir -p ${{ github.workspace }}/dcmqi-build/zlib-install
# Prepare the cache directories, which are DCMTK/ITK source and build directories
# since dcmqi build later requires DCMTK/ITK headers from source, and libraries from
# build directories. For ZLIB, installation directory is sufficient since it contains
# both, headers and libraries.
- name: Check for cached DCMTK, ITK and ZLIB
id: cache-dcmtk-itk-zlib
uses: actions/cache/restore@v4
env:
cache-name: cache-dcmtk-itk-zlib
with:
# The recursive content of these directories goes into the cache
path: |
${{ github.workspace }}/dcmqi-build/DCMTK
${{ github.workspace }}/dcmqi-build/DCMTK-build
${{ github.workspace }}/dcmqi-build/ITK
${{ github.workspace }}/dcmqi-build/ITK-build
${{ github.workspace }}/dcmqi-build/zlib-install
# The hash key decides whether cache entry is out of date or can be used.
# We use the hash of the CMakeExternals files to decide whether
# we must rebuild it. Also a change in the OS will trigger cash rebuild.
# A hashkey will have the form of macOS-<arch>-build-cache-dcmtk-itk-<hash>
key: ${{ runner.os }}-${{ matrix.arch }}-build-${{ env.cache-name }}-${{ hashFiles('CMakeExternals/DCMTK.cmake','CMakeExternals/ITK.cmake', 'CMakeExternals/zlib.cmake') }}
# Below is the key pattern that defines, which cache entries stored on the
# GitHub repository will match our key. We simply use the name of OS, architecture and
# name of the cache, i.e. every cache entry with key pattern
# macOS-<arch>-build-cache-dcmtk-itk-<hash> will match.
restore-keys: |
${{ runner.os }}-${{ matrix.arch }}-build-${{ env.cache-name }}-
# Report cache status for monitoring
- name: Report cache status
run: |
if [ "${{ steps.cache-dcmtk-itk-zlib.outputs.cache-hit }}" == "true" ]; then
echo "✓ Cache hit! Using cached DCMTK, ITK, and zlib"
echo "Cache key: ${{ steps.cache-dcmtk-itk-zlib.outputs.cache-primary-key }}"
du -sh ${{ github.workspace }}/dcmqi-build/DCMTK* ${{ github.workspace }}/dcmqi-build/ITK* ${{ github.workspace }}/dcmqi-build/zlib-install 2>/dev/null || true
else
echo "✗ Cache miss. Will build DCMTK, ITK, and zlib from source"
fi
# This is step executed if a cache entry is found
- name: "Configure dcmqi w/ cached DCMTK/ITK/ZLIB"
if: ${{ steps.cache-dcmtk-itk-zlib.outputs.cache-hit == 'true' }}
# Make sure to set ITK, DCMTK and ZLIB directories to dcmqi cmake configuration step
run: |
cd ${{ github.workspace }}/dcmqi-build && cmake -G Ninja ${{ github.workspace }} -DDCMTK_DIR=${{ github.workspace }}/dcmqi-build/DCMTK-build -DITK_DIR=${{ github.workspace }}/dcmqi-build/ITK-build -DZLIB_ROOT=${{ github.workspace }}/dcmqi-build/zlib-install
# If we don't have a matching cache entry, configure for full rebuild (regular dcmqi superbuild)
- name: "Configure dcmqi w/o cached DCMTK/ITK/ZLIB"
if: ${{ steps.cache-dcmtk-itk-zlib.outputs.cache-hit != 'true' }}
run: |
cd ${{ github.workspace }}/dcmqi-build && cmake -G Ninja ${{ github.workspace }}
# Build dcmqi
- name: "Build dcmqi"
run: |
cd ${{ github.workspace }}/dcmqi-build && ninja
- name: "Test dcmqi"
run: |
cd ${{ github.workspace }}/dcmqi-build/dcmqi-build
ctest -VV -DCTEST_MODEL=$CTEST_MODEL -DCTEST_EMPTY_BINARY_DIRECTORY=FALSE .
# ...and finally package it.
- name: "Package dcmqi"
run: |
cd ${{ github.workspace }}/dcmqi-build/dcmqi-build && ninja package
- name: "Upload package as artifact"
id: upload-artifact
uses: actions/upload-artifact@v4
continue-on-error: true
with:
name: dcmqi-macos-${{ matrix.arch }}-package
# Example:
# /Users/runner/work/dcmqi/dcmqi/dcmqi-build/dcmqi-build/dcmqi-1.4.0-mac-20260104-9b9b2be.tar.gz
path: ${{ github.workspace }}/dcmqi-build/dcmqi-build/dcmqi-*-mac*.tar.gz
- name: "Upload package as artifact (retry)"
if: steps.upload-artifact.outcome == 'failure'
uses: actions/upload-artifact@v4
with:
name: dcmqi-macos-${{ matrix.arch }}-package
path: ${{ github.workspace }}/dcmqi-build/dcmqi-build/dcmqi-*-mac*.tar.gz
# Save cache even if a later step (test, package) failed, so deps don't need rebuilding next run
- name: Save DCMTK, ITK and ZLIB cache
if: always() && steps.cache-dcmtk-itk-zlib.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: |
${{ github.workspace }}/dcmqi-build/DCMTK
${{ github.workspace }}/dcmqi-build/DCMTK-build
${{ github.workspace }}/dcmqi-build/ITK
${{ github.workspace }}/dcmqi-build/ITK-build
${{ github.workspace }}/dcmqi-build/zlib-install
key: ${{ steps.cache-dcmtk-itk-zlib.outputs.cache-primary-key }}
- name: Publish package
# Only run if the event is not a pull request and the repository owner is QIICR.
# The latter is to prevent forks from publishing packages even if the owner's token
# would have sufficient privileges.
if: ${{ (github.event_name != 'pull_request') && (github.repository_owner == 'QIICR')}}
env:
GH_TOKEN: ${{ secrets.GA_TOKEN }}
run: |
TAG=$(git describe --tags --exact-match 2>/dev/null || echo "")
if [ -n "$TAG" ]; then
gh release upload "$TAG" \
${{ github.workspace }}/dcmqi-build/dcmqi-build/dcmqi-*-mac-${{ matrix.arch }}.tar.gz \
--clobber
else
# Clean old prerelease assets for this architecture, then upload new ones
gh release view latest --json assets --jq '.assets[].name' 2>/dev/null \
| grep "dcmqi-.*-mac-${{ matrix.arch }}-" \
| xargs -I{} gh release delete-asset latest "{}" --yes || true
gh release upload latest \
${{ github.workspace }}/dcmqi-build/dcmqi-build/dcmqi-*-mac*.tar.gz \
--clobber
gh release edit latest --target $(git rev-parse HEAD)
fi