fix(windows): stop subprocess console-window popups + add CI guard (#53791)

* fix(windows): stop subprocess console-window popups + add CI guard

The single biggest source of Windows 'terminal popup' bug reports was bare
subprocess.run/Popen calls spawning a console window. The compat helpers
(windows_hide_flags / windows_detach_popen_kwargs) already existed but the
footgun checker had no rule to stop new bare calls from reintroducing the flash.

- scripts/check-windows-footguns.py: new AST-based rule flagging subprocess
  calls that can create a new console — output-redirection-aware (capture/
  redirect/check_output exempt) and POSIX-only-program-aware (launchctl/
  systemctl/brew/etc. exempt). Comprehensive on real popups, no annotation
  burden on calls that can't flash.
- Swept all genuine window-spawning sites through windows_hide_flags()/
  windows_detach_popen_kwargs(); marked intentionally-visible launches
  (editor/terminal/foreground re-exec) with '# windows-footgun: ok'.
- tests/scripts/test_windows_footgun_subprocess_rule.py: behavior-contract
  tests + full-repo cleanliness invariant.
- CONTRIBUTING.md: documents the rule + the helper pattern.

* test: accept creationflags kwarg in psutil_android fake_subprocess_run

The Windows no-window sweep added creationflags=windows_hide_flags() to
install_psutil_android.py's subprocess.run call; the test's fake stub had a
fixed (cmd) signature and raised TypeError on the new kwarg.
This commit is contained in:
Teknium 2026-06-27 13:03:51 -07:00 committed by GitHub
parent 3b44a3c8bb
commit ef17cd204d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 445 additions and 34 deletions

View file

@ -42,6 +42,7 @@ from hermes_cli.psutil_android import (
PsutilAndroidInstallError,
prepare_patched_psutil_sdist,
)
from hermes_cli._subprocess_compat import windows_hide_flags
@ -90,7 +91,7 @@ def main() -> int:
cmd = install_cmd_prefix + ["install", "--no-build-isolation", str(src_root)]
print(f" $ {' '.join(cmd)}")
result = subprocess.run(cmd)
result = subprocess.run(cmd, creationflags=windows_hide_flags())
if result.returncode != 0:
return result.returncode