runcastle 1.2.2 → 1.2.3
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/bin/runcastle.js +43 -16
- package/index.js +43 -16
- package/package.json +1 -1
- package/web/assets/index-BhOja4Fc.js +142 -0
- package/web/index.html +1 -1
- package/web/assets/index-Co7aViQi.js +0 -142
package/bin/runcastle.js
CHANGED
|
@@ -914,6 +914,23 @@ var init_resolve_executable = __esm(() => {
|
|
|
914
914
|
};
|
|
915
915
|
});
|
|
916
916
|
|
|
917
|
+
// src/pty/kill-tree.ts
|
|
918
|
+
import { execFile } from "child_process";
|
|
919
|
+
import { promisify } from "util";
|
|
920
|
+
async function killProcessTree(pid) {
|
|
921
|
+
try {
|
|
922
|
+
if (process.platform === "win32") {
|
|
923
|
+
await execFileAsync("taskkill", ["/pid", String(pid), "/T", "/F"], { windowsHide: true });
|
|
924
|
+
} else {
|
|
925
|
+
process.kill(-pid, "SIGTERM");
|
|
926
|
+
}
|
|
927
|
+
} catch {}
|
|
928
|
+
}
|
|
929
|
+
var execFileAsync;
|
|
930
|
+
var init_kill_tree = __esm(() => {
|
|
931
|
+
execFileAsync = promisify(execFile);
|
|
932
|
+
});
|
|
933
|
+
|
|
917
934
|
// src/pty/pty-sidecar.ts
|
|
918
935
|
import { spawn } from "child_process";
|
|
919
936
|
import { createRequire } from "module";
|
|
@@ -1095,6 +1112,9 @@ ${why.replace(/\n/g, `\r
|
|
|
1095
1112
|
}
|
|
1096
1113
|
}, 500);
|
|
1097
1114
|
},
|
|
1115
|
+
killTree() {
|
|
1116
|
+
return killProcessTree(process.platform === "win32" ? child.pid ?? pid : pid);
|
|
1117
|
+
},
|
|
1098
1118
|
get pid() {
|
|
1099
1119
|
return pid;
|
|
1100
1120
|
},
|
|
@@ -1107,6 +1127,7 @@ var HOST_PATH;
|
|
|
1107
1127
|
var init_pty_sidecar = __esm(() => {
|
|
1108
1128
|
init_asset_paths();
|
|
1109
1129
|
init_resolve_executable();
|
|
1130
|
+
init_kill_tree();
|
|
1110
1131
|
HOST_PATH = resolveAsset(ASSET_ENV.ptyHost, fileURLToPath(new URL("./pty-host.cjs", import.meta.url)));
|
|
1111
1132
|
});
|
|
1112
1133
|
|
|
@@ -1193,6 +1214,9 @@ function createNativePtySession(cmd, args, opts) {
|
|
|
1193
1214
|
proc.kill();
|
|
1194
1215
|
} catch {}
|
|
1195
1216
|
},
|
|
1217
|
+
killTree() {
|
|
1218
|
+
return killProcessTree(proc.pid);
|
|
1219
|
+
},
|
|
1196
1220
|
get pid() {
|
|
1197
1221
|
return proc.pid;
|
|
1198
1222
|
},
|
|
@@ -1204,6 +1228,7 @@ function createNativePtySession(cmd, args, opts) {
|
|
|
1204
1228
|
var cached = null, BACKEND_LOGGED;
|
|
1205
1229
|
var init_pty = __esm(() => {
|
|
1206
1230
|
init_resolve_executable();
|
|
1231
|
+
init_kill_tree();
|
|
1207
1232
|
init_pty_sidecar();
|
|
1208
1233
|
BACKEND_LOGGED = Symbol.for("runcastle.pty.backend.logged");
|
|
1209
1234
|
});
|
|
@@ -1796,7 +1821,6 @@ var init_waypoints = __esm(() => {
|
|
|
1796
1821
|
});
|
|
1797
1822
|
|
|
1798
1823
|
// src/pty/dev-pane.ts
|
|
1799
|
-
import { execFileSync } from "child_process";
|
|
1800
1824
|
function drivePaneId(ownerId) {
|
|
1801
1825
|
return `${DRIVE_PREFIX}${ownerId}`;
|
|
1802
1826
|
}
|
|
@@ -1856,24 +1880,24 @@ function devPaneLive(paneId) {
|
|
|
1856
1880
|
const entry = ptyRegistry().get(paneId);
|
|
1857
1881
|
return !!entry && !entry.exited;
|
|
1858
1882
|
}
|
|
1859
|
-
function
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
}
|
|
1866
|
-
}
|
|
1883
|
+
function killTreeBounded(pty) {
|
|
1884
|
+
return new Promise((resolve4) => {
|
|
1885
|
+
const timer = setTimeout(resolve4, KILL_TREE_TIMEOUT_MS);
|
|
1886
|
+
pty.killTree().catch(() => {}).then(() => {
|
|
1887
|
+
clearTimeout(timer);
|
|
1888
|
+
resolve4();
|
|
1889
|
+
});
|
|
1890
|
+
});
|
|
1867
1891
|
}
|
|
1868
|
-
function stopDevPane(paneId) {
|
|
1892
|
+
async function stopDevPane(paneId) {
|
|
1869
1893
|
const reg = ptyRegistry();
|
|
1870
1894
|
const entry = reg.get(paneId);
|
|
1871
1895
|
if (entry && !entry.exited)
|
|
1872
|
-
|
|
1896
|
+
await killTreeBounded(entry.pty);
|
|
1873
1897
|
reg.kill(paneId);
|
|
1874
1898
|
reg.remove(paneId);
|
|
1875
1899
|
}
|
|
1876
|
-
var DRIVE_PREFIX = "drive:", SNIFF_WINDOW = 8192;
|
|
1900
|
+
var DRIVE_PREFIX = "drive:", SNIFF_WINDOW = 8192, KILL_TREE_TIMEOUT_MS = 5000;
|
|
1877
1901
|
var init_dev_pane = __esm(() => {
|
|
1878
1902
|
init_events();
|
|
1879
1903
|
init_registry();
|
|
@@ -2802,7 +2826,7 @@ async function testDrive(ctx, project, feature, action) {
|
|
|
2802
2826
|
const detachedWorktree2 = testDriveState.detachedWorktree;
|
|
2803
2827
|
const devPaneId = testDriveState.devPaneId;
|
|
2804
2828
|
if (devPaneId)
|
|
2805
|
-
stopDevPane(devPaneId);
|
|
2829
|
+
await stopDevPane(devPaneId);
|
|
2806
2830
|
const teardown = await runDriveHookStep(ctx, scope, project.repoPath, "teardown", project.driveStopCommand, driveEnvFor(ctx, project, { slug: feature.slug, branch }, scope).env);
|
|
2807
2831
|
const carriedChanges = await dirtyPaths(g);
|
|
2808
2832
|
await g.checkout(previousBranch2);
|
|
@@ -2942,7 +2966,7 @@ async function startDryRun(ctx, project) {
|
|
|
2942
2966
|
async function stopDryRun(ctx, project, state) {
|
|
2943
2967
|
const scope = { projectId: project.id };
|
|
2944
2968
|
if (state.devPaneId)
|
|
2945
|
-
stopDevPane(state.devPaneId);
|
|
2969
|
+
await stopDevPane(state.devPaneId);
|
|
2946
2970
|
const teardown = await runDriveHookStep(ctx, scope, project.repoPath, "teardown", project.driveStopCommand, state.env);
|
|
2947
2971
|
state.observed.teardownOk = teardown?.result.ok;
|
|
2948
2972
|
testDriveState = undefined;
|
|
@@ -3437,7 +3461,7 @@ function landProjectSession(ctx, session) {
|
|
|
3437
3461
|
data: { sessionId: session.id, branch: PROJECT_BRANCH, ...data }
|
|
3438
3462
|
});
|
|
3439
3463
|
};
|
|
3440
|
-
landProjectBranch(project).then((res) => {
|
|
3464
|
+
const landing = landProjectBranch(project).then((res) => {
|
|
3441
3465
|
if (!res)
|
|
3442
3466
|
return;
|
|
3443
3467
|
if (res.landed) {
|
|
@@ -3450,6 +3474,8 @@ function landProjectSession(ctx, session) {
|
|
|
3450
3474
|
}).catch((e) => {
|
|
3451
3475
|
report("project.land_failed", `could not land the project session's work onto ${project.mainBranch}: ${e instanceof Error ? e.message : String(e)} \u2014 ${kept}`, { error: e instanceof Error ? e.message : String(e) });
|
|
3452
3476
|
});
|
|
3477
|
+
inFlightLandings.add(landing);
|
|
3478
|
+
landing.finally(() => inFlightLandings.delete(landing));
|
|
3453
3479
|
}
|
|
3454
3480
|
function markSessionEnded(ctx, id) {
|
|
3455
3481
|
const existing = getSessionRow(ctx, id);
|
|
@@ -3478,7 +3504,7 @@ function mostRecentLiveSession(ctx) {
|
|
|
3478
3504
|
const row = ctx.db.select().from(sessions).where(eq5(sessions.status, "live")).orderBy(desc3(sql2`rowid`)).limit(1).get();
|
|
3479
3505
|
return row ? rowToSession(row) : null;
|
|
3480
3506
|
}
|
|
3481
|
-
var KICKOFF_DELAY_MS = 1500, KICKOFF_SUBMIT_DELAY_MS = 350, KICKOFF_CONFIRM_MS = 12000, KICKOFF_MAX_ATTEMPTS = 3, CLEAR_INPUT = "\x15", SESSION_READY_TIMEOUT_MS = 25000, CONVERGE_KICKOFF_LINE, KICKOFF_LINES, RESUME_KICKOFF_PREFIX, pendingKickoffOverrides, deliveries, MATCH_PREFIX = 40, landedProjectSessions;
|
|
3507
|
+
var KICKOFF_DELAY_MS = 1500, KICKOFF_SUBMIT_DELAY_MS = 350, KICKOFF_CONFIRM_MS = 12000, KICKOFF_MAX_ATTEMPTS = 3, CLEAR_INPUT = "\x15", SESSION_READY_TIMEOUT_MS = 25000, CONVERGE_KICKOFF_LINE, KICKOFF_LINES, RESUME_KICKOFF_PREFIX, pendingKickoffOverrides, deliveries, MATCH_PREFIX = 40, landedProjectSessions, inFlightLandings;
|
|
3482
3508
|
var init_sessions = __esm(() => {
|
|
3483
3509
|
init_src();
|
|
3484
3510
|
init_schema();
|
|
@@ -3501,6 +3527,7 @@ var init_sessions = __esm(() => {
|
|
|
3501
3527
|
pendingKickoffOverrides = new Map;
|
|
3502
3528
|
deliveries = new Map;
|
|
3503
3529
|
landedProjectSessions = new Set;
|
|
3530
|
+
inFlightLandings = new Set;
|
|
3504
3531
|
});
|
|
3505
3532
|
|
|
3506
3533
|
// src/launcher/reconcile.ts
|
package/index.js
CHANGED
|
@@ -913,6 +913,23 @@ var init_resolve_executable = __esm(() => {
|
|
|
913
913
|
};
|
|
914
914
|
});
|
|
915
915
|
|
|
916
|
+
// src/pty/kill-tree.ts
|
|
917
|
+
import { execFile } from "child_process";
|
|
918
|
+
import { promisify } from "util";
|
|
919
|
+
async function killProcessTree(pid) {
|
|
920
|
+
try {
|
|
921
|
+
if (process.platform === "win32") {
|
|
922
|
+
await execFileAsync("taskkill", ["/pid", String(pid), "/T", "/F"], { windowsHide: true });
|
|
923
|
+
} else {
|
|
924
|
+
process.kill(-pid, "SIGTERM");
|
|
925
|
+
}
|
|
926
|
+
} catch {}
|
|
927
|
+
}
|
|
928
|
+
var execFileAsync;
|
|
929
|
+
var init_kill_tree = __esm(() => {
|
|
930
|
+
execFileAsync = promisify(execFile);
|
|
931
|
+
});
|
|
932
|
+
|
|
916
933
|
// src/pty/pty-sidecar.ts
|
|
917
934
|
import { spawn } from "child_process";
|
|
918
935
|
import { createRequire } from "module";
|
|
@@ -1094,6 +1111,9 @@ ${why.replace(/\n/g, `\r
|
|
|
1094
1111
|
}
|
|
1095
1112
|
}, 500);
|
|
1096
1113
|
},
|
|
1114
|
+
killTree() {
|
|
1115
|
+
return killProcessTree(process.platform === "win32" ? child.pid ?? pid : pid);
|
|
1116
|
+
},
|
|
1097
1117
|
get pid() {
|
|
1098
1118
|
return pid;
|
|
1099
1119
|
},
|
|
@@ -1106,6 +1126,7 @@ var HOST_PATH;
|
|
|
1106
1126
|
var init_pty_sidecar = __esm(() => {
|
|
1107
1127
|
init_asset_paths();
|
|
1108
1128
|
init_resolve_executable();
|
|
1129
|
+
init_kill_tree();
|
|
1109
1130
|
HOST_PATH = resolveAsset(ASSET_ENV.ptyHost, fileURLToPath(new URL("./pty-host.cjs", import.meta.url)));
|
|
1110
1131
|
});
|
|
1111
1132
|
|
|
@@ -1192,6 +1213,9 @@ function createNativePtySession(cmd, args, opts) {
|
|
|
1192
1213
|
proc.kill();
|
|
1193
1214
|
} catch {}
|
|
1194
1215
|
},
|
|
1216
|
+
killTree() {
|
|
1217
|
+
return killProcessTree(proc.pid);
|
|
1218
|
+
},
|
|
1195
1219
|
get pid() {
|
|
1196
1220
|
return proc.pid;
|
|
1197
1221
|
},
|
|
@@ -1203,6 +1227,7 @@ function createNativePtySession(cmd, args, opts) {
|
|
|
1203
1227
|
var cached = null, BACKEND_LOGGED;
|
|
1204
1228
|
var init_pty = __esm(() => {
|
|
1205
1229
|
init_resolve_executable();
|
|
1230
|
+
init_kill_tree();
|
|
1206
1231
|
init_pty_sidecar();
|
|
1207
1232
|
BACKEND_LOGGED = Symbol.for("runcastle.pty.backend.logged");
|
|
1208
1233
|
});
|
|
@@ -1795,7 +1820,6 @@ var init_waypoints = __esm(() => {
|
|
|
1795
1820
|
});
|
|
1796
1821
|
|
|
1797
1822
|
// src/pty/dev-pane.ts
|
|
1798
|
-
import { execFileSync } from "child_process";
|
|
1799
1823
|
function drivePaneId(ownerId) {
|
|
1800
1824
|
return `${DRIVE_PREFIX}${ownerId}`;
|
|
1801
1825
|
}
|
|
@@ -1855,24 +1879,24 @@ function devPaneLive(paneId) {
|
|
|
1855
1879
|
const entry = ptyRegistry().get(paneId);
|
|
1856
1880
|
return !!entry && !entry.exited;
|
|
1857
1881
|
}
|
|
1858
|
-
function
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
}
|
|
1865
|
-
}
|
|
1882
|
+
function killTreeBounded(pty) {
|
|
1883
|
+
return new Promise((resolve4) => {
|
|
1884
|
+
const timer = setTimeout(resolve4, KILL_TREE_TIMEOUT_MS);
|
|
1885
|
+
pty.killTree().catch(() => {}).then(() => {
|
|
1886
|
+
clearTimeout(timer);
|
|
1887
|
+
resolve4();
|
|
1888
|
+
});
|
|
1889
|
+
});
|
|
1866
1890
|
}
|
|
1867
|
-
function stopDevPane(paneId) {
|
|
1891
|
+
async function stopDevPane(paneId) {
|
|
1868
1892
|
const reg = ptyRegistry();
|
|
1869
1893
|
const entry = reg.get(paneId);
|
|
1870
1894
|
if (entry && !entry.exited)
|
|
1871
|
-
|
|
1895
|
+
await killTreeBounded(entry.pty);
|
|
1872
1896
|
reg.kill(paneId);
|
|
1873
1897
|
reg.remove(paneId);
|
|
1874
1898
|
}
|
|
1875
|
-
var DRIVE_PREFIX = "drive:", SNIFF_WINDOW = 8192;
|
|
1899
|
+
var DRIVE_PREFIX = "drive:", SNIFF_WINDOW = 8192, KILL_TREE_TIMEOUT_MS = 5000;
|
|
1876
1900
|
var init_dev_pane = __esm(() => {
|
|
1877
1901
|
init_events();
|
|
1878
1902
|
init_registry();
|
|
@@ -2801,7 +2825,7 @@ async function testDrive(ctx, project, feature, action) {
|
|
|
2801
2825
|
const detachedWorktree2 = testDriveState.detachedWorktree;
|
|
2802
2826
|
const devPaneId = testDriveState.devPaneId;
|
|
2803
2827
|
if (devPaneId)
|
|
2804
|
-
stopDevPane(devPaneId);
|
|
2828
|
+
await stopDevPane(devPaneId);
|
|
2805
2829
|
const teardown = await runDriveHookStep(ctx, scope, project.repoPath, "teardown", project.driveStopCommand, driveEnvFor(ctx, project, { slug: feature.slug, branch }, scope).env);
|
|
2806
2830
|
const carriedChanges = await dirtyPaths(g);
|
|
2807
2831
|
await g.checkout(previousBranch2);
|
|
@@ -2941,7 +2965,7 @@ async function startDryRun(ctx, project) {
|
|
|
2941
2965
|
async function stopDryRun(ctx, project, state) {
|
|
2942
2966
|
const scope = { projectId: project.id };
|
|
2943
2967
|
if (state.devPaneId)
|
|
2944
|
-
stopDevPane(state.devPaneId);
|
|
2968
|
+
await stopDevPane(state.devPaneId);
|
|
2945
2969
|
const teardown = await runDriveHookStep(ctx, scope, project.repoPath, "teardown", project.driveStopCommand, state.env);
|
|
2946
2970
|
state.observed.teardownOk = teardown?.result.ok;
|
|
2947
2971
|
testDriveState = undefined;
|
|
@@ -3436,7 +3460,7 @@ function landProjectSession(ctx, session) {
|
|
|
3436
3460
|
data: { sessionId: session.id, branch: PROJECT_BRANCH, ...data }
|
|
3437
3461
|
});
|
|
3438
3462
|
};
|
|
3439
|
-
landProjectBranch(project).then((res) => {
|
|
3463
|
+
const landing = landProjectBranch(project).then((res) => {
|
|
3440
3464
|
if (!res)
|
|
3441
3465
|
return;
|
|
3442
3466
|
if (res.landed) {
|
|
@@ -3449,6 +3473,8 @@ function landProjectSession(ctx, session) {
|
|
|
3449
3473
|
}).catch((e) => {
|
|
3450
3474
|
report("project.land_failed", `could not land the project session's work onto ${project.mainBranch}: ${e instanceof Error ? e.message : String(e)} \u2014 ${kept}`, { error: e instanceof Error ? e.message : String(e) });
|
|
3451
3475
|
});
|
|
3476
|
+
inFlightLandings.add(landing);
|
|
3477
|
+
landing.finally(() => inFlightLandings.delete(landing));
|
|
3452
3478
|
}
|
|
3453
3479
|
function markSessionEnded(ctx, id) {
|
|
3454
3480
|
const existing = getSessionRow(ctx, id);
|
|
@@ -3477,7 +3503,7 @@ function mostRecentLiveSession(ctx) {
|
|
|
3477
3503
|
const row = ctx.db.select().from(sessions).where(eq5(sessions.status, "live")).orderBy(desc3(sql2`rowid`)).limit(1).get();
|
|
3478
3504
|
return row ? rowToSession(row) : null;
|
|
3479
3505
|
}
|
|
3480
|
-
var KICKOFF_DELAY_MS = 1500, KICKOFF_SUBMIT_DELAY_MS = 350, KICKOFF_CONFIRM_MS = 12000, KICKOFF_MAX_ATTEMPTS = 3, CLEAR_INPUT = "\x15", SESSION_READY_TIMEOUT_MS = 25000, CONVERGE_KICKOFF_LINE, KICKOFF_LINES, RESUME_KICKOFF_PREFIX, pendingKickoffOverrides, deliveries, MATCH_PREFIX = 40, landedProjectSessions;
|
|
3506
|
+
var KICKOFF_DELAY_MS = 1500, KICKOFF_SUBMIT_DELAY_MS = 350, KICKOFF_CONFIRM_MS = 12000, KICKOFF_MAX_ATTEMPTS = 3, CLEAR_INPUT = "\x15", SESSION_READY_TIMEOUT_MS = 25000, CONVERGE_KICKOFF_LINE, KICKOFF_LINES, RESUME_KICKOFF_PREFIX, pendingKickoffOverrides, deliveries, MATCH_PREFIX = 40, landedProjectSessions, inFlightLandings;
|
|
3481
3507
|
var init_sessions = __esm(() => {
|
|
3482
3508
|
init_src();
|
|
3483
3509
|
init_schema();
|
|
@@ -3500,6 +3526,7 @@ var init_sessions = __esm(() => {
|
|
|
3500
3526
|
pendingKickoffOverrides = new Map;
|
|
3501
3527
|
deliveries = new Map;
|
|
3502
3528
|
landedProjectSessions = new Set;
|
|
3529
|
+
inFlightLandings = new Set;
|
|
3503
3530
|
});
|
|
3504
3531
|
|
|
3505
3532
|
// src/launcher/reconcile.ts
|