fix: runtime retain restore facts when Stop supersedes publication
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// @generated by yoi-companion-openapi-typescript@1. Do not edit.
|
||||
// Input: openapi/server-api.json
|
||||
// Input contract: 0.1.0 (sha256:5de3f3b716555717d3274b8c6a385fb66624585941628a53b8b3050cb58f8ab7)
|
||||
// Input contract: 0.1.0 (sha256:4159d6baa918c9d7d3cb6ae02207aad877a69ad1dd4207beb63b271deb24176e)
|
||||
// Options: companion-operation-schema-closure,openapi-3.1,strict-integer-ranges,sorted-output
|
||||
// Output: web/workspace/src/lib/generated/companion-api.ts
|
||||
// Regenerate/check: cargo run -q -p server-api --example generate_companion_api_types -- --check
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @generated by yoi-repository-openapi-typescript@1. Do not edit.
|
||||
// Input: openapi/server-api.json
|
||||
// Input contract: 0.1.0 (sha256:5de3f3b716555717d3274b8c6a385fb66624585941628a53b8b3050cb58f8ab7)
|
||||
// Input contract: 0.1.0 (sha256:4159d6baa918c9d7d3cb6ae02207aad877a69ad1dd4207beb63b271deb24176e)
|
||||
// Options: repository-operation-schema-closure,openapi-3.1,format:uint64=safe-number,strict-safe-integers,sorted-output
|
||||
// Output: web/workspace/src/lib/generated/repository-api.ts
|
||||
// Regenerate/check: cargo run -q -p server-api --example generate_repository_openapi_types -- --check
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @generated by yoi-runtime-openapi-typescript@1. Do not edit.
|
||||
// Input: openapi/server-api.json
|
||||
// Input contract: 0.1.0 (sha256:5de3f3b716555717d3274b8c6a385fb66624585941628a53b8b3050cb58f8ab7)
|
||||
// Input contract: 0.1.0 (sha256:4159d6baa918c9d7d3cb6ae02207aad877a69ad1dd4207beb63b271deb24176e)
|
||||
// Options: runtime-operation-schema-closure,openapi-3.1,strict-integer-ranges,sorted-output
|
||||
// Output: web/workspace/src/lib/generated/runtime-api.ts
|
||||
// Regenerate/check: cargo run -q -p server-api --example generate_runtime_api_types -- --check
|
||||
@@ -181,7 +181,7 @@ export type WorkerRestoreResponse = { result: WorkerRestoreResult; runtime_id: s
|
||||
|
||||
export type WorkerRestoreResult = { diagnostics?: Array<Diagnostic>; state: WorkerRestoreState; worker?: WorkerSummary | null; };
|
||||
|
||||
export type WorkerRestoreState = "accepted" | "rejected" | "rolled_back" | "reconciliation_required";
|
||||
export type WorkerRestoreState = "accepted" | "rejected" | "rolled_back" | "reconciliation_required" | "superseded";
|
||||
|
||||
export type WorkerRetentionResponse = { pinned: boolean; retention_state: string; runtime_id: string; worker_id: string; workspace_id: string; };
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @generated by yoi-ticket-browser-openapi-typescript@1. Do not edit.
|
||||
// Input: openapi/server-api.json
|
||||
// Input contract: 0.1.0 (sha256:5de3f3b716555717d3274b8c6a385fb66624585941628a53b8b3050cb58f8ab7)
|
||||
// Input contract: 0.1.0 (sha256:4159d6baa918c9d7d3cb6ae02207aad877a69ad1dd4207beb63b271deb24176e)
|
||||
// Options: ticket-objective-merge-request-browser-operation-schema-closure,openapi-3.1,strict-integer-ranges,sorted-output
|
||||
// Output: web/workspace/src/lib/generated/ticket-api.ts
|
||||
// Regenerate/check: cargo run -q -p server-api --example generate_ticket_api_types -- --check
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @generated by yoi-worker-openapi-typescript@1. Do not edit.
|
||||
// Input: openapi/server-api.json
|
||||
// Input contract: 0.1.0 (sha256:5de3f3b716555717d3274b8c6a385fb66624585941628a53b8b3050cb58f8ab7)
|
||||
// Input contract: 0.1.0 (sha256:4159d6baa918c9d7d3cb6ae02207aad877a69ad1dd4207beb63b271deb24176e)
|
||||
// Options: worker-operation-schema-closure,openapi-3.1,strict-integer-ranges,sorted-output
|
||||
// Output: web/workspace/src/lib/generated/worker-launch-api.ts
|
||||
// Regenerate/check: cargo run -q -p server-api --example generate_worker_launch_api_types -- --check
|
||||
|
||||
@@ -363,8 +363,13 @@ export function parseWorkerRestoreResponse(
|
||||
exactKeys(result, ["state"], ["diagnostics", "worker"], `${path}.result`);
|
||||
const state = boundedString(result.state, `${path}.result.state`);
|
||||
if (
|
||||
!["accepted", "rejected", "rolled_back", "reconciliation_required"]
|
||||
.includes(state)
|
||||
![
|
||||
"accepted",
|
||||
"rejected",
|
||||
"rolled_back",
|
||||
"superseded",
|
||||
"reconciliation_required",
|
||||
].includes(state)
|
||||
) {
|
||||
fail(`${path}.result.state`, "has an unknown value");
|
||||
}
|
||||
|
||||
@@ -427,7 +427,12 @@ test.each(["switch", "dispose"] as const)(
|
||||
);
|
||||
|
||||
function restoreResponse(
|
||||
state: "accepted" | "rejected" | "rolled_back" | "reconciliation_required",
|
||||
state:
|
||||
| "accepted"
|
||||
| "rejected"
|
||||
| "rolled_back"
|
||||
| "superseded"
|
||||
| "reconciliation_required",
|
||||
extra = {},
|
||||
) {
|
||||
return Response.json({
|
||||
@@ -461,7 +466,13 @@ test.each(["stopped", "idle", "running", "paused", "unavailable"] as const)(
|
||||
);
|
||||
|
||||
test.each(
|
||||
["accepted", "rejected", "rolled_back", "reconciliation_required"] as const,
|
||||
[
|
||||
"accepted",
|
||||
"rejected",
|
||||
"rolled_back",
|
||||
"superseded",
|
||||
"reconciliation_required",
|
||||
] as const,
|
||||
)(
|
||||
"Restore classifies %s through the shared helper, without treating HTTP 200 as success",
|
||||
async (state) => {
|
||||
@@ -470,10 +481,11 @@ test.each(
|
||||
const unsubscribe = workspaceAlerts.subscribe((value) => {
|
||||
alerts = value;
|
||||
});
|
||||
const request = vi.fn(async (input: RequestInfo | URL) =>
|
||||
String(input).endsWith("/restore")
|
||||
? restoreResponse(state)
|
||||
: Response.json(plan())
|
||||
const request = vi.fn(
|
||||
async (input: RequestInfo | URL, _init?: RequestInit) =>
|
||||
String(input).endsWith("/restore")
|
||||
? restoreResponse(state)
|
||||
: Response.json(plan()),
|
||||
);
|
||||
vi.stubGlobal("fetch", request);
|
||||
render(WorkersPage, { data: data() });
|
||||
@@ -498,6 +510,16 @@ test.each(
|
||||
screen.queryByRole("button", { name: "Retry Restore Catalog worker" }),
|
||||
),
|
||||
).toBe(state === "reconciliation_required");
|
||||
expect(
|
||||
request.mock.calls.filter(([url]) => String(url).endsWith("/restore")),
|
||||
).toHaveLength(1);
|
||||
expect(
|
||||
request.mock.calls
|
||||
.filter(([, init]) => init?.method && init.method !== "GET")
|
||||
.map(([url]) => String(url)),
|
||||
).toEqual([
|
||||
"/api/w/page-test/runtimes/runtime-a/workers/worker-a/restore",
|
||||
]);
|
||||
// The response is never projected into the catalog by the action.
|
||||
expect(screen.getByRole("cell", { name: "stopped" })).toBeTruthy();
|
||||
unsubscribe();
|
||||
|
||||
@@ -305,6 +305,7 @@ Deno.test("Restore classification never promotes nonaccepted results and preserv
|
||||
"accepted",
|
||||
"rejected",
|
||||
"rolled_back",
|
||||
"superseded",
|
||||
"reconciliation_required",
|
||||
] as const
|
||||
) {
|
||||
|
||||
@@ -173,12 +173,13 @@ function restoredWorker() {
|
||||
restore_observation_token: "generation-b",
|
||||
};
|
||||
}
|
||||
Deno.test("Restore parser preserves all four states and optional Workspace summary", () => {
|
||||
Deno.test("Restore parser preserves typed outcomes and optional Workspace summary", () => {
|
||||
for (
|
||||
const state of [
|
||||
"accepted",
|
||||
"rejected",
|
||||
"rolled_back",
|
||||
"superseded",
|
||||
"reconciliation_required",
|
||||
]
|
||||
) {
|
||||
|
||||
Reference in New Issue
Block a user