diff --git a/docs/RUNBOOK-PhaseC.md b/docs/RUNBOOK-PhaseC.md index 05740cd..41babd7 100644 --- a/docs/RUNBOOK-PhaseC.md +++ b/docs/RUNBOOK-PhaseC.md @@ -201,7 +201,9 @@ default `--snapshot-name` is `BaseClean`, so Linux jobs must pass `--skip-artifact`, `--xvfb` (Linux GUI builds), `--extra-env-json '{"KEY":"VALUE"}'` - **VM**: `--guest-cpu N`, `--guest-memory-mb N`, `--template-path`, - `--snapshot-name`, `--ready-timeout` + `--snapshot-name`, `--ready-timeout`, `--gui` / `--nogui` (default `--nogui`, + headless; `--gui` opens the Workstation window and needs an X display — + see [§4.7](#47-open-a-vm-in-the-workstation-gui)) - **Auth**: `--gitea-credential-target` (private repos) > For a zero-config end-to-end check, prefer `smoke run` ([§7](#7-phase-c-testing)) diff --git a/src/ci_orchestrator/commands/job.py b/src/ci_orchestrator/commands/job.py index a8d4f3e..eeefbd4 100644 --- a/src/ci_orchestrator/commands/job.py +++ b/src/ci_orchestrator/commands/job.py @@ -390,6 +390,14 @@ def _destroy_clone( show_default=True, ) @click.option("--vmrun-path", "vmrun_path", default=None) +@click.option( + "--gui/--nogui", + "gui", + default=False, + show_default=True, + help="Start the VM with the Workstation GUI window (--gui) or headless " + "(--nogui, the default).", +) def job( job_id: str, repo_url: str, @@ -419,6 +427,7 @@ def job( ready_timeout: float, poll_interval: float, vmrun_path: str | None, + gui: bool, ) -> None: """Run the full CI pipeline against an ephemeral build VM. @@ -547,9 +556,10 @@ def job( phase_start = _now() # ── Phase 2/5: start VM ───────────────────────────────────────── - click.echo("\n[job] Phase 2/5 — starting VM (headless)") + mode = "GUI" if gui else "headless" + click.echo(f"\n[job] Phase 2/5 — starting VM ({mode})") try: - backend.start(handle, headless=True) + backend.start(handle, headless=not gui) except BackendError as exc: raise click.ClickException(f"vmrun start failed: {exc}") from exc