源码快照 @ 2026-09-02 (source-only, 剔除非源码素材)
This commit is contained in:
@@ -0,0 +1,241 @@
|
||||
import assert from "node:assert/strict"
|
||||
import test from "node:test"
|
||||
|
||||
import {
|
||||
pruneDaytonaDevSnapshots,
|
||||
selectDevSnapshotPrunes,
|
||||
} from "./prune-daytona-dev-snapshots.mjs"
|
||||
|
||||
const apiKey = "test-daytona-api-key"
|
||||
const apiUrl = "https://app.daytona.io/api"
|
||||
|
||||
function jsonResponse(value, init) {
|
||||
return new Response(JSON.stringify(value), init)
|
||||
}
|
||||
|
||||
function snapshot(id, name, createdAt, state = "inactive") {
|
||||
return { id, name, state, createdAt }
|
||||
}
|
||||
|
||||
function inventoryFetch(snapshots, sandboxes = []) {
|
||||
const calls = []
|
||||
const fetchImpl = async (url, options) => {
|
||||
calls.push({ url, options })
|
||||
if (url.includes("/snapshots?")) {
|
||||
return jsonResponse({ items: snapshots, total: snapshots.length })
|
||||
}
|
||||
if (url.includes("/sandbox?")) {
|
||||
return jsonResponse(sandboxes)
|
||||
}
|
||||
return jsonResponse({})
|
||||
}
|
||||
return { calls, fetchImpl }
|
||||
}
|
||||
|
||||
test("selection prunes only unprotected dev snapshots", () => {
|
||||
const snapshots = [
|
||||
snapshot("old", "openwork-dev-old", "2026-01-01T00:00:00Z"),
|
||||
snapshot("stopped", "openwork-dev-stopped", "2026-01-02T00:00:00Z"),
|
||||
snapshot("explicit", "openwork-dev-explicit", "2026-01-03T00:00:00Z"),
|
||||
snapshot("pulling", "openwork-dev-pulling", "2026-01-04T00:00:00Z", "pulling"),
|
||||
snapshot("active", "openwork-dev-active-ref", "2026-01-05T00:00:00Z"),
|
||||
snapshot("recent-1", "openwork-dev-recent-1", "2026-01-06T00:00:00Z"),
|
||||
snapshot("recent-2", "openwork-dev-recent-2", "2026-01-07T00:00:00Z"),
|
||||
snapshot("release", "openwork-0.18.23", "2026-01-08T00:00:00Z"),
|
||||
snapshot("base", "daytonaio/sandbox:0.8.0", "2026-01-09T00:00:00Z"),
|
||||
snapshot("windows", "windows-small", "2026-01-10T00:00:00Z"),
|
||||
]
|
||||
const sandboxes = [
|
||||
{ id: "started", state: "started", snapshot: "openwork-dev-active-ref" },
|
||||
{ id: "stopped", state: "stopped", snapshot: "openwork-dev-stopped" },
|
||||
{ id: "archived", state: "archived", snapshot: "openwork-dev-stopped" },
|
||||
]
|
||||
|
||||
const result = selectDevSnapshotPrunes({
|
||||
snapshots,
|
||||
sandboxes,
|
||||
nameBase: "openwork",
|
||||
keepNames: ["openwork-dev-explicit"],
|
||||
keepCount: 2,
|
||||
})
|
||||
|
||||
assert.deepEqual(result.prune.map((item) => item.name), [
|
||||
"openwork-dev-old",
|
||||
"openwork-dev-stopped",
|
||||
])
|
||||
assert.deepEqual(result.keep.map((item) => [item.name, item.reason]), [
|
||||
["openwork-dev-explicit", "explicit"],
|
||||
["openwork-dev-pulling", "in-flight"],
|
||||
["openwork-dev-active-ref", "active-ref"],
|
||||
["openwork-dev-recent-1", "recent"],
|
||||
["openwork-dev-recent-2", "recent"],
|
||||
])
|
||||
assert.equal(result.prune.some((item) => !item.name.startsWith("openwork-dev-")), false)
|
||||
})
|
||||
|
||||
test("exactly keepCount in-scope snapshots prunes nothing", () => {
|
||||
const snapshots = [
|
||||
snapshot("one", "openwork-dev-one", "2026-01-01T00:00:00Z"),
|
||||
snapshot("two", "openwork-dev-two", "2026-01-02T00:00:00Z"),
|
||||
]
|
||||
const result = selectDevSnapshotPrunes({
|
||||
snapshots,
|
||||
sandboxes: [],
|
||||
nameBase: "openwork",
|
||||
keepNames: [],
|
||||
keepCount: 2,
|
||||
})
|
||||
|
||||
assert.deepEqual(result.prune, [])
|
||||
})
|
||||
|
||||
test("dry-run fetches inventory but sends no DELETE requests", async () => {
|
||||
const snapshots = [
|
||||
snapshot("old", "openwork-dev-old", "2026-01-01T00:00:00Z"),
|
||||
snapshot("new", "openwork-dev-new", "2026-01-02T00:00:00Z"),
|
||||
]
|
||||
const { calls, fetchImpl } = inventoryFetch(snapshots)
|
||||
|
||||
const result = await pruneDaytonaDevSnapshots({
|
||||
apiKey,
|
||||
keepNames: ["openwork-dev-new"],
|
||||
keepCount: 1,
|
||||
dryRun: true,
|
||||
fetchImpl,
|
||||
log: () => {},
|
||||
})
|
||||
|
||||
assert.deepEqual(result.prune.map((item) => item.id), ["old"])
|
||||
assert.equal(calls.filter((call) => call.options.method === "DELETE").length, 0)
|
||||
assert.equal(calls.filter((call) => call.options.method === "GET").length, 2)
|
||||
})
|
||||
|
||||
test("real run deletes every selected id and no kept ids", async () => {
|
||||
const snapshots = [
|
||||
snapshot("old-1", "openwork-dev-old-1", "2026-01-01T00:00:00Z"),
|
||||
snapshot("old-2", "openwork-dev-old-2", "2026-01-02T00:00:00Z"),
|
||||
snapshot("new", "openwork-dev-new", "2026-01-03T00:00:00Z"),
|
||||
]
|
||||
const { calls, fetchImpl } = inventoryFetch(snapshots)
|
||||
|
||||
await pruneDaytonaDevSnapshots({
|
||||
apiKey,
|
||||
keepNames: ["openwork-dev-new"],
|
||||
keepCount: 1,
|
||||
fetchImpl,
|
||||
log: () => {},
|
||||
})
|
||||
|
||||
assert.deepEqual(
|
||||
calls.filter((call) => call.options.method === "DELETE").map((call) => call.url),
|
||||
[`${apiUrl}/snapshots/old-1`, `${apiUrl}/snapshots/old-2`],
|
||||
)
|
||||
})
|
||||
|
||||
test("pagination protects newest snapshots and reads all sandbox pages", async () => {
|
||||
const firstPage = Array.from({ length: 200 }, (_, index) =>
|
||||
snapshot(
|
||||
`old-${index}`,
|
||||
`openwork-dev-old-${String(index).padStart(3, "0")}`,
|
||||
`2025-01-${String((index % 28) + 1).padStart(2, "0")}T00:00:00Z`,
|
||||
),
|
||||
)
|
||||
const newest = snapshot("newest", "openwork-dev-newest", "2026-01-01T00:00:00Z")
|
||||
const calls = []
|
||||
const fetchImpl = async (url, options) => {
|
||||
calls.push({ url, options })
|
||||
if (url.includes("/snapshots?")) {
|
||||
const page = Number(new URL(url).searchParams.get("page"))
|
||||
return jsonResponse({
|
||||
items: page === 1 ? firstPage : [newest],
|
||||
total: 201,
|
||||
})
|
||||
}
|
||||
if (url.includes("/sandbox?")) {
|
||||
const cursor = new URL(url).searchParams.get("cursor")
|
||||
return jsonResponse(
|
||||
cursor
|
||||
? {
|
||||
items: [
|
||||
{ id: "active", state: "started", snapshot: firstPage[0].name },
|
||||
],
|
||||
nextCursor: null,
|
||||
}
|
||||
: {
|
||||
items: Array.from({ length: 200 }, (_, index) => ({
|
||||
id: `sandbox-${index}`,
|
||||
state: "stopped",
|
||||
snapshot: null,
|
||||
})),
|
||||
nextCursor: "cursor-2",
|
||||
},
|
||||
)
|
||||
}
|
||||
return jsonResponse({})
|
||||
}
|
||||
|
||||
const result = await pruneDaytonaDevSnapshots({
|
||||
apiKey,
|
||||
keepNames: [newest.name],
|
||||
keepCount: 1,
|
||||
fetchImpl,
|
||||
log: () => {},
|
||||
})
|
||||
|
||||
assert.equal(result.keep.some((item) => item.id === "newest"), true)
|
||||
assert.equal(result.keep.some((item) => item.id === "old-0"), true)
|
||||
assert.equal(result.prune.length, 199)
|
||||
assert.equal(calls.some((call) => call.url.includes("/snapshots/newest")), false)
|
||||
assert.equal(calls.some((call) => call.url.includes("/snapshots/old-0")), false)
|
||||
assert.equal(calls.some((call) => call.url.endsWith("/snapshots/old-1")), true)
|
||||
const sandboxCalls = calls.filter((call) => call.url.includes("/sandbox?"))
|
||||
assert.equal(sandboxCalls.length, 2)
|
||||
assert.equal(sandboxCalls[1].url.includes("cursor=cursor-2"), true)
|
||||
assert.equal(sandboxCalls[1].url.includes("page="), false)
|
||||
})
|
||||
|
||||
test("a failed DELETE does not prevent later deletes and rejects with the result", async () => {
|
||||
const snapshots = [
|
||||
snapshot("old-1", "openwork-dev-old-1", "2026-01-01T00:00:00Z"),
|
||||
snapshot("old-2", "openwork-dev-old-2", "2026-01-02T00:00:00Z"),
|
||||
snapshot("new", "openwork-dev-new", "2026-01-03T00:00:00Z"),
|
||||
]
|
||||
const calls = []
|
||||
const messages = []
|
||||
const fetchImpl = async (url, options) => {
|
||||
calls.push({ url, options })
|
||||
if (url.includes("/snapshots?")) {
|
||||
return jsonResponse({ items: snapshots, total: snapshots.length })
|
||||
}
|
||||
if (url.includes("/sandbox?")) {
|
||||
return jsonResponse([])
|
||||
}
|
||||
if (url.endsWith("/old-1")) {
|
||||
return new Response("upstream exploded", { status: 500 })
|
||||
}
|
||||
return jsonResponse({})
|
||||
}
|
||||
|
||||
await assert.rejects(
|
||||
pruneDaytonaDevSnapshots({
|
||||
apiKey,
|
||||
keepNames: ["openwork-dev-new"],
|
||||
keepCount: 1,
|
||||
fetchImpl,
|
||||
log: (message) => messages.push(message),
|
||||
}),
|
||||
(error) => {
|
||||
assert.equal(error.result.failures.length, 1)
|
||||
assert.equal(
|
||||
error.result.summary,
|
||||
"summary: pruned=1 kept=1 out-of-scope=0 failed=1",
|
||||
)
|
||||
return true
|
||||
},
|
||||
)
|
||||
assert.deepEqual(
|
||||
calls.filter((call) => call.options.method === "DELETE").map((call) => call.url),
|
||||
[`${apiUrl}/snapshots/old-1`, `${apiUrl}/snapshots/old-2`],
|
||||
)
|
||||
assert.equal(messages.at(-1), "summary: pruned=1 kept=1 out-of-scope=0 failed=1")
|
||||
})
|
||||
Reference in New Issue
Block a user