build: use execFileSync for npm scripts

Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
Akos Kitta 2023-04-26 14:53:17 +02:00 committed by Akos Kitta
parent 192aac5a81
commit 33ab2a6955
4 changed files with 220 additions and 244 deletions

View File

@ -4,31 +4,29 @@
const version = '1.10.0'; const version = '1.10.0';
(async () => { (async () => {
const os = require('os'); const os = require('node:os');
const { promises: fs } = require('fs'); const { promises: fs } = require('node:fs');
const path = require('path'); const path = require('node:path');
const shell = require('shelljs'); const shell = require('shelljs');
const { v4 } = require('uuid'); const { v4 } = require('uuid');
const { exec } = require('./utils');
const repository = path.join(os.tmpdir(), `${v4()}-arduino-examples`); const repository = path.join(os.tmpdir(), `${v4()}-arduino-examples`);
if (shell.mkdir('-p', repository).code !== 0) { if (shell.mkdir('-p', repository).code !== 0) {
shell.exit(1); shell.exit(1);
} }
if ( exec(
shell.exec( 'git',
`git clone https://github.com/arduino/arduino-examples.git ${repository}` ['clone', 'https://github.com/arduino/arduino-examples.git', repository],
).code !== 0 shell
) { );
shell.exit(1);
}
if ( exec(
shell.exec(`git -C ${repository} checkout tags/${version} -b ${version}`) 'git',
.code !== 0 ['-C', repository, 'checkout', `tags/${version}`, '-b', version],
) { shell
shell.exit(1); );
}
const destination = path.join(__dirname, '..', 'Examples'); const destination = path.join(__dirname, '..', 'Examples');
shell.mkdir('-p', destination); shell.mkdir('-p', destination);

View File

@ -1,12 +1,11 @@
// @ts-check // @ts-check
(async () => { (async () => {
const fs = require('fs'); const path = require('node:path');
const path = require('path');
const temp = require('temp');
const shell = require('shelljs'); const shell = require('shelljs');
const semver = require('semver'); const semver = require('semver');
const downloader = require('./downloader'); const downloader = require('./downloader');
const { taskBuildFromGit } = require('./utils');
const version = (() => { const version = (() => {
const pkg = require(path.join(__dirname, '..', 'package.json')); const pkg = require(path.join(__dirname, '..', 'package.json'));
@ -86,81 +85,6 @@
shell.exit(1); shell.exit(1);
} }
} else { } else {
// We assume an object with `owner`, `repo`, commitish?` properties. taskBuildFromGit(version, destinationPath, 'Firmware Uploader');
const { owner, repo, commitish } = version;
if (!owner) {
shell.echo(`Could not retrieve 'owner' from ${JSON.stringify(version)}`);
shell.exit(1);
}
if (!repo) {
shell.echo(`Could not retrieve 'repo' from ${JSON.stringify(version)}`);
shell.exit(1);
}
const url = `https://github.com/${owner}/${repo}.git`;
shell.echo(
`Building Firmware Uploader from ${url}. Commitish: ${
commitish ? commitish : 'HEAD'
}`
);
if (fs.existsSync(destinationPath)) {
shell.echo(
`Skipping the Firmware Uploader build because it already exists: ${destinationPath}`
);
return;
}
if (shell.mkdir('-p', buildFolder).code !== 0) {
shell.echo('Could not create build folder.');
shell.exit(1);
}
const tempRepoPath = temp.mkdirSync();
shell.echo(`>>> Cloning Firmware Uploader source to ${tempRepoPath}...`);
if (shell.exec(`git clone ${url} ${tempRepoPath}`).code !== 0) {
shell.exit(1);
}
shell.echo('<<< Cloned Firmware Uploader repo.');
if (commitish) {
shell.echo(`>>> Checking out ${commitish}...`);
if (
shell.exec(`git -C ${tempRepoPath} checkout ${commitish}`).code !== 0
) {
shell.exit(1);
}
shell.echo(`<<< Checked out ${commitish}.`);
}
shell.echo(`>>> Building the Firmware Uploader...`);
if (shell.exec('go build', { cwd: tempRepoPath }).code !== 0) {
shell.exit(1);
}
shell.echo('<<< Firmware Uploader build done.');
if (!fs.existsSync(path.join(tempRepoPath, fwuploderName))) {
shell.echo(
`Could not find the Firmware Uploader at ${path.join(
tempRepoPath,
fwuploderName
)}.`
);
shell.exit(1);
}
const builtFwUploaderPath = path.join(tempRepoPath, fwuploderName);
shell.echo(
`>>> Copying Firmware Uploader from ${builtFwUploaderPath} to ${destinationPath}...`
);
if (shell.cp(builtFwUploaderPath, destinationPath).code !== 0) {
shell.exit(1);
}
shell.echo(`<<< Copied the Firmware Uploader.`);
shell.echo('<<< Verifying Firmware Uploader...');
if (!fs.existsSync(destinationPath)) {
shell.exit(1);
}
shell.echo('>>> Verified Firmware Uploader.');
} }
})(); })();

View File

@ -1,15 +1,13 @@
// @ts-check // @ts-check
(async () => { (async () => {
const os = require('node:os');
const os = require('os'); const path = require('node:path');
const path = require('path'); const { exec } = require('./utils');
const glob = require('glob'); const glob = require('glob');
const { v4 } = require('uuid'); const { v4 } = require('uuid');
const shell = require('shelljs'); const shell = require('shelljs');
const protoc = path.dirname(require('protoc/protoc')); const protoc = path.dirname(require('protoc/protoc'));
shell.env.PATH = `${shell.env.PATH}${path.delimiter}${protoc}`;
shell.env.PATH = `${shell.env.PATH}${path.delimiter}${path.join(__dirname, '..', 'node_modules', '.bin')}`;
const repository = path.join(os.tmpdir(), `${v4()}-arduino-cli`); const repository = path.join(os.tmpdir(), `${v4()}-arduino-cli`);
if (shell.mkdir('-p', repository).code !== 0) { if (shell.mkdir('-p', repository).code !== 0) {
@ -23,23 +21,28 @@
shell.exit(1); shell.exit(1);
} }
const defaultVersion = {
owner: 'arduino',
repo: 'arduino-cli',
commitish: undefined,
};
const { arduino } = pkg; const { arduino } = pkg;
if (!arduino) { if (!arduino) {
return { owner: 'arduino', repo: 'arduino-cli' }; return defaultVersion;
} }
const { cli } = arduino; const { cli } = arduino;
if (!cli) { if (!cli) {
return { owner: 'arduino', repo: 'arduino-cli' }; return defaultVersion;
} }
const { version } = cli; const { version } = cli;
if (!version) { if (!version) {
return { owner: 'arduino', repo: 'arduino-cli' }; return defaultVersion;
} }
if (typeof version === 'string') { if (typeof version === 'string') {
return { owner: 'arduino', repo: 'arduino-cli' }; return defaultVersion;
} }
// We assume an object with `owner`, `repo`, commitish?` properties. // We assume an object with `owner`, `repo`, commitish?` properties.
@ -58,15 +61,16 @@
const url = `https://github.com/${owner}/${repo}.git`; const url = `https://github.com/${owner}/${repo}.git`;
shell.echo(`>>> Cloning repository from '${url}'...`); shell.echo(`>>> Cloning repository from '${url}'...`);
if (shell.exec(`git clone ${url} ${repository}`).code !== 0) { exec('git', ['clone', url, repository], shell);
shell.exit(1);
}
shell.echo(`<<< Repository cloned.`); shell.echo(`<<< Repository cloned.`);
const { platform } = process; const { platform } = process;
const build = path.join(__dirname, '..', 'build'); const build = path.join(__dirname, '..', 'build');
const cli = path.join(build, `arduino-cli${platform === 'win32' ? '.exe' : ''}`); const cli = path.join(
const versionJson = shell.exec(`${cli} version --format json`).trim(); build,
`arduino-cli${platform === 'win32' ? '.exe' : ''}`
);
const versionJson = exec(cli, ['version', '--format', 'json'], shell).trim();
if (!versionJson) { if (!versionJson) {
shell.echo(`Could not retrieve the CLI version from ${cli}.`); shell.echo(`Could not retrieve the CLI version from ${cli}.`);
shell.exit(1); shell.exit(1);
@ -87,70 +91,94 @@
*/ */
const versionObject = JSON.parse(versionJson); const versionObject = JSON.parse(versionJson);
const version = versionObject.VersionString; const version = versionObject.VersionString;
if (version && !version.startsWith('nightly-') && version !== '0.0.0-git' && version !== 'git-snapshot') { if (
version &&
!version.startsWith('nightly-') &&
version !== '0.0.0-git' &&
version !== 'git-snapshot'
) {
shell.echo(`>>> Checking out tagged version: '${version}'...`); shell.echo(`>>> Checking out tagged version: '${version}'...`);
shell.exec(`git -C ${repository} fetch --all --tags`); exec('git', ['-C', repository, 'fetch', '--all', '--tags'], shell);
if (shell.exec(`git -C ${repository} checkout tags/${version} -b ${version}`).code !== 0) { exec(
shell.exit(1); 'git',
} ['-C', repository, 'checkout', `tags/${version}`, '-b', version],
shell.echo(`<<< Checked out tagged version: '${commitish}'.`); shell
);
shell.echo(`<<< Checked out tagged version: '${version}'.`);
} else if (commitish) { } else if (commitish) {
shell.echo(`>>> Checking out commitish from 'package.json': '${commitish}'...`); shell.echo(
if (shell.exec(`git -C ${repository} checkout ${commitish}`).code !== 0) { `>>> Checking out commitish from 'package.json': '${commitish}'...`
shell.exit(1); );
} exec('git', ['-C', repository, 'checkout', commitish], shell);
shell.echo(`<<< Checked out commitish from 'package.json': '${commitish}'.`); shell.echo(
`<<< Checked out commitish from 'package.json': '${commitish}'.`
);
} else if (versionObject.Commit) { } else if (versionObject.Commit) {
shell.echo(`>>> Checking out commitish from the CLI: '${versionObject.Commit}'...`); shell.echo(
if (shell.exec(`git -C ${repository} checkout ${versionObject.Commit}`).code !== 0) { `>>> Checking out commitish from the CLI: '${versionObject.Commit}'...`
shell.exit(1); );
} exec('git', ['-C', repository, 'checkout', versionObject.Commit], shell);
shell.echo(`<<< Checked out commitish from the CLI: '${versionObject.Commit}'.`); shell.echo(
`<<< Checked out commitish from the CLI: '${versionObject.Commit}'.`
);
} else { } else {
shell.echo(`WARN: no 'git checkout'. Generating from the HEAD revision.`); shell.echo(`WARN: no 'git checkout'. Generating from the HEAD revision.`);
} }
shell.echo('>>> Generating TS/JS API from:'); shell.echo('>>> Generating TS/JS API from:');
if (shell.exec(`git -C ${repository} rev-parse --abbrev-ref HEAD`).code !== 0) { exec('git', ['-C', repository, 'rev-parse', '--abbrev-ref', 'HEAD'], shell);
shell.exit(1);
}
const rpc = path.join(repository, 'rpc'); const rpc = path.join(repository, 'rpc');
const out = path.join(__dirname, '..', 'src', 'node', 'cli-protocol'); const out = path.join(__dirname, '..', 'src', 'node', 'cli-protocol');
shell.mkdir('-p', out); shell.mkdir('-p', out);
const protos = await new Promise(resolve => const protos = await new Promise((resolve) =>
glob('**/*.proto', { cwd: rpc }, (error, matches) => { glob('**/*.proto', { cwd: rpc }, (error, matches) => {
if (error) { if (error) {
shell.echo(error.stack); shell.echo(error.stack ?? error.message);
resolve([]); resolve([]);
return; return;
} }
resolve(matches.map(filename => path.join(rpc, filename))); resolve(matches.map((filename) => path.join(rpc, filename)));
})); })
);
if (!protos || protos.length === 0) { if (!protos || protos.length === 0) {
shell.echo(`Could not find any .proto files under ${rpc}.`); shell.echo(`Could not find any .proto files under ${rpc}.`);
shell.exit(1); shell.exit(1);
} }
// Generate JS code from the `.proto` files. // Generate JS code from the `.proto` files.
if (shell.exec(`grpc_tools_node_protoc \
--js_out=import_style=commonjs,binary:${out} \ exec(
--grpc_out=generate_package_definition:${out} \ 'grpc_tools_node_protoc',
-I ${rpc} \ [
${protos.join(' ')}`).code !== 0) { `--js_out=import_style=commonjs,binary:${out}`,
shell.exit(1); `--grpc_out=generate_package_definition:${out}`,
} '-I',
rpc,
...protos,
],
shell
);
// Generate the `.d.ts` files for JS. // Generate the `.d.ts` files for JS.
if (shell.exec(`protoc \ exec(
--plugin=protoc-gen-ts=${path.resolve(__dirname, '..', 'node_modules', '.bin', `protoc-gen-ts${platform === 'win32' ? '.cmd' : ''}`)} \ path.join(protoc, `protoc${platform === 'win32' ? '.exe' : ''}`),
--ts_out=generate_package_definition:${out} \ [
-I ${rpc} \ `--plugin=protoc-gen-ts=${path.resolve(
${protos.join(' ')}`).code !== 0) { __dirname,
shell.exit(1); '..',
} 'node_modules',
'.bin',
`protoc-gen-ts${platform === 'win32' ? '.cmd' : ''}`
)}`,
`--ts_out=generate_package_definition:${out}`,
'-I',
rpc,
...protos,
],
shell
);
shell.echo('<<< Generation was successful.'); shell.echo('<<< Generation was successful.');
})(); })();

View File

@ -1,3 +1,31 @@
// @ts-check
const exec = (
/** @type {string} */ command,
/** @type {readonly string[]} */ args,
/** @type {import('shelljs')|undefined}*/ shell = undefined,
/** @type {import('node:child_process').ExecFileSyncOptionsWithStringEncoding|undefined} */ options = undefined
) => {
try {
const stdout = require('node:child_process').execFileSync(
command,
args,
options ? options : { encoding: 'utf8' }
);
if (shell) {
shell.echo(stdout.trim());
}
return stdout;
} catch (err) {
if (shell) {
shell.echo(err instanceof Error ? err.message : String(err));
shell.exit(1);
}
throw err;
}
};
exports.exec = exec;
/** /**
* Clones something from GitHub and builds it with [`Task`](https://taskfile.dev/). * Clones something from GitHub and builds it with [`Task`](https://taskfile.dev/).
* *
@ -21,11 +49,15 @@ exports.goBuildFromGit = (version, destinationPath, taskName) => {
}; };
/** /**
* The `command` is either `go` or `task`. * The `command` must be either `'go'` or `'task'`.
* @param {string} command
* @param {{ owner: any; repo: any; commitish: any; }} version
* @param {string} destinationPath
* @param {string} taskName
*/ */
function buildFromGit(command, version, destinationPath, taskName) { function buildFromGit(command, version, destinationPath, taskName) {
const fs = require('fs'); const fs = require('node:fs');
const path = require('path'); const path = require('node:path');
const temp = require('temp'); const temp = require('temp');
const shell = require('shelljs'); const shell = require('shelljs');
@ -66,23 +98,17 @@ function buildFromGit(command, version, destinationPath, taskName) {
const tempRepoPath = temp.mkdirSync(); const tempRepoPath = temp.mkdirSync();
shell.echo(`>>> Cloning ${taskName} source to ${tempRepoPath}...`); shell.echo(`>>> Cloning ${taskName} source to ${tempRepoPath}...`);
if (shell.exec(`git clone ${url} ${tempRepoPath}`).code !== 0) { exec('git', ['clone', url, tempRepoPath], shell);
shell.exit(1);
}
shell.echo(`<<< Cloned ${taskName} repo.`); shell.echo(`<<< Cloned ${taskName} repo.`);
if (commitish) { if (commitish) {
shell.echo(`>>> Checking out ${commitish}...`); shell.echo(`>>> Checking out ${commitish}...`);
if (shell.exec(`git -C ${tempRepoPath} checkout ${commitish}`).code !== 0) { exec('git', ['-C', tempRepoPath, 'checkout', commitish], shell);
shell.exit(1);
}
shell.echo(`<<< Checked out ${commitish}.`); shell.echo(`<<< Checked out ${commitish}.`);
} }
shell.echo(`>>> Building the ${taskName}...`); shell.echo(`>>> Building the ${taskName}...`);
if (shell.exec(`${command} build`, { cwd: tempRepoPath }).code !== 0) { exec(command, ['build'], shell, { cwd: tempRepoPath, encoding: 'utf8' });
shell.exit(1);
}
shell.echo(`<<< Done ${taskName} build.`); shell.echo(`<<< Done ${taskName} build.`);
const binName = path.basename(destinationPath); const binName = path.basename(destinationPath);