chore: open conversion flow + disable scout import noise
Some checks failed
Deploy to 110 WOOO Server / deploy (push) Failing after 8s
Some checks failed
Deploy to 110 WOOO Server / deploy (push) Failing after 8s
This commit is contained in:
136
scripts/runtime/purge-github-issue-tasks.ts
Normal file
136
scripts/runtime/purge-github-issue-tasks.ts
Normal file
@@ -0,0 +1,136 @@
|
||||
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();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user