mirror of
https://github.com/kuaifan/dootask.git
synced 2026-09-14 16:08:35 +00:00
fix(electron): 修复 macOS 签名钥匙串密码传递
This commit is contained in:
parent
a776a94f70
commit
e34dc01d22
@ -8,9 +8,9 @@
|
||||
"start": "electron-forge start",
|
||||
"start-quiet": "sleep 3 && electron-forge start",
|
||||
"build": "electron-builder",
|
||||
"build-mac": "electron-builder --mac",
|
||||
"build-mac": "node scripts/patch-mac-keychain.js && electron-builder --mac",
|
||||
"build-win": "electron-builder --win",
|
||||
"build-mac-publish": "electron-builder --publish always --mac",
|
||||
"build-mac-publish": "node scripts/patch-mac-keychain.js && electron-builder --publish always --mac",
|
||||
"build-win-publish": "electron-builder --publish always --win",
|
||||
"package": "electron-forge package",
|
||||
"make": "electron-forge make",
|
||||
|
||||
50
electron/scripts/patch-mac-keychain.js
vendored
Normal file
50
electron/scripts/patch-mac-keychain.js
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const {createRequire} = require('node:module');
|
||||
|
||||
// Remove this workaround once the supported builder uses the keychain password.
|
||||
const replacements = [
|
||||
['return await importCerts(keychainFile, certPaths, cscPasswords);',
|
||||
'return await importCerts(keychainFile, certPaths, cscPasswords, keychainPassword);'],
|
||||
['async function importCerts(keychainFile, paths, keyPasswords) {',
|
||||
'async function 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]'],
|
||||
];
|
||||
|
||||
function patchSource(source, version) {
|
||||
if (!['26.8.1', '26.15.3'].includes(version)) {
|
||||
throw new Error(`Unsupported app-builder-lib ${version}; review the macOS keychain workaround before building.`);
|
||||
}
|
||||
const count = (text) => source.split(text).length - 1;
|
||||
if (replacements.every(([before, after]) => count(before) === 0 && count(after) === 1)) {
|
||||
return source;
|
||||
}
|
||||
if (!replacements.every(([before, after]) => count(before) === 1 && count(after) === 0)) {
|
||||
throw new Error('Unexpected macCodeSign.js source; refusing to apply the keychain workaround.');
|
||||
}
|
||||
for (const [before, after] of replacements) {
|
||||
source = source.replace(before, after);
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
function patchInstalledBuilder() {
|
||||
// Resolve from electron-builder so a nested dependency is patched correctly.
|
||||
const builderRequire = createRequire(require.resolve('electron-builder/package.json'));
|
||||
const packageFile = builderRequire.resolve('app-builder-lib/package.json');
|
||||
const {version} = JSON.parse(fs.readFileSync(packageFile, 'utf8'));
|
||||
const file = path.join(path.dirname(packageFile), 'out/codeSign/macCodeSign.js');
|
||||
const source = fs.readFileSync(file, 'utf8');
|
||||
const patched = patchSource(source, version);
|
||||
if (patched !== source) {
|
||||
fs.writeFileSync(file, patched);
|
||||
}
|
||||
console.log(`macOS keychain workaround ready (app-builder-lib ${version}).`);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
patchInstalledBuilder();
|
||||
}
|
||||
|
||||
module.exports = {patchSource};
|
||||
47
electron/scripts/patch-mac-keychain.test.js
vendored
Normal file
47
electron/scripts/patch-mac-keychain.test.js
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const vm = require('node:vm');
|
||||
const {patchSource} = require('./patch-mac-keychain');
|
||||
|
||||
const source = `
|
||||
async function createKeychain(keychainFile, certPaths, cscPasswords) {
|
||||
const keychainPassword = "random-keychain-password";
|
||||
return await importCerts(keychainFile, certPaths, cscPasswords);
|
||||
}
|
||||
async function importCerts(keychainFile, paths, keyPasswords) {
|
||||
for (let i = 0; i < paths.length; i++) {
|
||||
const password = keyPasswords[i] ?? "";
|
||||
await exec("/usr/bin/security", ["import", paths[i], "-k", keychainFile, "-P", password]);
|
||||
await exec("/usr/bin/security", ["set-key-partition-list", "-S", "apple-tool:,apple:", "-s", "-k", password, keychainFile]);
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
for (const version of ['26.8.1', '26.15.3']) {
|
||||
test(`patch is idempotent for ${version}`, () => {
|
||||
const patched = patchSource(source, version);
|
||||
assert.notEqual(patched, source);
|
||||
assert.equal(patchSource(patched, version), patched);
|
||||
});
|
||||
}
|
||||
|
||||
for (const passwords of [[''], ['certificate-password'], ['distribution-password', 'installer-password']]) {
|
||||
test(`keeps certificate passwords separate: ${passwords.length} certificate(s), empty=${passwords[0] === ''}`, async () => {
|
||||
const calls = [];
|
||||
const context = vm.createContext({exec: async (command, args) => calls.push({command, args})});
|
||||
vm.runInContext(patchSource(source, '26.15.3'), context);
|
||||
await context.createKeychain('test.keychain', passwords.map((_, i) => `cert-${i}.p12`), passwords);
|
||||
assert.equal(calls.length, passwords.length * 2);
|
||||
for (let i = 0; i < passwords.length; i++) {
|
||||
assert.equal(calls[i * 2].args.at(-1), passwords[i]);
|
||||
assert.equal(calls[i * 2 + 1].args.at(-2), 'random-keychain-password');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
test('rejects unknown versions and changed or partially patched sources', () => {
|
||||
assert.throws(() => patchSource(source, '27.0.0'), /Unsupported/);
|
||||
assert.throws(() => patchSource(source.replace('return await importCerts', 'return importCerts'), '26.15.3'), /Unexpected/);
|
||||
assert.throws(() => patchSource(source + source, '26.15.3'), /Unexpected/);
|
||||
assert.throws(() => patchSource(source.replace('cscPasswords);', 'cscPasswords, keychainPassword);'), '26.15.3'), /Unexpected/);
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user