diff --git a/ci/ci.sh b/ci/ci.sh index a6952f72093b5..fc1afab003ced 100755 --- a/ci/ci.sh +++ b/ci/ci.sh @@ -743,10 +743,13 @@ build() { } run_minimal_test() { + EXPECTED_PYTHON_VERSION=$1 BAZEL_EXPORT_OPTIONS="$(./ci/run/bazel_export_options)" # Ignoring shellcheck is necessary because if ${BAZEL_EXPORT_OPTIONS} is wrapped by the double quotation, # bazel test cannot recognize the option. # shellcheck disable=SC2086 + bazel test --test_output=streamed --config=ci --test_env=RAY_MINIMAL=1 --test_env=EXPECTED_PYTHON_VERSION=$EXPECTED_PYTHON_VERSION ${BAZEL_EXPORT_OPTIONS} python/ray/tests/test_minimal_install + # shellcheck disable=SC2086 bazel test --test_output=streamed --config=ci --test_env=RAY_MINIMAL=1 ${BAZEL_EXPORT_OPTIONS} python/ray/tests/test_basic # shellcheck disable=SC2086 bazel test --test_output=streamed --config=ci --test_env=RAY_MINIMAL=1 --test_env=TEST_EXTERNAL_REDIS=1 ${BAZEL_EXPORT_OPTIONS} python/ray/tests/test_basic @@ -787,7 +790,7 @@ test_minimal() { ./ci/env/install-minimal.sh "$1" echo "Installed minimal dependencies." ./ci/env/env_info.sh - python ./ci/env/check_minimal_install.py + python ./ci/env/check_minimal_install.py --expected-python-version "$1" run_minimal_test "$1" } diff --git a/ci/env/check_minimal_install.py b/ci/env/check_minimal_install.py index aa3d6a7f337cc..1d48f0a114ca5 100644 --- a/ci/env/check_minimal_install.py +++ b/ci/env/check_minimal_install.py @@ -4,9 +4,13 @@ This is to ensure that tests with minimal dependencies are not tainted by too many installed packages. + +It also ensures the correct Python version. """ from typing import List +import argparse +import sys # These are taken from `setup.py` for ray[default] DEFAULT_BLACKLIST = [ @@ -47,5 +51,28 @@ def assert_packages_not_installed(blacklist: List[str]): ) +def assert_python_version(expected_python_version: str) -> None: + actual_major, actual_minor = sys.version_info[:2] + actual_version = f"{actual_major}.{actual_minor}" + expected_version = expected_python_version.strip() + assert expected_version == actual_version, ( + f"Expected Python version expected_version={expected_version}, " + f"actual_version={actual_version}" + ) + + if __name__ == "__main__": + + parser = argparse.ArgumentParser() + parser.add_argument( + "--expected-python-version", + type=str, + help="Expected Python version in MAJOR.MINOR format, e.g. 3.11", + default=None, + ) + args = parser.parse_args() + assert_packages_not_installed(DEFAULT_BLACKLIST) + + if args.expected_python_version is not None: + assert_python_version(args.expected_python_version) diff --git a/ci/env/install-minimal.sh b/ci/env/install-minimal.sh index 045239badc485..949da63c92d88 100755 --- a/ci/env/install-minimal.sh +++ b/ci/env/install-minimal.sh @@ -1,11 +1,6 @@ #!/usr/bin/env bash -if [ "$1" == "3.11" ]; then - # TODO: fix build wheels unsupported tags in the future - echo "'set -xe' not working for Python 3.11" -else - set -xe -fi +set -xe # Python version can be specified as 3.7, 3.8, 3.9, etc.. if [ -z "$1" ]; then @@ -32,7 +27,7 @@ echo "Python version is ${PYTHON_VERSION}" ROOT_DIR=$(cd "$(dirname "$0")/$(dirname "$(test -L "$0" && readlink "$0" || echo "/")")" || exit; pwd) WORKSPACE_DIR="${ROOT_DIR}/../.." -# Installs conda and python 3.7 +# Installs conda and the specified python version MINIMAL_INSTALL=1 PYTHON=${PYTHON_VERSION} "${WORKSPACE_DIR}/ci/env/install-dependencies.sh" # Re-install Ray wheels diff --git a/python/ray/tests/BUILD b/python/ray/tests/BUILD index 4aade4624351e..f9645040beb89 100644 --- a/python/ray/tests/BUILD +++ b/python/ray/tests/BUILD @@ -199,6 +199,7 @@ py_test_module_list( "test_metrics_agent_2.py", "test_microbenchmarks.py", "test_mini.py", + "test_minimal_install.py", "test_numba.py", "test_redis_tls.py", "test_raylet_output.py", diff --git a/python/ray/tests/test_minimal_install.py b/python/ray/tests/test_minimal_install.py new file mode 100644 index 0000000000000..a52207c876465 --- /dev/null +++ b/python/ray/tests/test_minimal_install.py @@ -0,0 +1,36 @@ +# coding: utf-8 +""" +Tests that are specific to minimal installations. +""" + +import pytest +import os +import sys + + +@pytest.mark.skipif( + os.environ.get("RAY_MINIMAL", "0") != "1", + reason="Skip unless running in a minimal install.", +) +def test_correct_python_version(): + """ + Validate that Bazel uses the correct Python version in our minimal tests. + """ + expected_python_version = os.environ.get("EXPECTED_PYTHON_VERSION", "").strip() + assert ( + expected_python_version + ), f"EXPECTED_PYTHON_VERSION is {expected_python_version}" + + actual_major, actual_minor = sys.version_info[:2] + actual_version = f"{actual_major}.{actual_minor}" + assert actual_version == expected_python_version, ( + f"expected_python_version={expected_python_version}" + f"actual_version={actual_version}" + ) + + +if __name__ == "__main__": + if os.environ.get("PARALLEL_CI"): + sys.exit(pytest.main(["-n", "auto", "--boxed", "-vs", __file__])) + else: + sys.exit(pytest.main(["-sv", __file__]))