Fix container image upgrade migrations before gateway readiness (#101881)

* run all 'openclaw upgrade' migrations with container image upgrades

Signed-off-by: sallyom <somalley@redhat.com>

* fix: block gateway startup on plugin repair warnings

Signed-off-by: sallyom <somalley@redhat.com>

---------

Signed-off-by: sallyom <somalley@redhat.com>
This commit is contained in:
Sally O'Malley
2026-07-08 14:19:05 -04:00
committed by GitHub
parent aa27ae9d9f
commit b81666ca6a
13 changed files with 1003 additions and 116 deletions

View File

@@ -206,6 +206,27 @@ describe("ensureConfigReady", () => {
});
});
it("requires a startup migration checkpoint for foreground gateway startup", async () => {
await runEnsureConfigReady(["gateway"]);
expect(loadAndMaybeMigrateDoctorConfigMock).toHaveBeenCalledWith({
migrateState: true,
migrateLegacyConfig: false,
invalidConfigNote: false,
requireStartupMigrationCheckpoint: true,
});
});
it("does not require a startup migration checkpoint for gateway probes", async () => {
await runEnsureConfigReady(["gateway", "health"]);
expect(loadAndMaybeMigrateDoctorConfigMock).toHaveBeenCalledWith({
migrateState: true,
migrateLegacyConfig: false,
invalidConfigNote: false,
});
});
it("runs doctor flow for legacy sessions without task sidecars", async () => {
const root = useTempOpenClawHome();
fs.mkdirSync(path.join(root, ".openclaw", "sessions"), { recursive: true });

View File

@@ -10,14 +10,7 @@ import { resolveRequiredHomeDir } from "../../infra/home-dir.js";
import type { RuntimeEnv } from "../../runtime.js";
import { shouldMigrateStateFromPath } from "../argv.js";
const ALLOWED_INVALID_COMMANDS = new Set([
"audit",
"doctor",
"logs",
"health",
"help",
"status",
]);
const ALLOWED_INVALID_COMMANDS = new Set(["audit", "doctor", "logs", "health", "help", "status"]);
const ALLOWED_INVALID_GATEWAY_SUBCOMMANDS = new Set([
"run",
"status",
@@ -177,6 +170,15 @@ function snapshotHasConfiguredSessionStore(
return typeof store === "string" && store.trim().length > 0;
}
function shouldRequireStartupMigrationCheckpoint(commandPath: string[]): boolean {
const commandName = commandPath[0];
const subcommandName = commandPath[1];
return (
commandName === "gateway" &&
(subcommandName === undefined || subcommandName === "run" || subcommandName.trim() === "")
);
}
async function getConfigSnapshot() {
// Tests often mutate config fixtures; caching can make those flaky.
if (process.env.VITEST === "true") {
@@ -212,6 +214,9 @@ export async function ensureConfigReady(params: {
migrateState: true,
migrateLegacyConfig: false,
invalidConfigNote: false,
...(shouldRequireStartupMigrationCheckpoint(commandPath)
? { requireStartupMigrationCheckpoint: true }
: {}),
...(params.beforeStateMigrations
? { beforeStateMigrations: params.beforeStateMigrations }
: {}),