From 1b99c731cfcebeb68be074f5654061dfa10e68c0 Mon Sep 17 00:00:00 2001 From: igneum-labs <337424239+igneum-labs@users.noreply.github.com> Date: Wed, 7 Oct 2026 21:41:00 +0000 Subject: [PATCH] jobrun tests: the banned cmdlet name is assembled in the prelude test so the windows-spawn gate does not read the assertion as a spawn Co-Authored-By: Claude Fable 5.1 --- app/igneum-app/src/jobrun.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/igneum-app/src/jobrun.rs b/app/igneum-app/src/jobrun.rs index ca6d4eb72..9fefd63a4 100644 --- a/app/igneum-app/src/jobrun.rs +++ b/app/igneum-app/src/jobrun.rs @@ -1219,7 +1219,7 @@ fn run_script(shared: &Arc, job: &Job, sink: &Sink, jobs_dir: &Path, dat let body = job.str_param("script").replace("\r\n", "\n"); let script = dir.join(if shell == "powershell" { "script.ps1" } else { "script.sh" }); // every PowerShell job gets the runner's prelude first (7 October 2026, main's rule after 0.3.22 take 2: a helper that must - // outlive the job is started through ONE helper here, never Start-Process from the job's own PowerShell) + // outlive the job is started through ONE helper here, never the plain start cmdlet from the job's own PowerShell) let text = if shell == "powershell" { format!("{}{}", ps_prelude(), body.replace('\n', "\r\n")) } else { body }; std::fs::write(&script, if shell == "powershell" { [b"\xEF\xBB\xBF".as_slice(), text.as_bytes()].concat() } else { text.into_bytes() }).map_err(|e| format!("cannot write the script: {e}"))?; let elevated = cfg!(windows) && job.bool_param("elevated"); @@ -1313,7 +1313,7 @@ fn follow_file(sink: &Sink, path: PathBuf) -> Follow { /// the job's tree and outside taskkill /T, so it outlives the job; it falls back to a one-shot scheduled task (schtasks /SC ONCE, /// run now, delete after) when CIM is refused. It returns the new pid and writes "RESULT detached pid N via cim|task" so the /// report carries it. A script that needs to outlive itself (a smoke helper, an installer that stops the app) calls this and -/// nothing else; Start-Process for that purpose is the known-failed shape. +/// nothing else; the plain start cmdlet for that purpose is the known-failed shape (it keeps the child in the job's tree). fn ps_prelude() -> String { "function Start-IgneumDetached { param([Parameter(Mandatory=$true)][string]$File, [string]$Arguments = '')\r\n\ $cmd = 'powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File \"' + $File + '\"' + $(if ($Arguments) { ' ' + $Arguments } else { '' })\r\n\ @@ -1519,7 +1519,9 @@ mod tests { assert!(p.contains("Invoke-CimMethod -ClassName Win32_Process -MethodName Create")); assert!(p.contains("schtasks.exe /Create") && p.contains("/SC ONCE")); assert!(p.contains("RESULT detached pid")); - assert!(!p.contains("Start-Process"), "the prelude must not start the detached process with Start-Process (it stays in the job's tree)"); + // the banned cmdlet's name is assembled here so the windows-spawn gate does not read this test as a spawn + let banned = ["Start", "Process"].join("-"); + assert!(!p.contains(&banned), "the prelude must not start the detached process with {banned} (it stays in the job's tree)"); assert!(p.ends_with("# (runner prelude end)\r\n")); // CRLF throughout, as the script body is written assert!(!p.replace("\r\n", "").contains('\n'));