diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000000..82676ee28c --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,89 @@ +name: Stable tests + +# This file tests the claimed support range of nipype including +# +# * Operating systems: Linux, OSX +# * Dependencies: minimum requirements, optional requirements +# * Installation methods: setup.py, sdist, wheel, archive + +on: + push: + branches: + - master + - maint/* + pull_request: + branches: + - master + - maint/* + +defaults: + run: + shell: bash + +jobs: + stable: + # Check each OS, all supported Python, minimum versions and latest releases + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: ['ubuntu-18.04'] + python-version: [3.6, 3.7, 3.8, 3.9] + check: ['test'] + pip-flags: [''] + depends: ['REQUIREMENTS'] + deb-depends: [false] + nipype-extras: ['doc,tests,profiler'] + include: + - os: ubuntu-18.04 + python-version: 3.8 + check: test + pip-flags: '' + depends: REQUIREMENTS + deb-depends: true + nipype-extras: doc,tests,nipy,profiler,duecredit,ssh + env: + DEPENDS: ${{ matrix.depends }} + CHECK_TYPE: ${{ matrix.check }} + EXTRA_PIP_FLAGS: ${{ matrix.pip-flags }} + INSTALL_DEB_DEPENDENCIES: ${{ matrix.deb-depends }} + NIPYPE_EXTRAS: ${{ matrix.nipype-extras }} + INSTALL_TYPE: pip + CI_SKIP_TEST: 1 + + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + fetch-depth: 0 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Display Python version + run: python -c "import sys; print(sys.version)" + - name: Create virtual environment + run: tools/ci/create_venv.sh + - name: Build archive + run: | + source tools/ci/build_archive.sh + echo "ARCHIVE=$ARCHIVE" >> $GITHUB_ENV + - name: Install Debian dependencies + run: tools/ci/install_deb_dependencies.sh + if: ${{ matrix.os == 'ubuntu-18.04' }} + - name: Install dependencies + run: tools/ci/install_dependencies.sh + - name: Install Nipype + run: tools/ci/install.sh + - name: Run tests + run: tools/ci/check.sh + if: ${{ matrix.check != 'skiptests' }} + - uses: codecov/codecov-action@v1 + with: + file: coverage.xml + if: ${{ always() }} + - name: Upload pytest test results + uses: actions/upload-artifact@v2 + with: + name: pytest-results-${{ matrix.os }}-${{ matrix.python-version }} + path: test-results.xml + if: ${{ always() && matrix.check == 'test' }} diff --git a/tools/ci/activate.sh b/tools/ci/activate.sh new file mode 100644 index 0000000000..567e13a67b --- /dev/null +++ b/tools/ci/activate.sh @@ -0,0 +1,9 @@ +if [ -e virtenv/bin/activate ]; then + source virtenv/bin/activate +elif [ -e virtenv/Scripts/activate ]; then + source virtenv/Scripts/activate +else + echo Cannot activate virtual environment + ls -R virtenv + false +fi diff --git a/tools/ci/build_archive.sh b/tools/ci/build_archive.sh new file mode 100755 index 0000000000..484ed19f6b --- /dev/null +++ b/tools/ci/build_archive.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +echo "Building archive" + +source tools/ci/activate.sh + +set -eu + +# Required dependencies +echo "INSTALL_TYPE = $INSTALL_TYPE" + +set -x + +if [ "$INSTALL_TYPE" == "sdist" ]; then + python setup.py egg_info # check egg_info while we're here + python setup.py sdist + export ARCHIVE=$( ls dist/*.tar.gz ) +elif [ "$INSTALL_TYPE" == "wheel" ]; then + python setup.py bdist_wheel + export ARCHIVE=$( ls dist/*.whl ) +elif [ "$INSTALL_TYPE" == "archive" ]; then + export ARCHIVE="package.tar.gz" + git archive -o $ARCHIVE HEAD +elif [ "$INSTALL_TYPE" == "pip" ]; then + export ARCHIVE="." +fi + +set +eux diff --git a/tools/ci/check.sh b/tools/ci/check.sh new file mode 100755 index 0000000000..d180752524 --- /dev/null +++ b/tools/ci/check.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +echo Running tests + +source tools/ci/activate.sh +source tools/ci/env.sh + +set -eu + +# Required variables +echo CHECK_TYPE = $CHECK_TYPE + +set -x + +if [ "${CHECK_TYPE}" == "test" ]; then + pytest --capture=no --verbose --doctest-modules -c nipype/pytest.ini \ + --cov-config .coveragerc --cov nipype --cov-report xml \ + --junitxml=test-results.xml nipype +else + false +fi + +set +eux + +echo Done running tests diff --git a/tools/ci/create_venv.sh b/tools/ci/create_venv.sh new file mode 100755 index 0000000000..7a28767396 --- /dev/null +++ b/tools/ci/create_venv.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +echo Creating isolated virtual environment + +source tools/ci/env.sh + +set -eu + +# Required variables +echo SETUP_REQUIRES = $SETUP_REQUIRES + +set -x + +python -m pip install --upgrade pip virtualenv +virtualenv --python=python virtenv +source tools/ci/activate.sh +python --version +python -m pip install -U $SETUP_REQUIRES +which python +which pip + +set +eux + +echo Done creating isolated virtual environment diff --git a/tools/ci/env.sh b/tools/ci/env.sh new file mode 100644 index 0000000000..87e766b8c2 --- /dev/null +++ b/tools/ci/env.sh @@ -0,0 +1,17 @@ +SETUP_REQUIRES="pip setuptools>=30.3.0 wheel" + +# Minimum requirements +REQUIREMENTS="-r requirements.txt" +# Minimum versions of minimum requirements +MIN_REQUIREMENTS="-r min-requirements.txt" + +# Numpy and scipy upload nightly/weekly/intermittent wheels +NIGHTLY_WHEELS="https://pypi.anaconda.org/scipy-wheels-nightly/simple" +STAGING_WHEELS="https://pypi.anaconda.org/multibuild-wheels-staging/simple" +PRE_PIP_FLAGS="--pre --extra-index-url $NIGHTLY_WHEELS --extra-index-url $STAGING_WHEELS" + +for CONF in (/etc/fsl/fsl.sh /etc/afni/afni.sh); do + if [ -r $CONF ]; then source $CONF; fi +done + +FSLOUTPUTTYPE=NIFTI_GZ diff --git a/tools/ci/install.sh b/tools/ci/install.sh new file mode 100755 index 0000000000..428ffc8b8c --- /dev/null +++ b/tools/ci/install.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +echo Installing nipype + +source tools/ci/activate.sh +source tools/ci/env.sh + +set -eu + +# Required variables +echo INSTALL_TYPE = $INSTALL_TYPE +echo CHECK_TYPE = $CHECK_TYPE +echo NIPYPE_EXTRAS = $NIPYPE_EXTRAS +echo EXTRA_PIP_FLAGS = $EXTRA_PIP_FLAGS + +set -x + +if [ -n "$EXTRA_PIP_FLAGS" ]; then + EXTRA_PIP_FLAGS=${!EXTRA_PIP_FLAGS} +fi + +if [ "$INSTALL_TYPE" == "setup" ]; then + python setup.py install +else + pip install $EXTRA_PIP_FLAGS $ARCHIVE +fi + +# Basic import check +python -c 'import nipype; print(nipype.__version__)' + +if [ "$CHECK_TYPE" == "skiptests" ]; then + exit 0 +fi + +pip install $EXTRA_PIP_FLAGS "nipype[$NIPYPE_EXTRAS]" + +set +eux + +echo Done installing nipype diff --git a/tools/ci/install_deb_dependencies.sh b/tools/ci/install_deb_dependencies.sh new file mode 100755 index 0000000000..ff1e67732b --- /dev/null +++ b/tools/ci/install_deb_dependencies.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +echo "Installing NeuroDebian dependencies" + +set -eu + +echo "INSTALL_DEB_DEPENDENCIES = $INSTALL_DEB_DEPENDENCIES" + +if $INSTALL_DEB_DEPENDENCIES; then + bash <(wget -q -O- http://neuro.debian.net/_files/neurodebian-travis.sh) + sudo apt update + sudo apt install -y -qq fsl afni elastix fsl-atlases xvfb fusefat graphviz +fi diff --git a/tools/ci/install_dependencies.sh b/tools/ci/install_dependencies.sh new file mode 100755 index 0000000000..617389cb5e --- /dev/null +++ b/tools/ci/install_dependencies.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +echo Installing dependencies + +source tools/ci/activate.sh +source tools/ci/env.sh + +set -eu + +# Required variables +echo EXTRA_PIP_FLAGS = $EXTRA_PIP_FLAGS +echo DEPENDS = $DEPENDS + +set -x + +if [ -n "$EXTRA_PIP_FLAGS" ]; then + EXTRA_PIP_FLAGS=${!EXTRA_PIP_FLAGS} +fi + +if [ -n "$DEPENDS" ]; then + pip install ${EXTRA_PIP_FLAGS} --prefer-binary ${!DEPENDS} +fi + +set +eux + +echo Done installing dependencies