82 lines
2.3 KiB
TypeScript
82 lines
2.3 KiB
TypeScript
|
|
/**
|
||
|
|
* One-off relink helper.
|
||
|
|
*
|
||
|
|
* Re-runs the linking engine on a project without pulling in the server-only
|
||
|
|
* modules — same pattern as scripts/backfill.ts. Run with:
|
||
|
|
* set -a && source .env.local && set +a
|
||
|
|
* npx tsx scripts/relink.ts <projectId>
|
||
|
|
*/
|
||
|
|
|
||
|
|
import PocketBase from "pocketbase";
|
||
|
|
|
||
|
|
import { resolveCommitCard, type LinkCandidate } from "../src/lib/linking/resolve";
|
||
|
|
|
||
|
|
const PB_URL = process.env.NEXT_PUBLIC_PB_URL!;
|
||
|
|
|
||
|
|
async function main() {
|
||
|
|
const projectId = process.argv[2];
|
||
|
|
if (!projectId) throw new Error("Usage: tsx scripts/relink.ts <projectId>");
|
||
|
|
|
||
|
|
const pb = new PocketBase(PB_URL);
|
||
|
|
pb.autoCancellation(false);
|
||
|
|
await pb.collection("_superusers").authWithPassword(
|
||
|
|
process.env.PB_SUPERUSER_EMAIL!,
|
||
|
|
process.env.PB_SUPERUSER_PASSWORD!
|
||
|
|
);
|
||
|
|
|
||
|
|
const cards = await pb.collection("cards").getFullList({
|
||
|
|
filter: `project = "${projectId}"`,
|
||
|
|
fields: "id,number,scope_rule,start_date,created,archived",
|
||
|
|
});
|
||
|
|
const candidates: LinkCandidate[] = cards.map((card) => ({
|
||
|
|
id: card.id,
|
||
|
|
number: card.number,
|
||
|
|
scopeRule: card.scope_rule ?? "",
|
||
|
|
startDate: card.start_date ?? "",
|
||
|
|
created: card.created,
|
||
|
|
archived: Boolean(card.archived),
|
||
|
|
}));
|
||
|
|
|
||
|
|
const commits = await pb.collection("commits").getFullList({
|
||
|
|
filter: `project = "${projectId}"`,
|
||
|
|
fields: "id,message,scope,authored_at,is_merge,card,link_source",
|
||
|
|
});
|
||
|
|
|
||
|
|
let linked = 0;
|
||
|
|
let unlinked = 0;
|
||
|
|
let preserved = 0;
|
||
|
|
|
||
|
|
for (const commit of commits) {
|
||
|
|
if (commit.link_source === "manual") {
|
||
|
|
preserved++;
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
const resolution = resolveCommitCard(
|
||
|
|
{
|
||
|
|
message: commit.message ?? "",
|
||
|
|
scope: commit.scope ?? "",
|
||
|
|
authoredAt: commit.authored_at,
|
||
|
|
isMerge: Boolean(commit.is_merge),
|
||
|
|
},
|
||
|
|
candidates
|
||
|
|
);
|
||
|
|
const nextCard = resolution.cardId ?? "";
|
||
|
|
const nextSource = resolution.source;
|
||
|
|
if (commit.card === nextCard && commit.link_source === nextSource) continue;
|
||
|
|
await pb.collection("commits").update(commit.id, {
|
||
|
|
card: nextCard,
|
||
|
|
link_source: nextSource,
|
||
|
|
});
|
||
|
|
if (nextCard) linked++;
|
||
|
|
else unlinked++;
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log(
|
||
|
|
JSON.stringify({ examined: commits.length - preserved, linked, unlinked, preserved })
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
main().catch((e) => {
|
||
|
|
console.error(e);
|
||
|
|
process.exit(1);
|
||
|
|
});
|