Files
CICD/docs/scripts/baseline-migrations.js
SpecialX 13e91e628d
Some checks failed
CI / build-and-test (push) Failing after 3m34s
CI / deploy (push) Has been skipped
Merge exams grading into homework
Redirect /teacher/exams/grading* to /teacher/homework/submissions; remove exam grading UI/actions/data-access; add homework student workflow and update design docs.
2025-12-31 11:59:03 +08:00

91 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

require("dotenv/config");
const fs = require("node:fs");
const crypto = require("node:crypto");
const path = require("node:path");
const mysql = require("mysql2/promise");
const JOURNAL = {
"0000_aberrant_cobalt_man": 1766460456274,
"0001_flawless_texas_twister": 1767004087964,
"0002_equal_wolfpack": 1767145757594,
};
function sha256Hex(input) {
return crypto.createHash("sha256").update(input).digest("hex");
}
async function main() {
const url = process.env.DATABASE_URL;
if (!url) {
throw new Error("DATABASE_URL is not set");
}
const conn = await mysql.createConnection(url);
await conn.query(
"CREATE TABLE IF NOT EXISTS `__drizzle_migrations` (id serial primary key, hash text not null, created_at bigint)"
);
const [existing] = await conn.query(
"SELECT id, hash, created_at FROM `__drizzle_migrations` ORDER BY created_at DESC LIMIT 1"
);
if (Array.isArray(existing) && existing.length > 0) {
console.log("✅ __drizzle_migrations already has entries. Skip baselining.");
await conn.end();
return;
}
const [[accountsRow]] = await conn.query(
"SELECT COUNT(*) AS cnt FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name='accounts'"
);
const accountsExists = Number(accountsRow?.cnt ?? 0) > 0;
if (!accountsExists) {
console.log(" No existing tables detected (accounts missing). Skip baselining.");
await conn.end();
return;
}
const [[structureRow]] = await conn.query(
"SELECT COUNT(*) AS cnt FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='exams' AND column_name='structure'"
);
const examsStructureExists = Number(structureRow?.cnt ?? 0) > 0;
const [[homeworkRow]] = await conn.query(
"SELECT COUNT(*) AS cnt FROM information_schema.tables WHERE table_schema=DATABASE() AND table_name='homework_assignments'"
);
const homeworkExists = Number(homeworkRow?.cnt ?? 0) > 0;
const baselineTags = [];
baselineTags.push("0000_aberrant_cobalt_man");
if (examsStructureExists) baselineTags.push("0001_flawless_texas_twister");
if (homeworkExists) baselineTags.push("0002_equal_wolfpack");
const drizzleDir = path.resolve(__dirname, "..", "..", "drizzle");
for (const tag of baselineTags) {
const sqlPath = path.join(drizzleDir, `${tag}.sql`);
if (!fs.existsSync(sqlPath)) {
throw new Error(`Missing migration file: ${sqlPath}`);
}
const sqlText = fs.readFileSync(sqlPath).toString();
const hash = sha256Hex(sqlText);
const createdAt = JOURNAL[tag];
if (typeof createdAt !== "number") {
throw new Error(`Missing journal timestamp for: ${tag}`);
}
await conn.query(
"INSERT INTO `__drizzle_migrations` (`hash`, `created_at`) VALUES (?, ?)",
[hash, createdAt]
);
}
console.log(`✅ Baselined __drizzle_migrations: ${baselineTags.join(", ")}`);
await conn.end();
}
main().catch((err) => {
console.error("❌ Baseline failed:", err);
process.exit(1);
});