Files
actionbook__actionbook/.github
Junliang Feng 11e71d9d03 feat(daemon): add Windows TCP localhost IPC support (ACT-897) (#508)
* test(daemon): add Windows daemon red coverage (ACT-897)

Add tests and CI configuration for Windows daemon TCP transport:
- config.rs: test_actionbook_home_uses_userprofile_when_home_unset — cross-platform
  red test; fails until USERPROFILE fallback is implemented
- server.rs: port_path() stub (path-only) + #[cfg(all(test,windows))] unit tests for
  is_daemon_running, send_sigterm, is_pid_alive Windows behaviour
- tests/e2e/windows_daemon.rs: 3 e2e tests ignored on non-Windows, run on Windows CI
- .github/workflows/e2e-windows.yml: windows-latest CI job for unit + e2e tests

* feat(daemon): add Windows TCP localhost IPC support (ACT-897)

Unix behaviour is unchanged (UnixListener/UnixStream, flock).
Windows now uses TCP localhost instead of the missing Unix socket:

server.rs:
- run_daemon(): bind TcpListener on 127.0.0.1:0, write ephemeral port to
  daemon.port; use fs2::FileExt for cross-platform exclusive file locking
- is_daemon_running(): TCP connect-probe against daemon.port (Windows)
- send_sigterm(): taskkill /F /PID (Windows)
- is_pid_alive(): delegates to is_daemon_running() TCP probe (Windows)
- handle_connection_inner(): generic AsyncRead+AsyncWrite handler shared by
  both platforms; Unix/Windows handle_connection() call it with the
  appropriate stream type
- port_path(): daemon.port path (used both platforms for path derivation)

client.rs:
- DaemonClient (Windows): TcpStream-based connect/send_action
- auto_start_daemon_windows(): spawns daemon with DETACHED_PROCESS |
  CREATE_NEW_PROCESS_GROUP flags so it survives parent exit
- wait/restart/cleanup helpers mirroring the Unix equivalents

config.rs:
- actionbook_home(): fall back to USERPROFILE when HOME is not set
  (standard Windows home directory convention)

Cargo.toml:
- Add fs2 = "0.4" for cross-platform LockFileEx file locking

* style: apply cargo fmt to windows_daemon tests

* fix: serialize USERPROFILE test with config test_lock to prevent env var race

The test_actionbook_home_uses_userprofile_when_home_unset test manipulates
ACTIONBOOK_HOME and HOME env vars without acquiring the shared test_lock,
causing intermittent failures in other config tests that run concurrently.

* fix: gate Unix-only kill() FFI behind #[cfg(unix)] for Windows build

- start.rs: wrap orphan Chrome kill(pid, 0)/kill(pid, 9) in #[cfg(unix)],
  add #[cfg(windows)] equivalent using taskkill
- chrome_reaper.rs: gate Duration/Instant imports behind #[cfg(unix)]
  since they're only used in the Unix SIGTERM graceful shutdown path

* fix: make drop_session_entry test cross-platform for Windows CI

The test used Unix-only `sleep` and `kill -0` commands. Use `ping` for
a long-lived process on Windows and `tasklist` for liveness checks.

* ci: limit Windows e2e to lifecycle, tab management, and daemon tests

Run only windows_daemon, browser_lifecycle, and tab_management test
modules on Windows CI to avoid timeouts from tests not yet adapted
for Windows. Run sequentially with --test-threads=1.

* ci: narrow Windows e2e to windows_daemon + tab_management

browser_lifecycle tests hang on Windows (close_kills_chrome_process
stuck for 30min). These tests exercise daemon lifecycle edge cases
not yet adapted for Windows. Narrow scope to windows_daemon and
tab_management which cover core IPC and browser operations.

* ci: narrow Windows e2e to windows_daemon tests only

tab_management tests require full Chrome browser interaction and hang
on Windows CI. Only run our Windows-specific daemon IPC tests which
validate the TCP localhost approach without Chrome dependencies.

* fix: avoid pipe-inheritance hang in e2e harness on Windows

On Windows, assert_cmd pipes stdout/stderr. When the CLI spawns a
detached daemon, the daemon inherits those pipe handles via
CreateProcess(bInheritHandles=TRUE). Even after the CLI exits, the
daemon still holds write handles, blocking the test's read_to_end()
forever.

Fix: redirect stdout/stderr to temp files on Windows instead of pipes.
Also make SoloEnv::drop() cross-platform (taskkill on Windows).

* fix: add wait-timeout dev-dependency for Windows e2e harness

The Windows-specific timeout code in the e2e harness uses
wait_timeout::ChildExt directly. It was previously only available
transitively via assert_cmd, which isn't sufficient on Windows.

* fix: add Windows Chrome discovery and fix e2e test subcommand

- find_chrome(): Add Windows paths (Program Files, LOCALAPPDATA) and
  use `where` instead of `which` for PATH lookup on Windows
- Fix session_status_works_over_tcp test: use 'status' subcommand
  (not 'session-status' which doesn't exist)

* fix: use test env's ACTIONBOOK_HOME for daemon.port path assertion

The port file test was checking the global ~/.actionbook/daemon.port
but the test daemon writes to SoloEnv's isolated temp directory.
2026-04-12 10:06:24 +08:00
..