release pipeline
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
"use strict";
|
||||
|
||||
const test = require("node:test");
|
||||
const assert = require("node:assert/strict");
|
||||
const { createHash } = require("node:crypto");
|
||||
const { mkdtemp, readFile, rm } = require("node:fs/promises");
|
||||
const os = require("node:os");
|
||||
const path = require("node:path");
|
||||
const { inflateRawSync } = require("node:zlib");
|
||||
const {
|
||||
ARCHIVE_FILES,
|
||||
normalizeVersion,
|
||||
packageExtension
|
||||
} = require("../scripts/package-extension.js");
|
||||
|
||||
function readZipEntries(archive) {
|
||||
const entries = new Map();
|
||||
let offset = 0;
|
||||
|
||||
while (archive.readUInt32LE(offset) === 0x04034b50) {
|
||||
const method = archive.readUInt16LE(offset + 8);
|
||||
const compressedSize = archive.readUInt32LE(offset + 18);
|
||||
const nameLength = archive.readUInt16LE(offset + 26);
|
||||
const extraLength = archive.readUInt16LE(offset + 28);
|
||||
const nameStart = offset + 30;
|
||||
const dataStart = nameStart + nameLength + extraLength;
|
||||
const name = archive.subarray(nameStart, nameStart + nameLength).toString("utf8");
|
||||
const compressed = archive.subarray(dataStart, dataStart + compressedSize);
|
||||
|
||||
assert.equal(method, 8, `${name} should use DEFLATE compression`);
|
||||
entries.set(name, inflateRawSync(compressed));
|
||||
offset = dataStart + compressedSize;
|
||||
}
|
||||
|
||||
assert.equal(archive.readUInt32LE(offset), 0x02014b50, "central directory is present");
|
||||
return entries;
|
||||
}
|
||||
|
||||
test("normalizes release tags and rejects versions Firefox cannot publish", () => {
|
||||
assert.equal(normalizeVersion("1.2.3"), "1.2.3");
|
||||
assert.equal(normalizeVersion("v2.0"), "2.0");
|
||||
assert.equal(normalizeVersion("V3"), "3");
|
||||
|
||||
for (const version of ["", "v", "1.2.3.4.5", "1.02", "1.0-beta", "1000000000"]) {
|
||||
assert.throws(() => normalizeVersion(version), /Invalid Mozilla extension version|required/);
|
||||
}
|
||||
});
|
||||
|
||||
test("builds a deterministic unsigned XPI with the release version and runtime files only", async (context) => {
|
||||
const rootDirectory = path.resolve(__dirname, "..");
|
||||
const firstOutput = await mkdtemp(path.join(os.tmpdir(), "glagolify-package-"));
|
||||
const secondOutput = await mkdtemp(path.join(os.tmpdir(), "glagolify-package-"));
|
||||
context.after(async () => {
|
||||
await Promise.all([
|
||||
rm(firstOutput, { recursive: true, force: true }),
|
||||
rm(secondOutput, { recursive: true, force: true })
|
||||
]);
|
||||
});
|
||||
|
||||
const first = await packageExtension({
|
||||
rootDirectory,
|
||||
outputDirectory: firstOutput,
|
||||
version: "v9.8.7"
|
||||
});
|
||||
const second = await packageExtension({
|
||||
rootDirectory,
|
||||
outputDirectory: secondOutput,
|
||||
version: "9.8.7"
|
||||
});
|
||||
const firstArchive = await readFile(first.archivePath);
|
||||
const secondArchive = await readFile(second.archivePath);
|
||||
const entries = readZipEntries(firstArchive);
|
||||
|
||||
assert.equal(first.archiveName, "glagolify-9.8.7.xpi");
|
||||
assert.deepEqual([...entries.keys()], [...ARCHIVE_FILES]);
|
||||
assert.equal(JSON.parse(entries.get("manifest.json")).version, "9.8.7");
|
||||
assert.equal(entries.has("package.json"), false);
|
||||
assert.equal(entries.has("tests/package-extension.test.js"), false);
|
||||
assert.deepEqual(firstArchive, secondArchive);
|
||||
|
||||
const digest = createHash("sha256").update(firstArchive).digest("hex");
|
||||
assert.equal(
|
||||
await readFile(first.checksumPath, "utf8"),
|
||||
`${digest} glagolify-9.8.7.xpi\n`
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user