fix(cli): preserve update lifecycle config path
This commit is contained in:
parent
bc7f23a0de
commit
968f0c388f
|
|
@ -600,7 +600,10 @@ describe("update command", () => {
|
|||
expect(mockSpawn.mock.calls[0]).toEqual([
|
||||
"ao",
|
||||
["stop", "--yes"],
|
||||
expect.objectContaining({ stdio: "inherit" }),
|
||||
expect.objectContaining({
|
||||
stdio: "inherit",
|
||||
env: expect.objectContaining({ AO_CONFIG_PATH: "/tmp/test-global-config.yaml" }),
|
||||
}),
|
||||
]);
|
||||
expect(mockSpawn.mock.calls[1][0]).toBe("pnpm");
|
||||
expect(mockSpawn.mock.calls[1][1]).toEqual(["add", "-g", "@aoagents/ao@latest"]);
|
||||
|
|
@ -609,7 +612,10 @@ describe("update command", () => {
|
|||
expect(mockSpawn.mock.calls[3]).toEqual([
|
||||
"ao",
|
||||
["start", "my-app", "--restore"],
|
||||
expect.objectContaining({ stdio: "inherit" }),
|
||||
expect.objectContaining({
|
||||
stdio: "inherit",
|
||||
env: expect.objectContaining({ AO_CONFIG_PATH: "/tmp/test-global-config.yaml" }),
|
||||
}),
|
||||
]);
|
||||
|
||||
const stopOrder = mockSpawn.mock.invocationCallOrder[0];
|
||||
|
|
@ -662,6 +668,11 @@ describe("update command", () => {
|
|||
|
||||
expect(mockSpawn.mock.calls[0][0]).toBe("ao");
|
||||
expect(mockSpawn.mock.calls[0][1]).toEqual(["stop", "--yes"]);
|
||||
expect(mockSpawn.mock.calls[0][2]).toEqual(
|
||||
expect.objectContaining({
|
||||
env: expect.objectContaining({ AO_CONFIG_PATH: "/tmp/test-global-config.yaml" }),
|
||||
}),
|
||||
);
|
||||
expect(mockSpawn.mock.calls[1][0]).toBe("pnpm");
|
||||
expect(mockSpawn.mock.calls[2][0]).toBe("ao");
|
||||
expect(mockSpawn.mock.calls[2][1]).toEqual(["--version"]);
|
||||
|
|
@ -683,7 +694,10 @@ describe("update command", () => {
|
|||
expect(mockSpawn.mock.calls.at(-1)).toEqual([
|
||||
"ao",
|
||||
["start", "my-app", "--no-restore"],
|
||||
expect.objectContaining({ stdio: "inherit" }),
|
||||
expect.objectContaining({
|
||||
stdio: "inherit",
|
||||
env: expect.objectContaining({ AO_CONFIG_PATH: "/tmp/test-global-config.yaml" }),
|
||||
}),
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
@ -705,7 +719,10 @@ describe("update command", () => {
|
|||
expect(mockSpawn.mock.calls[0][0]).toBe("ao");
|
||||
expect(mockSpawn.mock.calls[0][1]).toEqual(["stop", "--yes"]);
|
||||
expect(mockSpawn.mock.calls.some((call) => call[0] === "pnpm")).toBe(false);
|
||||
const stderr = vi.mocked(console.error).mock.calls.map((c) => String(c[0])).join("\n");
|
||||
const stderr = vi
|
||||
.mocked(console.error)
|
||||
.mock.calls.map((c) => String(c[0]))
|
||||
.join("\n");
|
||||
expect(stderr).toContain("AO still appears to be running after `ao stop --yes`");
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -147,12 +147,14 @@ async function handleCheck(): Promise<void> {
|
|||
*/
|
||||
interface UpdateLifecyclePlan {
|
||||
runningBeforeUpdate: boolean;
|
||||
configPath?: string;
|
||||
primaryProjectId?: string;
|
||||
activeSessions: Session[];
|
||||
}
|
||||
|
||||
async function getUpdateLifecyclePlan(): Promise<UpdateLifecyclePlan> {
|
||||
let sessions: Session[];
|
||||
let configPath: string | undefined;
|
||||
let primaryProjectId: string | undefined;
|
||||
let runningBeforeUpdate = false;
|
||||
try {
|
||||
|
|
@ -168,6 +170,7 @@ async function getUpdateLifecyclePlan(): Promise<UpdateLifecyclePlan> {
|
|||
const running = await getRunning();
|
||||
if (running && running.projects.length > 0) {
|
||||
runningBeforeUpdate = true;
|
||||
configPath = running.configPath;
|
||||
primaryProjectId = running.projects[0];
|
||||
// running.configPath could be local-wrapped (a project's
|
||||
// agent-orchestrator.yaml) OR the canonical global path. loadConfig
|
||||
|
|
@ -184,15 +187,16 @@ async function getUpdateLifecyclePlan(): Promise<UpdateLifecyclePlan> {
|
|||
// sessions to `killed`, so terminal statuses don't block the update.
|
||||
const globalPath = getGlobalConfigPath();
|
||||
if (!existsSync(globalPath)) {
|
||||
return { runningBeforeUpdate, primaryProjectId, activeSessions: [] };
|
||||
return { runningBeforeUpdate, configPath, primaryProjectId, activeSessions: [] };
|
||||
}
|
||||
const globalConfig = loadGlobalConfig(globalPath);
|
||||
if (!globalConfig || Object.keys(globalConfig.projects).length === 0) {
|
||||
return { runningBeforeUpdate, primaryProjectId, activeSessions: [] };
|
||||
return { runningBeforeUpdate, configPath, primaryProjectId, activeSessions: [] };
|
||||
}
|
||||
if (!isCanonicalGlobalConfigPath(globalPath)) {
|
||||
return { runningBeforeUpdate, primaryProjectId, activeSessions: [] };
|
||||
return { runningBeforeUpdate, configPath, primaryProjectId, activeSessions: [] };
|
||||
}
|
||||
configPath = globalPath;
|
||||
const config = loadConfig(globalPath);
|
||||
primaryProjectId = Object.keys(config.projects)[0];
|
||||
const sm = await getSessionManager(config);
|
||||
|
|
@ -204,11 +208,11 @@ async function getUpdateLifecyclePlan(): Promise<UpdateLifecyclePlan> {
|
|||
console.error(
|
||||
chalk.yellow("⚠ Could not check for active sessions before updating. Proceeding anyway."),
|
||||
);
|
||||
return { runningBeforeUpdate, primaryProjectId, activeSessions: [] };
|
||||
return { runningBeforeUpdate, configPath, primaryProjectId, activeSessions: [] };
|
||||
}
|
||||
|
||||
const active = sessions.filter((s) => ACTIVE_SESSION_STATUSES.has(s.status));
|
||||
return { runningBeforeUpdate, primaryProjectId, activeSessions: active };
|
||||
return { runningBeforeUpdate, configPath, primaryProjectId, activeSessions: active };
|
||||
}
|
||||
|
||||
async function pauseAoForUpdate(plan: UpdateLifecyclePlan): Promise<boolean> {
|
||||
|
|
@ -232,7 +236,9 @@ async function pauseAoForUpdate(plan: UpdateLifecyclePlan): Promise<boolean> {
|
|||
console.log(chalk.dim("\nAO is running; it will be restarted after the update."));
|
||||
}
|
||||
|
||||
const stopExit = await runAoLifecycleCommand(["stop", "--yes"]);
|
||||
const stopExit = await runAoLifecycleCommand(["stop", "--yes"], {
|
||||
configPath: plan.configPath,
|
||||
});
|
||||
if (stopExit !== 0) {
|
||||
recordActivityEvent({
|
||||
source: "cli",
|
||||
|
|
@ -288,7 +294,7 @@ async function restartAoAfterUpdate(
|
|||
args.push(opts.restore ? "--restore" : "--no-restore");
|
||||
|
||||
console.log(chalk.dim(`\nRestarting AO: ao ${args.join(" ")}`));
|
||||
const exitCode = await runAoLifecycleCommand(args);
|
||||
const exitCode = await runAoLifecycleCommand(args, { configPath: plan.configPath });
|
||||
if (exitCode !== 0) {
|
||||
recordActivityEvent({
|
||||
source: "cli",
|
||||
|
|
@ -307,12 +313,16 @@ async function restartAoAfterUpdate(
|
|||
}
|
||||
}
|
||||
|
||||
function runAoLifecycleCommand(args: string[]): Promise<number> {
|
||||
function runAoLifecycleCommand(
|
||||
args: string[],
|
||||
opts: { configPath?: string } = {},
|
||||
): Promise<number> {
|
||||
return new Promise<number>((resolveExit) => {
|
||||
const child = spawn("ao", args, {
|
||||
stdio: "inherit",
|
||||
shell: isWindows(),
|
||||
windowsHide: true,
|
||||
env: opts.configPath ? { ...process.env, AO_CONFIG_PATH: opts.configPath } : process.env,
|
||||
});
|
||||
child.on("error", (error) => {
|
||||
console.error(chalk.yellow(`Could not run ao ${args.join(" ")}: ${error.message}`));
|
||||
|
|
|
|||
Loading…
Reference in New Issue