worktree-bay 2.3.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/engine.js +26 -3
- package/dist/proc.js +8 -0
- package/package.json +1 -1
package/dist/engine.js
CHANGED
|
@@ -7,7 +7,7 @@ import { addWorktree } from './git.js';
|
|
|
7
7
|
import { runShellLive, run, spliceArgv, isTTY } from './util/exec.js';
|
|
8
8
|
import { warn, log } from './util/log.js';
|
|
9
9
|
import { withProgress } from './util/progress.js';
|
|
10
|
-
import { startDetached, recordedFor, pidAlive } from './proc.js';
|
|
10
|
+
import { startDetached, recordedFor, pidAlive, stopManaged, readLogTail } from './proc.js';
|
|
11
11
|
import { t } from './i18n.js';
|
|
12
12
|
export function mergeEnvText(text, kv) {
|
|
13
13
|
const lines = text.split('\n');
|
|
@@ -86,8 +86,31 @@ export async function ensureStarted(ctx) {
|
|
|
86
86
|
log(t(` • 端口 ${port} 已在监听,视为 ${service} dev server 在跑,跳过启动`, ` • port ${port} already listening; treating ${service} dev server as up, skip`));
|
|
87
87
|
return;
|
|
88
88
|
}
|
|
89
|
-
const
|
|
90
|
-
|
|
89
|
+
const cmd = renderTemplate(sp.start, vars);
|
|
90
|
+
const r = startDetached(ws, dir, service, slug, port, cmd);
|
|
91
|
+
// 验证没立刻挂:轮询 ~3s,端口起来=成功,pid 没了=启动失败(命令多半不对)
|
|
92
|
+
const alive = await waitStartup(r.pid, port, 3000);
|
|
93
|
+
if (alive) {
|
|
94
|
+
log(t(` ▸ 已后台启动 ${service} dev server(pid ${r.pid},端口 ${port}) 日志: ${r.log}`, ` ▸ started ${service} dev server in background (pid ${r.pid}, port ${port}) log: ${r.log}`));
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
stopManaged(ws, dir); // 进程已死,清掉登记,别留假状态
|
|
98
|
+
const tail = readLogTail(r.log);
|
|
99
|
+
warn(t(` ✗ ${service} dev server 启动后立即退出——start 命令多半不对。\n 命令: ${cmd}\n 请在 worktree 里手动跑一遍排查: cd ${dir} && ${cmd}\n 日志(${r.log}):\n${tail || '(空)'}`, ` ✗ ${service} dev server exited immediately — the start command is likely wrong.\n command: ${cmd}\n reproduce in the worktree: cd ${dir} && ${cmd}\n log (${r.log}):\n${tail || '(empty)'}`));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// 端口起来→true(成功);pid 死了→false(崩了);超时仍存活→true(还在启动,如 vite 冷启动较慢)
|
|
103
|
+
async function waitStartup(pid, port, ms) {
|
|
104
|
+
const end = Date.now() + ms;
|
|
105
|
+
for (;;) {
|
|
106
|
+
if (!pidAlive(pid))
|
|
107
|
+
return false;
|
|
108
|
+
if (!(await isPortFree(port)))
|
|
109
|
+
return true;
|
|
110
|
+
if (Date.now() >= end)
|
|
111
|
+
return pidAlive(pid);
|
|
112
|
+
await new Promise((r) => setTimeout(r, 150));
|
|
113
|
+
}
|
|
91
114
|
}
|
|
92
115
|
export function execArgv(ctx, cmd) {
|
|
93
116
|
const tpl = (ctx.sp.exec ?? ['sh', '-c', '{cmd...}']).map((el) => el === '{cmd...}' ? el : renderTemplate(el, ctx.vars));
|
package/dist/proc.js
CHANGED
|
@@ -17,6 +17,14 @@ catch {
|
|
|
17
17
|
return false;
|
|
18
18
|
} }
|
|
19
19
|
export function recordedFor(ws, dir) { return readProcs(ws).find((r) => r.dir === dir); }
|
|
20
|
+
export function readLogTail(file, lines = 15) {
|
|
21
|
+
try {
|
|
22
|
+
return fs.readFileSync(file, 'utf8').split(/\r?\n/).filter(Boolean).slice(-lines).join('\n');
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return '';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
20
28
|
export function startDetached(ws, dir, service, slug, port, cmd) {
|
|
21
29
|
const logDir = path.join(ws, '.worktree-bay', 'logs');
|
|
22
30
|
fs.mkdirSync(logDir, { recursive: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "worktree-bay",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.1",
|
|
4
4
|
"description": "Per-feature git worktree + port slots for parallel multi-service development: auto deps, env wiring, frontend-to-backend, merge-aware reclaim, plus an MCP server for AI agents.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"git",
|