-
-
Notifications
You must be signed in to change notification settings - Fork 190
/
Copy pathverify-build-artifacts.js
133 lines (120 loc) · 4.15 KB
/
verify-build-artifacts.js
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
129
130
131
132
133
/**
* Description:
* This script verifies the existence and content of build artifacts based on the
* provided CLI flags. It exists with exit code `0` if all verifications pass, otherwise
* with exit code `1`.
*
* Usage:
* node scripts/verify-build-artifacts.js [options]
*
* Options:
* --electron-unbundled Verify artifacts for the unbundled Electron application.
* --electron-bundled Verify artifacts for the bundled Electron application.
* --web Verify artifacts for the web application.
*/
import { access, readdir } from 'node:fs/promises';
import { exec } from 'node:child_process';
import { resolve } from 'node:path';
const PROCESS_ARGUMENTS = process.argv.slice(2);
const PRINT_DIST_DIR_SCRIPT_BASE_COMMAND = 'node scripts/print-dist-dir';
async function main() {
const buildConfigs = getBuildVerificationConfigs();
if (!anyCommandsFound(Object.keys(buildConfigs))) {
die(`No valid command found in process arguments. Expected one of: ${Object.keys(buildConfigs).join(', ')}`);
}
/* eslint-disable no-await-in-loop */
for (const [command, config] of Object.entries(buildConfigs)) {
if (PROCESS_ARGUMENTS.includes(command)) {
const distDir = await executePrintDistDirScript(config.printDistDirScriptArgument);
await verifyDirectoryExists(distDir);
await verifyNonEmptyDirectory(distDir);
await verifyFilesExist(distDir, config.filePatterns);
}
}
/* eslint-enable no-await-in-loop */
console.log('✅ Build completed successfully and all expected artifacts are in place.');
process.exit(0);
}
function getBuildVerificationConfigs() {
return {
'--electron-unbundled': {
printDistDirScriptArgument: '--electron-unbundled',
filePatterns: [
/main[/\\]index\.(cjs|mjs|js)/,
/preload[/\\]index\.(cjs|mjs|js)/,
/renderer[/\\]index\.htm(l)?/,
],
},
'--electron-bundled': {
printDistDirScriptArgument: '--electron-bundled',
filePatterns: [
/latest.*\.yml/, // generates latest.yml for auto-updates
/.*-\d+\.\d+\.\d+\..*/, // a file with extension and semantic version (packaged application)
],
},
'--web': {
printDistDirScriptArgument: '--web',
filePatterns: [
/index\.htm(l)?/,
],
},
};
}
function anyCommandsFound(commands) {
return PROCESS_ARGUMENTS.some((arg) => commands.includes(arg));
}
async function verifyDirectoryExists(directoryPath) {
try {
await access(directoryPath);
} catch (error) {
die(`Directory does not exist at \`${directoryPath}\`:\n\t${error.message}`);
}
}
async function verifyNonEmptyDirectory(directoryPath) {
const files = await readdir(directoryPath);
if (files.length === 0) {
die(`Directory is empty at \`${directoryPath}\``);
}
}
async function verifyFilesExist(directoryPath, filePatterns) {
const files = await listAllFilesRecursively(directoryPath);
for (const pattern of filePatterns) {
const match = files.some((file) => pattern.test(file));
if (!match) {
die(
`No file matches the pattern ${pattern.source} in directory \`${directoryPath}\``,
`\nFiles in directory:\n${files.map((file) => `- ${file}`).join('\n')}`,
);
}
}
}
async function listAllFilesRecursively(directoryPath) {
const dir = await readdir(directoryPath, { withFileTypes: true });
const files = await Promise.all(dir.map(async (dirent) => {
const absolutePath = resolve(directoryPath, dirent.name);
if (dirent.isDirectory()) {
return listAllFilesRecursively(absolutePath);
}
return absolutePath;
}));
return files.flat();
}
async function executePrintDistDirScript(flag) {
return new Promise((resolve, reject) => {
const commandToRun = `${PRINT_DIST_DIR_SCRIPT_BASE_COMMAND} ${flag}`;
exec(commandToRun, (error, stdout, stderr) => {
if (error) {
reject(new Error(`Execution failed with error: ${error}`));
} else if (stderr) {
reject(new Error(`Execution failed with stderr: ${stderr}`));
} else {
resolve(stdout.trim());
}
});
});
}
function die(...message) {
console.error(...message);
process.exit(1);
}
await main();