fix(release): use the keychain password for macOS signing setup (#8445)

Backport the pinned packaging tool correction in the workflow so existing release tags can be rebuilt without changing their dependencies.
This commit is contained in:
Mohamed Boudra
2026-11-01 13:35:11 +07:00
committed by GitHub
parent 6ae6308cfb
commit 891e62309c
2 changed files with 77 additions and 1 deletions
+26
View File
@@ -135,6 +135,32 @@ jobs:
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Backport electron-builder#10172 to the pinned build tool only.
# Remove this step when app-builder-lib is upgraded to a release containing it.
- name: Repair temporary keychain password in signing tool
shell: bash
run: |
node <<'KEYCHAIN_FIX'
const fs = require('node:fs');
const path = require('node:path');
const manifestPath = require.resolve('app-builder-lib/package.json');
if (JSON.parse(fs.readFileSync(manifestPath, 'utf8')).version !== '26.8.1') {
throw new Error('Reassess/remove the signing backport for the new app-builder-lib version');
}
const sourcePath = path.join(path.dirname(manifestPath), 'out/codeSign/macCodeSign.js');
let source = fs.readFileSync(sourcePath, 'utf8');
const replacements = [
['importCerts(keychainFile, certPaths, cscPasswords)', 'importCerts(keychainFile, certPaths, cscPasswords, keychainPassword)'],
['importCerts(keychainFile, paths, keyPasswords)', 'importCerts(keychainFile, paths, keyPasswords, keychainPassword)'],
['["set-key-partition-list", "-S", "apple-tool:,apple:", "-s", "-k", password, keychainFile]', '["set-key-partition-list", "-S", "apple-tool:,apple:", "-s", "-k", keychainPassword, keychainFile]'],
];
for (const [before, after] of replacements) {
if (source.split(before).length !== 2) throw new Error('Unexpected signing tool source; refusing to patch');
source = source.replace(before, after);
}
fs.writeFileSync(sourcePath, source);
KEYCHAIN_FIX
- name: Set desktop package version from tag
shell: bash
run: |
+51 -1
View File
@@ -1,5 +1,5 @@
import assert from "node:assert/strict";
import { readFileSync, readdirSync, mkdtempSync, writeFileSync, rmSync } from "node:fs";
import { readFileSync, readdirSync, mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
import { spawnSync } from "node:child_process";
import { tmpdir } from "node:os";
import { join } from "node:path";
@@ -679,3 +679,53 @@ test("macOS jobs use latest runners while preserving release architectures", ()
// GitHub has no standard macos-latest-intel alias; use the newest Intel image.
assert.match(release, /runner: macos-26-intel\n\s+electron_arch: x64/);
});
test("macOS signing repair keeps certificate and keychain passwords separate", () => {
const workflow = readFileSync(new URL(".github/workflows/desktop-release.yml", repoRoot), "utf8");
const match = workflow.match(/<<'KEYCHAIN_FIX'\n([\s\S]*?)\n KEYCHAIN_FIX/);
assert.ok(match, "the release workflow repairs the pinned signing tool");
const script = match[1].replace(/^ /gm, "");
const original = [
"return await importCerts(keychainFile, certPaths, cscPasswords);",
"async function importCerts(keychainFile, paths, keyPasswords) {",
'["import", paths[i], "-P", password]',
'["set-key-partition-list", "-S", "apple-tool:,apple:", "-s", "-k", password, keychainFile]',
"}",
].join("\n");
const directory = mkdtempSync(join(tmpdir(), "signing-repair-"));
try {
const packageDirectory = join(directory, "node_modules/app-builder-lib");
mkdirSync(join(packageDirectory, "out/codeSign"), { recursive: true });
const manifest = join(packageDirectory, "package.json");
const sourcePath = join(packageDirectory, "out/codeSign/macCodeSign.js");
for (const [version, source, succeeds] of [
["26.8.1", original, true],
["26.8.1", original.replace("cscPasswords);", "differentArguments);"), false],
["26.18.0", original, false],
]) {
writeFileSync(manifest, JSON.stringify({ name: "app-builder-lib", version }));
writeFileSync(sourcePath, source);
const result = spawnSync(process.execPath, ["-e", script], {
cwd: directory,
encoding: "utf8",
});
const actual = readFileSync(sourcePath, "utf8");
if (succeeds) {
assert.equal(result.status, 0, result.stderr);
assert.ok(
actual.includes("importCerts(keychainFile, certPaths, cscPasswords, keychainPassword)"),
);
assert.ok(
actual.includes("importCerts(keychainFile, paths, keyPasswords, keychainPassword)"),
);
assert.ok(actual.includes('["import", paths[i], "-P", password]'));
assert.ok(actual.includes('"-k", keychainPassword, keychainFile]'));
} else {
assert.notEqual(result.status, 0);
assert.equal(actual, source, "unexpected tool inputs must fail without a partial write");
}
}
} finally {
rmSync(directory, { recursive: true, force: true });
}
});