From 383d15e0a673350fd33070448a6d3470498d9e3b Mon Sep 17 00:00:00 2001 From: Irfan Alibay Date: Wed, 2 Dec 2020 18:56:39 +0000 Subject: [PATCH] Adds basic GH Actions CI workflow (#3040) Fixes #3036 ## Work done in this PR - Adds a continuous integration workflow based on github actions. - Disables previous continuous integration workflow based on TravisCI. - Fixes minor Visibledeprecation warnings with the hole2 tests. --- .travis.yml => .disabled-travis.yml | 0 .github/workflows/gh-ci.yaml | 281 ++++++++++++++++++ maintainer/install_hole.sh | 115 ------- .../MDAnalysisTests/analysis/test_hole2.py | 6 +- 4 files changed, 284 insertions(+), 118 deletions(-) rename .travis.yml => .disabled-travis.yml (100%) create mode 100644 .github/workflows/gh-ci.yaml delete mode 100755 maintainer/install_hole.sh diff --git a/.travis.yml b/.disabled-travis.yml similarity index 100% rename from .travis.yml rename to .disabled-travis.yml diff --git a/.github/workflows/gh-ci.yaml b/.github/workflows/gh-ci.yaml new file mode 100644 index 00000000000..a9fee810031 --- /dev/null +++ b/.github/workflows/gh-ci.yaml @@ -0,0 +1,281 @@ +name: mda_gh_ci +on: + push: + branches: + - develop + - master + pull_request: + branches: + - develop + - master + +defaults: + run: + shell: bash -l {0} + +env: + MDA_CONDA_MIN_DEPS: "pip pytest mmtf-python biopython networkx cython matplotlib scipy griddataformats hypothesis gsd codecov" + MDA_CONDA_EXTRA_DEPS: "seaborn>=0.7.0 clustalw=2.1 netcdf4 scikit-learn joblib>=0.12 chemfiles tqdm>=4.43.0 tidynamics>=1.0.0 rdkit>=2020.03.1 h5py==2.10.0" + MDA_PIP_MIN_DEPS: 'coveralls coverage<5 pytest-cov pytest-xdist' + MDA_PIP_EXTRA_DEPS: 'duecredit parmed' + +jobs: + main_tests: + if: "github.repository == 'MDAnalysis/mdanalysis'" + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, ] + python-version: [3.6, 3.7, 3.8] + run_type: [FULL, ] + install_hole: [true, ] + codecov: [true, ] + include: + - name: macOS + os: macOS-latest + python-version: 3.7 + run_type: FULL + install_hole: true + codecov: true + - name: minimal-ubuntu + os: ubuntu-latest + python-version: 3.6 + run_type: MIN + install_hole: false + codecov: true + - name: numpy_min + os: ubuntu-latest + python-version: 3.6 + run_type: FULL + install_hole: false + codecov: false + numpy: numpy=1.16.0 + - name: asv_check + os: ubuntu-latest + python-version: 3.7 + run_type: FULL + install_hole: false + codecov: false + env: + CYTHON_TRACE_NOGIL: 1 + MPLBACKEND: agg + GH_OS: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v2 + + - name: setup_osx + if: startsWith(matrix.os, 'macOS') + run: | + # Set OS specific vars and compiler flags + echo "OS_NAME=osx" >> $GITHUB_ENV + # TODO: work out why this is necessary (from CI helpers) + echo "MACOSX_DEPLOYMENT_TARGET=10.9" >> $GITHUB_ENV + ulimit -S -n 2048 + clang -v + echo "CC=clang" >> $GITHUB_ENV + clang++ -v + echo "CXX=clang++" >> $GITHUB_ENV + gfortran-9 -v + echo "FC=gfortran-9" >> $GITHUB_ENV + + - name: setup_linux + if: startsWith(matrix.os, 'ubuntu') + run: | + # Set OS specific vars and compiler flags + echo "OS_NAME=linux" >> $GITHUB_ENV + gcc -v + echo "CC=gcc" >> $GITHUB_ENV + g++ -v + echo "CXX=g++" >> $GITHUB_ENV + gfortran -v + echo "FC=gfortran" >> $GITHUB_ENV + + - name: setup_miniconda + uses: conda-incubator/setup-miniconda@v2 + with: + python-version: ${{ matrix.python-version }} + auto-update-conda: true + channel-priority: flexible + channels: biobuilds, conda-forge + add-pip-as-python-dependency: true + # TODO: mamba causes pip to segfault, switch when fixed + #mamba-version: "*" + architecture: x64 + + - name: install_deps + env: + MDA_CONDA_FULL_DEPS: "${{ env.MDA_CONDA_MIN_DEPS }} ${{ env.MDA_CONDA_EXTRA_DEPS }}" + MDA_PIP_FULL_DEPS: "${{ env.MDA_PIP_MIN_DEPS }} ${{ env.MDA_PIP_EXTRA_DEPS }}" + run: | + # NOTE: vars need to be re-assigned + # NOTE: set matrix.numpy to pin to a specific numpy version + conda_deps="${{ matrix.numpy }} ${MDA_CONDA_${{ matrix.run_type }}_DEPS}" + pip_deps=${MDA_PIP_${{ matrix.run_type }}_DEPS} + conda install ${conda_deps} + pip install ${pip_deps} + + # also install asv if required + if [ ${{ matrix.name }} = "asv_check" ]; then + pip install asv + fi + + - name: check_setup + run: | + # Check OS and python setup + echo "OS: ${OS_NAME}" + which python + which pip + pip list + conda info + conda list + + - name: install_hole + if : matrix.install_hole + run: | + # We manually build hole2 to avoid OS incompatibilities + git clone https://github.com/MDAnalysis/hole2.git + cd hole2/src + source ../source.apache + (make FC=${FC}) && (make PREFIX=${HOME}/hole2 FC=${FC} install) + source ../source.unset + echo "HOLE_BINDIR=${HOME}/hole2/bin" >> $GITHUB_ENV + echo "${HOME}/hole2/bin" >> $GITHUB_PATH + + - name: install_mda + run: | + # TODO: using install instead of develop here causes coverage to drop + # for .pyx file. If possible a solution for this should be found. + (cd package/ && python setup.py develop) && (cd testsuite/ && python setup.py install) + + - name: run_tests + if: contains(matrix.name, 'asv_check') != true + run: | + PYTEST_FLAGS="--disable-pytest-warnings --durations=50" + if [ ${{ matrix.codecov }} = "true" ]; then + PYTEST_FLAGS="${PYTEST_FLAGS} --cov=MDAnalysis --cov-report=xml" + fi + echo $PYTEST_FLAGS + pytest -n 2 testsuite/MDAnalysisTests $PYTEST_FLAGS + + - name: run_asv + if: contains(matrix.name, 'asv_check') + run: | + cd benchmarks + time python -m asv check -E existing + + - name: codecov + if: matrix.codecov + uses: codecov/codecov-action@v1 + with: + file: coverage.xml + fail_ci_if_error: True + verbose: True + + + build_docs: + if: "github.repository == 'MDAnalysis/mdanalysis'" + runs-on: ubuntu-latest + env: + CYTHON_TRACE_NOGIL: 1 + MPLBACKEND: agg + + steps: + - uses: actions/checkout@v2 + + - name: setup_miniconda + uses: conda-incubator/setup-miniconda@v2 + with: + python-version: 3.7 + auto-update-conda: true + channel-priority: flexible + channels: biobuilds, conda-forge + add-pip-as-python-dependency: true + architecture: x64 + + - name: install_deps + run: | + conda_deps="${{ env.MDA_CONDA_MIN_DEPS }} ${{ env.MDA_CONDA_EXTRA_DEPS}}" + pip_deps="${{ env.MDA_PIP_MIN_DEPS}} ${{ env.MDA_PIP_EXTRA_DEPS }} sphinx==1.8.5 sphinx-sitemap sphinx_rtd_theme msmb_theme==1.2.0" + conda install ${conda_deps} + pip install ${pip_deps} + + - name: install_mda + run: | + cd package && python setup.py develop + + - name: build_docs + run: | + cd package && python setup.py build_sphinx -E + + - name: deploy_docs + if: github.event_name != 'pull_request' + run: | + # place the deploy call here + echo "Oh, maple syrup roast parsnips [Richard Gowers]" + + + pylint_check: + if: "github.repository == 'MDAnalysis/mdanalysis'" + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: setup_miniconda + uses: conda-incubator/setup-miniconda@v2 + with: + python-version: 3.7 + auto-update-conda: true + channel-priority: flexible + channels: conda-forge + add-pip-as-python-dependency: true + mamba-version: "*" + architecture: x64 + + - name: install + run: | + which pip + which python + pip install pylint + + - name: pylint + env: + PYLINTRC: package/.pylintrc + run: | + pylint --py3k package/MDAnalysis && pylint --py3k testsuite/MDAnalysisTests + + + pypi_check: + if: "github.repository == 'MDAnalysis/mdanalysis'" + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: setup_miniconda + uses: conda-incubator/setup-miniconda@v2 + with: + python-version: 3.7 + auto-update-conda: true + channel-priority: flexible + channels: conda-forge + add-pip-as-python-dependency: true + mamba-version: "*" + architecture: x64 + + - name: install_conda + run: | + conda install setuptools cython numpy twine + + - name: install_mdanalysis + run: | + cd package && python setup.py sdist + + - name: check_package_build + run: | + DISTRIBUTION=$(ls -t1 package/dist/MDAnalysis-*.tar.gz | head -n 1) + test -n "${DISTRIBUTION}" || { echo "no distribution package/dist/MDAnalysis-*.tar.gz found"; exit 1; } + echo "twine check $DISTRIBUTION" + twine check $DISTRIBUTION diff --git a/maintainer/install_hole.sh b/maintainer/install_hole.sh deleted file mode 100755 index 8e2046ae310..00000000000 --- a/maintainer/install_hole.sh +++ /dev/null @@ -1,115 +0,0 @@ -#!/bin/bash -# -# Written by Oliver Beckstein, 2016 -# -# This script is placed into the Public Domain using the CC0 1.0 Public Domain -# Dedication https://creativecommons.org/publicdomain/zero/1.0/ -# -# -# NOTE: IF YOU RUN THIS SCRIPT YOU MUST BE ABLE TO COMPLY WITH THE HOLE -# NOT-FOR-PROFIT LICENSE. -# -# -# Install HOLE from http://www.holeprogram.org/ -# -# arguments -# OSNAME : linux | darwin -# PREFIX : "path/to/installdir" -# -# PREFIX can be relative to CWD or an absolute path; it will be created -# and HOLE unpacked under PREFIX (the tar file contains "hole2/...") -# -# -# HOLE v2.2004 is used under the terms of the 'HOLE END USER LICENCE AGREEMENT -# NOT-FOR-PROFIT VERSION' as provided in the installation tarball as file -# 'doc/Licence-not-for-profit.asciidoc' and see copy at -# https://github.com/MDAnalysis/mdanalysis/files/372246/Licence-not-for-profit.txt -# (recent as of 2016-07-19). -# - - -set -o errexit -o nounset - -SCRIPT=$(basename $0) - -# We still use the 2.2004 versions (academic only) because -# for the v2.2005 (Apache license) there are no pre-compiled binaries -# available at http://www.holeprogram.org/ as of 2018-02-22 - -# could switch to http://www.holeprogram.org/downloads/2.2.004/hole2-NotForProfit-2.2.004-Linux-i686.tar.gz -DOWNLOAD_URL_LINUX='https://www.holeprogram.org/downloads/2.2.004/hole2-NotForProfit-2.2.004-Linux-x86_64.tar.gz' -TARFILE_LINUX='hole2-NotForProfit-2.2.004-Linux-x86_64.tar.gz' - -# could switch to http://www.holeprogram.org/downloads/2.2.004/hole2-NotForProfit-2.2.004-Darwin-i386.tar.gz -DOWNLOAD_URL_DARWIN='https://www.holeprogram.org/downloads/2.2.004/hole2-NotForProfit-2.2.004-Darwin-i386.tar.gz' -TARFILE_DARWIN=hole2-NotForProfit-2.2.004-Darwin-i386.tar.gz - -# path to dir with executables in the current HOLE distribution -HOLE_EXE_DIR=hole2/exe - -function die () { - local msg="$1" err=$2 - echo "[${SCRIPT}] ERROR: $msg [$err]" - exit $err -} - -function is_native_executable () { - local filename="$1" OSNAME="$2" - file "${filename}" | grep -qi ${OFORMAT} - return $? -} - -OSNAME="$1" -case "$OSNAME" in - Linux|linux) - OSNAME=Linux - OFORMAT=Linux - DOWNLOAD_URL="${DOWNLOAD_URL_LINUX}" - TARFILE=${TARFILE_LINUX} - ;; - OSX|osx|Darwin|darwin) - OSNAME=Darwin - OFORMAT="Mach-O" - DOWNLOAD_URL="${DOWNLOAD_URL_DARWIN}" - TARFILE=${TARFILE_DARWIN} - ;; - *) - die "OS '${OSNAME}' not supported." 10;; -esac - -PREFIX="$2" -test -n "$PREFIX" || die "missing second argument PREFIX (installation directory)" 10 - -#------------------------------------------------------------ -# start installation -#------------------------------------------------------------ - -mkdir -p "$PREFIX" && cd "$PREFIX" || die "Failed to create and cd to $PREFIX" 1 -if ! test -f ${TARFILE}; then - echo "Downloading ${TARFILE} from ${DOWNLOAD_URL}..." - # fixing curl on travis/anaconda, see http://stackoverflow.com/a/31060428/334357 - export CURL_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt - curl -L ${DOWNLOAD_URL} -o ${TARFILE} || \ - die "Failed to download ${TARFILE} from ${DOWNLOAD_URL}" 1 -fi - -# only install the executables in HOLE_EXE_DIR -tar xvf ${TARFILE} ${HOLE_EXE_DIR} || die "Failed 'tar xvf ${TARFILE} ${HOLE_EXE_DIR}'" 1 - -MDA_HOLE_BINDIR="${PWD}/${HOLE_EXE_DIR}" -HOLE_EXE="${MDA_HOLE_BINDIR}/hole" - -test -d "${MDA_HOLE_BINDIR}" || { \ - echo "Content of ${PWD}:"; - ls -la; - die "no HOLE exe dir ${MDA_HOLE_BINDIR} in $PWD" 2; } -test -f "${HOLE_EXE}" || die "hole executable ${HOLE_EXE} not installed" 2 -is_native_executable ${HOLE_EXE} ${OFORMAT} || \ - { file ${HOLE_EXE}; \ - die "${HOLE_EXE} will not run on ${OSNAME} (object format ${OFORMAT})" 3; } - -echo "HOLE executables were installed into ${MDA_HOLE_BINDIR}" -echo ">>> export PATH=\${PATH}:${MDA_HOLE_BINDIR}" - -# repeat this line in .travis.yml -export PATH=${PATH}:${MDA_HOLE_BINDIR} diff --git a/testsuite/MDAnalysisTests/analysis/test_hole2.py b/testsuite/MDAnalysisTests/analysis/test_hole2.py index 700827f027f..580b28485aa 100644 --- a/testsuite/MDAnalysisTests/analysis/test_hole2.py +++ b/testsuite/MDAnalysisTests/analysis/test_hole2.py @@ -488,7 +488,7 @@ def test_over_order_parameters(self, hole): assert key == rmsd idx = np.argsort(op) - arr = np.array(list(hole.profiles.values())) + arr = np.array(list(hole.profiles.values()), dtype=object) for op_prof, arr_prof in zip(profiles.values(), arr[idx]): assert op_prof is arr_prof @@ -504,7 +504,7 @@ def test_over_order_parameters_file(self, hole, tmpdir): assert key == rmsd idx = np.argsort(op) - arr = np.array(list(hole.profiles.values())) + arr = np.array(list(hole.profiles.values()), dtype=object) for op_prof, arr_prof in zip(profiles.values(), arr[idx]): assert op_prof is arr_prof @@ -528,7 +528,7 @@ def test_over_order_parameters_frames(self, hole): idx = np.argsort(op[:n_frames]) values = list(hole.profiles.values())[:n_frames] - arr = np.array(values) + arr = np.array(values, dtype=object) for op_prof, arr_prof in zip(profiles.values(), arr[idx]): assert op_prof is arr_prof