Repository navigation
417 lines (397 loc) · 15.8 KB
/
Copy pathcicd_tests.yml
File metadata and controls
417 lines (397 loc) · 15.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
name: tests
on:
# quick tests for pull requests and the releasing branches
push:
branches:
- dev
- main
- releasing/*
pull_request:
branches:
- dev
- main
- releasing/*
permissions:
contents: read
concurrency:
# automatically cancel the previously triggered workflows when there's a newer version
group: cicd-tests-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
# Supported versions of Python and PyTorch are listed here for use below and as documentation
env:
# supported versions of Python
PYTHON_VER1: '3.10'
PYTHON_VER2: '3.11'
PYTHON_VER3: '3.12'
PYTHON_VER4: '3.13'
# PYTHON_VER5: '3.14' # TODO: not compatible with Torchscript, re-enable once Torchscript removed from MONAI
# supported versions of PyTorch
PYTORCH_VER1: '2.8.0'
PYTORCH_VER2: '2.9.1'
PYTORCH_VER3: '2.10.0'
PYTORCH_VER4: '2.11.0'
TORCHVISION_VER1: '0.23.0' # used for testing with lowest PyTorch version (PYTORCH_VER1), update as needed
# versions of PyTorch/Torchvision to use for full-dep Windows tests, needed to get around a gloo bug
WIN_FULLDEP_VER: '2.11.0'
WIN_FULLDEP_VISION_VER: '0.26.0'
PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION: python # https://github.com/Project-MONAI/MONAI/issues/4354
# These jobs run the CICD tests, type checking, and testing packaging. These use the minimum supported versions of
# Python and PyTorch in many places using the above environment variables but also hard coded where necessary.
# When support is dropped for a version it is important to update these as appropriate.
jobs:
# This job will set its output value `skip` to 2 if only documentation was changed, either documentation files or
# the docstrings of source files. If any source lines are changed, or non-documentation files are changed, the
# result is 0 which then triggers tests to run. This job works by using the compare_sources.py script to compare
# changed files to see if they differ in ways other than comments or docstrings.
test_skip:
runs-on: ubuntu-latest
outputs:
skip: ${{ steps.check-changes.outputs.skip }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 2
- name: Set up Python ${{ env.PYTHON_VER1 }}
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VER1 }}
cache: 'pip'
- name: Check File Changes
id: check-changes
shell: bash
run: |
echo "skip=1" >> $GITHUB_OUTPUT
mkdir -p /tmp/check_changes
if ! git diff --name-only HEAD^..HEAD ':!docs' > /tmp/check_changes/changed_files
then
echo "skip=0" >> "$GITHUB_OUTPUT"
exit 0
fi
while read i
do
echo "Checking for changes: $i"
if ! git show HEAD^:$i > /tmp/check_changes/$(basename $i)
then
echo "New file found, or 'git show' failed, running tests."
elif ! python monai/utils/compare_sources.py $i /tmp/check_changes/$(basename $i)
then
echo "Change found, running tests."
else
continue
fi
echo "skip=0" >> $GITHUB_OUTPUT
break
done < /tmp/check_changes/changed_files
static-checks: # Perform static type and other checks using runtests.sh
runs-on: ubuntu-latest
strategy:
matrix:
opt: ["codeformat", "pyrefly"]
steps:
- name: Clean unused tools
run: |
find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \;
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc /usr/local/.ghcup
sudo docker system prune -f
- uses: actions/checkout@v7
- name: Set up Python ${{ env.PYTHON_VER1 }}
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VER1 }}
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip wheel
python -m pip install .[all,testing]
- name: Lint and type check
run: |
# clean up temporary files
$(pwd)/runtests.sh --build --clean
$(pwd)/runtests.sh --build --${{ matrix.opt }}
min-dep: # Test with minumum dependencies installed for different OS, Python, and PyTorch combinations
runs-on: ${{ matrix.os }}
needs: test_skip
strategy:
fail-fast: false
matrix:
# Base test cases are to test on all three OSes with the lowest versions of Python and PyTorch, other cases are
# added below as special cases to cover other Python and PyTorch versions under Ubuntu
os: [windows-latest, macOS-latest, ubuntu-latest]
python-version: ['3.10']
pytorch-version: ['2.8.0']
include:
# Test Python versions under Ubuntu with lowest PyTorch version supported
- os: ubuntu-latest
pytorch-version: '2.8.0'
python-version: '3.11'
- os: ubuntu-latest
pytorch-version: '2.8.0'
python-version: '3.12'
- os: ubuntu-latest
pytorch-version: '2.8.0'
python-version: '3.13'
# - os: ubuntu-latest
# pytorch-version: '2.9.1'
# python-version: '3.14'
# Test PyTorch versions under Ubuntu with lowest Python version supported
- os: ubuntu-latest
python-version: '3.10'
pytorch-version: '2.9.1'
- os: ubuntu-latest
python-version: '3.10'
pytorch-version: '2.10.0'
- os: ubuntu-latest
python-version: '3.10'
pytorch-version: '2.11.0'
timeout-minutes: 40
steps:
- name: Clean unused tools
if: runner.os == 'Linux' && needs.test_skip.outputs.skip == 0
run: |
find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \;
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc /usr/local/.ghcup
sudo docker system prune -f
- uses: actions/checkout@v7
if: needs.test_skip.outputs.skip == 0
- name: Set up Python ${{ matrix.python-version }}
if: needs.test_skip.outputs.skip == 0
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Prepare pip wheel
if: needs.test_skip.outputs.skip == 0
run: |
which python
python -m pip install --upgrade pip wheel tomli
- name: Install the minimum dependencies
if: needs.test_skip.outputs.skip == 0
run: |
# min. requirements
python -m pip install torch==${{ matrix.pytorch-version }}
python monai/config/print_dependencies.py build-system | xargs pip install --no-build-isolation
python -m pip install --no-build-isolation .[testing]
python -m pip list
shell: bash
- name: Run quick tests
if: needs.test_skip.outputs.skip == 0
run: |
nvidia-smi || true
python monai/config/check_env.py --env --monai
./runtests.sh --min
shell: bash
env:
QUICKTEST: True
NGC_API_KEY: ${{ secrets.NGC_API_KEY }}
NGC_ORG: ${{ secrets.NGC_ORG }}
NGC_TEAM: ${{ secrets.NGC_TEAM }}
full-dep: # Test with full dependencies installed for different OS runners
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [windows-latest, ubuntu-latest, macOS-latest] # macOS-latest is very slow (#8864), testing install only
timeout-minutes: 120
needs: test_skip
env:
QUICKTEST: True
steps:
- name: Clean unused tools
if: runner.os == 'Linux' && needs.test_skip.outputs.skip == 0
run: |
find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \;
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc /usr/local/.ghcup
sudo docker system prune -f
- name: Config pagefile (Windows only)
if: runner.os == 'windows' && needs.test_skip.outputs.skip == 0
uses: al-cheb/configure-pagefile-action@v1.5
with:
minimum-size: 8GB
maximum-size: 16GB
disk-root: "D:"
- uses: actions/checkout@v7
if: needs.test_skip.outputs.skip == 0
- name: Set up Python ${{ env.PYTHON_VER1 }}
if: needs.test_skip.outputs.skip == 0
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VER1 }}
cache: 'pip'
- name: Prepare pip wheel
if: needs.test_skip.outputs.skip == 0
run: |
which python
python -m pip install --upgrade pip wheel
- if: runner.os == 'windows' && needs.test_skip.outputs.skip == 0
name: Install torch cpu from pytorch.org (Windows only)
run: |
python -m pip install torch==${WIN_FULLDEP_VER} torchvision==${WIN_FULLDEP_VISION_VER}+cpu --index-url https://download.pytorch.org/whl/cpu
shell: bash
- if: runner.os != 'windows' && needs.test_skip.outputs.skip == 0
name: Install torch gpu
run: |
# install the lowest version of PyTorch supported
python -m pip install torch==${PYTORCH_VER1} torchvision==${TORCHVISION_VER1}
shell: bash
- if: runner.os == 'Linux' && needs.test_skip.outputs.skip == 0
name: Install itk pre-release (Linux only)
run: |
python -m pip install --pre -U itk
shell: bash
- name: Install the complete dependencies
if: needs.test_skip.outputs.skip == 0
run: |
python -m pip install --user --upgrade pip wheel tomli
python monai/config/print_dependencies.py build-system | xargs pip install --no-build-isolation
python -m pip install --no-build-isolation .[all,testing]
python -m pip list
shell: bash
- name: Run compiled (${{ runner.os }})
if: needs.test_skip.outputs.skip == 0
run: |
python -m pip uninstall -y monai
BUILD_MONAI=1 python -m pip install --no-build-isolation -e . # compile the cpp extensions
python -c 'import monai._C' > /dev/null
nvidia-smi || true
python monai/config/check_env.py --env --monai
shell: bash
- if: runner.os != 'macOS' && needs.test_skip.outputs.skip == 0
name: Run full tests
run: |
python -m unittest -v
shell: bash
- if: runner.os == 'macOS' && needs.test_skip.outputs.skip == 0
name: Run min tests
run: |
# TODO: enable large range of macOS tests which don't take a very long time
./runtests.sh --min
shell: bash
hyena-dep: # Optional HyenaND dependency + the no-CUDA Hyena tests.
# nvsubquadratic >= 0.1.1 supports Python >= 3.10 and keeps its CUDA-kernel sdist
# (subquadratic-ops-torch-cu12) plus the megatron / dali / timm packages in opt-in
# extras, so it installs on a CPU runner. We still pass ``--no-deps`` deliberately:
# (1) the HyenaND operators import only torch + einops + omegaconf at runtime, so
# skipping the (still batteries-included: datasets/lightning/wandb) core deps
# keeps this job lean; and
# (2) nvsubquadratic pins torch>=2.10,<2.11, which would otherwise upgrade/clash
# with the torch this job (and MONAI's matrix) installs.
# CUDA-required Hyena tests skip cleanly here; the GPU surface is covered by
# ``.github/workflows/pythonapp-hyena-gpu.yml``.
runs-on: ubuntu-latest
timeout-minutes: 30
needs: test_skip
if: needs.test_skip.outputs.skip == 0
steps:
- name: Clean unused tools
run: |
find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \;
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc /usr/local/.ghcup
sudo docker system prune -f
- uses: actions/checkout@v6
- name: Set up Python ${{ env.PYTHON_VER1 }}
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VER1 }}
cache: 'pip'
- name: Install dependencies + nvsubquadratic (no-deps)
run: |
python -m pip install --upgrade pip wheel tomli pytest
# need a specific version of torch for nvsubquadratic
python monai/config/print_dependencies.py build-system | \
xargs -d '\n' pip install --no-build-isolation torch==2.10.0 torchvision==0.25.0
# # nvsubquadratic runtime imports need only torch + einops + omegaconf; install
# # the package itself without its core dependency tree (see job comment above).
python -m pip install --no-build-isolation omegaconf
python -m pip install --no-build-isolation --no-deps 'nvsubquadratic>=0.1.1'
python -m pip install --no-build-isolation .[hyena,testing]
python -m pip list
shell: bash
- name: Run Hyena tests (CUDA-required cases skip cleanly)
run: |
python -c "from monai.networks.blocks.hyena import is_nvsubquadratic_available; \
assert is_nvsubquadratic_available(), 'nvsubquadratic must be importable'"
python -m pytest -v \
tests/networks/blocks/test_hyena_block.py \
tests/networks/nets/test_hyena_nd_unetr.py \
tests/networks/nets/test_swin_unetr.py
shell: bash
packaging: # Test package generation
runs-on: ubuntu-latest
env:
QUICKTEST: True
INDEX_URL: "https://download.pytorch.org/whl/cpu"
steps:
- name: Clean unused tools
run: |
find /opt/hostedtoolcache/* -maxdepth 0 ! -name 'Python' -exec rm -rf {} \;
sudo rm -rf /usr/share/dotnet
sudo rm -rf /usr/local/lib/android
sudo rm -rf /opt/ghc /usr/local/.ghcup
sudo docker system prune -f
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Set up Python ${{ env.PYTHON_VER1 }}
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VER1 }}
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --user --upgrade pip setuptools wheel twine packaging tomli
# install the latest pytorch for testing
python monai/config/print_dependencies.py build-system all testing | \
xargs -d '\n' pip install --no-build-isolation torch==${PYTORCH_VER1} --extra-index-url $INDEX_URL
- name: Check packages
run: |
python -m pip uninstall -y monai
python -m pip list | grep -iv monai
git fetch --depth=1 origin +refs/tags/*:refs/tags/*
set -e
# build tar.gz and wheel
python setup.py check -m -s
python setup.py sdist bdist_wheel
python -m twine check dist/*
- run: echo "pwd=$PWD" >> $GITHUB_OUTPUT
id: root
- run: echo "tmp_dir=$(mktemp -d)" >> $GITHUB_OUTPUT
id: mktemp
- name: Move packages
run: |
printf ${{ steps.root.outputs.pwd }}
printf ${{ steps.mktemp.outputs.tmp_dir }}
# move packages to a temp dir
cp dist/monai* "${{ steps.mktemp.outputs.tmp_dir }}"
rm -r build dist monai.egg-info
cd "${{ steps.mktemp.outputs.tmp_dir }}"
ls -al
- name: Install wheel file
working-directory: ${{ steps.mktemp.outputs.tmp_dir }}
run: |
# install from wheel
python -m pip install --no-build-isolation monai*.whl --extra-index-url $INDEX_URL
python -m monai.config
python -m pip uninstall -y monai
rm monai*.whl
- name: Install source archive
working-directory: ${{ steps.mktemp.outputs.tmp_dir }}
run: |
for name in *.tar.gz; do break; done
echo $name
python -m pip install --no-build-isolation ${name}[all] --extra-index-url $INDEX_URL
python -m monai.config
python -m pip uninstall -y monai
- name: Install using uv
working-directory: ${{ steps.root.outputs.pwd }}
run: |
pip install uv
uv pip install --system --no-build-isolation .[all] --extra-index-url $INDEX_URL
python -m monai.config