Update CI lock files [free-threaded] #132
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Unit tests | |
| permissions: | |
| contents: read | |
| on: | |
| push: | |
| pull_request: | |
| schedule: | |
| # Nightly build at 02:30 UTC | |
| - cron: "30 2 * * *" | |
| # Manual run | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} | |
| cancel-in-progress: true | |
| env: | |
| VIRTUALENV: testvenv | |
| TEST_DIR: ${{ github.workspace }}/tmp_folder | |
| CCACHE_DIR: ${{ github.workspace }}/ccache | |
| COVERAGE: 'true' | |
| JUNITXML: 'test-data.xml' | |
| jobs: | |
| lint: | |
| name: Lint | |
| runs-on: ubuntu-latest | |
| if: github.repository == 'scikit-learn/scikit-learn' | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.12' | |
| cache: 'pip' | |
| - name: Install linters | |
| run: | | |
| source build_tools/shared.sh | |
| # Include pytest compatibility with mypy | |
| pip install pytest $(get_dep ruff min) $(get_dep mypy min) cython-lint | |
| - name: Run linters | |
| run: ./build_tools/linting.sh | |
| - name: Run Meson OpenMP checks | |
| run: | | |
| pip install ninja meson scipy | |
| python build_tools/check-meson-openmp-dependencies.py | |
| retrieve-commit-message: | |
| name: Retrieve the latest commit message | |
| runs-on: ubuntu-latest | |
| if: github.repository == 'scikit-learn/scikit-learn' | |
| outputs: | |
| message: ${{ steps.git-log.outputs.message }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| - id: git-log | |
| name: Retrieve the latest commit message | |
| shell: bash | |
| run: | | |
| set -eu | |
| message=$(git log --format=%B -n 1) | |
| { | |
| echo 'message<<EOF' | |
| echo "${message}" | |
| echo EOF | |
| } >> "${GITHUB_OUTPUT}" | |
| retrieve-selected-tests: | |
| # Parse the commit message to check if `build_tools/azure/test_script.sh` should run | |
| # only specific tests. | |
| # | |
| # If so, selected tests will be run with SKLEARN_TESTS_GLOBAL_RANDOM_SEED="all". | |
| # | |
| # The commit message must take the form: | |
| # <title> [all random seeds] | |
| # <test_name_1> | |
| # <test_name_2> | |
| # ... | |
| name: Retrieve the selected tests | |
| runs-on: ubuntu-latest | |
| if: github.repository == 'scikit-learn/scikit-learn' | |
| outputs: | |
| tests: ${{ steps.selected-tests.outputs.tests }} | |
| needs: [retrieve-commit-message] | |
| steps: | |
| - id: selected-tests | |
| name: Retrieve the selected tests | |
| shell: python | |
| env: | |
| COMMIT_MESSAGE: ${{ needs.retrieve-commit-message.outputs.message }} | |
| run: | | |
| import os | |
| commit_message = os.environ["COMMIT_MESSAGE"] | |
| # Retrieve selected tests from commit message | |
| if "[all random seeds]" in commit_message: | |
| selected_tests = commit_message.split("[all random seeds]")[1].strip() | |
| selected_tests = selected_tests.replace("\n", " or ") | |
| # quote 'selected_tests' to cover the case of multiple selected tests | |
| selected_tests = f"{selected_tests!r}" | |
| else: | |
| selected_tests = "" | |
| # Write selected tests to `GITHUB_OUTPUT` | |
| with open(os.environ["GITHUB_OUTPUT"], "a") as file: | |
| file.write(f"tests={selected_tests}\n") | |
| unit-tests: | |
| name: ${{ matrix.name }} | |
| runs-on: ${{ matrix.os }} | |
| if: github.repository == 'scikit-learn/scikit-learn' | |
| needs: [lint, retrieve-commit-message, retrieve-selected-tests] | |
| strategy: | |
| # Ensures that all builds run to completion even if one of them fails | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - name: Linux pymin_conda_forge_arm | |
| os: ubuntu-24.04-arm | |
| DISTRIB: conda | |
| LOCK_FILE: build_tools/github/pymin_conda_forge_arm_linux-aarch64_conda.lock | |
| - name: Linux x86-64 pylatest_conda_forge_mkl | |
| os: ubuntu-22.04 | |
| DISTRIB: conda | |
| LOCK_FILE: build_tools/azure/pylatest_conda_forge_mkl_linux-64_conda.lock | |
| COVERAGE: true | |
| SKLEARN_TESTS_GLOBAL_RANDOM_SEED: 42 # default global random seed | |
| SCIPY_ARRAY_API: 1 | |
| # Tests that require large downloads over the networks are skipped in CI. | |
| # Here we make sure, that they are still run on a regular basis. | |
| SKLEARN_SKIP_NETWORK_TESTS: ${{ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && '0' || '1' }} | |
| # Check compilation with Ubuntu 22.04 LTS (Jammy Jellyfish) and scipy from conda-forge | |
| - name: Linux x86-64 pymin_conda_forge_openblas_ubuntu_2204 | |
| os: ubuntu-22.04 | |
| DISTRIB: conda | |
| LOCK_FILE: build_tools/azure/pymin_conda_forge_openblas_ubuntu_2204_linux-64_conda.lock | |
| SKLEARN_WARNINGS_AS_ERRORS: 1 | |
| COVERAGE: false | |
| SKLEARN_TESTS_GLOBAL_RANDOM_SEED: 0 # non-default seed | |
| # Linux build with minimum supported version of dependencies | |
| - name: Linux x86-64 pymin_conda_forge_openblas_min_dependencies | |
| os: ubuntu-22.04 | |
| DISTRIB: conda | |
| LOCK_FILE: build_tools/azure/pymin_conda_forge_openblas_min_dependencies_linux-64_conda.lock | |
| # Enable debug Cython directives to capture IndexError exceptions in | |
| # combination with the -Werror::pytest.PytestUnraisableExceptionWarning | |
| # flag for pytest. | |
| # https://github.com/scikit-learn/scikit-learn/pull/24438 | |
| SKLEARN_ENABLE_DEBUG_CYTHON_DIRECTIVES: 1 | |
| SKLEARN_RUN_FLOAT32_TESTS: 1 | |
| SKLEARN_TESTS_GLOBAL_RANDOM_SEED: 2 # non-default seed | |
| # Linux environment to test the latest available dependencies. | |
| # It runs tests requiring lightgbm, pandas and PyAMG. | |
| - name: Linux pylatest_pip_openblas_pandas | |
| os: ubuntu-24.04 | |
| DISTRIB: conda | |
| LOCK_FILE: build_tools/azure/pylatest_pip_openblas_pandas_linux-64_conda.lock | |
| SKLEARN_TESTS_GLOBAL_RANDOM_SEED: 3 # non-default seed | |
| SCIPY_ARRAY_API: 1 | |
| CHECK_PYTEST_SOFT_DEPENDENCY: true | |
| SKLEARN_WARNINGS_AS_ERRORS: 1 | |
| # disable pytest-xdist to have 1 job where OpenMP and BLAS are not single | |
| # threaded because by default the tests configuration (sklearn/conftest.py) | |
| # makes sure that they are single threaded in each xdist subprocess. | |
| PYTEST_XDIST_VERSION: none | |
| PIP_BUILD_ISOLATION: true | |
| # Linux environment to test that scikit-learn can be built against | |
| # versions of numpy, scipy with ATLAS that comes with Ubuntu 24.04 | |
| # Noble Numbat i.e. numpy 1.26.4 and scipy 1.11.4 | |
| - name: Linux x86-64 ubuntu_atlas | |
| os: ubuntu-24.04 | |
| DISTRIB: ubuntu | |
| LOCK_FILE: build_tools/azure/ubuntu_atlas_lock.txt | |
| COVERAGE: false | |
| SKLEARN_TESTS_GLOBAL_RANDOM_SEED: 1 # non-default seed | |
| - name: macOS pylatest_conda_forge_arm | |
| os: macos-15 | |
| DISTRIB: conda | |
| LOCK_FILE: build_tools/azure/pylatest_conda_forge_osx-arm64_conda.lock | |
| SKLEARN_TESTS_GLOBAL_RANDOM_SEED: 5 # non-default seed | |
| SCIPY_ARRAY_API: 1 | |
| PYTORCH_ENABLE_MPS_FALLBACK: 1 | |
| CHECK_PYTEST_SOFT_DEPENDENCY: true | |
| - name: macOS x86-64 pylatest_conda_forge_mkl_no_openmp | |
| os: macos-15-intel | |
| DISTRIB: conda | |
| LOCK_FILE: build_tools/azure/pylatest_conda_forge_mkl_no_openmp_osx-64_conda.lock | |
| SKLEARN_TEST_NO_OPENMP: true | |
| SKLEARN_SKIP_OPENMP_TEST: true | |
| SKLEARN_TESTS_GLOBAL_RANDOM_SEED: 6 # non-default seed | |
| - name: Windows x64 pymin_conda_forge_openblas | |
| os: windows-latest | |
| DISTRIB: conda | |
| LOCK_FILE: build_tools/azure/pymin_conda_forge_openblas_win-64_conda.lock | |
| SKLEARN_WARNINGS_AS_ERRORS: 1 | |
| # The Windows runner is typically much slower than other CI runners | |
| # due to the lack of compiler cache. Running the tests with coverage | |
| # enabled makes them run extra slow. Since very few parts of the | |
| # code should have windows-specific code branches, code coverage | |
| # collection is only done for the non-windows runners. | |
| COVERAGE: false | |
| # Enable debug Cython directives to capture IndexError exceptions in | |
| # combination with the -Werror::pytest.PytestUnraisableExceptionWarning | |
| # flag for pytest. | |
| # https://github.com/scikit-learn/scikit-learn/pull/24438 | |
| SKLEARN_ENABLE_DEBUG_CYTHON_DIRECTIVES: 1 | |
| SKLEARN_TESTS_GLOBAL_RANDOM_SEED: 7 # non-default seed | |
| env: ${{ matrix }} | |
| steps: &unit-tests-steps | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| # This step is necessary to access the job name the same way in both matrix and | |
| # non-matrix jobs (like free-threaded or scipy-dev builds). | |
| - name: Set JOB_NAME variable | |
| shell: bash | |
| run: | | |
| if [[ -z "$JOB_NAME" ]]; then | |
| echo "JOB_NAME=${{ matrix.name }}" >> $GITHUB_ENV | |
| fi | |
| - name: Create cache for ccache | |
| uses: actions/cache@v5 | |
| with: | |
| path: ${{ env.CCACHE_DIR }} | |
| key: ccache-v1-${{ env.JOB_NAME }}-${{ hashFiles('**/*.pyx*', '**/*.pxd*', '**/*.pxi*', '**/*.h', '**/*.c', '**/*.cpp', format('{0}', env.LOCK_FILE)) }} | |
| restore-keys: ccache-${{ env.JOB_NAME }} | |
| - name: Set up conda | |
| uses: conda-incubator/setup-miniconda@v3 | |
| if: ${{ startsWith(env.DISTRIB, 'conda') }} | |
| with: | |
| miniforge-version: latest | |
| auto-activate-base: true | |
| activate-environment: "" | |
| - name: Build scikit-learn | |
| run: bash -l build_tools/azure/install.sh | |
| - name: Set random seed for nightly/manual runs | |
| if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| run: echo "SKLEARN_TESTS_GLOBAL_RANDOM_SEED=$((RANDOM % 100))" >> $GITHUB_ENV | |
| shell: bash | |
| - name: Run tests | |
| env: | |
| COMMIT_MESSAGE: ${{ needs.retrieve-commit-message.outputs.message }} | |
| SELECTED_TESTS: ${{ needs.retrieve-selected-tests.outputs.tests }} | |
| COVERAGE: ${{ env.COVERAGE == 'true' && needs.retrieve-selected-tests.outputs.tests == ''}} | |
| run: bash -l build_tools/azure/test_script.sh | |
| - name: Run doctests in .py and .rst files | |
| run: bash -l build_tools/azure/test_docs.sh | |
| if: ${{ needs.retrieve-selected-tests.outputs.tests == ''}} | |
| - name: Run pytest soft dependency test | |
| run: bash -l build_tools/azure/test_pytest_soft_dependency.sh | |
| if: ${{ env.CHECK_PYTEST_SOFT_DEPENDENCY == 'true' && needs.retrieve-selected-tests.outputs.tests == ''}} | |
| - name: Combine coverage reports from parallel test runners | |
| run: bash -l build_tools/azure/combine_coverage_reports.sh | |
| if: ${{ env.COVERAGE == 'true' && needs.retrieve-selected-tests.outputs.tests == ''}} | |
| - name: Upload coverage report to Codecov | |
| uses: codecov/codecov-action@v5 | |
| if: ${{ env.COVERAGE == 'true' && needs.retrieve-selected-tests.outputs.tests == ''}} | |
| with: | |
| files: ./coverage.xml | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| disable_search: true | |
| - name: Update tracking issue | |
| if: ${{ always() && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')}} | |
| shell: bash | |
| run: | | |
| set -ex | |
| pip install defusedxml PyGithub | |
| python maint_tools/update_tracking_issue.py \ | |
| ${{ secrets.BOT_GITHUB_TOKEN }} \ | |
| "$GITHUB_WORKFLOW $JOB_NAME" \ | |
| "$GITHUB_REPOSITORY" \ | |
| https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID \ | |
| --junit-file $TEST_DIR/$JUNITXML \ | |
| --auto-close false \ | |
| --job-name "$JOB_NAME" | |
| free-threaded: | |
| name: &free-threaded-job-name | |
| Linux x86-64 pylatest_free_threaded | |
| runs-on: ubuntu-latest | |
| needs: [lint, retrieve-commit-message, retrieve-selected-tests] | |
| if: contains(needs.retrieve-commit-message.outputs.message, '[free-threaded]') || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| env: | |
| DISTRIB: conda-free-threaded | |
| LOCK_FILE: build_tools/azure/pylatest_free_threaded_linux-64_conda.lock | |
| COVERAGE: false | |
| # Disable pytest-xdist to use multiple cores for stress-testing with pytest-run-parallel | |
| PYTEST_XDIST_VERSION: none | |
| # To be able to access the job name in the steps, it must be set as an env variable. | |
| JOB_NAME: *free-threaded-job-name | |
| steps: *unit-tests-steps | |
| scipy-dev: | |
| name: &scipy-dev-job-name | |
| Linux x86-64 pylatest_pip_scipy_dev | |
| runs-on: ubuntu-22.04 | |
| needs: [lint, retrieve-commit-message, retrieve-selected-tests] | |
| if: contains(needs.retrieve-commit-message.outputs.message, '[scipy-dev]') || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| env: | |
| DISTRIB: conda-pip-scipy-dev | |
| LOCK_FILE: build_tools/azure/pylatest_pip_scipy_dev_linux-64_conda.lock | |
| SKLEARN_WARNINGS_AS_ERRORS: 1 | |
| CHECK_PYTEST_SOFT_DEPENDENCY: true | |
| # To be able to access the job name in the steps, it must be set as an env variable. | |
| JOB_NAME: *scipy-dev-job-name | |
| steps: *unit-tests-steps | |
| debian-32bit: | |
| name: &debian-32bit-job-name | |
| Linux i386 debian_32bit | |
| runs-on: ubuntu-24.04 | |
| needs: [lint, retrieve-commit-message, retrieve-selected-tests] | |
| env: | |
| DISTRIB: debian-32 | |
| LOCK_FILE: build_tools/azure/debian_32bit_lock.txt | |
| SKLEARN_TESTS_GLOBAL_RANDOM_SEED: 4 # non-default seed | |
| DOCKER_CONTAINER: i386/debian:trixie | |
| # To be able to access the job name in the steps, it must be set as an env variable. | |
| JOB_NAME: *debian-32bit-job-name | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| - name: Create cache for ccache | |
| uses: actions/cache@v5 | |
| with: | |
| path: ${{ env.CCACHE_DIR }} | |
| key: ccache-v1-${{ env.JOB_NAME }}-${{ hashFiles('**/*.pyx*', '**/*.pxd*', '**/*.pxi*', '**/*.h', '**/*.c', '**/*.cpp', format('{0}', env.LOCK_FILE)) }} | |
| restore-keys: ccache-${{ env.JOB_NAME }} | |
| - name: Set up conda | |
| uses: conda-incubator/setup-miniconda@v3 | |
| if: ${{ startsWith(env.DISTRIB, 'conda') }} | |
| with: | |
| miniforge-version: latest | |
| auto-activate-base: true | |
| activate-environment: "" | |
| - name: Set random seed for nightly/manual runs | |
| if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| run: echo "SKLEARN_TESTS_GLOBAL_RANDOM_SEED=$((RANDOM % 100))" >> $GITHUB_ENV | |
| - name: Start container | |
| # Environment variable are passed when starting the container rather | |
| # than in "Run tests step" for more standard jobs | |
| env: | |
| COMMIT_MESSAGE: ${{ needs.retrieve-commit-message.outputs.message }} | |
| SELECTED_TESTS: ${{ needs.retrieve-selected-tests.outputs.tests }} | |
| COVERAGE: ${{ env.COVERAGE == 'true' && needs.retrieve-selected-tests.outputs.tests == ''}} | |
| run: > | |
| docker container run --rm | |
| --volume $TEST_DIR:/temp_dir | |
| --volume $PWD:/scikit-learn | |
| --volume $CCACHE_DIR:/ccache | |
| -w /scikit-learn | |
| --detach | |
| --name skcontainer | |
| -e TEST_DIR=/temp_dir | |
| -e CCACHE_DIR=/ccache | |
| -e COVERAGE | |
| -e DISTRIB | |
| -e LOCK_FILE | |
| -e JUNITXML | |
| -e VIRTUALENV | |
| -e PYTEST_XDIST_VERSION | |
| -e SKLEARN_SKIP_NETWORK_TESTS | |
| -e SELECTED_TESTS | |
| -e CCACHE_COMPRESS | |
| -e COMMIT_MESSAGE | |
| -e JOB_NAME | |
| -e SKLEARN_TESTS_GLOBAL_RANDOM_SEED | |
| $DOCKER_CONTAINER | |
| sleep 1000000 | |
| - name: Build scikit-learn | |
| run: docker exec skcontainer bash -l build_tools/azure/install.sh | |
| - name: Run tests | |
| run: docker exec skcontainer bash -l build_tools/azure/test_script.sh | |
| - name: Run doctests in .py and .rst files | |
| run: docker exec skcontainer bash -l build_tools/azure/test_docs.sh | |
| if: ${{ needs.retrieve-selected-tests.outputs.tests == ''}} | |
| - name: Run pytest soft dependency test | |
| run: docker exec skcontainer build_tools/azure/test_pytest_soft_dependency.sh | |
| if: ${{ env.CHECK_PYTEST_SOFT_DEPENDENCY == 'true' && needs.retrieve-selected-tests.outputs.tests == ''}} | |
| - name: Combine coverage reports from parallel test runners | |
| run: docker exec skcontainer bash -l build_tools/azure/combine_coverage_reports.sh | |
| if: ${{ env.COVERAGE == 'true' && needs.retrieve-selected-tests.outputs.tests == ''}} | |
| - name: Upload coverage report to Codecov | |
| uses: codecov/codecov-action@v5 | |
| if: ${{ env.COVERAGE == 'true' && needs.retrieve-selected-tests.outputs.tests == ''}} | |
| with: | |
| files: ./coverage.xml | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| disable_search: true | |
| - name: Update tracking issue | |
| if: ${{ always() && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')}} | |
| run: | | |
| set -ex | |
| pip install defusedxml PyGithub | |
| python maint_tools/update_tracking_issue.py \ | |
| ${{ secrets.BOT_GITHUB_TOKEN }} \ | |
| "$GITHUB_WORKFLOW $JOB_NAME" \ | |
| "$GITHUB_REPOSITORY" \ | |
| https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID \ | |
| --junit-file $TEST_DIR/$JUNITXML \ | |
| --auto-close false \ | |
| --job-name "$JOB_NAME" |