Skip to content

Commit 06df3b8

Browse files
committed
Handle read-only shared pixi environments
This requires adding an `--as-is` flag to pixi calls.
1 parent 19fe3e4 commit 06df3b8

File tree

2 files changed

+80
-2
lines changed

2 files changed

+80
-2
lines changed

mache/deploy/templates/load.sh.j2

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,32 @@ export PIXI_TOML="${MACHE_DEPLOY_ACTIVE_PIXI_TOML}"
114114
export MACHE_DEPLOY_TARGET_LOAD_SNIPPET="${MACHE_DEPLOY_ACTIVE_TARGET_LOAD_SNIPPET}"
115115
export {{ software_upper }}_PIXI_MPI="${MACHE_DEPLOY_ACTIVE_PIXI_MPI}"
116116

117+
_mache_deploy_active_env_prefix() {
118+
printf '%s\n' "${MACHE_DEPLOY_ACTIVE_PIXI_PREFIX}/.pixi/envs/default"
119+
}
120+
121+
_mache_deploy_require_active_env() {
122+
local active_env_prefix
123+
local pixi_metadata
124+
125+
active_env_prefix="$(_mache_deploy_active_env_prefix)"
126+
pixi_metadata="${active_env_prefix}/conda-meta/pixi"
127+
128+
if [[ ! -d "${active_env_prefix}" ]]; then
129+
echo "ERROR: deployed pixi environment not found." >&2
130+
echo " Expected: ${active_env_prefix}" >&2
131+
return 1
132+
fi
133+
134+
if [[ ! -f "${pixi_metadata}" ]]; then
135+
echo "ERROR: deployed pixi environment metadata not found." >&2
136+
echo " Expected: ${pixi_metadata}" >&2
137+
return 1
138+
fi
139+
}
140+
141+
_mache_deploy_require_active_env || return 1
142+
117143
# Optional: verify the deployed software version matches the runtime version.
118144
#
119145
# The probe command (if set) is executed in the target pixi environment via
@@ -131,7 +157,7 @@ if [[ -n "${MACHE_DEPLOY_RUNTIME_VERSION_CMD:-}" ]]; then
131157
probe_output="$(
132158
env -u PIXI_PROJECT_MANIFEST -u PIXI_PROJECT_ROOT \
133159
-u PIXI_ENVIRONMENT_NAME -u PIXI_IN_SHELL \
134-
"${PIXI}" run -m "${MACHE_DEPLOY_ACTIVE_PIXI_TOML}" -- \
160+
"${PIXI}" run --as-is -m "${MACHE_DEPLOY_ACTIVE_PIXI_TOML}" -- \
135161
bash -c "${MACHE_DEPLOY_RUNTIME_VERSION_CMD}" 2>&1
136162
)"
137163
status=$?
@@ -167,9 +193,12 @@ fi
167193

168194
echo "loading ${MACHE_DEPLOY_ACTIVE_ENV_KIND} pixi env..."
169195
# Use `shell-hook` (not `pixi run`) so activation applies to this shell.
196+
# Shared deployments can be read-only for downstream users, so avoid any
197+
# lockfile or environment writes during activation.
170198
eval "$(env -u PIXI_PROJECT_MANIFEST -u PIXI_PROJECT_ROOT \
171199
-u PIXI_ENVIRONMENT_NAME -u PIXI_IN_SHELL \
172-
"${PIXI}" shell-hook -s bash -m "${MACHE_DEPLOY_ACTIVE_PIXI_TOML}")"
200+
"${PIXI}" shell-hook --as-is -s bash -m \
201+
"${MACHE_DEPLOY_ACTIVE_PIXI_TOML}")"
173202
echo " pixi env loaded."
174203

175204
# Spack activation (optional)

tests/test_deploy_run.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import argparse
22
import configparser
3+
import subprocess
34
from pathlib import Path
45

56
import pytest
@@ -463,6 +464,54 @@ def test_write_load_script_uses_user_pixi_when_configured_for_path_lookup(
463464
)
464465
assert 'command -v pixi' in script_text
465466
assert 'Set PIXI to a pixi executable path' in script_text
467+
assert '"${PIXI}" shell-hook --as-is -s bash -m' in script_text
468+
assert '"${PIXI}" run --as-is -m' in script_text
469+
470+
471+
def test_load_script_fails_before_calling_pixi_when_env_missing(
472+
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
473+
):
474+
monkeypatch.chdir(tmp_path)
475+
476+
marker = tmp_path / 'pixi-called.txt'
477+
pixi_exe = tmp_path / 'bin' / 'pixi'
478+
pixi_exe.parent.mkdir(parents=True, exist_ok=True)
479+
pixi_exe.write_text(
480+
f'#!/bin/sh\nprintf called > {marker}\nexit 99\n',
481+
encoding='utf-8',
482+
)
483+
pixi_exe.chmod(0o755)
484+
485+
compute_prefix = tmp_path / 'compute'
486+
compute_prefix.mkdir()
487+
488+
script_path = deploy_run._write_load_script(
489+
prefix=str(compute_prefix),
490+
login_env=None,
491+
pixi_exe=str(pixi_exe),
492+
branch_path=str(tmp_path),
493+
load_script_pixi_exe=_explicit_load_script_pixi(str(pixi_exe)),
494+
software='e3sm-unified',
495+
software_version='1.0.0',
496+
runtime_version_cmd=None,
497+
machine=None,
498+
compute_pixi_mpi='nompi',
499+
toolchain_compiler=None,
500+
toolchain_mpi=None,
501+
spack_library_view=None,
502+
spack_activation='',
503+
)
504+
505+
result = subprocess.run(
506+
['bash', '-lc', f'source {script_path!s}'],
507+
text=True,
508+
capture_output=True,
509+
)
510+
511+
assert result.returncode == 1
512+
assert 'deployed pixi environment not found' in result.stderr
513+
assert str(compute_prefix / '.pixi' / 'envs' / 'default') in result.stderr
514+
assert not marker.exists()
466515

467516

468517
def test_write_load_script_without_login_env_skips_compute_detection(

0 commit comments

Comments
 (0)