mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-02 09:11:34 +00:00
fix(ci): repair full release validation regressions (#117447)
* fix(worktrees): reject repositories without commits * test(memory-wiki): allow agent isolation runtime * test(ios): await queued approval retry
This commit is contained in:
@@ -1684,9 +1684,9 @@ private func overrideNotificationServingPreference(_ enabled: Bool) -> () -> Voi
|
||||
}
|
||||
appModel._test_setUnifiedExecApprovalGetResponse(makePendingExecApprovalJSON(approvalID))
|
||||
await appModel._test_reconcileWatchExecApprovalCache(reason: "operator_reconnected")
|
||||
let deadline = ContinuousClock().now.advanced(by: .seconds(2))
|
||||
let deadline = ContinuousClock().now.advanced(by: .seconds(10))
|
||||
while await !writeGate.hasStarted(), ContinuousClock().now < deadline {
|
||||
await Task.yield()
|
||||
try await Task.sleep(for: .milliseconds(10))
|
||||
}
|
||||
let writeCount = await writeGate.callCount()
|
||||
#expect(writeCount == 1)
|
||||
|
||||
@@ -263,5 +263,5 @@ describe("agent-scoped memory-wiki tools", () => {
|
||||
} finally {
|
||||
clearMemoryPluginState();
|
||||
}
|
||||
}, 240_000);
|
||||
}, 360_000);
|
||||
});
|
||||
|
||||
@@ -76,6 +76,8 @@ export class WorktreeSnapshotError extends Error {
|
||||
this.snapshotError = snapshotError;
|
||||
}
|
||||
}
|
||||
|
||||
export class WorktreeRepositoryError extends Error {}
|
||||
const SNAPSHOT_REF_PREFIX = "refs/openclaw/snapshots";
|
||||
const log = createSubsystemLogger("agents/worktrees");
|
||||
|
||||
@@ -181,9 +183,13 @@ async function resolveRepositoryFromRealPath(
|
||||
): Promise<ResolvedRepository> {
|
||||
const rootResult = await runGit(requested, ["rev-parse", "--show-toplevel"]);
|
||||
if (rootResult.code !== 0) {
|
||||
throw new Error(`not a git checkout: ${requestedLabel}`);
|
||||
throw new WorktreeRepositoryError(`not a git checkout: ${requestedLabel}`);
|
||||
}
|
||||
const sourceRoot = await fs.realpath(rootResult.stdout.trim());
|
||||
const headResult = await runGit(sourceRoot, ["rev-parse", "--verify", "HEAD^{commit}"]);
|
||||
if (headResult.code !== 0) {
|
||||
throw new WorktreeRepositoryError(`git checkout has no commits: ${requestedLabel}`);
|
||||
}
|
||||
const commonRaw = await requireGit(sourceRoot, ["rev-parse", "--git-common-dir"]);
|
||||
const commonDir = await fs.realpath(
|
||||
path.isAbsolute(commonRaw) ? commonRaw : path.resolve(sourceRoot, commonRaw),
|
||||
|
||||
@@ -15,7 +15,7 @@ import { resolveSandboxRuntimeStatus } from "../../agents/sandbox/runtime-status
|
||||
import { ensureAgentWorkspace } from "../../agents/workspace.js";
|
||||
import { insideGitCheckout } from "../../agents/worktrees/git.js";
|
||||
import { slugifyWorktreeTitle } from "../../agents/worktrees/name.js";
|
||||
import { managedWorktrees } from "../../agents/worktrees/service.js";
|
||||
import { managedWorktrees, WorktreeRepositoryError } from "../../agents/worktrees/service.js";
|
||||
import { resolveAgentMainSessionKey } from "../../config/sessions/main-session.js";
|
||||
import { sessionEntryForkedFromParent } from "../../config/sessions/session-entry-lineage.js";
|
||||
import type { SessionEntry } from "../../config/sessions/types.js";
|
||||
@@ -375,6 +375,14 @@ export const sessionCreateHandlers: GatewayRequestHandlers = {
|
||||
provisionedSessionWorktree = true;
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof WorktreeRepositoryError) {
|
||||
respond(
|
||||
false,
|
||||
undefined,
|
||||
errorShape(ErrorCodes.INVALID_REQUEST, "agent workspace is not a git checkout"),
|
||||
);
|
||||
return;
|
||||
}
|
||||
respond(false, undefined, errorShape(ErrorCodes.UNAVAILABLE, formatErrorMessage(error)));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1405,6 +1405,28 @@ test("sessions.create rejects worktrees for non-git agent workspaces", async ()
|
||||
}
|
||||
});
|
||||
|
||||
test("sessions.create rejects worktrees for agent workspaces without a commit", async () => {
|
||||
const workspace = await makeNonGitTempDir("openclaw-session-unborn-workspace-");
|
||||
await execFileAsync("git", ["init", workspace]);
|
||||
testState.agentConfig = { workspace };
|
||||
await createSessionStoreDir();
|
||||
try {
|
||||
const created = await directSessionReq(
|
||||
"sessions.create",
|
||||
{ agentId: "main", worktree: true },
|
||||
{ client: { connect: { scopes: ["operator.admin"] } } as never },
|
||||
);
|
||||
|
||||
expect(created.ok).toBe(false);
|
||||
expect(created.error).toMatchObject({
|
||||
code: "INVALID_REQUEST",
|
||||
message: "agent workspace is not a git checkout",
|
||||
});
|
||||
} finally {
|
||||
testState.agentConfig = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
test("sessions.create stores dashboard model, thinking, and parent linkage, and creates a transcript", async () => {
|
||||
const { storePath } = await createSessionStoreDir();
|
||||
agentDiscoveryMock.enabled = true;
|
||||
|
||||
Reference in New Issue
Block a user