Files
agent-bounty-protocol/scripts/runtime/purge-github-issue-tasks.ts
OG T 4fd89a447e
Some checks failed
Deploy to 110 WOOO Server / deploy (push) Failing after 8s
chore: open conversion flow + disable scout import noise
2026-06-07 18:56:45 +08:00

137 lines
4.3 KiB
TypeScript

import { PrismaClient } from "../../apps/web/prisma/generated/client";
const prisma = new PrismaClient();
const TARGET_PREFIX = process.env.GITHUB_ISSUE_PREFIX || "GitHub Issue:";
const BATCH_SIZE = Math.max(parseInt(process.env.PURGE_BATCH_SIZE || "100", 10), 1);
const args = new Set(process.argv.slice(2));
const isDryRun = args.has("--dry-run");
const forceRun = args.has("--force");
function chunk<T>(items: T[], size: number): T[][] {
const output: T[][] = [];
for (let index = 0; index < items.length; index += size) {
output.push(items.slice(index, index + size));
}
return output;
}
function normalizeJudgeCount(value: unknown): number {
return typeof value === "number" ? value : 0;
}
async function main() {
if (!isDryRun && !forceRun) {
console.error(
"Refuse to run without explicit mode. Use --dry-run 先看影響筆數,或加上 --force 正式刪除。"
);
process.exit(1);
}
const targetTasks = await prisma.task.findMany({
where: {
title: {
startsWith: TARGET_PREFIX,
},
},
select: { id: true },
});
const targetTaskIds = targetTasks.map((task) => task.id);
if (targetTaskIds.length === 0) {
console.log(`No task with prefix "${TARGET_PREFIX}" found. done.`);
return;
}
const submissionIdsForAll = (
await prisma.submission.findMany({
where: { task_id: { in: targetTaskIds } },
select: { id: true },
})
).map((row) => row.id);
const [taskCount, submissionCount, claimCount, judgeCount, ledgerCount, auditCount, scoutDraftEvents] =
await Promise.all([
prisma.task.count({ where: { id: { in: targetTaskIds } } }),
prisma.submission.count({ where: { task_id: { in: targetTaskIds } } }),
prisma.claim.count({ where: { task_id: { in: targetTaskIds } } }),
submissionIdsForAll.length
? prisma.judgeResult.count({ where: { submission_id: { in: submissionIdsForAll } } })
: Promise.resolve(0),
prisma.ledgerEntry.count({ where: { task_id: { in: targetTaskIds } } }),
prisma.auditEvent.count({ where: { entityType: "TASK", entityId: { in: targetTaskIds } } }),
prisma.auditEvent.count({ where: { action: { startsWith: "SCOUT_DRAFT_" } } }),
]);
console.log("=== Purge Impact Preview ===");
console.log(`Task count: ${normalizeJudgeCount(taskCount)}`);
console.log(`Submission count: ${normalizeJudgeCount(submissionCount)}`);
console.log(`Claim count: ${normalizeJudgeCount(claimCount)}`);
console.log(`JudgeResult count: ${normalizeJudgeCount(judgeCount)}`);
console.log(`LedgerEntry count: ${normalizeJudgeCount(ledgerCount)}`);
console.log(`AuditEvent (entityType TASK) count: ${normalizeJudgeCount(auditCount)}`);
console.log(`AuditEvent (SCOUT_DRAFT_*) count: ${normalizeJudgeCount(scoutDraftEvents)}`);
console.log(`Target batch size: ${BATCH_SIZE}`);
if (isDryRun) {
console.log("Dry-run complete. No data was modified.");
return;
}
for (const idBatch of chunk(targetTaskIds, BATCH_SIZE)) {
await prisma.$transaction(async (tx) => {
const batchSubmissionIds = (
await tx.submission.findMany({
where: { task_id: { in: idBatch } },
select: { id: true },
})
).map((row) => row.id);
if (batchSubmissionIds.length > 0) {
await tx.judgeResult.deleteMany({
where: { submission_id: { in: batchSubmissionIds } },
});
}
await tx.submission.deleteMany({
where: { task_id: { in: idBatch } },
});
await tx.claim.deleteMany({
where: { task_id: { in: idBatch } },
});
await tx.ledgerEntry.deleteMany({
where: { task_id: { in: idBatch } },
});
await tx.auditEvent.deleteMany({
where: {
OR: [
{
entityType: "TASK",
entityId: { in: idBatch },
},
{
action: { startsWith: "SCOUT_DRAFT_" },
entityId: { in: idBatch },
},
],
},
});
await tx.task.deleteMany({
where: { id: { in: idBatch } },
});
});
}
console.log(`Deleted ${taskCount} GitHub Issue task entries.`);
}
main()
.catch((error) => {
console.error("Purge script failed:", error);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});