mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(release): reserve installer gateway port
This commit is contained in:
@@ -420,8 +420,9 @@ export async function runOnboardWithInstalledCli(params: {
|
||||
providerConfig: ProviderConfig;
|
||||
installDaemon: boolean;
|
||||
logPath: string;
|
||||
allocateGatewayPort?: boolean;
|
||||
}) {
|
||||
await withAllocatedGatewayPort(params.lane, async () => {
|
||||
const runOnboard = async () => {
|
||||
const args = buildReleaseOnboardArgs({
|
||||
authChoice: params.providerConfig.authChoice,
|
||||
gatewayPort: params.lane.gatewayPort,
|
||||
@@ -436,7 +437,15 @@ export async function runOnboardWithInstalledCli(params: {
|
||||
logPath: params.logPath,
|
||||
timeoutMs: 10 * 60 * 1000,
|
||||
});
|
||||
});
|
||||
};
|
||||
if (params.allocateGatewayPort === false) {
|
||||
if (params.lane.gatewayPort <= 0) {
|
||||
throw new Error("Installed onboarding requires a reserved gateway port.");
|
||||
}
|
||||
await runOnboard();
|
||||
return;
|
||||
}
|
||||
await withAllocatedGatewayPort(params.lane, runOnboard);
|
||||
}
|
||||
|
||||
export function buildReleaseOnboardArgs(params: {
|
||||
|
||||
@@ -59,7 +59,12 @@ import {
|
||||
waitForInstalledGatewayToStop,
|
||||
} from "./installed.ts";
|
||||
import { maybeRunDiscordRoundtrip } from "./network-smokes.ts";
|
||||
import { runCleanup, startStaticFileServer, stopGateway } from "./process.ts";
|
||||
import {
|
||||
reserveGatewayPortForLane,
|
||||
runCleanup,
|
||||
startStaticFileServer,
|
||||
stopGateway,
|
||||
} from "./process.ts";
|
||||
import { logLanePhase, runTimedLanePhase } from "./reporting.ts";
|
||||
import {
|
||||
exerciseManagedGatewayLifecycle,
|
||||
@@ -432,6 +437,15 @@ export async function runInstallerFreshSuite(
|
||||
});
|
||||
}
|
||||
|
||||
// Hold the configured port through onboarding and model setup so another runner process
|
||||
// cannot claim it before the manual gateway starts. Release immediately before spawn.
|
||||
const gatewayPortReservation = usesManagedGateway
|
||||
? null
|
||||
: await reserveGatewayPortForLane(lane);
|
||||
if (gatewayPortReservation) {
|
||||
cleanup.push(() => gatewayPortReservation.release());
|
||||
}
|
||||
|
||||
logLanePhase(lane, "onboard");
|
||||
await runOnboardWithInstalledCli({
|
||||
lane,
|
||||
@@ -440,6 +454,7 @@ export async function runInstallerFreshSuite(
|
||||
providerConfig: params.providerConfig,
|
||||
installDaemon: usesManagedGateway,
|
||||
logPath: join(params.logsDir, "installer-fresh-onboard.log"),
|
||||
allocateGatewayPort: gatewayPortReservation === null,
|
||||
});
|
||||
|
||||
if (shouldExerciseManagedGatewayLifecycleAfterInstall()) {
|
||||
@@ -483,6 +498,7 @@ export async function runInstallerFreshSuite(
|
||||
logPath: join(params.logsDir, "installer-fresh-gateway-stop-managed-status.log"),
|
||||
});
|
||||
}
|
||||
await gatewayPortReservation?.release();
|
||||
logLanePhase(lane, "gateway-start");
|
||||
const gateway = await startManualGatewayFromInstalledCli({
|
||||
lane,
|
||||
|
||||
@@ -593,6 +593,22 @@ export async function withAllocatedGatewayPort<T>(lane: LaneState, callback: ()
|
||||
);
|
||||
}
|
||||
|
||||
export async function reserveGatewayPortForLane(lane: LaneState) {
|
||||
const reservation = await reservePort();
|
||||
lane.gatewayPort = reservation.port;
|
||||
let released = false;
|
||||
return {
|
||||
port: reservation.port,
|
||||
release: async () => {
|
||||
if (released) {
|
||||
return;
|
||||
}
|
||||
released = true;
|
||||
await reservation.release();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function reservePort(): Promise<{ port: number; release: () => Promise<void> }> {
|
||||
return new Promise((resolvePromise, rejectPromise) => {
|
||||
const server = createNetServer();
|
||||
|
||||
@@ -69,6 +69,7 @@ import {
|
||||
readInstalledVersion,
|
||||
readBoundedCrossOsResponseText,
|
||||
readRunnerOverrideEnv,
|
||||
reserveGatewayPortForLane,
|
||||
resolveDashboardAssetUrls,
|
||||
resolveCrossOsAgentTurnOptional,
|
||||
runCommand,
|
||||
@@ -1794,6 +1795,19 @@ describe("scripts/openclaw-cross-os-release-checks", () => {
|
||||
expect(await canConnectToLoopbackPort(port, 100)).toBe(false);
|
||||
});
|
||||
|
||||
it("keeps a release gateway port reserved until the lane is ready to start", async () => {
|
||||
const lane = { gatewayPort: 0 } as Parameters<typeof reserveGatewayPortForLane>[0];
|
||||
const reservation = await reserveGatewayPortForLane(lane);
|
||||
try {
|
||||
expect(lane.gatewayPort).toBe(reservation.port);
|
||||
expect(await canConnectToLoopbackPort(reservation.port)).toBe(true);
|
||||
} finally {
|
||||
await reservation.release();
|
||||
}
|
||||
await reservation.release();
|
||||
expect(await canConnectToLoopbackPort(reservation.port, 100)).toBe(false);
|
||||
});
|
||||
|
||||
it("writes Discord smoke config using the strict guild channel schema", () => {
|
||||
expect(buildDiscordSmokeGuildsConfig("guild-123", "channel-456")).toEqual({
|
||||
"guild-123": {
|
||||
|
||||
Reference in New Issue
Block a user