diff --git a/.github/workflows/ci-pytest.yml b/.github/workflows/ci-pytest.yml new file mode 100644 index 00000000..de5a57ab --- /dev/null +++ b/.github/workflows/ci-pytest.yml @@ -0,0 +1,104 @@ +name: ci-pytest + +# Fast tests with cached antspy build designed to test changes in the python code +# Builds on Linux only, with a single python version + +on: + push: + branches: + - master + pull_request: + branches: + - master + workflow_dispatch: + +env: + # Updates or changes to this, or the runner OS or arch will invalidate the cache + python_version: '3.10' # Python version to use for testing - update when needed + +jobs: + test: + runs-on: ubuntu-20.04 + # Default shell needs to be bash for conda + # https://github.com/conda-incubator/setup-miniconda?tab=readme-ov-file#important + defaults: + run: + shell: bash -el {0} + steps: + - name: Setup Miniconda + uses: conda-incubator/setup-miniconda@030178870c779d9e5e1b4e563269f3aa69b04081 # v3.0.3, devs recommend using hash + with: + miniconda-version: "latest" + python-version: ${{ env.python_version }} + auto-update-conda: true + activate-environment: "test-env" + + - name: Configure Conda to use only .tar.bz2 + run: | + conda config --set use_only_tar_bz2 true + + - name: Checkout code + uses: actions/checkout@v4 # Checkout PR code to 'antspy-pr' + with: + path: antspy-pr + + - name: Load conda environment from cache if available + id: cache-env + uses: actions/cache@v4 + with: + path: ~/conda-env.tar.bz2 + key: >- + ${{ runner.os }}-conda-${{ env.python_version }}- + ${{ hashFiles('antspy-pr/ants/environment.yml', 'antspy-pr/ants/requirements.txt', 'antspy-pr/ants/setup.py', + 'antspy-pr/ants/scripts/configure_ITK.sh', 'antspy-pr/ants/scripts/configure_ANTsPy.sh', + 'antspy-pr/ants/lib/*') }} + + - name: Unpack cached environment + if: steps.cache-env.outputs.cache-hit == 'true' + run: | + mkdir -p ${CONDA}/envs/antspy-env + tar -xjf ~/conda-env.tar.bz2 -C ${CONDA}/envs/antspy-env + conda activate antspy-env + conda-unpack + + - name: Install dependencies and ANTsPy from PR + if: steps.cache-env.outputs.cache-hit != 'true' + run: | + conda create -n antspy-env python=${{ env.python_version }} -y + conda activate antspy-env + conda install -c conda-forge conda-pack + conda info + pip install ./antspy-pr + conda list + antspy-pr/tests/run_tests.sh + conda pack -n antspy-env -o ~/conda-env.tar.bz2 + + - name: Cache Conda environment + if: steps.cache-env.outputs.cache-hit != 'true' + uses: actions/cache@v4 + with: + path: ~/conda-env.tar.bz2 + key: >- + ${{ runner.os }}-conda-${{ env.python_version }}- + ${{ hashFiles('antspy-pr/ants/environment.yml', 'antspy-pr/ants/requirements.txt', 'antspy-pr/ants/setup.py', + 'antspy-pr/ants/scripts/configure_ITK.sh', 'antspy-pr/ants/scripts/configure_ANTsPy.sh', + 'antspy-pr/ants/lib/*') }}) }} + + - name: Replace installed ANTsPy with PR code + if: steps.cache-env.outputs.cache-hit == 'true' + run: | + conda activate antspy-env + echo "List of installed packages in cached env:" + conda list + ANTS_SITE_PACKAGES="${CONDA}/envs/antspy-env/lib/python${{ env.python_version }}/site-packages/ants" + for d in contrib core learn registration segmentation utils viz; do + rm -rf $ANTS_SITE_PACKAGES/$d; + cp -r antspy-pr/ants/$d $ANTS_SITE_PACKAGES/$d; + done + find $ANTS_SITE_PACKAGES -name '__pycache__' -exec rm -rf {} + + + - name: Run tests + if: steps.cache-env.outputs.cache-hit == 'true' + run: | + conda activate antspy-env + bash antspy-pr/tests/run_tests.sh diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 8ba1cb8a..a1ef72a4 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -1,12 +1,8 @@ name: Build on: - push: - branches: - - master - pull_request: - branches: - - master + schedule: + - cron: "0 2 * * *" release: types: [created] workflow_dispatch: @@ -204,7 +200,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} - name: Publish prep - if: ${{ (github.event_name == 'push') && (runner.os == 'Linux') }} + if: ${{ (github.event_name == 'release') && (runner.os == 'Linux') }} run: | mywhl=`find ~/ -name "antspyx*.whl"` extrawheeldir=`dirname $mywhl` @@ -218,7 +214,7 @@ jobs: - name: Publish package uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 - if: ${{ (github.event_name == 'push') && (runner.os == 'Linux') }} + if: ${{ (github.event_name == 'release') && (runner.os == 'Linux') }} with: user: __token__ password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/wheels_faster.yml b/.github/workflows/wheels_faster.yml new file mode 100644 index 00000000..892d3081 --- /dev/null +++ b/.github/workflows/wheels_faster.yml @@ -0,0 +1,126 @@ +name: Cross-platform wheel test + +on: + push: + branches: + - master + workflow_dispatch: + +jobs: + build_wheels: + name: Build wheel for cp${{ matrix.cibw_python }}-${{ matrix.platform_id }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + # Have to specify python version twice so that the same python is used to build and test + # Need to quote decimal versions as string to avoid the "Norway problem" + + # Windows 64-bit + - os: windows-latest + python: '3.9' + cibw_python: 39 + platform_id: win_amd64 + + # Linux 64-bit + - os: ubuntu-latest + python: '3.9' + cibw_python: 39 + platform_id: manylinux_x86_64 + + # macOS on Intel 64-bit + - os: macos-12 + python: '3.9' + cibw_python: 39 + arch: x86_64 + platform_id: macosx_x86_64 + + # macOS on Apple M1 64-bit, supported for Python 3.10 and later + - os: macos-14 + python: '3.10' + cibw_python: 310 + arch: arm64 + platform_id: macosx_arm64 + + steps: + - uses: actions/checkout@v4 + with: + submodules: true + + - uses: actions/setup-python@v5 + name: Install Python host for cibuildwheel + with: + python-version: ${{ matrix.python }} + + # Visual Studio + - name: Set up MSVC x64 + if: matrix.platform_id == 'win_amd64' + uses: ilammy/msvc-dev-cmd@v1 + + - name: Install cibuildwheel + run: python -m pip install cibuildwheel==2.16.2 setuptools + + - name: Get package name and version (Linux / Mac) + if: ${{ ! startsWith(matrix.os, 'windows-') }} + run: | + echo PACKAGE_NAME=$( python setup.py --name ) >> $GITHUB_ENV + echo PACKAGE_VERSION=$( python setup.py --version ) >> $GITHUB_ENV + + # Some shells require "-Encoding utf8" to append to GITHUB_ENV + # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions?tool=powershell#environment-files + - name: Get package name and version (Windows) + if: startsWith(matrix.os, 'windows-') + run: | + echo "PACKAGE_NAME=$( python setup.py --name )" | Out-File -FilePath $env:GITHUB_ENV ` + -Append + echo "PACKAGE_VERSION=$( python setup.py --version )" | Out-File -FilePath $env:GITHUB_ENV ` + -Append + - name: Build wheels + env: + CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014 + CIBW_MANYLINUX_I686_IMAGE: manylinux2014 + CIBW_BUILD: cp${{ matrix.cibw_python }}-${{ matrix.platform_id }} + + # Include latest Python beta + CIBW_PRERELEASE_PYTHONS: True + + CIBW_BEFORE_ALL_LINUX: | + echo "Installing system dependencies with yum" + yum install -y gcc-c++ libpng-devel libpng + echo "pip installing cmake and ninja" + python -m pip install cmake ninja setuptools + + CIBW_BEFORE_ALL_WINDOWS: | + python -m pip install cmake ninja setuptools + + CIBW_ARCHS_MACOS: ${{ matrix.arch }} + CIBW_BEFORE_ALL_MACOS: | + python -m pip install cmake ninja setuptools + brew update + if ! brew list libpng &>/dev/null; then + HOMEBREW_NO_AUTO_UPDATE=1 brew install libpng + fi + + CIBW_ENVIRONMENT_MACOS: | + CMAKE_OSX_ARCHITECTURES=${{ matrix.arch }} CMAKE_PREFIX_PATH=/usr/local + + run: python -m cibuildwheel --output-dir wheelhouse/cp${{ matrix.cibw_python }}-${{matrix.platform_id }} + + - name: Install and test (Linux / Mac) + if: ${{ ! startsWith(matrix.os, 'windows-') }} + run: | + python -m pip install wheelhouse/cp${{ matrix.cibw_python }}-${{matrix.platform_id }}/*.whl + tests/run_tests.sh + + - name: Install and test (Windows) + if: startsWith(matrix.os, 'windows-') + run: | + python -m pip install --find-links=.\wheelhouse\cp${{ matrix.cibw_python }}-${{matrix.platform_id }} antspyx + tests\run_tests.ps1 + + - uses: actions/upload-artifact@v3 + with: + retention-days: 3 + name: ${{ env.PACKAGE_NAME }}-${{ env.PACKAGE_VERSION }}-cp${{ matrix.cibw_python }}-${{ matrix.platform_id }} + path: ./wheelhouse/cp${{ matrix.cibw_python }}-${{ matrix.platform_id }}/*.whl