--- a +++ b/azure-pipelines.yml @@ -0,0 +1,301 @@ +trigger: + # start a new build for every push + batch: false + branches: + include: + - 'main' + - 'maint/*' +pr: + branches: + include: + - '*' # must quote since "*" is a YAML reserved character; we want a string + + +stages: + + - stage: Check + jobs: + - job: Skip + pool: + vmImage: 'ubuntu-latest' + variables: + DECODE_PERCENTS: 'false' + RET: 'true' + BUILD_REASON: $(Build.Reason) + steps: + - bash: | + git_log=`git log --format=oneline -n 1 --skip=1` + echo "##vso[task.setvariable variable=log]$git_log" + - bash: echo "##vso[task.setvariable variable=RET]false" + condition: and(eq(variables.BUILD_REASON, 'PullRequest'), or(contains(variables.log, '[skip azp]'), contains(variables.log, '[azp skip]'), contains(variables.log, '[skip ci]'), contains(variables.log, '[ci skip]'))) + - bash: echo "##vso[task.setvariable variable=start_main;isOutput=true]$RET" + name: result + + - stage: Style + variables: + AZURE_CI: 'true' + jobs: + - job: All + pool: + vmImage: 'ubuntu-latest' + variables: + PYTHON_VERSION: '3.11' + PYTHON_ARCH: 'x64' + steps: + - bash: echo $(COMMIT_MSG) + - task: UsePythonVersion@0 + inputs: + versionSpec: $(PYTHON_VERSION) + architecture: $(PYTHON_ARCH) + addToPath: true + displayName: 'Get Python' + - bash: | + set -eo pipefail + python -m pip install --progress-bar off --upgrade pip build + python -m pip install --progress-bar off -ve .[hdf5,test] + python -m pip uninstall -yq pytest-qt # don't want to set up display, etc. for this + pre-commit install --install-hooks + displayName: Install dependencies + - bash: | + make pre-commit + displayName: make pre-commit + condition: always() + - bash: | + make nesting + displayName: make nesting + condition: always() + - bash: | + make check-readme + displayName: make check-readme + condition: always() + - bash: mypy + displayName: mypy + condition: always() + - bash: vulture + displayName: vulture + condition: always() + + + - stage: Test + condition: and(succeeded(), eq(dependencies.Check.outputs['Skip.result.start_main'], 'true')) + dependsOn: ['Style', 'Check'] + variables: + AZURE_CI: 'true' + jobs: + - job: Ultraslow_PG + pool: + vmImage: 'ubuntu-22.04' + variables: + DISPLAY: ':99' + OPENBLAS_NUM_THREADS: '1' + MNE_TEST_ALLOW_SKIP: '^.*(PySide6 causes segfaults).*$' + MNE_BROWSER_PRECOMPUTE: 'false' + steps: + - bash: | + set -e + ./tools/setup_xvfb.sh + sudo apt install -yq tcsh + displayName: 'Install Ubuntu dependencies' + - bash: | + source tools/get_minimal_commands.sh + displayName: 'Install minimal commands' + - bash: | + echo $PATH + mne_surf2bem --version + fsl_rigid_register --version + displayName: 'Test minimal commands' + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.12' + architecture: 'x64' + addToPath: true + displayName: 'Get Python' + - bash: | + set -e + python -m pip install --progress-bar off --upgrade pip + python -m pip install --progress-bar off "mne-qt-browser[opengl] @ git+https://github.com/mne-tools/mne-qt-browser.git" pyvista scikit-learn python-picard qtpy nibabel sphinx-gallery "PySide6!=6.8.0,!=6.8.0.1,!=6.8.1.1" pandas neo pymatreader antio defusedxml + python -m pip uninstall -yq mne + python -m pip install --progress-bar off --upgrade -e .[test] + displayName: 'Install dependencies with pip' + - bash: | + set -e + mne sys_info -pd + mne sys_info -pd | grep "qtpy .*(PySide6=.*)$" + displayName: Print config + - bash: | + set -e + LD_DEBUG=libs python -c "from PySide6.QtWidgets import QApplication, QWidget; app = QApplication([]); import matplotlib; matplotlib.use('QtAgg'); import matplotlib.pyplot as plt; plt.figure()" + - bash: source tools/get_testing_version.sh + displayName: 'Get testing version' + - task: Cache@2 + inputs: + key: $(testing_version) + path: /home/vsts/mne_data + displayName: 'Cache testing data' + - script: python -c "import mne; mne.datasets.testing.data_path(verbose=True)" + displayName: 'Get test data' + - script: pytest -m "ultraslowtest or pgtest" --tb=short --cov=mne --cov-report=xml -vv mne + displayName: 'slow and mne-qt-browser tests' + # Coverage + - bash: bash <(curl -s https://codecov.io/bash) + displayName: 'Codecov' + condition: succeededOrFailed() + - task: PublishTestResults@2 + inputs: + testResultsFiles: '**/junit-*.xml' + testRunTitle: 'Publish test results for $(Agent.JobName)' + failTaskOnFailedTests: true + condition: succeededOrFailed() + - task: PublishCodeCoverageResults@2 + inputs: + summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml' + + - job: Qt + pool: + vmImage: 'ubuntu-22.04' + variables: + DISPLAY: ':99' + OPENBLAS_NUM_THREADS: '1' + TEST_OPTIONS: "--tb=short --cov=mne --cov-report=xml --cov-append -vv mne/viz/_brain mne/viz/backends mne/viz/tests/test_evoked.py mne/gui mne/report" + MNE_TEST_ALLOW_SKIP: '^.*(PySide6 causes segfaults).*$' + steps: + - bash: ./tools/setup_xvfb.sh + displayName: 'Install Ubuntu dependencies' + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.10' + architecture: 'x64' + addToPath: true + displayName: 'Get Python' + - bash: | + set -e + python -m pip install --progress-bar off --upgrade pip + python -m pip install --progress-bar off --upgrade --pre --only-binary=\"numpy,scipy,matplotlib,vtk\" numpy scipy matplotlib vtk + python -c "import vtk" + python -m pip install --progress-bar off --upgrade -ve .[full,test_extra] + displayName: 'Install dependencies with pip' + - bash: | + set -e + which mne + mne sys_info -pd + python ./tools/check_mne_location.py + displayName: Print config + - bash: source tools/get_testing_version.sh + displayName: 'Get testing version' + - task: Cache@2 + inputs: + key: $(testing_version) + path: /home/vsts/mne_data + displayName: 'Cache testing data' + - script: python -c "import mne; mne.datasets.testing.data_path(verbose=True)" + displayName: 'Get test data' + - bash: | + set -eo pipefail + python -m pip install PyQt6 + LD_DEBUG=libs python -c "from PyQt6.QtWidgets import QApplication, QWidget; app = QApplication([]); import matplotlib; matplotlib.use('QtAgg'); import matplotlib.pyplot as plt; plt.figure()" + displayName: 'Check Qt import' + - bash: | + set -eo pipefail + mne sys_info -pd + mne sys_info -pd | grep "qtpy .* (PyQt6=.*)$" + PYTEST_QT_API=PyQt6 pytest ${TEST_OPTIONS} + python -m pip uninstall -yq PyQt6 PyQt6-sip PyQt6-Qt6 + displayName: 'PyQt6' + - bash: | + set -eo pipefail + python -m pip install "PySide6!=6.8.0,!=6.8.0.1" + mne sys_info -pd + mne sys_info -pd | grep "qtpy .* (PySide6=.*)$" + PYTEST_QT_API=PySide6 pytest ${TEST_OPTIONS} + python -m pip uninstall -yq PySide6 + displayName: 'PySide6' + # PyQt5 leaves cruft behind, so run it last + - bash: | + set -eo pipefail + python -m pip install PyQt5 + mne sys_info -pd + mne sys_info -pd | grep "qtpy .* (PyQt5=.*)$" + PYTEST_QT_API=PyQt5 pytest ${TEST_OPTIONS} + python -m pip uninstall -yq PyQt5 PyQt5-sip PyQt5-Qt5 + displayName: 'PyQt5' + # Coverage + - bash: bash <(curl -s https://codecov.io/bash) + displayName: 'Codecov' + condition: succeededOrFailed() + - task: PublishTestResults@2 + inputs: + testResultsFiles: '**/junit-*.xml' + testRunTitle: 'Publish test results for $(Agent.JobName)' + failTaskOnFailedTests: true + condition: succeededOrFailed() + - task: PublishCodeCoverageResults@2 + inputs: + summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml' + + - job: Windows + pool: + vmImage: 'windows-latest' + variables: + MNE_LOGGING_LEVEL: 'warning' + MNE_FORCE_SERIAL: 'true' + OPENBLAS_NUM_THREADS: '2' + OMP_DYNAMIC: 'false' + PYTHONUNBUFFERED: 1 + PYTHONIOENCODING: 'utf-8' + AZURE_CI_WINDOWS: 'true' + PYTHON_ARCH: 'x64' + timeoutInMinutes: 90 + strategy: + maxParallel: 4 + matrix: + 3.10 pip: + TEST_MODE: 'pip' + PYTHON_VERSION: '3.10' + 3.12 pip pre: + TEST_MODE: 'pip-pre' + PYTHON_VERSION: '3.12' + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: $(PYTHON_VERSION) + architecture: $(PYTHON_ARCH) + addToPath: true + displayName: 'Get Python' + - bash: | + set -eo pipefail + git clone --depth 1 https://github.com/pyvista/setup-headless-display-action.git + MESA3D_VERSION=24.3.0 bash setup-headless-display-action/windows/install_opengl.sh + displayName: Install OpenGL + - bash: ./tools/azure_dependencies.sh + displayName: Install dependencies with pip + - script: pip install -e . + displayName: 'Install MNE-Python dev' + - script: mne sys_info -pd + displayName: 'Print config' + - script: python -c "import numpy; numpy.show_config()" + displayName: Print NumPy config + - script: python -c "import numpy; import scipy.linalg; import sklearn.neighbors; from threadpoolctl import threadpool_info; from pprint import pprint; pprint(threadpool_info())" + displayName: Print threadpoolctl info + - bash: source tools/get_testing_version.sh + displayName: 'Get testing version' + - task: Cache@2 + inputs: + key: $(testing_version) + path: C:\Users\VssAdministrator\mne_data + displayName: 'Cache testing data' + - script: python -c "import mne; mne.datasets.testing.data_path(verbose=True)" + displayName: 'Get test data' + - script: pytest -m "not (slowtest or pgtest)" --tb=short --cov=mne --cov-report=xml -vv mne + displayName: 'Run tests' + - bash: bash <(curl -s https://codecov.io/bash) + displayName: 'Codecov' + condition: succeededOrFailed() + - task: PublishTestResults@2 + inputs: + testResultsFiles: '**/junit-*.xml' + testRunTitle: 'Publish test results for $(Agent.JobName) $(TEST_MODE) $(PYTHON_VERSION)' + failTaskOnFailedTests: true + condition: succeededOrFailed() + - task: PublishCodeCoverageResults@2 + inputs: + summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'