micro-fix: quickstart dashboard auto-launch for PowerShell (#6655)

* Fix quickstart dashboard auto-launch on Windows

* chore: refresh locks

* fix: gate quickstart hive shim to Git Bash

* chore: revert unrelated frontend lockfile churn
This commit is contained in:
Sundaram Kumar Jha
2026-03-22 13:51:02 +05:30
committed by GitHub
parent a2cd96a1a7
commit 27d5061d97
4 changed files with 157 additions and 18 deletions
+33 -4
View File
@@ -1561,6 +1561,22 @@ def _open_browser(url: str) -> None:
pass # Best-effort — don't crash if browser can't open
def _format_subprocess_output(output: str | bytes | None, limit: int = 2000) -> str:
"""Return subprocess output as trimmed text safe for console logging."""
if not output:
return ""
if isinstance(output, bytes):
text = output.decode(errors="replace")
else:
text = output
text = text.strip()
if len(text) <= limit:
return text
return text[-limit:]
def _build_frontend() -> bool:
"""Build the frontend if source is newer than dist. Returns True if dist exists."""
import subprocess
@@ -1596,18 +1612,25 @@ def _build_frontend() -> bool:
# Need to build
print("Building frontend...")
npm_cmd = "npm.cmd" if sys.platform == "win32" else "npm"
try:
# Incremental tsc caches can drift across branch changes and block builds.
for cache_file in frontend_dir.glob("tsconfig*.tsbuildinfo"):
cache_file.unlink(missing_ok=True)
# Ensure deps are installed
subprocess.run(
["npm", "install", "--no-fund", "--no-audit"],
[npm_cmd, "install", "--no-fund", "--no-audit"],
encoding="utf-8",
errors="replace",
cwd=frontend_dir,
check=True,
capture_output=True,
)
subprocess.run(
["npm", "run", "build"],
[npm_cmd, "run", "build"],
encoding="utf-8",
errors="replace",
cwd=frontend_dir,
check=True,
capture_output=True,
@@ -1618,8 +1641,14 @@ def _build_frontend() -> bool:
print("Node.js not found — skipping frontend build.")
return dist_dir.is_dir()
except subprocess.CalledProcessError as exc:
stderr = exc.stderr.decode(errors="replace") if exc.stderr else ""
print(f"Frontend build failed: {stderr[:500]}")
stdout = _format_subprocess_output(exc.stdout)
stderr = _format_subprocess_output(exc.stderr)
cmd = " ".join(exc.cmd) if isinstance(exc.cmd, (list, tuple)) else str(exc.cmd)
details = "\n".join(part for part in [stdout, stderr] if part).strip()
if details:
print(f"Frontend build failed while running {cmd}:\n{details}")
else:
print(f"Frontend build failed while running {cmd} (exit {exc.returncode}).")
return dist_dir.is_dir()
+60
View File
@@ -0,0 +1,60 @@
"""Tests for frontend build fallback in the runner CLI."""
import subprocess
from framework.runner import cli as runner_cli
def _write_frontend_tree(tmp_path, *, with_dist: bool = False):
frontend_dir = tmp_path / "core" / "frontend"
(frontend_dir / "src").mkdir(parents=True)
(frontend_dir / "package.json").write_text("{}", encoding="utf-8")
(frontend_dir / "src" / "main.tsx").write_text("console.log('hi')", encoding="utf-8")
if with_dist:
(frontend_dir / "dist").mkdir()
(frontend_dir / "dist" / "index.html").write_text("<!doctype html>", encoding="utf-8")
return frontend_dir
def test_build_frontend_handles_text_calledprocesserror(monkeypatch, tmp_path, capsys):
_write_frontend_tree(tmp_path)
monkeypatch.chdir(tmp_path)
def fake_run(cmd, **kwargs):
raise subprocess.CalledProcessError(
1,
cmd,
output="npm output",
stderr="vite config failed",
)
monkeypatch.setattr(subprocess, "run", fake_run)
assert runner_cli._build_frontend() is False
output = capsys.readouterr().out
assert "Frontend build failed while running" in output
assert "vite config failed" in output
def test_build_frontend_cleans_cache_and_uses_windows_npm_cmd(monkeypatch, tmp_path):
frontend_dir = _write_frontend_tree(tmp_path)
cache_file = frontend_dir / "tsconfig.app.tsbuildinfo"
cache_file.write_text("stale", encoding="utf-8")
monkeypatch.chdir(tmp_path)
monkeypatch.setattr(runner_cli.sys, "platform", "win32")
commands = []
def fake_run(cmd, **kwargs):
commands.append(cmd)
return subprocess.CompletedProcess(cmd, 0, stdout="", stderr="")
monkeypatch.setattr(subprocess, "run", fake_run)
assert runner_cli._build_frontend() is True
assert not cache_file.exists()
assert commands == [
["npm.cmd", "install", "--no-fund", "--no-audit"],
["npm.cmd", "run", "build"],
]
+47 -9
View File
@@ -66,6 +66,32 @@ function Write-Fail {
Write-Color -Text " X $Text" -Color Red
}
function Write-CommandFailureDetails {
param(
[object[]]$Output,
[int]$Tail = 40
)
$lines = @($Output | Where-Object { $_ -ne $null } | ForEach-Object { "$_" })
if ($lines.Count -eq 0) {
return
}
$start = [Math]::Max(0, $lines.Count - $Tail)
if ($start -gt 0) {
Write-Host " ... showing last $($lines.Count - $start) lines ..." -ForegroundColor DarkGray
}
for ($i = $start; $i -lt $lines.Count; $i++) {
Write-Host " $($lines[$i])" -ForegroundColor DarkGray
}
}
function Test-FrontendDistReady {
param([string]$RootDir)
return (Test-Path (Join-Path $RootDir "core\frontend\dist\index.html"))
}
function Prompt-YesNo {
param(
[string]$Prompt,
@@ -540,6 +566,7 @@ Write-Host ""
# Build frontend (if Node.js is available)
$FrontendBuilt = $false
$FrontendDistReady = Test-FrontendDistReady -RootDir $ScriptDir
if ($NodeAvailable) {
Write-Step -Number "" -Text "Building frontend dashboard..."
Write-Host ""
@@ -548,30 +575,33 @@ if ($NodeAvailable) {
Write-Host " Installing npm packages... " -NoNewline
Push-Location $frontendDir
try {
$null = & npm install --no-fund --no-audit 2>&1
$installOutput = & npm install --no-fund --no-audit 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Ok "ok"
# Clean stale tsbuildinfo cache — tsc -b incremental builds fail
# silently when these are out of sync with source files
Get-ChildItem -Path $frontendDir -Filter "tsconfig*.tsbuildinfo" -ErrorAction SilentlyContinue | Remove-Item -Force
Write-Host " Building frontend... " -NoNewline
$null = & npm run build 2>&1
$buildOutput = & npm run build 2>&1
if ($LASTEXITCODE -eq 0) {
Write-Ok "ok"
Write-Ok "Frontend built -> core/frontend/dist/"
$FrontendBuilt = $true
$FrontendDistReady = $true
} else {
Write-Warn "build failed"
Write-Host " Run 'cd core\frontend && npm run build' manually to debug." -ForegroundColor DarkGray
Write-CommandFailureDetails -Output $buildOutput -Tail 60
Write-Host " Quickstart will still try '.\hive.ps1 open' if Hive can rebuild the dashboard." -ForegroundColor DarkGray
}
} else {
Write-Warn "npm install failed"
$NodeAvailable = $false
Write-CommandFailureDetails -Output $installOutput -Tail 60
}
} finally {
Pop-Location
}
}
$FrontendDistReady = Test-FrontendDistReady -RootDir $ScriptDir
Write-Host ""
}
@@ -2016,13 +2046,21 @@ Write-Color -Text "hive open" -Color Cyan -NoNewline
Write-Host ". Run .\quickstart.ps1 again to reconfigure." -ForegroundColor DarkGray
Write-Host ""
if ($FrontendBuilt) {
Write-Color -Text "Launching dashboard..." -Color White
if ($FrontendDistReady -or $NodeAvailable) {
if ($FrontendDistReady) {
Write-Color -Text "Launching dashboard..." -Color White
} else {
Write-Color -Text "Launching dashboard (retrying frontend build via hive open)..." -Color White
}
Write-Host ""
& hive open
& $hivePs1Path open
if ($LASTEXITCODE -ne 0) {
Write-Warn "Dashboard launch failed"
Write-Host " Run '.\hive.ps1 open' manually to inspect the error." -ForegroundColor DarkGray
}
} else {
Write-Color -Text "Frontend build was skipped or failed." -Color Yellow -NoNewline
Write-Color -Text "Frontend build was skipped or failed, and no built dashboard is available." -Color Yellow -NoNewline
Write-Host " Launch manually when ready:"
Write-Color -Text " hive open" -Color Cyan
Write-Color -Text " .\hive.ps1 open" -Color Cyan
Write-Host ""
}
+17 -5
View File
@@ -1792,15 +1792,27 @@ echo ""
# Ensure ~/.local/bin exists and is in PATH
mkdir -p "$HOME/.local/bin"
# Create/update symlink
# Git Bash on Windows may materialize `ln -s` as a plain file copy.
# Use a launcher shim there, but prefer a real symlink on Linux/macOS.
HIVE_SCRIPT="$SCRIPT_DIR/hive"
HIVE_LINK="$HOME/.local/bin/hive"
HIVE_SCRIPT_ESCAPED=$(printf '%q' "$HIVE_SCRIPT")
if [ -L "$HIVE_LINK" ] || [ -e "$HIVE_LINK" ]; then
rm -f "$HIVE_LINK"
fi
ln -s "$HIVE_SCRIPT" "$HIVE_LINK"
if [ -n "$MSYSTEM" ] || [ -n "$MINGW_PREFIX" ]; then
cat > "$HIVE_LINK" <<EOF
#!/usr/bin/env bash
set -e
HIVE_SCRIPT=$HIVE_SCRIPT_ESCAPED
exec "\$HIVE_SCRIPT" "\$@"
EOF
chmod +x "$HIVE_LINK"
else
ln -s "$HIVE_SCRIPT" "$HIVE_LINK"
fi
echo -e "${GREEN} ✓ hive CLI installed to ~/.local/bin/hive${NC}"
# Check if ~/.local/bin is in PATH
@@ -1894,15 +1906,15 @@ if [ "$CODEX_AVAILABLE" = true ]; then
fi
echo -e "${DIM}API keys saved to ${CYAN}$SHELL_RC_FILE${NC}${DIM}. New terminals pick them up automatically.${NC}"
echo -e "${DIM}Launch anytime with ${CYAN}hive open${NC}${DIM}. Run ./quickstart.sh again to reconfigure.${NC}"
echo -e "${DIM}Launch anytime from this project root with ${CYAN}./hive open${NC}${DIM}. Run ./quickstart.sh again to reconfigure.${NC}"
echo ""
if [ "$FRONTEND_BUILT" = true ]; then
echo -e "${BOLD}Launching dashboard...${NC}"
echo ""
hive open
"$SCRIPT_DIR/hive" open
else
echo -e "${YELLOW}Frontend build was skipped or failed.${NC} Launch manually when ready:"
echo -e " ${CYAN}hive open${NC}"
echo -e " ${CYAN}./hive open${NC}"
echo ""
fi