From 47432b0bc796d310174eeda467f83078b29b879c Mon Sep 17 00:00:00 2001 From: Daniel Han Date: Fri, 8 May 2026 02:43:22 +0000 Subject: [PATCH] cli(windows): capture setup.ps1 Write-Host output via -Command + *>&1 `unsloth studio update --local 2>&1 | tee logs/update.log` was producing an empty update.log on windows-latest because _run_setup_script() invoked powershell.exe -File studio/setup.ps1. setup.ps1 emits every step/substep line via Write-Host, which on PowerShell 5+ lands on the Information stream (#6) and is NOT merged into stdout when -File is used and the parent's stdout is a pipe. The bash tee in CI therefore saw nothing, and the post-step grep for "prebuilt up to date and validated" failed with ::error::no prebuilt up-to-date marker in update.log. Switch the Windows branch from -File to -Command, with the script path single-quoted (apostrophes escaped per PowerShell rules) and followed by *>&1 so all six PS streams (stdout, stderr, warning, verbose, debug, information) are merged into the success stream. That stream is then inherited by the Python subprocess and reaches the parent's stdout pipe verbatim. This also makes the install.ps1 -> unsloth.exe -> setup.ps1 grandchild output visible at install time for the first time, so logs/install.log gains the existing "prebuilt installed and validated" marker. The Windows-update workflow's filesystem-based fallback is unchanged and still works. Mac is untouched (still uses bash setup.sh -- plain stdout). --- unsloth_cli/commands/studio.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/unsloth_cli/commands/studio.py b/unsloth_cli/commands/studio.py index 76aac3dc15..f80fc5b087 100644 --- a/unsloth_cli/commands/studio.py +++ b/unsloth_cli/commands/studio.py @@ -998,7 +998,21 @@ def _run_setup_script(*, verbose: bool = False) -> None: powershell_args.extend( ["-NoLogo", "-NoProfile", "-NonInteractive", "-WindowStyle", "Hidden"] ) - powershell_args.extend(["-ExecutionPolicy", "Bypass", "-File", str(script)]) + # Use -Command + `*>&1` instead of -File so setup.ps1's + # Write-Host output (PowerShell Information stream / #6) is + # merged into the success stream and reaches the parent's + # stdout. With -File, Information stream output is dropped + # whenever stdout is a pipe, which is exactly the situation + # CI hits with `unsloth studio update --local 2>&1 | tee + # logs/update.log`. Single-quote escaping handles paths that + # contain apostrophes. + script_pwsh_literal = str(script).replace("'", "''") + powershell_args.extend( + [ + "-ExecutionPolicy", "Bypass", + "-Command", f"& '{script_pwsh_literal}' *>&1", + ] + ) result = subprocess.run( powershell_args, env = env,