From 538aa6cae0d838817971064c939acee61eabd555 Mon Sep 17 00:00:00 2001 From: Tom Fleet Date: Sun, 13 Feb 2022 17:59:40 +0000 Subject: [PATCH] Missing interpreters now error the session on CI by default (#567) --- docs/usage.rst | 4 +++- nox/_option_set.py | 2 ++ nox/_options.py | 1 + nox/sessions.py | 3 +++ tests/test_sessions.py | 21 +++++++++++++++++++-- 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/docs/usage.rst b/docs/usage.rst index 1309a841..e9b0c3aa 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -218,7 +218,7 @@ If the Noxfile sets ``nox.options.stop_on_first_error``, you can override the No Failing sessions when the interpreter is missing ------------------------------------------------ -By default, Nox will skip sessions where the Python interpreter can't be found. If you want Nox to mark these sessions as failed, you can use ``--error-on-missing-interpreters``: +By default, when not on CI, Nox will skip sessions where the Python interpreter can't be found. If you want Nox to mark these sessions as failed, you can use ``--error-on-missing-interpreters``: .. code-block:: console @@ -226,6 +226,8 @@ By default, Nox will skip sessions where the Python interpreter can't be found. If the Noxfile sets ``nox.options.error_on_missing_interpreters``, you can override the Noxfile setting from the command line by using ``--no-error-on-missing-interpreters``. +If being run on Continuous Integration (CI) systems, Nox will treat missing interpreters as errors by default to avoid sessions silently passing when the requested python interpreter is not installed. Nox does this by looking for an environment variable called ``CI`` which is a convention used by most CI providers. + .. _opt-error-on-external-run: Disallowing external programs diff --git a/nox/_option_set.py b/nox/_option_set.py index 6c2ba62a..1656860b 100644 --- a/nox/_option_set.py +++ b/nox/_option_set.py @@ -157,6 +157,7 @@ def make_flag_pair( name: str, enable_flags: tuple[str, str] | tuple[str], disable_flags: tuple[str], + default: bool = False, **kwargs: Any, ) -> tuple[Option, Option]: """Returns two options - one to enable a behavior and another to disable it. @@ -172,6 +173,7 @@ def make_flag_pair( *enable_flags, noxfile=True, merge_func=functools.partial(flag_pair_merge_func, name, disable_name), + default=default, **kwargs, ) diff --git a/nox/_options.py b/nox/_options.py index bdb032b5..b61c41cd 100644 --- a/nox/_options.py +++ b/nox/_options.py @@ -419,6 +419,7 @@ def _session_completer( ("--no-error-on-missing-interpreters",), group=options.groups["execution"], help="Error instead of skipping sessions if an interpreter can not be located.", + default="CI" in os.environ, ), *_option_set.make_flag_pair( "error_on_external_run", diff --git a/nox/sessions.py b/nox/sessions.py index b3d9c8ad..75fb6716 100644 --- a/nox/sessions.py +++ b/nox/sessions.py @@ -694,6 +694,9 @@ def execute(self) -> Result: if self.global_config.error_on_missing_interpreters: return Result(self, Status.FAILED, reason=str(exc)) else: + logger.warning( + "Missing interpreters will error by default on CI systems." + ) return Result(self, Status.SKIPPED, reason=str(exc)) except _SessionQuit as exc: diff --git a/tests/test_sessions.py b/tests/test_sessions.py index e753850c..a71d1f94 100644 --- a/tests/test_sessions.py +++ b/tests/test_sessions.py @@ -749,7 +749,7 @@ def make_runner(self): envdir="envdir", posargs=[], reuse_existing_virtualenvs=False, - error_on_missing_interpreters=False, + error_on_missing_interpreters="CI" in os.environ, ), manifest=mock.create_autospec(nox.manifest.Manifest), ) @@ -904,7 +904,11 @@ def test_execute_with_manifest_null_session_func(self): assert result.status == nox.sessions.Status.SKIPPED assert "no parameters" in result.reason - def test_execute_skip_missing_interpreter(self): + def test_execute_skip_missing_interpreter(self, caplog, monkeypatch): + # Important to have this first here as the runner will pick it up + # to set default for --error-on-missing-interpreters + monkeypatch.delenv("CI", raising=False) + runner = self.make_runner_with_mock_venv() runner._create_venv.side_effect = nox.virtualenv.InterpreterNotFound("meep") @@ -912,6 +916,19 @@ def test_execute_skip_missing_interpreter(self): assert result.status == nox.sessions.Status.SKIPPED assert "meep" in result.reason + assert ( + "Missing interpreters will error by default on CI systems." in caplog.text + ) + + def test_execute_missing_interpreter_on_CI(self, monkeypatch): + monkeypatch.setenv("CI", "True") + runner = self.make_runner_with_mock_venv() + runner._create_venv.side_effect = nox.virtualenv.InterpreterNotFound("meep") + + result = runner.execute() + + assert result.status == nox.sessions.Status.FAILED + assert "meep" in result.reason def test_execute_error_missing_interpreter(self): runner = self.make_runner_with_mock_venv()