From 2c4bc677d75a2e932afd1d0b824727d3d67d585e Mon Sep 17 00:00:00 2001 From: Adrian Gierakowski Date: Fri, 6 Mar 2026 11:00:51 +0100 Subject: [PATCH] feat: add preHook option to landrunApp This adds a `preHook` option to `landrunApp`, allowing users to inject shell commands that run before the sandbox is initialized. This is useful for creating directories needed by the sandbox or decrypting/setting environment variables. - Modified `options.nix` to add `preHook`. - Updated `linux/wrapper.nix` and `darwin/wrapper.nix` to inject hooks. - Added integration tests in `tests/flake.nix` and `tests/test.bats`. closes #19 --- .../flake-parts/landrun/darwin/wrapper.nix | 2 ++ modules/flake-parts/landrun/linux/wrapper.nix | 2 ++ modules/flake-parts/landrun/options.nix | 5 +++++ tests/flake.nix | 10 +++++++++ tests/test.bats | 22 +++++++++++++++++++ 5 files changed, 41 insertions(+) diff --git a/modules/flake-parts/landrun/darwin/wrapper.nix b/modules/flake-parts/landrun/darwin/wrapper.nix index 0e5ab30..21c7b65 100644 --- a/modules/flake-parts/landrun/darwin/wrapper.nix +++ b/modules/flake-parts/landrun/darwin/wrapper.nix @@ -65,6 +65,8 @@ let EOF + ${config.preHook} + # Isolation of environment variables (like landrun does) ALLOWED_VARS=(${lib.concatStringsSep " " (map (e: "\"${e}\"") config.cli.env)}) KEEP_VARS=("HOME" "USER" "LOGNAME" "PATH" "TERM" "SHELL" "LANG" "LC_ALL" "DISPLAY") diff --git a/modules/flake-parts/landrun/linux/wrapper.nix b/modules/flake-parts/landrun/linux/wrapper.nix index 32436da..3758f4d 100644 --- a/modules/flake-parts/landrun/linux/wrapper.nix +++ b/modules/flake-parts/landrun/linux/wrapper.nix @@ -29,6 +29,8 @@ name = config.name; runtimeInputs = [ pkgs.landrun ]; text = '' + ${config.preHook} + args=() # Add conditional --rox paths diff --git a/modules/flake-parts/landrun/options.nix b/modules/flake-parts/landrun/options.nix index b3dc309..384e888 100644 --- a/modules/flake-parts/landrun/options.nix +++ b/modules/flake-parts/landrun/options.nix @@ -16,6 +16,11 @@ in description = "The program to wrap with landrun (e.g., \${pkgs.foo}/bin/foo)"; }; + preHook = mkOption { + type = types.lines; + default = ""; + description = "Shell commands to execute before starting the sandbox"; + }; features = mkOption { type = types.submodule { diff --git a/tests/flake.nix b/tests/flake.nix index 1a0eb38..266613c 100644 --- a/tests/flake.nix +++ b/tests/flake.nix @@ -125,6 +125,16 @@ # We pass -v (verbose) to landrun via extraArgs cli.extraArgs = [ "-v" ]; }; + test-prestart-dir = { + program = "${pkgs.coreutils}/bin/ls"; + cli.rw = [ "./created_by_hook" ]; + preHook = "mkdir -p ./created_by_hook"; + }; + test-prestart-env = { + program = "${pkgs.bash}/bin/bash"; + cli.env = [ "HOOK_SECRET" ]; + preHook = "export HOOK_SECRET='decrypted_value'"; + }; }; devShells.default = pkgs.mkShell { diff --git a/tests/test.bats b/tests/test.bats index 3558645..cd896e3 100755 --- a/tests/test.bats +++ b/tests/test.bats @@ -26,6 +26,28 @@ log_output () { [ "$status" -eq 0 ] } +@test "test-prestart-dir: creates directory before sandbox starts" { + # The hook runs 'mkdir -p ./created_by_hook' + # The program runs 'ls -d ./created_by_hook' implicitly via test-ls command if arguments allow, + # but here test-prestart-dir is 'ls', so we pass the directory as argument. + + run test-prestart-dir -d ./created_by_hook + log_output + [ "$status" -eq 0 ] + [ -d "created_by_hook" ] +} + +@test "test-prestart-env: sets environment variable in hook" { + # The hook runs 'export HOOK_SECRET=decrypted_value' + # The cli.env has "HOOK_SECRET". + # Wrapper exports the var, landrun picks it up. + + run test-prestart-env -c 'echo $HOOK_SECRET' + log_output + [ "$status" -eq 0 ] + [[ "$output" == *"decrypted_value"* ]] +} + @test "test-no-nix-fail: program cannot exec if it cannot access libs from nix store" { run test-no-nix-fail -c "echo ok" log_output