From 830af86098c4bce10c3fae6b3826271271efbd8b Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Thu, 5 Nov 2026 12:25:50 -0800 Subject: [PATCH] fix(dev): keep the dev shell out of the MOQ_* namespace #7710 exported MOQ_QUEST, which every moq binary rejects as an unknown variable. Rename it to DEV_SHELL_QUEST and assert the shell exports no MOQ_*. Co-Authored-By: Claude Opus 5.5 --- flake.nix | 79 ++++++++++++++++++++++----------------- sh/dispatch-query.test.py | 2 +- sh/js/workspace.test.py | 2 +- sh/local.test.py | 6 +-- sh/quest.sh | 6 +-- 5 files changed, 53 insertions(+), 42 deletions(-) diff --git a/flake.nix b/flake.nix index 2d0545d981e..94ebd0dc3cf 100644 --- a/flake.nix +++ b/flake.nix @@ -691,40 +691,51 @@ PATH=$(printf '%s' "$PATH" | awk -v RS=: '!seen[$0]++ { printf "%s%s", sep, $0; sep = ":" }') ''; - env = { - # What sh/dispatch.sh checks before a scoped `just check` or `just - # fix`. IN_NIX_SHELL would also pass inside another project's shell. - IN_MOQ_DEV_SHELL = "1"; - - # Local launchers need the exact build without evaluating the flake again. - MOQ_QUEST = "${quest-cli}/bin/quest"; - - PLAYWRIGHT_BROWSERS_PATH = "${pkgs.playwright-driver.browsers}"; - PLAYWRIGHT_VERSION = pkgs.playwright-driver.version; - PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS = "true"; - - # Where `just obs compile` and `just obs test` look for libobs. Set - # on every platform so the plugin type-checks against the pinned OBS - # release everywhere, rather than whatever the host happens to have. - OBS_INCLUDE_DIR = "${obs-headers}/include/obs"; - - # What `just obs check` compares the two in-repo OBS pins against. - # Exported rather than read back out of nix, so the guard costs a - # variable lookup instead of a nested evaluation of this flake. - OBS_LINKED_VERSION = obs-linked-version; - - # Link libvpx statically for moq-video's `vpx` feature, the shape the - # quest ships: no system codec library at runtime. - VPX_STATIC = "1"; - } - // pkgs.lib.optionalAttrs (!pkgs.stdenv.hostPlatform.isDarwin) { - ALSA_PLUGIN_DIR = "${alsaPlugins}/lib/alsa-lib"; - # Firefox loads these at runtime; harness.ts exposes them only to its process. - PLAYWRIGHT_FIREFOX_LIBRARY_PATH = pkgs.lib.makeLibraryPath [ - pkgs.ffmpeg - pkgs.libpulseaudio - ]; - }; + # moq binaries reject any MOQ_* variable they don't read, so the + # shell must export none. + env = + let + vars = { + # What sh/dispatch.sh checks before a scoped `just check` or `just + # fix`. IN_NIX_SHELL would also pass inside another project's shell. + IN_MOQ_DEV_SHELL = "1"; + + # Local launchers need the exact build without evaluating the flake again. + # QUEST_* belongs to quest itself. + DEV_SHELL_QUEST = "${quest-cli}/bin/quest"; + + PLAYWRIGHT_BROWSERS_PATH = "${pkgs.playwright-driver.browsers}"; + PLAYWRIGHT_VERSION = pkgs.playwright-driver.version; + PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS = "true"; + + # Where `just obs compile` and `just obs test` look for libobs. Set + # on every platform so the plugin type-checks against the pinned OBS + # release everywhere, rather than whatever the host happens to have. + OBS_INCLUDE_DIR = "${obs-headers}/include/obs"; + + # What `just obs check` compares the two in-repo OBS pins against. + # Exported rather than read back out of nix, so the guard costs a + # variable lookup instead of a nested evaluation of this flake. + OBS_LINKED_VERSION = obs-linked-version; + + # Link libvpx statically for moq-video's `vpx` feature, the shape the + # quest ships: no system codec library at runtime. + VPX_STATIC = "1"; + } + // pkgs.lib.optionalAttrs (!pkgs.stdenv.hostPlatform.isDarwin) { + ALSA_PLUGIN_DIR = "${alsaPlugins}/lib/alsa-lib"; + # Firefox loads these at runtime; harness.ts exposes them only to its process. + PLAYWRIGHT_FIREFOX_LIBRARY_PATH = pkgs.lib.makeLibraryPath [ + pkgs.ffmpeg + pkgs.libpulseaudio + ]; + }; + moq = builtins.filter (pkgs.lib.hasPrefix "MOQ_") (builtins.attrNames vars); + in + assert pkgs.lib.assertMsg ( + moq == [ ] + ) "dev shell must not export MOQ_* (moq binaries reject them): ${toString moq}"; + vars; }; formatter = pkgs.nixfmt-tree; diff --git a/sh/dispatch-query.test.py b/sh/dispatch-query.test.py index 346f8fe7454..b2669c5149d 100644 --- a/sh/dispatch-query.test.py +++ b/sh/dispatch-query.test.py @@ -288,7 +288,7 @@ def stub_ci(self, just=""): nix.chmod(0o755) quest = self.bin / "quest" quest.write_text('#!/usr/bin/env bash\nprintf "pinned quest %s\\n" "$*" >>"$CALLS"\n') - self.env.update(IN_MOQ_DEV_SHELL="1", MOQ_QUEST=str(quest), CALLS=str(self.root / "calls")) + self.env.update(IN_MOQ_DEV_SHELL="1", DEV_SHELL_QUEST=str(quest), CALLS=str(self.root / "calls")) (self.root / "calls").unlink(missing_ok=True) for script in ("markdown.sh", "shell.sh", "large-files.sh", "text.sh"): path = self.repo / "sh" / script diff --git a/sh/js/workspace.test.py b/sh/js/workspace.test.py index cdae09e53c9..9f9ad2bac50 100644 --- a/sh/js/workspace.test.py +++ b/sh/js/workspace.test.py @@ -79,7 +79,7 @@ def test_dispatcher_passes_only_js_impact_paths(self): env = dispatch_env( PATH=f"{tools}:{os.environ['PATH']}", ALLOW_HOST_TOOLCHAIN="1", - MOQ_QUEST=str(tools / "quest"), + DEV_SHELL_QUEST=str(tools / "quest"), SELECT_CALLS=str(calls), ) for script in ("markdown.sh", "shell.sh", "large-files.sh", "text.sh"): diff --git a/sh/local.test.py b/sh/local.test.py index b2cdb5a7ff4..74e6dc913bd 100644 --- a/sh/local.test.py +++ b/sh/local.test.py @@ -25,7 +25,7 @@ def env(self, **changes): "LOCAL_SUPERVISED", "GITHUB_ACTIONS", "NEXTEST_TEST_THREADS", - "MOQ_QUEST", + "DEV_SHELL_QUEST", "ALLOW_HOST_TOOLCHAIN", "BASH_ENV", ): @@ -78,7 +78,7 @@ def test_admission_precedes_launch_and_nested_calls_skip_it(self): f"sys.exit(subprocess.call([{BASH!r}, {str(LAUNCHER)!r}, " 'sys.executable, "-c", "print(\'inner\'); exit(11)"]))' ) - result = self.run_command(script, PATH=directory, MOQ_QUEST=str(quest)) + result = self.run_command(script, PATH=directory, DEV_SHELL_QUEST=str(quest)) self.assertEqual(result.returncode, 11, result.stderr) self.assertEqual(result.stdout.splitlines(), ["admitted", "outer", "inner"]) @@ -101,7 +101,7 @@ def test_pinned_review_preserves_arguments_cwd_and_failure_without_host_fallback result = subprocess.run( [BASH, str(ROOT / "sh/quest.sh"), "review", "--base", "origin/main", "--responses", "a file.json"], cwd=directory, - env=self.env(PATH=directory, MOQ_QUEST=str(quest)), + env=self.env(PATH=directory, DEV_SHELL_QUEST=str(quest)), capture_output=True, text=True, ) diff --git a/sh/quest.sh b/sh/quest.sh index e211493fe8f..9af9b60f4e8 100644 --- a/sh/quest.sh +++ b/sh/quest.sh @@ -3,9 +3,9 @@ set -euo pipefail root=$(cd "${BASH_SOURCE[0]%/*}/.." && pwd) -if [[ -n ${MOQ_QUEST:-} ]]; then - printf 'Dev-shell quest: %s\n' "$MOQ_QUEST" >&2 - exec "$MOQ_QUEST" "$@" +if [[ -n ${DEV_SHELL_QUEST:-} ]]; then + printf 'Dev-shell quest: %s\n' "$DEV_SHELL_QUEST" >&2 + exec "$DEV_SHELL_QUEST" "$@" fi if [[ -n ${ALLOW_HOST_TOOLCHAIN:-} || $OSTYPE == msys || $OSTYPE == cygwin ]]; then