diff --git a/docs/changelog/3442.feature.rst b/docs/changelog/3442.feature.rst new file mode 100644 index 000000000..4fc3ee339 --- /dev/null +++ b/docs/changelog/3442.feature.rst @@ -0,0 +1 @@ +Add ``__TOX_ENVIRONMENT_VARIABLE_ORIGINAL_CI``, which passes through the ``CI`` variable if present. This is intended for use by other libraries to detect if tox is running under CI. diff --git a/docs/config.rst b/docs/config.rst index 19e702d5d..b50c14e22 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -561,6 +561,8 @@ Base options - ✅ - ❌ + If the environment variable ``CI`` is present, ``__TOX_ENVIRONMENT_VARIABLE_ORIGINAL_CI`` will be set to the value of ``CI``. The ``CI`` variable itself will not be passed through. + More environment variable-related information can be found in :ref:`environment variable substitutions`. .. conf:: diff --git a/src/tox/tox_env/api.py b/src/tox/tox_env/api.py index 5e50a5a32..d07177de3 100644 --- a/src/tox/tox_env/api.py +++ b/src/tox/tox_env/api.py @@ -379,6 +379,8 @@ def environment_variables(self) -> dict[str, str]: result["TOX_ENV_NAME"] = self.name result["TOX_WORK_DIR"] = str(self.core["work_dir"]) result["TOX_ENV_DIR"] = str(self.conf["env_dir"]) + if (ci := os.environ.get("CI")) is not None: + result["__TOX_ENVIRONMENT_VARIABLE_ORIGINAL_CI"] = ci return result @staticmethod diff --git a/tests/tox_env/test_ci_passthrough.py b/tests/tox_env/test_ci_passthrough.py new file mode 100644 index 000000000..28c643816 --- /dev/null +++ b/tests/tox_env/test_ci_passthrough.py @@ -0,0 +1,29 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +import pytest + +if TYPE_CHECKING: + from tox.pytest import ToxProjectCreator + + +@pytest.mark.parametrize("value", ["1", "0", "", "arbitrary_value"]) +def test_ci_passthrough_present(value: str, tox_project: ToxProjectCreator, monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setenv("CI", value) + prj = tox_project({"tox.ini": "[testenv]\npackage=skip\ncommands=python -c 'print(0)'\n"}) + execute_calls = prj.patch_execute(lambda _r: 0) + result = prj.run("r", "-e", "py") + result.assert_success() + req = execute_calls.call_args[0][3] + assert req.env["__TOX_ENVIRONMENT_VARIABLE_ORIGINAL_CI"] == value + + +def test_ci_passthrough_absent(tox_project: ToxProjectCreator, monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.delenv("CI", raising=False) + prj = tox_project({"tox.ini": "[testenv]\npackage=skip\ncommands=python -c 'print(0)'\n"}) + execute_calls = prj.patch_execute(lambda _r: 0) + result = prj.run("r", "-e", "py") + result.assert_success() + req = execute_calls.call_args[0][3] + assert "__TOX_ENVIRONMENT_VARIABLE_ORIGINAL_CI" not in req.env