-
-
Notifications
You must be signed in to change notification settings - Fork 48
Expand file tree
/
Copy pathcustomSign.js
More file actions
128 lines (102 loc) · 4.62 KB
/
Copy pathcustomSign.js
File metadata and controls
128 lines (102 loc) · 4.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
'use strict';
const fs = require('fs');
const path = require('path');
const { execFile } = require('child_process');
const { promisify } = require('util');
const execFileAsync = promisify(execFile);
const DEFAULT_TIMEOUT_MS = 10 * 60 * 1000;
const ENV_FILES = ['build-config.env', 'electron-builder.env'];
const DEFAULT_CERTIFICATE_FILE = 'certs/electroncapture.pfx';
function loadLocalEnvFiles() {
for (const envFile of ENV_FILES) {
const envPath = path.join(__dirname, envFile);
if (!fs.existsSync(envPath)) continue;
const lines = fs.readFileSync(envPath, 'utf8').split(/\r?\n/);
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) continue;
const match = /^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(trimmed);
if (!match) continue;
const name = match[1];
let value = match[2].trim();
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
value = value.slice(1, -1);
}
if (!process.env[name]) process.env[name] = value;
}
}
}
function resolveCertificateFile(certificateFile) {
if (!certificateFile || typeof certificateFile !== 'string') return null;
if (path.isAbsolute(certificateFile) && fs.existsSync(certificateFile)) return certificateFile;
const projectRelativePath = path.resolve(__dirname, certificateFile);
if (fs.existsSync(projectRelativePath)) return projectRelativePath;
const cwdRelativePath = path.resolve(process.cwd(), certificateFile);
if (fs.existsSync(cwdRelativePath)) return cwdRelativePath;
return null;
}
function getPassword(configuration) {
return configuration?.cscInfo?.password || process.env.WIN_CSC_KEY_PASSWORD || process.env.CSC_KEY_PASSWORD || '';
}
function sanitizeOutput(value, password) {
let sanitized = String(value || '');
if (password) sanitized = sanitized.split(password).join('***');
return sanitized.trim();
}
async function runSignTool(toolPath, args, toolEnv, password) {
const timeout = Number.parseInt(process.env.SIGNTOOL_TIMEOUT, 10) || DEFAULT_TIMEOUT_MS;
try {
await execFileAsync(toolPath, args, {
cwd: __dirname,
env: { ...process.env, ...(toolEnv || {}) },
timeout,
windowsHide: true,
maxBuffer: 10 * 1024 * 1024,
});
} catch (error) {
const stdout = sanitizeOutput(error.stdout, password);
const stderr = sanitizeOutput(error.stderr, password);
const message = sanitizeOutput(error.message, password);
const details = [...new Set([stdout, stderr, message].filter(Boolean))].join('\n');
throw new Error(`signtool failed for ${path.basename(args[args.length - 1])}${details ? `\n${details}` : ''}`);
}
}
async function getSignTool(signingManager, isWindows) {
const toolInfo = await signingManager.getToolPath(isWindows);
if (!isWindows || fs.existsSync(toolInfo.path) || process.arch !== 'arm64') return toolInfo;
const architectureDirectory = path.dirname(toolInfo.path);
if (path.basename(architectureDirectory).toLowerCase() !== 'arm64') return toolInfo;
const x64ToolPath = path.join(path.dirname(architectureDirectory), 'x64', path.basename(toolInfo.path));
if (!fs.existsSync(x64ToolPath)) return toolInfo;
console.log(` * using x64 signtool under Windows ARM emulation path=${x64ToolPath}`);
return { ...toolInfo, path: x64ToolPath };
}
exports.default = async function signWindowsArtifact(configuration, packager) {
loadLocalEnvFiles();
const certificateFile = resolveCertificateFile(configuration?.cscInfo?.file || DEFAULT_CERTIFICATE_FILE);
if (!certificateFile) {
console.log(` * skipping signing reason=certificate not found at ${DEFAULT_CERTIFICATE_FILE}`);
return false;
}
const password = getPassword(configuration);
if (!password) {
console.log(' * skipping signing reason=WIN_CSC_KEY_PASSWORD not set');
return false;
}
if (!configuration?.path) {
throw new Error('Invalid signing configuration from electron-builder');
}
const cscInfo = {
...(configuration.cscInfo || {}),
file: certificateFile,
password,
};
const isWindows = process.platform === 'win32';
if (!packager?.signingManager) throw new Error('Windows signing manager is unavailable');
const signingManager = await packager.signingManager.value;
const toolInfo = await getSignTool(signingManager, isWindows);
const args = signingManager.computeSignToolArgs({ ...configuration, cscInfo }, isWindows);
console.log(` * signing file=${configuration.path} certificateFile=${path.relative(__dirname, certificateFile)}`);
await runSignTool(toolInfo.path, args, toolInfo.env, password);
return true;
};