Skip to content

Commit d66da25

Browse files
author
Akos Kitta
committed
build: use execa for the packager
Signed-off-by: Akos Kitta <[email protected]>
1 parent 36e4dd9 commit d66da25

File tree

6 files changed

+197
-301
lines changed

6 files changed

+197
-301
lines changed

electron/packager/config.js

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
//@ts-check
22

3-
const fs = require('fs');
4-
const path = require('path');
3+
const fs = require('node:fs');
4+
const path = require('node:path');
55
const semver = require('semver');
66
const merge = require('deepmerge');
77
const dateFormat = require('dateformat');
88
const { isNightly, isRelease, git } = require('./utils');
99

10-
function artifactName() {
10+
async function artifactName() {
1111
const { platform, arch } = process;
12-
const id = (() => {
12+
const id = await (() => {
1313
if (isRelease) {
1414
return getVersion();
1515
} else if (isNightly) {
@@ -69,8 +69,8 @@ function electronPlatform() {
6969
}
7070
}
7171

72-
function getVersion() {
73-
const repositoryRootPath = git('rev-parse --show-toplevel');
72+
async function getVersion() {
73+
const repositoryRootPath = await git(['rev-parse', '--show-toplevel']);
7474
let version = JSON.parse(
7575
fs.readFileSync(path.join(repositoryRootPath, 'package.json'), {
7676
encoding: 'utf8',
@@ -85,7 +85,7 @@ function getVersion() {
8585
if (isNightly) {
8686
version = `${version}-nightly-${timestamp()}`;
8787
} else {
88-
version = `${version}-snapshot-${currentCommitish()}`;
88+
version = `${version}-snapshot-${await currentCommitish()}`;
8989
}
9090
if (!semver.valid(version)) {
9191
throw new Error(`Invalid patched version: '${version}'.`);
@@ -109,18 +109,18 @@ function timestamp() {
109109
return dateFormat(new Date(), 'yyyymmdd');
110110
}
111111

112-
function currentCommitish() {
113-
return git('rev-parse --short HEAD');
112+
async function currentCommitish() {
113+
return git(['rev-parse', '--short', 'HEAD']);
114114
}
115115

116116
// function currentBranch() {
117117
// return git('rev-parse --abbrev-ref HEAD');
118118
// }
119119

120-
function generateTemplate(buildDate) {
120+
async function generateTemplate(buildDate) {
121121
// do `export PUBLISH=true yarn package` if you want to mimic CI build locally.
122122
// const electronPublish = release || (isCI && currentBranch() === 'main') || process.env.PUBLISH === 'true';
123-
const version = getVersion();
123+
const version = await getVersion();
124124
const productName = 'Arduino IDE';
125125
const name = 'arduino-ide';
126126
const updateChannel = getChannel();
@@ -139,7 +139,7 @@ function generateTemplate(buildDate) {
139139
productName,
140140
appId: 'cc.arduino.IDE2',
141141
[electronPlatform()]: {
142-
artifactName: artifactName(),
142+
artifactName: await artifactName(),
143143
},
144144
},
145145
};

electron/packager/index.js

+68-40
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
throw reason;
2222
});
2323

24-
const fs = require('fs');
25-
const join = require('path').join;
24+
const fs = require('node:fs');
25+
const join = require('node:path').join;
2626
const shell = require('shelljs');
2727
const { echo, cp, mkdir, mv, rm } = shell;
2828
shell.config.fatal = true;
@@ -32,7 +32,7 @@
3232
// https://github.com/shelljs/shelljs/issues/1024#issuecomment-1001552543
3333
shell.env.NODE_OPTIONS = '--max_old_space_size=4096'; // Increase heap size for the CI
3434
shell.env.PUPPETEER_SKIP_CHROMIUM_DOWNLOAD = 'true'; // Skip download and avoid `ERROR: Failed to download Chromium`.
35-
const template = require('./config').generateTemplate(
35+
const template = await require('./config').generateTemplate(
3636
new Date().toISOString()
3737
);
3838
const utils = require('./utils');
@@ -74,12 +74,14 @@
7474
// Clean up the `./electron/build/resources` folder with Git.
7575
// To avoid file duplication between bundled app and dev mode, some files are copied from `./electron-app` to `./electron/build` folder.
7676
const foldersToSyncFromDev = ['resources'];
77-
foldersToSyncFromDev.forEach((filename) =>
78-
shell.exec(
79-
`git -C ${join(repoRoot, 'electron', 'build', filename)} clean -ffxdq`,
80-
{
81-
async: false,
82-
}
77+
await Promise.all(
78+
foldersToSyncFromDev.map((filename) =>
79+
exec('git', [
80+
'-C',
81+
join(repoRoot, 'electron', 'build', filename),
82+
'clean',
83+
'-ffxdq',
84+
])
8385
)
8486
);
8587

@@ -104,15 +106,20 @@
104106
// Build and test the extensions |
105107
//-------------------------------+
106108
for (const extension of extensions) {
107-
exec(
108-
`yarn --network-timeout 1000000 --cwd ${join(repoRoot, extension)}`,
109+
await exec(
110+
'yarn',
111+
['--network-timeout', '1000000', '--cwd', join(repoRoot, extension)],
109112
`Building and testing ${extension}`
110113
);
111-
exec(
112-
`yarn --network-timeout 1000000 --cwd ${join(
113-
repoRoot,
114-
extension
115-
)} test:slow`,
114+
await exec(
115+
'yarn',
116+
[
117+
'--network-timeout',
118+
'1000000',
119+
'--cwd',
120+
join(repoRoot, extension),
121+
'test:slow',
122+
],
116123
`Executing slow tests ${extension}`
117124
);
118125
}
@@ -142,11 +149,21 @@
142149
for (const extension of extensions) {
143150
const packageJsonPath = join(repoRoot, extension, 'package.json');
144151
const versionToRestore = readJson(packageJsonPath).version;
145-
exec(
146-
`yarn --network-timeout 1000000 --cwd ${join(
147-
repoRoot,
148-
extension
149-
)} publish --ignore-scripts --new-version ${version} --no-git-tag-version --registry http://localhost:4873`,
152+
await exec(
153+
'yarn',
154+
[
155+
'--network-timeout',
156+
'1000000',
157+
'--cwd',
158+
join(repoRoot, extension),
159+
'publish',
160+
'--ignore-scripts',
161+
'--new-version',
162+
version,
163+
'--no-git-tag-version',
164+
'--registry',
165+
'http://localhost:4873',
166+
],
150167
`Publishing ${extension}@${version} to the private npm registry`
151168
);
152169
// Publishing will change the version number, this should be reverted up after the build.
@@ -250,20 +267,26 @@ ${fs
250267
//-------------------------------------------------------------------------------------------+
251268
// Install all private and public dependencies for the electron application and build Theia. |
252269
//-------------------------------------------------------------------------------------------+
253-
exec(
254-
`yarn --network-timeout 1000000 --cwd ${join(
255-
repoRoot,
256-
'electron',
257-
'build'
258-
)} --registry http://localhost:4873`,
270+
await exec(
271+
'yarn',
272+
[
273+
'--network-timeout',
274+
'1000000',
275+
'--cwd',
276+
join(repoRoot, 'electron', 'build'),
277+
'--registry',
278+
'http://localhost:4873',
279+
],
259280
'Installing dependencies'
260281
);
261-
exec(
262-
`yarn --cwd ${join(repoRoot, 'electron', 'build')} build`,
282+
await exec(
283+
'yarn',
284+
['--cwd', join(repoRoot, 'electron', 'build'), 'build'],
263285
`Building the ${productName} application`
264286
);
265-
exec(
266-
`yarn --cwd ${join(repoRoot, 'electron', 'build')} rebuild`,
287+
await exec(
288+
'yarn',
289+
['--cwd', join(repoRoot, 'electron', 'build'), 'rebuild'],
267290
'Rebuilding native dependencies'
268291
);
269292

@@ -284,8 +307,9 @@ ${fs
284307
//-----------------------------------+
285308
// Package the electron application. |
286309
//-----------------------------------+
287-
exec(
288-
`yarn --cwd ${join(repoRoot, 'electron', 'build')} package`,
310+
await exec(
311+
'yarn',
312+
['--cwd', join(repoRoot, 'electron', 'build'), 'package'],
289313
`Packaging the ${productName} application`
290314
);
291315

@@ -317,15 +341,19 @@ ${fs
317341
//--------+
318342
// Utils. |
319343
//--------+
320-
function exec(command, toEcho) {
344+
/**
345+
* @param {string} command
346+
* @param {readonly string[]} args
347+
*/
348+
async function exec(command, args, toEcho = '') {
321349
if (toEcho) {
322350
echo(`⏱️ >>> ${toEcho}...`);
323351
}
324-
const { stdout } = shell.exec(command);
352+
const stdout = await utils.exec(command, args);
325353
if (toEcho) {
326354
echo(`👌 <<< ${toEcho}.`);
327355
}
328-
return stdout;
356+
return stdout.trim();
329357
}
330358

331359
async function copyFilesToBuildArtifacts() {
@@ -437,13 +465,13 @@ ${fs
437465
}
438466

439467
/**
440-
* @param {import('fs').PathLike} file
468+
* @param {import('node:fs').PathLike} file
441469
* @param {string|undefined} [algorithm="sha512"]
442470
* @param {BufferEncoding|undefined} [encoding="base64"]
443471
* @param {object|undefined} [options]
444472
*/
445473
function hashFile(file, algorithm = 'sha512', encoding = 'base64', options) {
446-
const crypto = require('crypto');
474+
const crypto = require('node:crypto');
447475
return new Promise((resolve, reject) => {
448476
const hash = crypto.createHash(algorithm);
449477
hash.on('error', reject).setEncoding(encoding);
@@ -500,11 +528,11 @@ ${fs
500528

501529
/**
502530
* @param {string} configPath
503-
* @return {Promise<import('child_process').ChildProcess>}
531+
* @return {Promise<import('node:child_process').ChildProcess>}
504532
*/
505533
function startNpmRegistry(configPath) {
506534
return new Promise((resolve, reject) => {
507-
const fork = require('child_process').fork(
535+
const fork = require('node:child_process').fork(
508536
require.resolve('verdaccio/bin/verdaccio'),
509537
['-c', configPath]
510538
);

electron/packager/package.json

+2-5
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,11 @@
1313
"author": "Arduino SA",
1414
"license": "AGPL-3.0-or-later",
1515
"dependencies": {
16-
"@types/file-type": "^10.9.1",
17-
"@types/temp": "^0.8.32",
1816
"7zip-min": "^1.1.1",
1917
"chai": "^4.2.0",
20-
"crypto": "^1.0.1",
2118
"dateformat": "^3.0.3",
2219
"deepmerge": "2.01",
20+
"execa": "^7.1.1",
2321
"file-type": "^14.1.4",
2422
"glob": "^7.1.6",
2523
"is-ci": "^2.0.0",
@@ -29,8 +27,7 @@
2927
"sinon": "^9.0.1",
3028
"temp": "^0.9.1",
3129
"verdaccio": "6-next",
32-
"yaml": "^1.10.2",
33-
"yargs": "^12.0.5"
30+
"yaml": "^1.10.2"
3431
},
3532
"engines": {
3633
"node": ">=16.0.0 <17"

electron/packager/test/utils.test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
const fs = require('fs');
2-
const path = require('path');
1+
const fs = require('node:fs');
2+
const path = require('node:path');
33
const expect = require('chai').expect;
44
const track = require('temp').track();
55
const unpack = require('../utils').unpack;

electron/packager/utils.js

+24-8
Original file line numberDiff line numberDiff line change
@@ -125,20 +125,21 @@ const isElectronPublish = false; // TODO: support auto-updates
125125
const isNightly = process.env.IS_NIGHTLY === 'true';
126126
const isRelease = process.env.IS_RELEASE === 'true';
127127

128-
function git(command) {
128+
/**
129+
* @param {readonly string[]} args
130+
*/
131+
async function git(args) {
129132
try {
130-
const gitPath = shell.which('git');
133+
const git = shell.which('git');
131134
const error = shell.error();
132135
if (error) {
133136
throw new Error(error);
134137
}
135-
const { stderr, stdout } = shell.exec(`"${gitPath}" ${command}`, {
136-
silent: true,
137-
});
138-
if (stderr) {
139-
throw new Error(stderr.toString().trim());
138+
if (!git) {
139+
throw new Error("Could not find 'git' on the $PATH");
140140
}
141-
return stdout.toString().trim();
141+
const stdout = await exec(git.toString(), args);
142+
return stdout;
142143
} catch (e) {
143144
throw e;
144145
}
@@ -168,6 +169,20 @@ function getChannelFile(platform) {
168169
);
169170
}
170171

172+
/**
173+
* @param {string} command
174+
* @param {readonly string[]} args
175+
*/
176+
async function exec(command, args) {
177+
const execa = await import('execa');
178+
const promise = execa.execa(command, args);
179+
if (promise.pipeStdout) {
180+
promise.pipeStdout(process.stdout);
181+
}
182+
const { stdout } = await promise;
183+
return stdout;
184+
}
185+
171186
module.exports = {
172187
adjustArchiveStructure,
173188
isZip,
@@ -177,4 +192,5 @@ module.exports = {
177192
isElectronPublish,
178193
git,
179194
getChannelFile,
195+
exec,
180196
};

0 commit comments

Comments
 (0)