Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 36e4dd9

Browse files
author
Akos Kitta
committedApr 28, 2023
build: use execFileSync for npm scripts
Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
1 parent 12187bb commit 36e4dd9

File tree

4 files changed

+223
-247
lines changed

4 files changed

+223
-247
lines changed
 

‎arduino-ide-extension/scripts/download-examples.js

+14-16
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,29 @@
44
const version = '1.10.0';
55

66
(async () => {
7-
const os = require('os');
8-
const { promises: fs } = require('fs');
9-
const path = require('path');
7+
const os = require('node:os');
8+
const { promises: fs } = require('node:fs');
9+
const path = require('node:path');
1010
const shell = require('shelljs');
1111
const { v4 } = require('uuid');
12+
const { exec } = require('./utils');
1213

1314
const repository = path.join(os.tmpdir(), `${v4()}-arduino-examples`);
1415
if (shell.mkdir('-p', repository).code !== 0) {
1516
shell.exit(1);
1617
}
1718

18-
if (
19-
shell.exec(
20-
`git clone https://github.com/arduino/arduino-examples.git ${repository}`
21-
).code !== 0
22-
) {
23-
shell.exit(1);
24-
}
19+
exec(
20+
'git',
21+
['clone', 'https://github.com/arduino/arduino-examples.git', repository],
22+
shell
23+
);
2524

26-
if (
27-
shell.exec(`git -C ${repository} checkout tags/${version} -b ${version}`)
28-
.code !== 0
29-
) {
30-
shell.exit(1);
31-
}
25+
exec(
26+
'git',
27+
['-C', repository, 'checkout', `tags/${version}`, '-b', version],
28+
shell
29+
);
3230

3331
const destination = path.join(__dirname, '..', 'Examples');
3432
shell.mkdir('-p', destination);
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
// @ts-check
22

33
(async () => {
4-
const fs = require('fs');
5-
const path = require('path');
6-
const temp = require('temp');
4+
const path = require('node:path');
75
const shell = require('shelljs');
86
const semver = require('semver');
97
const downloader = require('./downloader');
8+
const { taskBuildFromGit } = require('./utils');
109

1110
const version = (() => {
1211
const pkg = require(path.join(__dirname, '..', 'package.json'));
@@ -86,81 +85,6 @@
8685
shell.exit(1);
8786
}
8887
} else {
89-
// We assume an object with `owner`, `repo`, commitish?` properties.
90-
const { owner, repo, commitish } = version;
91-
if (!owner) {
92-
shell.echo(`Could not retrieve 'owner' from ${JSON.stringify(version)}`);
93-
shell.exit(1);
94-
}
95-
if (!repo) {
96-
shell.echo(`Could not retrieve 'repo' from ${JSON.stringify(version)}`);
97-
shell.exit(1);
98-
}
99-
const url = `https://github.com/${owner}/${repo}.git`;
100-
shell.echo(
101-
`Building Firmware Uploader from ${url}. Commitish: ${
102-
commitish ? commitish : 'HEAD'
103-
}`
104-
);
105-
106-
if (fs.existsSync(destinationPath)) {
107-
shell.echo(
108-
`Skipping the Firmware Uploader build because it already exists: ${destinationPath}`
109-
);
110-
return;
111-
}
112-
113-
if (shell.mkdir('-p', buildFolder).code !== 0) {
114-
shell.echo('Could not create build folder.');
115-
shell.exit(1);
116-
}
117-
118-
const tempRepoPath = temp.mkdirSync();
119-
shell.echo(`>>> Cloning Firmware Uploader source to ${tempRepoPath}...`);
120-
if (shell.exec(`git clone ${url} ${tempRepoPath}`).code !== 0) {
121-
shell.exit(1);
122-
}
123-
shell.echo('<<< Cloned Firmware Uploader repo.');
124-
125-
if (commitish) {
126-
shell.echo(`>>> Checking out ${commitish}...`);
127-
if (
128-
shell.exec(`git -C ${tempRepoPath} checkout ${commitish}`).code !== 0
129-
) {
130-
shell.exit(1);
131-
}
132-
shell.echo(`<<< Checked out ${commitish}.`);
133-
}
134-
135-
shell.echo(`>>> Building the Firmware Uploader...`);
136-
if (shell.exec('go build', { cwd: tempRepoPath }).code !== 0) {
137-
shell.exit(1);
138-
}
139-
shell.echo('<<< Firmware Uploader build done.');
140-
141-
if (!fs.existsSync(path.join(tempRepoPath, fwuploderName))) {
142-
shell.echo(
143-
`Could not find the Firmware Uploader at ${path.join(
144-
tempRepoPath,
145-
fwuploderName
146-
)}.`
147-
);
148-
shell.exit(1);
149-
}
150-
151-
const builtFwUploaderPath = path.join(tempRepoPath, fwuploderName);
152-
shell.echo(
153-
`>>> Copying Firmware Uploader from ${builtFwUploaderPath} to ${destinationPath}...`
154-
);
155-
if (shell.cp(builtFwUploaderPath, destinationPath).code !== 0) {
156-
shell.exit(1);
157-
}
158-
shell.echo(`<<< Copied the Firmware Uploader.`);
159-
160-
shell.echo('<<< Verifying Firmware Uploader...');
161-
if (!fs.existsSync(destinationPath)) {
162-
shell.exit(1);
163-
}
164-
shell.echo('>>> Verified Firmware Uploader.');
88+
taskBuildFromGit(version, destinationPath, 'Firmware Uploader');
16589
}
16690
})();
Original file line numberDiff line numberDiff line change
@@ -1,156 +1,184 @@
11
// @ts-check
22

33
(async () => {
4-
5-
const os = require('os');
6-
const path = require('path');
7-
const glob = require('glob');
8-
const { v4 } = require('uuid');
9-
const shell = require('shelljs');
10-
const protoc = path.dirname(require('protoc/protoc'));
11-
shell.env.PATH = `${shell.env.PATH}${path.delimiter}${protoc}`;
12-
shell.env.PATH = `${shell.env.PATH}${path.delimiter}${path.join(__dirname, '..', 'node_modules', '.bin')}`;
13-
14-
const repository = path.join(os.tmpdir(), `${v4()}-arduino-cli`);
15-
if (shell.mkdir('-p', repository).code !== 0) {
16-
shell.exit(1);
4+
const os = require('node:os');
5+
const path = require('node:path');
6+
const { exec } = require('./utils');
7+
const glob = require('glob');
8+
const { v4 } = require('uuid');
9+
const shell = require('shelljs');
10+
const protoc = path.dirname(require('protoc/protoc'));
11+
12+
const repository = path.join(os.tmpdir(), `${v4()}-arduino-cli`);
13+
if (shell.mkdir('-p', repository).code !== 0) {
14+
shell.exit(1);
15+
}
16+
17+
const { owner, repo, commitish } = (() => {
18+
const pkg = require(path.join(__dirname, '..', 'package.json'));
19+
if (!pkg) {
20+
shell.echo(`Could not parse the 'package.json'.`);
21+
shell.exit(1);
1722
}
1823

19-
const { owner, repo, commitish } = (() => {
20-
const pkg = require(path.join(__dirname, '..', 'package.json'));
21-
if (!pkg) {
22-
shell.echo(`Could not parse the 'package.json'.`);
23-
shell.exit(1);
24-
}
25-
26-
const { arduino } = pkg;
27-
if (!arduino) {
28-
return { owner: 'arduino', repo: 'arduino-cli' };
29-
}
30-
31-
const { cli } = arduino;
32-
if (!cli) {
33-
return { owner: 'arduino', repo: 'arduino-cli' };
34-
}
35-
36-
const { version } = cli;
37-
if (!version) {
38-
return { owner: 'arduino', repo: 'arduino-cli' };
39-
}
40-
41-
if (typeof version === 'string') {
42-
return { owner: 'arduino', repo: 'arduino-cli' };
43-
}
44-
45-
// We assume an object with `owner`, `repo`, commitish?` properties.
46-
const { owner, repo, commitish } = version;
47-
if (!owner) {
48-
shell.echo(`Could not retrieve 'owner' from ${JSON.stringify(version)}`);
49-
shell.exit(1);
50-
}
51-
if (!repo) {
52-
shell.echo(`Could not retrieve 'repo' from ${JSON.stringify(version)}`);
53-
shell.exit(1);
54-
}
55-
56-
return { owner, repo, commitish };
57-
})();
58-
59-
const url = `https://github.com/${owner}/${repo}.git`;
60-
shell.echo(`>>> Cloning repository from '${url}'...`);
61-
if (shell.exec(`git clone ${url} ${repository}`).code !== 0) {
62-
shell.exit(1);
63-
}
64-
shell.echo(`<<< Repository cloned.`);
65-
66-
const { platform } = process;
67-
const build = path.join(__dirname, '..', 'build');
68-
const cli = path.join(build, `arduino-cli${platform === 'win32' ? '.exe' : ''}`);
69-
const versionJson = shell.exec(`${cli} version --format json`).trim();
70-
if (!versionJson) {
71-
shell.echo(`Could not retrieve the CLI version from ${cli}.`);
72-
shell.exit(1);
73-
}
74-
// As of today (28.01.2021), the `VersionString` can be one of the followings:
75-
// - `nightly-YYYYMMDD` stands for the nightly build, we use the , the `commitish` from the `package.json` to check out the code.
76-
// - `0.0.0-git` for local builds, we use the `commitish` from the `package.json` to check out the code and generate the APIs.
77-
// - `git-snapshot` for local build executed via `task build`. We do not do this.
78-
// - rest, we assume it is a valid semver and has the corresponding tagged code, we use the tag to generate the APIs from the `proto` files.
79-
/*
80-
{
81-
"Application": "arduino-cli",
82-
"VersionString": "nightly-20210126",
83-
"Commit": "079bb6c6",
84-
"Status": "alpha",
85-
"Date": "2021-01-26T01:46:31Z"
86-
}
87-
*/
88-
const versionObject = JSON.parse(versionJson);
89-
const version = versionObject.VersionString;
90-
if (version && !version.startsWith('nightly-') && version !== '0.0.0-git' && version !== 'git-snapshot') {
91-
shell.echo(`>>> Checking out tagged version: '${version}'...`);
92-
shell.exec(`git -C ${repository} fetch --all --tags`);
93-
if (shell.exec(`git -C ${repository} checkout tags/${version} -b ${version}`).code !== 0) {
94-
shell.exit(1);
95-
}
96-
shell.echo(`<<< Checked out tagged version: '${commitish}'.`);
97-
} else if (commitish) {
98-
shell.echo(`>>> Checking out commitish from 'package.json': '${commitish}'...`);
99-
if (shell.exec(`git -C ${repository} checkout ${commitish}`).code !== 0) {
100-
shell.exit(1);
101-
}
102-
shell.echo(`<<< Checked out commitish from 'package.json': '${commitish}'.`);
103-
} else if (versionObject.Commit) {
104-
shell.echo(`>>> Checking out commitish from the CLI: '${versionObject.Commit}'...`);
105-
if (shell.exec(`git -C ${repository} checkout ${versionObject.Commit}`).code !== 0) {
106-
shell.exit(1);
107-
}
108-
shell.echo(`<<< Checked out commitish from the CLI: '${versionObject.Commit}'.`);
109-
} else {
110-
shell.echo(`WARN: no 'git checkout'. Generating from the HEAD revision.`);
24+
const defaultVersion = {
25+
owner: 'arduino',
26+
repo: 'arduino-cli',
27+
commitish: undefined,
28+
};
29+
const { arduino } = pkg;
30+
if (!arduino) {
31+
return defaultVersion;
11132
}
11233

113-
shell.echo('>>> Generating TS/JS API from:');
114-
if (shell.exec(`git -C ${repository} rev-parse --abbrev-ref HEAD`).code !== 0) {
115-
shell.exit(1);
34+
const { cli } = arduino;
35+
if (!cli) {
36+
return defaultVersion;
11637
}
11738

118-
const rpc = path.join(repository, 'rpc');
119-
const out = path.join(__dirname, '..', 'src', 'node', 'cli-protocol');
120-
shell.mkdir('-p', out);
121-
122-
const protos = await new Promise(resolve =>
123-
glob('**/*.proto', { cwd: rpc }, (error, matches) => {
124-
if (error) {
125-
shell.echo(error.stack);
126-
resolve([]);
127-
return;
128-
}
129-
resolve(matches.map(filename => path.join(rpc, filename)));
130-
}));
131-
if (!protos || protos.length === 0) {
132-
shell.echo(`Could not find any .proto files under ${rpc}.`);
133-
shell.exit(1);
39+
const { version } = cli;
40+
if (!version) {
41+
return defaultVersion;
13442
}
13543

136-
// Generate JS code from the `.proto` files.
137-
if (shell.exec(`grpc_tools_node_protoc \
138-
--js_out=import_style=commonjs,binary:${out} \
139-
--grpc_out=generate_package_definition:${out} \
140-
-I ${rpc} \
141-
${protos.join(' ')}`).code !== 0) {
142-
shell.exit(1);
44+
if (typeof version === 'string') {
45+
return defaultVersion;
14346
}
14447

145-
// Generate the `.d.ts` files for JS.
146-
if (shell.exec(`protoc \
147-
--plugin=protoc-gen-ts=${path.resolve(__dirname, '..', 'node_modules', '.bin', `protoc-gen-ts${platform === 'win32' ? '.cmd' : ''}`)} \
148-
--ts_out=generate_package_definition:${out} \
149-
-I ${rpc} \
150-
${protos.join(' ')}`).code !== 0) {
151-
shell.exit(1);
48+
// We assume an object with `owner`, `repo`, commitish?` properties.
49+
const { owner, repo, commitish } = version;
50+
if (!owner) {
51+
shell.echo(`Could not retrieve 'owner' from ${JSON.stringify(version)}`);
52+
shell.exit(1);
53+
}
54+
if (!repo) {
55+
shell.echo(`Could not retrieve 'repo' from ${JSON.stringify(version)}`);
56+
shell.exit(1);
15257
}
15358

154-
shell.echo('<<< Generation was successful.');
155-
59+
return { owner, repo, commitish };
60+
})();
61+
62+
const url = `https://github.com/${owner}/${repo}.git`;
63+
shell.echo(`>>> Cloning repository from '${url}'...`);
64+
exec('git', ['clone', url, repository], shell);
65+
shell.echo(`<<< Repository cloned.`);
66+
67+
const { platform } = process;
68+
const build = path.join(__dirname, '..', 'build');
69+
const cli = path.join(
70+
build,
71+
`arduino-cli${platform === 'win32' ? '.exe' : ''}`
72+
);
73+
const versionJson = exec(cli, ['version', '--format', 'json'], shell).trim();
74+
if (!versionJson) {
75+
shell.echo(`Could not retrieve the CLI version from ${cli}.`);
76+
shell.exit(1);
77+
}
78+
// As of today (28.01.2021), the `VersionString` can be one of the followings:
79+
// - `nightly-YYYYMMDD` stands for the nightly build, we use the , the `commitish` from the `package.json` to check out the code.
80+
// - `0.0.0-git` for local builds, we use the `commitish` from the `package.json` to check out the code and generate the APIs.
81+
// - `git-snapshot` for local build executed via `task build`. We do not do this.
82+
// - rest, we assume it is a valid semver and has the corresponding tagged code, we use the tag to generate the APIs from the `proto` files.
83+
/*
84+
{
85+
"Application": "arduino-cli",
86+
"VersionString": "nightly-20210126",
87+
"Commit": "079bb6c6",
88+
"Status": "alpha",
89+
"Date": "2021-01-26T01:46:31Z"
90+
}
91+
*/
92+
const versionObject = JSON.parse(versionJson);
93+
const version = versionObject.VersionString;
94+
if (
95+
version &&
96+
!version.startsWith('nightly-') &&
97+
version !== '0.0.0-git' &&
98+
version !== 'git-snapshot'
99+
) {
100+
shell.echo(`>>> Checking out tagged version: '${version}'...`);
101+
exec('git', ['-C', repository, 'fetch', '--all', '--tags'], shell);
102+
exec(
103+
'git',
104+
['-C', repository, 'checkout', `tags/${version}`, '-b', version],
105+
shell
106+
);
107+
shell.echo(`<<< Checked out tagged version: '${version}'.`);
108+
} else if (commitish) {
109+
shell.echo(
110+
`>>> Checking out commitish from 'package.json': '${commitish}'...`
111+
);
112+
exec('git', ['-C', repository, 'checkout', commitish], shell);
113+
shell.echo(
114+
`<<< Checked out commitish from 'package.json': '${commitish}'.`
115+
);
116+
} else if (versionObject.Commit) {
117+
shell.echo(
118+
`>>> Checking out commitish from the CLI: '${versionObject.Commit}'...`
119+
);
120+
exec('git', ['-C', repository, 'checkout', versionObject.Commit], shell);
121+
shell.echo(
122+
`<<< Checked out commitish from the CLI: '${versionObject.Commit}'.`
123+
);
124+
} else {
125+
shell.echo(`WARN: no 'git checkout'. Generating from the HEAD revision.`);
126+
}
127+
128+
shell.echo('>>> Generating TS/JS API from:');
129+
exec('git', ['-C', repository, 'rev-parse', '--abbrev-ref', 'HEAD'], shell);
130+
131+
const rpc = path.join(repository, 'rpc');
132+
const out = path.join(__dirname, '..', 'src', 'node', 'cli-protocol');
133+
shell.mkdir('-p', out);
134+
135+
const protos = await new Promise((resolve) =>
136+
glob('**/*.proto', { cwd: rpc }, (error, matches) => {
137+
if (error) {
138+
shell.echo(error.stack ?? error.message);
139+
resolve([]);
140+
return;
141+
}
142+
resolve(matches.map((filename) => path.join(rpc, filename)));
143+
})
144+
);
145+
if (!protos || protos.length === 0) {
146+
shell.echo(`Could not find any .proto files under ${rpc}.`);
147+
shell.exit(1);
148+
}
149+
150+
// Generate JS code from the `.proto` files.
151+
152+
exec(
153+
'grpc_tools_node_protoc',
154+
[
155+
`--js_out=import_style=commonjs,binary:${out}`,
156+
`--grpc_out=generate_package_definition:${out}`,
157+
'-I',
158+
rpc,
159+
...protos,
160+
],
161+
shell
162+
);
163+
164+
// Generate the `.d.ts` files for JS.
165+
exec(
166+
path.join(protoc, `protoc${platform === 'win32' ? '.exe' : ''}`),
167+
[
168+
`--plugin=protoc-gen-ts=${path.resolve(
169+
__dirname,
170+
'..',
171+
'node_modules',
172+
'.bin',
173+
`protoc-gen-ts${platform === 'win32' ? '.cmd' : ''}`
174+
)}`,
175+
`--ts_out=generate_package_definition:${out}`,
176+
'-I',
177+
rpc,
178+
...protos,
179+
],
180+
shell
181+
);
182+
183+
shell.echo('<<< Generation was successful.');
156184
})();

‎arduino-ide-extension/scripts/utils.js

+38-12
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,31 @@
1+
// @ts-check
2+
3+
const exec = (
4+
/** @type {string} */ command,
5+
/** @type {readonly string[]} */ args,
6+
/** @type {import('shelljs')|undefined}*/ shell = undefined,
7+
/** @type {import('node:child_process').ExecFileSyncOptionsWithStringEncoding|undefined} */ options = undefined
8+
) => {
9+
try {
10+
const stdout = require('node:child_process').execFileSync(
11+
command,
12+
args,
13+
options ? options : { encoding: 'utf8' }
14+
);
15+
if (shell) {
16+
shell.echo(stdout.trim());
17+
}
18+
return stdout;
19+
} catch (err) {
20+
if (shell) {
21+
shell.echo(err instanceof Error ? err.message : String(err));
22+
shell.exit(1);
23+
}
24+
throw err;
25+
}
26+
};
27+
exports.exec = exec;
28+
129
/**
230
* Clones something from GitHub and builds it with [`Task`](https://taskfile.dev/).
331
*
@@ -21,11 +49,15 @@ exports.goBuildFromGit = (version, destinationPath, taskName) => {
2149
};
2250

2351
/**
24-
* The `command` is either `go` or `task`.
52+
* The `command` must be either `'go'` or `'task'`.
53+
* @param {string} command
54+
* @param {{ owner: any; repo: any; commitish: any; }} version
55+
* @param {string} destinationPath
56+
* @param {string} taskName
2557
*/
2658
function buildFromGit(command, version, destinationPath, taskName) {
27-
const fs = require('fs');
28-
const path = require('path');
59+
const fs = require('node:fs');
60+
const path = require('node:path');
2961
const temp = require('temp');
3062
const shell = require('shelljs');
3163

@@ -66,23 +98,17 @@ function buildFromGit(command, version, destinationPath, taskName) {
6698

6799
const tempRepoPath = temp.mkdirSync();
68100
shell.echo(`>>> Cloning ${taskName} source to ${tempRepoPath}...`);
69-
if (shell.exec(`git clone ${url} ${tempRepoPath}`).code !== 0) {
70-
shell.exit(1);
71-
}
101+
exec('git', ['clone', url, tempRepoPath], shell);
72102
shell.echo(`<<< Cloned ${taskName} repo.`);
73103

74104
if (commitish) {
75105
shell.echo(`>>> Checking out ${commitish}...`);
76-
if (shell.exec(`git -C ${tempRepoPath} checkout ${commitish}`).code !== 0) {
77-
shell.exit(1);
78-
}
106+
exec('git', ['-C', tempRepoPath, 'checkout', commitish], shell);
79107
shell.echo(`<<< Checked out ${commitish}.`);
80108
}
81109

82110
shell.echo(`>>> Building the ${taskName}...`);
83-
if (shell.exec(`${command} build`, { cwd: tempRepoPath }).code !== 0) {
84-
shell.exit(1);
85-
}
111+
exec(command, ['build'], shell, { cwd: tempRepoPath, encoding: 'utf8' });
86112
shell.echo(`<<< Done ${taskName} build.`);
87113

88114
const binName = path.basename(destinationPath);

0 commit comments

Comments
 (0)
Please sign in to comment.