63 lines
3.1 KiB
JavaScript
63 lines
3.1 KiB
JavaScript
const assert = require("assert");
|
|
const crypto = require("crypto");
|
|
const fs = require("fs");
|
|
const os = require("os");
|
|
const path = require("path");
|
|
const AdmZip = require("adm-zip");
|
|
const { verifyPatchPackage } = require("../src/services/update-manager");
|
|
|
|
const root = path.join(__dirname, "..");
|
|
const archivePath = path.join(root, "dist", "lumi-core-1.2.0-to-0.2.2-repair.zip");
|
|
assert.equal(fs.existsSync(archivePath), true, "build the repair patch first");
|
|
const zip = new AdmZip(archivePath);
|
|
const entries = zip.getEntries().filter((entry) => !entry.isDirectory);
|
|
const names = new Set(entries.map((entry) => entry.entryName.replace(/\\/g, "/")));
|
|
assert.equal(names.has("patch-manifest.json"), true);
|
|
const manifest = JSON.parse(zip.readAsText("patch-manifest.json"));
|
|
assert.equal(manifest.target, "core");
|
|
assert.equal(manifest.to_version, "0.2.2");
|
|
assert.equal(manifest.data_policy, "preserve");
|
|
assert.deepEqual(manifest.from_versions, ["0.1.9", "1.2.0", "0.2.0", "0.2.1", "0.2.2"]);
|
|
|
|
const forbidden = /^(?:data|plugins|node_modules|config|storage|uploads|logs|database|databases|knowledge\/(?:community|corrections))(?:\/|$)|^\.env(?:\.|$)|^\.secrets$/;
|
|
for (const entry of entries) {
|
|
assert.doesNotMatch(entry.entryName, forbidden, `repair includes preserved data path ${entry.entryName}`);
|
|
}
|
|
for (const [relativePath, expected] of Object.entries(manifest.files)) {
|
|
assert.equal(names.has(relativePath), true, `${relativePath} is listed but missing`);
|
|
const actual = crypto.createHash("sha256").update(zip.readFile(relativePath)).digest("hex");
|
|
assert.equal(actual, expected, `${relativePath} checksum`);
|
|
}
|
|
assert.equal(Object.keys(manifest.files).length + 1, entries.length, "every repair file must be checksummed");
|
|
assert.equal(JSON.parse(zip.readAsText("package.json")).version, "0.2.2");
|
|
|
|
const simulation = fs.mkdtempSync(path.join(os.tmpdir(), "lumi-repair-simulation-"));
|
|
try {
|
|
const sentinels = [
|
|
"data/app.db",
|
|
"plugins/okf/data/local.db",
|
|
"node_modules/local-only/package.json",
|
|
"knowledge/community/people.md",
|
|
"knowledge/corrections/fix.md",
|
|
".env"
|
|
];
|
|
for (const sentinel of sentinels) {
|
|
const target = path.join(simulation, sentinel);
|
|
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
fs.writeFileSync(target, `preserve:${sentinel}`);
|
|
}
|
|
zip.extractAllTo(simulation, true);
|
|
assert.equal(verifyPatchPackage(simulation).to_version, "0.2.2");
|
|
for (const sentinel of sentinels) {
|
|
assert.equal(fs.readFileSync(path.join(simulation, sentinel), "utf8"), `preserve:${sentinel}`);
|
|
}
|
|
assert.equal(JSON.parse(fs.readFileSync(path.join(simulation, "package.json"), "utf8")).version, "0.2.2");
|
|
assert.equal(fs.existsSync(path.join(simulation, "src", "services", "dependency-manager.js")), true);
|
|
assert.equal(fs.existsSync(path.join(simulation, "src", "services", "production-diagnostics.js")), true);
|
|
assert.equal(fs.existsSync(path.join(simulation, "src", "web", "views", "admin-diagnostics.ejs")), true);
|
|
} finally {
|
|
fs.rmSync(simulation, { recursive: true, force: true });
|
|
}
|
|
|
|
console.log(`Core repair patch verification passed (${entries.length} files, no preserved data payloads).`);
|