All checks were successful
Deploy MineGeo to Dokploy / deploy (push) Successful in 5m57s
147 lines
4.4 KiB
JavaScript
147 lines
4.4 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { randomUUID } from "node:crypto";
|
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
import { createClient } from "@supabase/supabase-js";
|
|
import sharp from "sharp";
|
|
process.loadEnvFile(".env.local");
|
|
const origin = new URL(process.argv[2] || "https://minegeo.site").origin;
|
|
const db = createClient(
|
|
process.env.NEXT_PUBLIC_SUPABASE_URL,
|
|
process.env.SUPABASE_SECRET_KEY,
|
|
{ auth: { persistSession: false, autoRefreshToken: false } },
|
|
);
|
|
const checked = (r) => {
|
|
if (r.error) throw new Error(r.error.message);
|
|
return r.data;
|
|
};
|
|
const cookies = new Map();
|
|
let id;
|
|
await mkdir(".data/retention-check", { recursive: true });
|
|
async function api(path, body, expected = 200, stranger = false) {
|
|
const response = await fetch(`${origin}/api/v1/bug-reports${path}`, {
|
|
method: body === undefined ? "GET" : "POST",
|
|
headers: {
|
|
origin,
|
|
"content-type": "application/json",
|
|
cookie: stranger
|
|
? ""
|
|
: [...cookies].map(([k, v]) => `${k}=${v}`).join("; "),
|
|
},
|
|
...(body === undefined ? {} : { body: JSON.stringify(body) }),
|
|
signal: AbortSignal.timeout(60000),
|
|
});
|
|
if (!stranger)
|
|
for (const cookie of response.headers.getSetCookie()) {
|
|
const part = cookie.split(";")[0],
|
|
at = part.indexOf("=");
|
|
cookies.set(part.slice(0, at), part.slice(at + 1));
|
|
}
|
|
const result = await response.json();
|
|
assert.equal(response.status, expected, `${path}: ${JSON.stringify(result)}`);
|
|
return result;
|
|
}
|
|
async function row() {
|
|
return checked(
|
|
await db.from("bug_reports").select("*").eq("id", id).maybeSingle(),
|
|
);
|
|
}
|
|
async function waitFor(predicate, label) {
|
|
for (let n = 0; n < 40; n++) {
|
|
const current = await row();
|
|
if (predicate(current)) return current;
|
|
if (current?.cleanup_error) throw new Error(current.cleanup_error);
|
|
await new Promise((r) => setTimeout(r, 3000));
|
|
}
|
|
throw new Error(`Timed out: ${label}`);
|
|
}
|
|
assert.equal((await api("")).ready, true);
|
|
const created = await api("", {
|
|
clientId: randomUUID(),
|
|
title: `[Verification] Retention ${randomUUID()}`,
|
|
description:
|
|
"Automated temporary verification fixture for three-day report retention. This is not a real player bug.",
|
|
displayName: "Support verification",
|
|
pagePath: "/support",
|
|
screenshot: true,
|
|
});
|
|
id = created.id;
|
|
await writeFile(
|
|
".data/retention-check/fixture.json",
|
|
JSON.stringify({ id, cookies: [...cookies] }),
|
|
);
|
|
const image = await sharp({
|
|
create: { width: 8, height: 8, channels: 3, background: "#334455" },
|
|
})
|
|
.png()
|
|
.toBuffer();
|
|
assert.equal(
|
|
(
|
|
await fetch(created.upload, {
|
|
method: "PUT",
|
|
headers: { "content-type": "image/png" },
|
|
body: image,
|
|
})
|
|
).ok,
|
|
true,
|
|
);
|
|
await api(`/${id}/submit`, {});
|
|
await waitFor((r) => r?.issue_synced, "Linear issue creation");
|
|
await api(`/${id}/close`, {}, 404, true);
|
|
const closed = await api(`/${id}/close`, {});
|
|
assert.equal(closed.state, "done");
|
|
assert.equal(
|
|
Date.parse(closed.delete_after) - Date.parse(closed.closed_at),
|
|
3 * 86400000,
|
|
);
|
|
assert.equal((await api(`/${id}/close`, {})).delete_after, closed.delete_after);
|
|
await api(
|
|
`/${id}/messages`,
|
|
{ clientId: randomUUID(), text: "Blocked after closure" },
|
|
409,
|
|
);
|
|
await waitFor((r) => r?.linear_done_synced, "Linear Done status");
|
|
console.log(
|
|
JSON.stringify({
|
|
fixture: id,
|
|
checkpoint: "Done synchronized; three-day deadline and ownership verified",
|
|
}),
|
|
);
|
|
// Accelerate only this journaled verification fixture; no real report is modified.
|
|
const backdated = new Date(Date.now() - 3 * 86400000 - 60000).toISOString();
|
|
checked(
|
|
await db
|
|
.from("bug_reports")
|
|
.update({
|
|
closed_at: backdated,
|
|
delete_after: new Date(Date.now() - 60000).toISOString(),
|
|
cleanup_run_id: null,
|
|
cleanup_lease_until: null,
|
|
status_checked_at: new Date().toISOString(),
|
|
})
|
|
.eq("id", id)
|
|
.like("title", "[Verification] Retention %"),
|
|
);
|
|
await api(`/${id}/retry-cleanup`, {});
|
|
await waitFor((r) => r === null, "both-system deletion");
|
|
assert.equal(
|
|
checked(await db.from("bug_report_messages").select("id").eq("report_id", id))
|
|
.length,
|
|
0,
|
|
);
|
|
assert.equal(
|
|
checked(await db.storage.from("minegeo-support").list(id)).length,
|
|
0,
|
|
);
|
|
await api(`/${id}`, undefined, 404);
|
|
await writeFile(
|
|
".data/retention-check/fixture.json",
|
|
JSON.stringify({ id, deleted: true }),
|
|
);
|
|
console.log(
|
|
JSON.stringify({
|
|
fixture: id,
|
|
checkpoint:
|
|
"Expired report, messages, screenshots and Linear issue deleted",
|
|
}),
|
|
);
|