Skip to content

Commit b607b5c

Browse files
authored
feat: 统一跨平台重启工作流 (#273)
* docs: 补充项目界面预览 * feat: 统一跨平台重启流程 * fix: 规范cmd换行并保护关键PID
1 parent 8235829 commit b607b5c

File tree

4 files changed

+234
-0
lines changed

4 files changed

+234
-0
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.cmd text eol=crlf

cmd/workflows/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Workflow Scripts
2+
3+
This folder stores reusable developer workflow scripts.
4+
5+
## Build + Restart Dev
6+
7+
- Windows CMD: `cmd\workflows\build-restart.cmd`
8+
- Bash (macOS/Linux): `cmd/workflows/build-restart.sh`
9+
10+
Both scripts execute the same workflow:
11+
12+
1. `pnpm build` in `web`
13+
2. stop processes listening on ports `9880` and `9881`
14+
3. start `wails dev`
15+
16+
The scripts auto-detect the repository root by walking up from the script location and finding:
17+
18+
- `go.mod`
19+
- `web/package.json`
20+
21+
So they continue to work even if the script folder is moved deeper under the repo.

cmd/workflows/build-restart.cmd

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
@echo off
2+
setlocal EnableExtensions EnableDelayedExpansion
3+
4+
set "SCRIPT_DIR=%~dp0"
5+
for %%I in ("%SCRIPT_DIR%.") do set "CURRENT_DIR=%%~fI"
6+
7+
:findRoot
8+
if exist "!CURRENT_DIR!\go.mod" if exist "!CURRENT_DIR!\web\package.json" (
9+
set "REPO_ROOT=!CURRENT_DIR!"
10+
goto rootFound
11+
)
12+
13+
for %%I in ("!CURRENT_DIR!\..") do set "PARENT_DIR=%%~fI"
14+
if /I "!PARENT_DIR!"=="!CURRENT_DIR!" goto rootNotFound
15+
set "CURRENT_DIR=!PARENT_DIR!"
16+
goto findRoot
17+
18+
:rootNotFound
19+
echo [ERROR] Could not locate repo root from "%SCRIPT_DIR%".
20+
echo [ERROR] Expected files: go.mod and web\package.json
21+
exit /b 1
22+
23+
:rootFound
24+
set "WEB_DIR=!REPO_ROOT!\web"
25+
26+
echo [1/3] Build frontend ...
27+
cd /d "!WEB_DIR!" || (
28+
echo [ERROR] Failed to enter web dir: "!WEB_DIR!"
29+
exit /b 1
30+
)
31+
32+
call pnpm build
33+
if errorlevel 1 (
34+
echo [ERROR] pnpm build failed. Abort restart.
35+
exit /b 1
36+
)
37+
38+
echo [2/3] Stop processes on ports 9880 and 9881 ...
39+
set "KILLED_ANY=0"
40+
set "SEEN_PIDS=;"
41+
42+
call :killByPort 9880
43+
call :killByPort 9881
44+
45+
if "!KILLED_ANY!"=="0" (
46+
echo [INFO] No running process found on ports 9880/9881.
47+
)
48+
49+
echo [3/3] Start wails dev ...
50+
cd /d "!REPO_ROOT!" || (
51+
echo [ERROR] Failed to enter repo root: "!REPO_ROOT!"
52+
exit /b 1
53+
)
54+
55+
call wails dev %*
56+
set "EXIT_CODE=%ERRORLEVEL%"
57+
echo [INFO] wails dev exited with code %EXIT_CODE%.
58+
exit /b %EXIT_CODE%
59+
60+
:killByPort
61+
set "PORT=%~1"
62+
set "FOUND_ON_PORT=0"
63+
64+
for /f "tokens=2,5" %%A in ('netstat -ano -p tcp ^| findstr /R /C:":[0-9][0-9]* " 2^>nul') do (
65+
set "LOCAL_ADDR=%%A"
66+
set "PID=%%B"
67+
echo !LOCAL_ADDR! | findstr /R /C:":%PORT%$" >nul
68+
if not errorlevel 1 (
69+
set "FOUND_ON_PORT=1"
70+
call :tryKillPid !PID! %PORT%
71+
)
72+
)
73+
74+
if "!FOUND_ON_PORT!"=="0" (
75+
echo [INFO] Port %PORT% is free.
76+
)
77+
goto :eof
78+
79+
:tryKillPid
80+
set "PID=%~1"
81+
set "PORT=%~2"
82+
83+
if not defined PID (
84+
echo [WARN] Empty PID for port %PORT%, skip.
85+
goto :eof
86+
)
87+
88+
echo %PID%| findstr /R "^[0-9][0-9]*$" >nul
89+
if errorlevel 1 (
90+
echo [WARN] Invalid PID %PID% (port %PORT%), skip.
91+
goto :eof
92+
)
93+
94+
if %PID% LEQ 4 (
95+
echo [WARN] Skip protected PID %PID% (port %PORT%).
96+
goto :eof
97+
)
98+
99+
echo !SEEN_PIDS! | findstr /C:";%PID%;" >nul
100+
if not errorlevel 1 (
101+
goto :eof
102+
)
103+
104+
set "SEEN_PIDS=!SEEN_PIDS!%PID%;"
105+
echo [INFO] Killing PID %PID% (port %PORT%)...
106+
taskkill /PID %PID% /F >nul 2>&1
107+
if errorlevel 1 (
108+
echo [WARN] Failed to kill PID %PID% (might have exited already).
109+
) else (
110+
echo [OK] Killed PID %PID%.
111+
set "KILLED_ANY=1"
112+
)
113+
goto :eof

cmd/workflows/build-restart.sh

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5+
CURRENT_DIR="$SCRIPT_DIR"
6+
REPO_ROOT=""
7+
8+
while true; do
9+
if [[ -f "$CURRENT_DIR/go.mod" && -f "$CURRENT_DIR/web/package.json" ]]; then
10+
REPO_ROOT="$CURRENT_DIR"
11+
break
12+
fi
13+
14+
PARENT_DIR="$(dirname "$CURRENT_DIR")"
15+
if [[ "$PARENT_DIR" == "$CURRENT_DIR" ]]; then
16+
break
17+
fi
18+
CURRENT_DIR="$PARENT_DIR"
19+
done
20+
21+
if [[ -z "$REPO_ROOT" ]]; then
22+
echo "[ERROR] Could not locate repo root from \"$SCRIPT_DIR\"."
23+
echo "[ERROR] Expected files: go.mod and web/package.json"
24+
exit 1
25+
fi
26+
27+
WEB_DIR="$REPO_ROOT/web"
28+
29+
echo "[1/3] Build frontend ..."
30+
(
31+
cd "$WEB_DIR"
32+
pnpm build
33+
)
34+
35+
echo "[2/3] Stop processes on ports 9880 and 9881 ..."
36+
KILLED_ANY=0
37+
SEEN_PIDS=";"
38+
39+
kill_pid() {
40+
local pid="$1"
41+
local port="$2"
42+
43+
[[ -z "$pid" ]] && return 0
44+
case "$SEEN_PIDS" in
45+
*";$pid;"*) return 0 ;;
46+
esac
47+
48+
SEEN_PIDS="${SEEN_PIDS}${pid};"
49+
echo "[INFO] Killing PID $pid (port $port)..."
50+
if kill "$pid" >/dev/null 2>&1 || kill -9 "$pid" >/dev/null 2>&1; then
51+
echo "[OK] Killed PID $pid."
52+
KILLED_ANY=1
53+
else
54+
echo "[WARN] Failed to kill PID $pid (might have exited already)."
55+
fi
56+
}
57+
58+
kill_by_port() {
59+
local port="$1"
60+
local found=0
61+
local pids=""
62+
local scanner=""
63+
64+
if command -v lsof >/dev/null 2>&1; then
65+
scanner="lsof"
66+
pids="$(lsof -tiTCP:"$port" -sTCP:LISTEN 2>/dev/null || true)"
67+
elif command -v fuser >/dev/null 2>&1; then
68+
scanner="fuser"
69+
pids="$(fuser -n tcp "$port" 2>/dev/null || true)"
70+
elif command -v ss >/dev/null 2>&1; then
71+
scanner="ss"
72+
pids="$(ss -ltnp "sport = :$port" 2>/dev/null | sed -n 's/.*pid=\([0-9]\+\).*/\1/p' || true)"
73+
fi
74+
75+
if [[ -z "$scanner" ]]; then
76+
echo "[WARN] No port scanner found (need lsof/fuser/ss). Skip cleanup for port $port."
77+
return 0
78+
fi
79+
80+
for pid in $pids; do
81+
found=1
82+
kill_pid "$pid" "$port"
83+
done
84+
85+
if [[ "$found" -eq 0 ]]; then
86+
echo "[INFO] Port $port is free."
87+
fi
88+
}
89+
90+
kill_by_port 9880
91+
kill_by_port 9881
92+
93+
if [[ "$KILLED_ANY" -eq 0 ]]; then
94+
echo "[INFO] No running process found on ports 9880/9881."
95+
fi
96+
97+
echo "[3/3] Start wails dev ..."
98+
cd "$REPO_ROOT"
99+
exec wails dev "$@"

0 commit comments

Comments
 (0)