Skip to content

Commit

Permalink
chore: Switch to tox for testing and CI (#900)
Browse files Browse the repository at this point in the history
* chore(deps): Update lower bounds so uv lowest-direct passes tests

* chore(tox): Adapt tox from fmriprep, use uv_resolution

* chore(ci): Switch to tox-gh-actions for testing

* Replace test workflow with tox

* chore: Pin pyyaml 5.4

* chore: Update pytest/coverage config

* ci: Add FORCE_COLOR to CI environment

* ci: Skip pre-release tests for 3.9/3.10
  • Loading branch information
effigies authored Nov 15, 2024
1 parent b898643 commit 5d9e666
Show file tree
Hide file tree
Showing 3 changed files with 216 additions and 191 deletions.
229 changes: 67 additions & 162 deletions .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Python package
name: Tox

on:
push:
Expand All @@ -13,42 +10,17 @@ on:
- cron: '0 0 * * *'

concurrency:
group: python-${{ github.ref }}
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
job_metadata:
if: github.repository == 'nipreps/niworkflows'
runs-on: ubuntu-latest
outputs:
commit_message: ${{ steps.get_commit_message.outputs.commit_message }}
version: ${{ steps.show_version.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Print head git commit message
id: get_commit_message
run: |
if [[ -z "$COMMIT_MSG" ]]; then
COMMIT_MSG=$(git show -s --format=%s $REF)
fi
echo commit_message=$COMMIT_MSG | tee -a $GITHUB_OUTPUT
env:
COMMIT_MSG: ${{ github.event.head_commit.message }}
REF: ${{ github.event.pull_request.head.sha }}
- name: Detect version
id: show_version
run: |
if [[ "$GITHUB_REF" == refs/tags/* ]]; then
VERSION=${GITHUB_REF##*/}
else
pipx run hatch version # Once to avoid output of initial setup
VERSION=$( pipx run hatch version )
fi
echo version=$VERSION | tee -a $GITHUB_OUTPUT
permissions:
contents: read

env:
# Force tox and pytest to use color
FORCE_COLOR: true

jobs:
build:
if: github.repository == 'nipreps/niworkflows'
runs-on: ubuntu-latest
Expand Down Expand Up @@ -118,140 +90,73 @@ jobs:
datalad get -J 2 -r ds000003 ds000030/sub-10228/func
test:
needs: [build, get_data, job_metadata]
needs: [get_data]
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]
install: [repo]
dependencies: [latest, pre]
include:
- python-version: "3.12"
install: sdist
- python-version: "3.12"
install: wheel
- python-version: "3.12"
install: editable

env:
INSTALL_TYPE: ${{ matrix.install }}

steps:
- uses: actions/checkout@v4
if: matrix.install == 'repo' || matrix.install == 'editable'
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Load test data cache
uses: actions/cache@v4
id: stanford-crn
with:
path: ~/.cache/stanford-crn/
key: data-v0-${{ github.ref_name }}-${{ github.sha }}
- name: Load TemplateFlow cache
uses: actions/cache@v4
id: templateflow
with:
path: ~/.cache/templateflow
key: templateflow-v0-${{ github.ref_name }}-${{ strategy.job-index }}-${{ github.sha }}
restore-keys: |
templateflow-v0-${{ github.ref_name }}-
templateflow-v0-
- name: Fetch packages
if: matrix.install == 'sdist' || matrix.install == 'wheel'
uses: actions/download-artifact@v3
with:
name: dist
path: dist/
- name: Select archive
run: |
if [ "$INSTALL_TYPE" = "sdist" ]; then
ARCHIVE=$( ls dist/*.tar.gz )
elif [ "$INSTALL_TYPE" = "wheel" ]; then
ARCHIVE=$( ls dist/*.whl )
elif [ "$INSTALL_TYPE" = "repo" ]; then
ARCHIVE="."
elif [ "$INSTALL_TYPE" = "editable" ]; then
ARCHIVE="-e ."
fi
echo "ARCHIVE=$ARCHIVE" | tee -a $GITHUB_ENV
- name: Install package
run: python -m pip install $ARCHIVE
- name: Check version
run: |
INSTALLED_VERSION=$(python -c 'import niworkflows; print(niworkflows.__version__, end="")')
echo "INSTALLED: \"${INSTALLED_VERSION}\""
test "${INSTALLED_VERSION}" = "${VERSION}"
env:
VERSION: ${{ needs.job_metadata.outputs.version }}
- name: Install test dependencies
run: python -m pip install "niworkflows[tests]"
- name: Run tests
run: pytest -sv --doctest-modules --cov niworkflows --pyargs niworkflows
- uses: codecov/codecov-action@v4
name: Submit to CodeCov
with:
token: ${{ secrets.CODECOV_TOKEN }}

test-pre:
needs: [get_data, job_metadata]
if: ${{ !contains(needs.job_metadata.outputs.commit_message, '[skip pre]') }}
runs-on: ubuntu-latest
strategy:
matrix:
# Only run --pre tests on Python versions within SPEC0 support
python-version: ["3.11", "3.12"]
install: [repo]
pip-flags: ['--pre']
- python-version: "3.9"
dependencies: min
exclude:
# Do not test pre-releases for versions out of SPEC0
- python-version: "3.9"
dependencies: pre
- python-version: "3.10"
dependencies: pre

env:
INSTALL_TYPE: ${{ matrix.install }}
PIP_FLAGS: ${{ matrix.pip-flags }}
DEPENDS: ${{ matrix.dependencies }}

steps:
- name: Debug commit message
run: echo "${{ needs.job_metadata.outputs.commit_message }}"
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Load test data cache
uses: actions/cache@v4
id: stanford-crn
with:
path: ~/.cache/stanford-crn/
key: data-v0-${{ github.ref_name }}-${{ github.sha }}
- name: Load TemplateFlow cache
uses: actions/cache@v4
id: templateflow
with:
path: ~/.cache/templateflow
key: templateflow-v0-${{ github.ref_name }}-${{ strategy.job-index }}-${{ github.sha }}
restore-keys: |
templateflow-v0-${{ github.ref_name }}-
templateflow-v0-
- name: Install package
run: python -m pip install $PIP_FLAGS .
- name: Check version
run: |
INSTALLED_VERSION=$(python -c 'import niworkflows; print(niworkflows.__version__, end="")')
echo "INSTALLED: \"${INSTALLED_VERSION}\""
test "${INSTALLED_VERSION}" = "${VERSION}"
env:
VERSION: ${{ needs.job_metadata.outputs.version }}
- name: Install test dependencies
run: python -m pip install $PIP_FLAGS "niworkflows[tests]"
- name: Run tests
run: pytest -sv --doctest-modules --cov niworkflows --pyargs niworkflows
- uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
name: Submit to CodeCov
- uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: Install the latest version of uv
uses: astral-sh/setup-uv@v3
- name: Load test data cache
uses: actions/cache@v4
id: stanford-crn
with:
path: ~/.cache/stanford-crn/
key: data-v0-${{ github.ref_name }}-${{ github.sha }}
- name: Load TemplateFlow cache
uses: actions/cache@v4
id: templateflow
with:
path: ~/.cache/templateflow
key: templateflow-v0-${{ github.ref_name }}-${{ strategy.job-index }}-${{ github.sha }}
restore-keys: |
templateflow-v0-${{ github.ref_name }}-
templateflow-v0-
- uses: actions/cache@v4
with:
path: ~/.cache/templateflow
key: templateflow-v1
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y --no-install-recommends graphviz
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Display Python version
run: python -c "import sys; print(sys.version)"
- name: Install tox
run: |
uv tool install tox --with=tox-uv --with=tox-gh-actions
- name: Show tox config
run: tox c
- name: Run tox
run: tox -v --exit-and-dump-after 1200
- uses: codecov/codecov-action@v4
with:
file: coverage.xml
token: ${{ secrets.CODECOV_TOKEN }}
if: ${{ always() }}

flake8:
if: github.event_name != 'schedule'
Expand Down
72 changes: 43 additions & 29 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,26 @@ classifiers = [
]
dependencies = [
"acres",
"attrs",
"attrs >=20.1",
"importlib_resources >= 5.7; python_version < '3.11'",
"jinja2",
"jinja2 >=3",
"looseversion",
"matplotlib >= 3.4.2",
"matplotlib >= 3.5",
"nibabel >= 3.0",
"nilearn >= 0.5.2",
"nilearn >= 0.8",
"nipype >= 1.8.5",
"nitransforms >= 21.0.0",
"numpy",
"nitransforms >= 22.0.0",
"numpy >= 1.20",
"packaging",
"pandas",
"pandas >= 1.2",
"pybids >= 0.15.1",
"PyYAML",
"scikit-image",
"scipy",
"seaborn",
"PyYAML >= 5.4",
"scikit-image >= 0.18",
"scipy >= 1.8",
"seaborn >= 0.11",
"svgutils >= 0.3.4",
"templateflow >= 0.7.2",
"transforms3d",
"templateflow >= 23.1",
"transforms3d >= 0.4",
]

[project.optional-dependencies]
Expand All @@ -62,12 +62,12 @@ style = [
"flake8 >= 3.7.0",
]
tests = [
"coverage >=5.2.1",
"pytest >= 4.4",
"pytest-cov",
"coverage[toml] >=5.2.1",
"pytest >= 6",
"pytest-cov >= 2.11",
"pytest-env",
"pytest-xdist >= 1.28",
"pytest-xvfb",
"pytest-xdist >= 2.5",
"pytest-xvfb >= 2",
]
# Aliases
all = ["niworkflows[doc,pointclouds,style,tests]"]
Expand Down Expand Up @@ -116,23 +116,31 @@ skip-string-normalization = true
extend-exclude = '_version.py'

[tool.pytest.ini_options]
norecursedirs = ".git"
addopts = "-sv --doctest-modules"
minversion = "6"
testpaths = ["niworkflows"]
log_cli_level = "INFO"
xfail_strict = true
norecursedirs = [".git"]
addopts = [
"-svx",
"-ra",
"--strict-config",
"--strict-markers",
"--doctest-modules",
# Config pytest-cov
"--cov=niworkflows",
"--cov-report=xml",
"--cov-config=pyproject.toml",
]
doctest_optionflags = "ALLOW_UNICODE NORMALIZE_WHITESPACE ELLIPSIS"
env = """
PYTHONHASHSEED=0
"""
filterwarnings = """
ignore::DeprecationWarning
"""
env = "PYTHONHASHSEED=0"
filterwarnings = ["ignore::DeprecationWarning"]
junit_family = "xunit2"

[tool.coverage.run]
branch = true
omit = [
"*/tests/*",
"niworkflows/_version.py",
"niworkflows/conftest.py",
"*/_version.py",
]

[tool.coverage.report]
Expand All @@ -141,3 +149,9 @@ exclude_lines = [
"raise NotImplementedError",
"warnings\\.warn",
]

[tool.coverage.paths]
source = [
"niworkflows",
"**/site-packages/niworkflows"
]
Loading

0 comments on commit 5d9e666

Please sign in to comment.