From 88275f11f6df07d6ee1334e4bd30a439a9cdeee9 Mon Sep 17 00:00:00 2001 From: Julien Schueller Date: Thu, 21 May 2026 07:36:12 +0200 Subject: [PATCH 1/4] Allow setting env vars via `script_env` in the test section Add `test/script_env` support to meta.yaml, mirroring the existing `build/script_env` feature. Environment variables listed under `test/script_env` are forwarded to the test environment, with a warning if they are undefined. Supports both `NAME` (read from os.environ) and `NAME=VALUE` literal formats. Closes #4940 --- conda_build/build.py | 13 +++++++++++++ conda_build/metadata.py | 1 + tests/test_api_build.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/conda_build/build.py b/conda_build/build.py index 9e473facc9..6f11e14529 100644 --- a/conda_build/build.py +++ b/conda_build/build.py @@ -3483,6 +3483,19 @@ def test( if metadata.config.remove_work_dir: env["SRC_DIR"] = metadata.config.test_dir + for var in utils.ensure_list(metadata.get_value("test/script_env")): + if "=" in var: + val = var.split("=", 1)[1] + var = var.split("=", 1)[0] + env[var] = val + elif var not in os.environ: + warnings.warn( + f"The environment variable '{var}' specified in test/script_env is undefined.", + UserWarning, + ) + else: + env[var] = os.environ[var] + test_script, _ = write_test_scripts( metadata, env, py_files, pl_files, lua_files, r_files, shell_files, trace ) diff --git a/conda_build/metadata.py b/conda_build/metadata.py index 54961d0b47..379b68a3e7 100644 --- a/conda_build/metadata.py +++ b/conda_build/metadata.py @@ -727,6 +727,7 @@ def parse(data, config, path=None): "files": list, "imports": list, "source_files": list, + "script_env": list, "downstreams": list, }, "about": { diff --git a/tests/test_api_build.py b/tests/test_api_build.py index 5e002acfb2..7d94f19865 100644 --- a/tests/test_api_build.py +++ b/tests/test_api_build.py @@ -2008,6 +2008,37 @@ def assert_keyword(keyword): os.environ.pop(token) +@pytest.mark.sanity +def test_test_script_env_warnings(testing_config, recwarn): + recipe = os.path.join(metadata_dir, "_test_script_env") + token = "TEST_VAR" + + def assert_undefined_warning_present(): + messages = [str(w.message) for w in recwarn.list] + assert any( + token in m and "test/script_env" in m and "undefined" in m + for m in messages + ) + + def assert_undefined_warning_absent(): + messages = [str(w.message) for w in recwarn.list] + assert not any( + token in m and "test/script_env" in m and "undefined" in m + for m in messages + ) + + api.build(recipe, config=testing_config) + assert_undefined_warning_present() + recwarn.clear() + + os.environ[token] = "value" + try: + api.build(recipe, config=testing_config) + assert_undefined_warning_absent() + finally: + os.environ.pop(token) + + @pytest.mark.slow def test_activated_prefixes_in_actual_path(testing_metadata): """ From ba18224782dd95abbb265a64c10b53f5c1f05398 Mon Sep 17 00:00:00 2001 From: Julien Schueller Date: Thu, 21 May 2026 07:41:48 +0200 Subject: [PATCH 2/4] doc --- docs/source/resources/define-metadata.rst | 36 +++++++++++++++++++ .../user-guide/environment-variables.rst | 10 ++++++ news/4940-test-script-env | 7 ++++ 3 files changed, 53 insertions(+) create mode 100644 news/4940-test-script-env diff --git a/docs/source/resources/define-metadata.rst b/docs/source/resources/define-metadata.rst index 1ccf6f201c..0461346b10 100644 --- a/docs/source/resources/define-metadata.rst +++ b/docs/source/resources/define-metadata.rst @@ -772,6 +772,8 @@ disable this with: include_recipe: False +.. _script-env: + Use environment variables ------------------------- @@ -1282,6 +1284,40 @@ Commands that are run as part of the test. - bspatch4 -h +.. _test-script-env: + +Test environment variables +--------------------------- + +Pass environment variables through to the test environment. +This works identically to :ref:`build/script_env `. + +.. code-block:: yaml + + test: + script_env: + - MYVAR + - ANOTHER_VAR + +If a listed environment variable is missing from the environment +seen by the conda-build process itself, a UserWarning is +emitted during the test phase and the variable remains +undefined. + +Values can also be set inline with ``=`` syntax: + +.. code-block:: yaml + + test: + script_env: + - MY_VAR=some value + +.. note:: + Environment variables inherited via ``test/script_env`` are only + visible during the test phase, not the build phase. Use + :ref:`build/script_env ` for build-time variables. + + Python imports -------------- diff --git a/docs/source/user-guide/environment-variables.rst b/docs/source/user-guide/environment-variables.rst index 1689b9106b..0e0a14d16a 100644 --- a/docs/source/user-guide/environment-variables.rst +++ b/docs/source/user-guide/environment-variables.rst @@ -327,6 +327,16 @@ Additionally, values can be set by including ``=`` followed by the desired value this feature with caution or explicitly set values using the ``=`` syntax. +This feature can also be used in the :ref:`test section ` of +``meta.yaml`` to pass environment variables to the test phase: + +.. code-block:: yaml + + test: + script_env: + - TMPDIR + - MY_VAR=some value + .. note:: If you split your build and test phases with ``--no-test`` and ``--test``, you need to ensure that the environment variables present at build time and test diff --git a/news/4940-test-script-env b/news/4940-test-script-env new file mode 100644 index 0000000000..36a35ed623 --- /dev/null +++ b/news/4940-test-script-env @@ -0,0 +1,7 @@ +### Enhancements + +* Allow setting environment variables in the test section via `test/script_env`, matching the existing `build/script_env` feature. (#4940) + +### Docs + +* Document `test/script_env` in the test section reference. From 6ee7c66b9e4559ba90ffe1907514b4fe5dd53e6e Mon Sep 17 00:00:00 2001 From: Julien Schueller Date: Thu, 21 May 2026 07:55:06 +0200 Subject: [PATCH 3/4] reformat --- tests/test_api_build.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/test_api_build.py b/tests/test_api_build.py index 7d94f19865..f56aba3f1e 100644 --- a/tests/test_api_build.py +++ b/tests/test_api_build.py @@ -2016,15 +2016,13 @@ def test_test_script_env_warnings(testing_config, recwarn): def assert_undefined_warning_present(): messages = [str(w.message) for w in recwarn.list] assert any( - token in m and "test/script_env" in m and "undefined" in m - for m in messages + token in m and "test/script_env" in m and "undefined" in m for m in messages ) def assert_undefined_warning_absent(): messages = [str(w.message) for w in recwarn.list] assert not any( - token in m and "test/script_env" in m and "undefined" in m - for m in messages + token in m and "test/script_env" in m and "undefined" in m for m in messages ) api.build(recipe, config=testing_config) From 501d8423a445e9e8e0256cf5845e44d8f535f4b7 Mon Sep 17 00:00:00 2001 From: Julien Schueller Date: Thu, 21 May 2026 09:02:29 +0200 Subject: [PATCH 4/4] testdir --- tests/test_api_build.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/tests/test_api_build.py b/tests/test_api_build.py index f56aba3f1e..5be113a0f0 100644 --- a/tests/test_api_build.py +++ b/tests/test_api_build.py @@ -2009,8 +2009,26 @@ def assert_keyword(keyword): @pytest.mark.sanity -def test_test_script_env_warnings(testing_config, recwarn): - recipe = os.path.join(metadata_dir, "_test_script_env") +def test_test_script_env_warnings(testing_config, testing_workdir, recwarn): + os.makedirs("recipe") + with open("recipe/meta.yaml", "w") as f: + f.write(""" +package: + name: test-script-env-test + version: "1.0" + +build: + number: 0 + +test: + script_env: + - TEST_VAR + commands: + - echo "test" +""") + for empty in ("build.sh", "bld.bat"): + open(f"recipe/{empty}", "w").close() + token = "TEST_VAR" def assert_undefined_warning_present(): @@ -2025,13 +2043,13 @@ def assert_undefined_warning_absent(): token in m and "test/script_env" in m and "undefined" in m for m in messages ) - api.build(recipe, config=testing_config) + api.build("recipe", config=testing_config) assert_undefined_warning_present() recwarn.clear() os.environ[token] = "value" try: - api.build(recipe, config=testing_config) + api.build("recipe", config=testing_config) assert_undefined_warning_absent() finally: os.environ.pop(token)