diff --git a/CONSTRUCT.md b/CONSTRUCT.md
index f4ce1b18c..13d88f78d 100644
--- a/CONSTRUCT.md
+++ b/CONSTRUCT.md
@@ -380,6 +380,30 @@ _type:_ string
Application name in the Windows "Programs and Features" control panel.
Defaults to `${NAME} ${VERSION} (Python ${PYVERSION} ${ARCH})`.
+### `script_env_variables`
+
+_required:_ no
+_type:_ dictionary
+
+Dictionary of additional environment variables to be made available to
+the pre_install and post_install scripts, in the form of VAR:VALUE
+pairs. These environment variables are in addition to those in the
+`post_install` section above and take precedence in the case of name
+collisions.
+
+On Unix the variable values are automatically single quoted, allowing
+you to supply strings with spaces, without needing to worry about
+escaping. As a consequence, string interpolation is disabled: if you
+need string interpolation, you can apply it in the
+pre_install/post_install script(s). If you need to include single quotes
+in your value, you can escape them by replacing each single quote with
+`'''`.
+
+On Windows, single quotes and double quotes are not supported.
+
+Note that the # (hash) character cannot be used as it denotes yaml
+comments for all platforms.
+
### `pre_install`
_required:_ no
diff --git a/constructor/construct.py b/constructor/construct.py
index f386ff4b0..26e3f91aa 100644
--- a/constructor/construct.py
+++ b/constructor/construct.py
@@ -271,6 +271,26 @@
Defaults to `${NAME} ${VERSION} (Python ${PYVERSION} ${ARCH})`.
'''),
+ ('script_env_variables', False, (dict,), '''
+Dictionary of additional environment variables to be made available to
+the pre_install and post_install scripts, in the form of VAR:VALUE
+pairs. These environment variables are in addition to those in the
+`post_install` section above and take precedence in the case of name
+collisions.
+
+On Unix the variable values are automatically single quoted, allowing
+you to supply strings with spaces, without needing to worry about
+escaping. As a consequence, string interpolation is disabled: if you
+need string interpolation, you can apply it in the
+pre_install/post_install script(s). If you need to include single quotes
+in your value, you can escape them by replacing each single quote with
+`'\''`.
+
+On Windows, single quotes and double quotes are not supported.
+
+Note that the # (hash) character cannot be used as it denotes yaml
+comments for all platforms.
+'''),
('pre_install', False, str, '''
Path to a pre-install script, run after the package cache has been set, but
before the files are linked to their final locations. As a result, you should
diff --git a/constructor/header.sh b/constructor/header.sh
index 942ceee3e..b8db07aa2 100644
--- a/constructor/header.sh
+++ b/constructor/header.sh
@@ -23,6 +23,8 @@ fi
# Export variables to make installer metadata available to pre/post install scripts
# NOTE: If more vars are added, make sure to update the examples/scripts tests too
+
+_SCRIPT_ENV_VARIABLES_='' # Templated extra environment variable(s)
export INSTALLER_NAME='__NAME__'
export INSTALLER_VER='__VERSION__'
export INSTALLER_PLAT='__PLAT__'
diff --git a/constructor/nsis/main.nsi.tmpl b/constructor/nsis/main.nsi.tmpl
index c4897dac4..a2ae2fb28 100644
--- a/constructor/nsis/main.nsi.tmpl
+++ b/constructor/nsis/main.nsi.tmpl
@@ -1113,6 +1113,7 @@ Section "Install"
File /nonfatal /r __INDEX_CACHE__
File /r __REPODATA_RECORD__
+ @SCRIPT_ENV_VARIABLES@
System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_SAFETY_CHECKS", "disabled").r0'
System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_EXTRA_SAFETY_CHECKS", "no").r0'
System::Call 'kernel32::SetEnvironmentVariable(t,t)i("CONDA_PKGS_DIRS", "$INSTDIR\pkgs")".r0'
diff --git a/constructor/osx/run_user_script.sh b/constructor/osx/run_user_script.sh
index 53bd4501a..9f6291518 100644
--- a/constructor/osx/run_user_script.sh
+++ b/constructor/osx/run_user_script.sh
@@ -31,6 +31,7 @@ export INSTALLER_VER="__VERSION__"
export INSTALLER_PLAT="__PLAT__"
export INSTALLER_TYPE="PKG"
export PRE_OR_POST="__PRE_OR_POST__"
+_SCRIPT_ENV_VARIABLES_='' # Templated extra environment variable(s)
# Run user-provided script
if [ -f "$PREFIX/pkgs/user_${PRE_OR_POST}" ]; then
diff --git a/constructor/osxpkg.py b/constructor/osxpkg.py
index 64840c80e..22213a596 100644
--- a/constructor/osxpkg.py
+++ b/constructor/osxpkg.py
@@ -308,8 +308,12 @@ def move_script(src, dst, info, ensure_shebang=False, user_script_type=None):
'CONSTRUCTOR_VERSION': info['CONSTRUCTOR_VERSION'],
}
data = preprocess(data, ppd)
+ custom_variables = info.get('script_env_variables', {})
data = fill_template(data, replace)
+ data = data.replace("_SCRIPT_ENV_VARIABLES_=''", '\n'.join(
+ [f"export {key}='{value}'" for key, value in custom_variables.items()]))
+
with open(dst, 'w') as fo:
if (
ensure_shebang
diff --git a/constructor/shar.py b/constructor/shar.py
index 9d08fe2a6..178372075 100644
--- a/constructor/shar.py
+++ b/constructor/shar.py
@@ -92,8 +92,11 @@ def get_header(conda_exec, tarball, info):
data = read_header_template()
data = preprocess(data, ppd)
+ custom_variables = info.get('script_env_variables', {})
data = fill_template(data, replace)
+ data = data.replace("_SCRIPT_ENV_VARIABLES_=''", '\n'.join(
+ [f"export {key}='{value}'" for key, value in custom_variables.items()]))
return data
diff --git a/constructor/winexe.py b/constructor/winexe.py
index 345378ce7..3e22a9485 100644
--- a/constructor/winexe.py
+++ b/constructor/winexe.py
@@ -87,6 +87,23 @@ def insert_tempfiles_commands(paths: os.PathLike) -> List[str]:
return lines
+def setup_script_env_variables(info) -> List[str]:
+ """Helper function to insert extra environment variables into nsis template.
+
+ Args:
+ info: Dictionary of information parsed from construct.yaml
+
+ Returns:
+ List[str]: Commands to be inserted into nsi template
+ """
+ lines = []
+ for name, value in info.get('script_env_variables', {}).items():
+ lines.append(
+ "System::Call 'kernel32::SetEnvironmentVariable(t,t)i"
+ + f"""("{name}", {str_esc(value)}).r0'""")
+ return lines
+
+
def custom_nsi_insert_from_file(filepath: os.PathLike) -> str:
"""Insert NSI script commands from file.
@@ -332,6 +349,7 @@ def make_nsi(info, dir_path, extra_files=None, temp_extra_files=None):
'${NAME} ${VERSION} (Python ${PYVERSION} ${ARCH})'
)),
('@EXTRA_FILES@', '\n '.join(extra_files_commands(extra_files, dir_path))),
+ ('@SCRIPT_ENV_VARIABLES@', '\n '.join(setup_script_env_variables(info))),
(
'@CUSTOM_WELCOME_FILE@',
custom_nsi_insert_from_file(info.get('welcome_file', ''))
diff --git a/docs/source/construct-yaml.md b/docs/source/construct-yaml.md
index f4ce1b18c..13d88f78d 100644
--- a/docs/source/construct-yaml.md
+++ b/docs/source/construct-yaml.md
@@ -380,6 +380,30 @@ _type:_ string
Application name in the Windows "Programs and Features" control panel.
Defaults to `${NAME} ${VERSION} (Python ${PYVERSION} ${ARCH})`.
+### `script_env_variables`
+
+_required:_ no
+_type:_ dictionary
+
+Dictionary of additional environment variables to be made available to
+the pre_install and post_install scripts, in the form of VAR:VALUE
+pairs. These environment variables are in addition to those in the
+`post_install` section above and take precedence in the case of name
+collisions.
+
+On Unix the variable values are automatically single quoted, allowing
+you to supply strings with spaces, without needing to worry about
+escaping. As a consequence, string interpolation is disabled: if you
+need string interpolation, you can apply it in the
+pre_install/post_install script(s). If you need to include single quotes
+in your value, you can escape them by replacing each single quote with
+`'''`.
+
+On Windows, single quotes and double quotes are not supported.
+
+Note that the # (hash) character cannot be used as it denotes yaml
+comments for all platforms.
+
### `pre_install`
_required:_ no
diff --git a/examples/scripts/construct.yaml b/examples/scripts/construct.yaml
index 97d64e197..e57bdffa0 100644
--- a/examples/scripts/construct.yaml
+++ b/examples/scripts/construct.yaml
@@ -5,6 +5,14 @@ channels:
- http://repo.anaconda.com/pkgs/main/
specs:
- python
+
+script_env_variables:
+ CUSTOM_VARIABLE_1: FIR$T-CUSTOM_'\''STRING'\'' WITH SPACES AND @*! "CHARACTERS" # [not win]
+ CUSTOM_VARIABLE_2: $ECOND-CUSTOM_'\''STRING'\'' WITH SPACES AND @*! "CHARACTERS" # [not win]
+ CUSTOM_VARIABLE_1: FIR$T-CUSTOM_STRING WITH SPACES AND @*! CHARACTERS # [win]
+ CUSTOM_VARIABLE_2: $ECOND-CUSTOM_STRING WITH SPACES AND @*! CHARACTERS # [win]
+
+
pre_install: pre_install.sh # [unix]
pre_install: pre_install.bat # [win]
pre_install_desc: "Adding this description makes the script selectable in the UI"
diff --git a/examples/scripts/post_install.bat b/examples/scripts/post_install.bat
index 6b80f986a..7a435cafc 100644
--- a/examples/scripts/post_install.bat
+++ b/examples/scripts/post_install.bat
@@ -4,4 +4,6 @@ if not "%INSTALLER_VER%" == "X" exit 1
if not "%INSTALLER_PLAT%" == "win-64" exit 1
if not "%INSTALLER_TYPE%" == "EXE" exit 1
if "%PREFIX%" == "" exit 1
+if not "%CUSTOM_VARIABLE_1%" == "FIR$T-CUSTOM_STRING WITH SPACES AND @*! CHARACTERS" exit 1
+if not "%CUSTOM_VARIABLE_2%" == "$ECOND-CUSTOM_STRING WITH SPACES AND @*! CHARACTERS" exit 1
if not exist "%PREFIX%\pre_install_sentinel.txt" exit 1
diff --git a/examples/scripts/post_install.sh b/examples/scripts/post_install.sh
index 54d2b268e..1db67d136 100644
--- a/examples/scripts/post_install.sh
+++ b/examples/scripts/post_install.sh
@@ -9,10 +9,17 @@ echo "INSTALLER_NAME=${INSTALLER_NAME}"
echo "INSTALLER_VER=${INSTALLER_VER}"
echo "INSTALLER_PLAT=${INSTALLER_PLAT}"
echo "INSTALLER_TYPE=${INSTALLER_TYPE}"
+echo "CUSTOM_VARIABLE_1=${CUSTOM_VARIABLE_1}"
+echo "CUSTOM_VARIABLE_2=${CUSTOM_VARIABLE_2}"
echo "PREFIX=${PREFIX}"
test "${INSTALLER_NAME}" = "Scripts"
test "${INSTALLER_VER}" = "X"
+# shellcheck disable=SC2016 # String interpolation disabling is deliberate
+test "${CUSTOM_VARIABLE_1}" = 'FIR$T-CUSTOM_'\''STRING'\'' WITH SPACES AND @*! "CHARACTERS"'
+# shellcheck disable=SC2016 # String interpolation disabling is deliberate
+test "${CUSTOM_VARIABLE_2}" = '$ECOND-CUSTOM_'\''STRING'\'' WITH SPACES AND @*! "CHARACTERS"'
+
if [[ $(uname -s) == Linux ]]; then
if [[ ${INSTALLER_PLAT} != linux-* ]]; then
exit 1
diff --git a/examples/scripts/pre_install.bat b/examples/scripts/pre_install.bat
index d1bd0598a..5ece67c31 100644
--- a/examples/scripts/pre_install.bat
+++ b/examples/scripts/pre_install.bat
@@ -3,4 +3,6 @@ if not "%INSTALLER_VER%" == "X" exit 1
if not "%INSTALLER_PLAT%" == "win-64" exit 1
if not "%INSTALLER_TYPE%" == "EXE" exit 1
if "%PREFIX%" == "" exit 1
+if not "%CUSTOM_VARIABLE_1%" == "FIR$T-CUSTOM_STRING WITH SPACES AND @*! CHARACTERS" exit 1
+if not "%CUSTOM_VARIABLE_2%" == "$ECOND-CUSTOM_STRING WITH SPACES AND @*! CHARACTERS" exit 1
echo Added by pre-install script > "%PREFIX%\pre_install_sentinel.txt"
diff --git a/examples/scripts/pre_install.sh b/examples/scripts/pre_install.sh
index a865dcc0e..df0806980 100644
--- a/examples/scripts/pre_install.sh
+++ b/examples/scripts/pre_install.sh
@@ -6,10 +6,17 @@ echo "INSTALLER_NAME=${INSTALLER_NAME}"
echo "INSTALLER_VER=${INSTALLER_VER}"
echo "INSTALLER_PLAT=${INSTALLER_PLAT}"
echo "INSTALLER_TYPE=${INSTALLER_TYPE}"
+echo "CUSTOM_VARIABLE_1=${CUSTOM_VARIABLE_1}"
+echo "CUSTOM_VARIABLE_2=${CUSTOM_VARIABLE_2}"
echo "PREFIX=${PREFIX}"
test "${INSTALLER_NAME}" = "Scripts"
test "${INSTALLER_VER}" = "X"
+# shellcheck disable=SC2016 # String interpolation disabling is deliberate
+test "${CUSTOM_VARIABLE_1}" = 'FIR$T-CUSTOM_'\''STRING'\'' WITH SPACES AND @*! "CHARACTERS"'
+# shellcheck disable=SC2016 # String interpolation disabling is deliberate
+test "${CUSTOM_VARIABLE_2}" = '$ECOND-CUSTOM_'\''STRING'\'' WITH SPACES AND @*! "CHARACTERS"'
+
if [[ $(uname -s) == Linux ]]; then
if [[ ${INSTALLER_PLAT} != linux-* ]]; then
exit 1
diff --git a/news/718-script_env_variables-option b/news/718-script_env_variables-option
new file mode 100644
index 000000000..9ff8e5f67
--- /dev/null
+++ b/news/718-script_env_variables-option
@@ -0,0 +1,21 @@
+### Enhancements
+
+* Added support for `script_env_variables` allowing specification of
+ environment variables in the `construct.yaml` for use by pre- and
+ post-install scripts.
+
+### Bug fixes
+
+*
+
+### Deprecations
+
+*
+
+### Docs
+
+*
+
+### Other
+
+*