release: produce a versioned per-browser artifact and pin the Chrome extension id (closes #310)
All checks were successful
check / check (push) Successful in 32s
e2e / e2e-chrome (push) Successful in 1m44s
e2e / e2e-firefox (push) Successful in 32s

manifest/chrome.json now carries a fixed public key, so the extension id and the chrome.storage.local partition holding the wallet stay stable across checkout moves and re-clones instead of being derived from the absolute path. A release entrypoint produces a self-contained versioned artifact per browser, including the files that sit at dist/ root outside both browser directories. One version source of truth, enforced: the build fails naming the culprit when the two manifests and package.json disagree, and BUILD_COMMIT now marks a dirty tree as dirty. Firefox ships an unsigned XPI; the README states that release Firefox and ESR refuse it, that Developer Edition or Unbranded is required, and that Remove is irreversible except from the recovery phrase, which is asserted by test.
This commit was merged in pull request #347.
This commit is contained in:
2026-08-23 16:13:22 +02:00
parent 669c443bf9
commit 769f6a5289
21 changed files with 2142 additions and 42 deletions

View File

@@ -3,6 +3,7 @@ const path = require("path");
const crypto = require("crypto");
const { execSync } = require("child_process");
const esbuild = require("esbuild");
const { resolveVersion } = require("./script/lib/version");
const DIST = path.join(__dirname, "dist");
const DIST_CHROME = path.join(DIST, "chrome");
@@ -160,28 +161,53 @@ function isDebugBuild() {
return process.env.AUTISTMASK_DEBUG === "1";
}
// A short git output, or null when git cannot answer. Distinguishing "git said
// nothing" from "git could not be asked" matters below: a working tree whose
// state is unknown must not be stamped as clean.
function git(args) {
try {
return execSync(`git ${args}`, {
encoding: "utf8",
stdio: ["ignore", "pipe", "ignore"],
}).trim();
} catch {
// not a git repo, or git not available
return null;
}
}
// The working-tree state, as a suffix for the displayed commit: "" when the
// tree matches HEAD, "-dirty" when it does not, "-unknown" when git answered
// the hash but not the status. Without this a build from a modified tree
// stamped a clean hash, so the About screen named a commit whose contents were
// not what was running — the one thing that stamp exists to establish.
//
// git status --porcelain honours .gitignore, so dist/ and node_modules/ do not
// make every build dirty; an untracked file that is NOT ignored does, and
// correctly: it may well be in the bundle.
function worktreeSuffix() {
const status = git("status --porcelain");
if (status === null) return "-unknown";
return status === "" ? "" : "-dirty";
}
function getBuildInfo() {
const pkg = JSON.parse(
fs.readFileSync(path.join(__dirname, "package.json"), "utf8"),
);
let commitHash = "unknown";
try {
commitHash = execSync("git rev-parse --short HEAD", {
encoding: "utf8",
}).trim();
} catch {
// not a git repo or git not available
}
let commitHashFull = "unknown";
try {
commitHashFull = execSync("git rev-parse HEAD", {
encoding: "utf8",
}).trim();
} catch {
// not a git repo or git not available
}
const commitHashFull = git("rev-parse HEAD") || "unknown";
const shortHash = git("rev-parse --short HEAD") || "unknown";
// The full hash is left clean because it is the href of the commit link in
// the About screen, and "abc123-dirty" is not a commit anyone can fetch.
// The displayed short hash carries the marker, so the screen says the tree
// was modified while still linking somewhere real.
const commitHash =
shortHash === "unknown" ? shortHash : shortHash + worktreeSuffix();
return {
version: pkg.version,
// Fails the build when package.json and the two manifests disagree;
// see script/lib/version.js. Called before anything is emitted, so a
// tree with no single version never reaches dist/.
version: resolveVersion(__dirname),
license: pkg.license,
author: pkg.author,
commitHash,