chore(deps): update dependencies

To fix all security vulnerabilities detected by `Dependabot`.

 - remove `shelljs`. replace with `fs` and `console`.
 - remove `uuid`. replace with `@phosphor/coreutils`.

Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
Akos Kitta
2023-10-02 18:05:22 +02:00
committed by Akos Kitta
parent ed1cb6bcf9
commit 153e34f11b
17 changed files with 1473 additions and 2749 deletions

View File

@@ -2,7 +2,6 @@
(async () => {
const path = require('path');
const shell = require('shelljs');
const semver = require('semver');
const moment = require('moment');
const downloader = require('./downloader');
@@ -29,8 +28,8 @@
})();
if (!version) {
shell.echo(`Could not retrieve CLI version info from the 'package.json'.`);
shell.exit(1);
console.log(`Could not retrieve CLI version info from the 'package.json'.`);
process.exit(1);
}
const { platform, arch } = process;
@@ -71,24 +70,24 @@
}
})();
if (!suffix) {
shell.echo(`The CLI is not available for ${platform} ${arch}.`);
shell.exit(1);
console.log(`The CLI is not available for ${platform} ${arch}.`);
process.exit(1);
}
if (semver.valid(version)) {
const url = `https://downloads.arduino.cc/arduino-cli/arduino-cli_${version}_${suffix}`;
shell.echo(
console.log(
`📦 Identified released version of the CLI. Downloading version ${version} from '${url}'`
);
await downloader.downloadUnzipFile(url, destinationPath, 'arduino-cli');
} else if (moment(version, 'YYYYMMDD', true).isValid()) {
const url = `https://downloads.arduino.cc/arduino-cli/nightly/arduino-cli_nightly-${version}_${suffix}`;
shell.echo(
console.log(
`🌙 Identified nightly version of the CLI. Downloading version ${version} from '${url}'`
);
await downloader.downloadUnzipFile(url, destinationPath, 'arduino-cli');
} else {
shell.echo(`🔥 Could not interpret 'version': ${version}`);
shell.exit(1);
console.log(`🔥 Could not interpret 'version': ${version}`);
process.exit(1);
}
} else {
taskBuildFromGit(version, destinationPath, 'CLI');

View File

@@ -5,10 +5,14 @@ const version = '1.10.0';
(async () => {
const os = require('node:os');
const { existsSync, promises: fs } = require('node:fs');
const {
existsSync,
promises: fs,
mkdirSync,
readdirSync,
cpSync,
} = require('node:fs');
const path = require('node:path');
const shell = require('shelljs');
const { v4 } = require('uuid');
const { exec } = require('./utils');
const destination = path.join(
@@ -20,31 +24,38 @@ const version = '1.10.0';
'Examples'
);
if (existsSync(destination)) {
shell.echo(
console.log(
`Skipping Git checkout of the examples because the repository already exists: ${destination}`
);
return;
}
const repository = path.join(os.tmpdir(), `${v4()}-arduino-examples`);
if (shell.mkdir('-p', repository).code !== 0) {
shell.exit(1);
}
const repository = await fs.mkdtemp(
path.join(os.tmpdir(), 'arduino-examples-')
);
exec(
'git',
['clone', 'https://github.com/arduino/arduino-examples.git', repository],
shell
{ logStdout: true }
);
exec(
'git',
['-C', repository, 'checkout', `tags/${version}`, '-b', version],
shell
{ logStdout: true }
);
shell.mkdir('-p', destination);
shell.cp('-fR', path.join(repository, 'examples', '*'), destination);
mkdirSync(destination, { recursive: true });
const examplesPath = path.join(repository, 'examples');
const exampleResources = readdirSync(examplesPath);
for (const exampleResource of exampleResources) {
cpSync(
path.join(examplesPath, exampleResource),
path.join(destination, exampleResource),
{ recursive: true }
);
}
const isSketch = async (pathLike) => {
try {
@@ -104,5 +115,5 @@ const version = '1.10.0';
JSON.stringify(examples, null, 2),
{ encoding: 'utf8' }
);
shell.echo(`Generated output to ${path.join(destination, 'examples.json')}`);
console.log(`Generated output to ${path.join(destination, 'examples.json')}`);
})();

View File

@@ -2,7 +2,6 @@
(async () => {
const path = require('node:path');
const shell = require('shelljs');
const semver = require('semver');
const downloader = require('./downloader');
const { taskBuildFromGit } = require('./utils');
@@ -28,10 +27,10 @@
})();
if (!version) {
shell.echo(
console.log(
`Could not retrieve Firmware Uploader version info from the 'package.json'.`
);
shell.exit(1);
process.exit(1);
}
const { platform, arch } = process;
@@ -71,14 +70,14 @@
}
})();
if (!suffix) {
shell.echo(
console.log(
`The Firmware Uploader is not available for ${platform} ${arch}.`
);
shell.exit(1);
process.exit(1);
}
if (semver.valid(version)) {
const url = `https://downloads.arduino.cc/arduino-fwuploader/arduino-fwuploader_${version}_${suffix}`;
shell.echo(
console.log(
`📦 Identified released version of the Firmware Uploader. Downloading version ${version} from '${url}'`
);
await downloader.downloadUnzipFile(
@@ -87,8 +86,8 @@
'arduino-fwuploader'
);
} else {
shell.echo(`🔥 Could not interpret 'version': ${version}`);
shell.exit(1);
console.log(`🔥 Could not interpret 'version': ${version}`);
process.exit(1);
}
} else {
taskBuildFromGit(version, destinationPath, 'Firmware Uploader');

View File

@@ -5,7 +5,6 @@
(() => {
const path = require('path');
const shell = require('shelljs');
const downloader = require('./downloader');
const { goBuildFromGit } = require('./utils');
@@ -25,20 +24,20 @@
})();
if (!DEFAULT_LS_VERSION) {
shell.echo(
console.log(
`Could not retrieve Arduino Language Server version info from the 'package.json'.`
);
shell.exit(1);
process.exit(1);
}
if (!DEFAULT_CLANGD_VERSION) {
shell.echo(
console.log(
`Could not retrieve clangd version info from the 'package.json'.`
);
shell.exit(1);
process.exit(1);
}
const yargs = require('yargs')
const yargs = require('@theia/core/shared/yargs')
.option('ls-version', {
alias: 'lv',
default: DEFAULT_LS_VERSION,
@@ -114,10 +113,10 @@
throw new Error(`Unsupported platform/arch: ${platformArch}.`);
}
if (!lsSuffix || !clangdSuffix) {
shell.echo(
console.log(
`The arduino-language-server is not available for ${platform} ${arch}.`
);
shell.exit(1);
process.exit(1);
}
if (typeof lsVersion === 'string') {

View File

@@ -1,20 +1,19 @@
// @ts-check
const fs = require('fs');
const path = require('path');
const shell = require('shelljs');
const decompress = require('decompress');
const unzip = require('decompress-unzip');
const untargz = require('decompress-targz');
const untarbz2 = require('decompress-tarbz2');
process.on('unhandledRejection', (reason, _) => {
shell.echo(String(reason));
shell.exit(1);
throw reason;
process.on('unhandledRejection', (reason) => {
console.log(String(reason));
process.exit(1);
});
process.on('uncaughtException', (error) => {
shell.echo(String(error));
shell.exit(1);
throw error;
console.log(String(error));
process.exit(1);
});
/**
@@ -30,55 +29,42 @@ exports.downloadUnzipFile = async (
force = false
) => {
if (fs.existsSync(targetFile) && !force) {
shell.echo(`Skipping download because file already exists: ${targetFile}`);
console.log(`Skipping download because file already exists: ${targetFile}`);
return;
}
if (!fs.existsSync(path.dirname(targetFile))) {
if (shell.mkdir('-p', path.dirname(targetFile)).code !== 0) {
shell.echo('Could not create new directory.');
shell.exit(1);
}
}
fs.mkdirSync(path.dirname(targetFile), { recursive: true });
const downloads = path.join(__dirname, '..', 'downloads');
if (shell.rm('-rf', targetFile, downloads).code !== 0) {
shell.exit(1);
}
fs.rmSync(targetFile, { recursive: true, force: true });
fs.rmSync(downloads, { recursive: true, force: true });
shell.echo(`>>> Downloading from '${url}'...`);
const { default: download } = await import('@xhmikosr/downloader');
console.log(`>>> Downloading from '${url}'...`);
const data = await download(url);
shell.echo(`<<< Download succeeded.`);
console.log(`<<< Download succeeded.`);
shell.echo('>>> Decompressing...');
console.log('>>> Decompressing...');
const files = await decompress(data, downloads, {
plugins: [unzip(), untargz(), untarbz2()],
});
if (files.length === 0) {
shell.echo('Error ocurred while decompressing the archive.');
shell.exit(1);
console.log('Error ocurred while decompressing the archive.');
process.exit(1);
}
const fileIndex = files.findIndex((f) => f.path.startsWith(filePrefix));
if (fileIndex === -1) {
shell.echo(
console.log(
`The downloaded artifact does not contain any file with prefix ${filePrefix}.`
);
shell.exit(1);
process.exit(1);
}
shell.echo('<<< Decompressing succeeded.');
console.log('<<< Decompressing succeeded.');
if (
shell.mv('-f', path.join(downloads, files[fileIndex].path), targetFile)
.code !== 0
) {
shell.echo(`Could not move file to target path: ${targetFile}`);
shell.exit(1);
}
fs.renameSync(path.join(downloads, files[fileIndex].path), targetFile);
if (!fs.existsSync(targetFile)) {
shell.echo(`Could not find file: ${targetFile}`);
shell.exit(1);
console.log(`Could not find file: ${targetFile}`);
process.exit(1);
}
shell.echo(`Done: ${targetFile}`);
console.log(`Done: ${targetFile}`);
};
/**
@@ -86,7 +72,7 @@ exports.downloadUnzipFile = async (
* @param targetDir {string} Directory into which to decompress the archive
* @param targetFile {string} Path to the main file expected after decompressing
* @param force {boolean} Whether to download even if the target file exists
* @param decompressOptions {import('decompress').DecompressOptions}
* @param decompressOptions {import('decompress').DecompressOptions|undefined} [decompressOptions]
*/
exports.downloadUnzipAll = async (
url,
@@ -96,22 +82,16 @@ exports.downloadUnzipAll = async (
decompressOptions = undefined
) => {
if (fs.existsSync(targetFile) && !force) {
shell.echo(`Skipping download because file already exists: ${targetFile}`);
console.log(`Skipping download because file already exists: ${targetFile}`);
return;
}
if (!fs.existsSync(targetDir)) {
if (shell.mkdir('-p', targetDir).code !== 0) {
shell.echo('Could not create new directory.');
shell.exit(1);
}
}
fs.mkdirSync(targetDir, { recursive: true });
shell.echo(`>>> Downloading from '${url}'...`);
const { default: download } = await import('@xhmikosr/downloader');
console.log(`>>> Downloading from '${url}'...`);
const data = await download(url);
shell.echo(`<<< Download succeeded.`);
console.log(`<<< Download succeeded.`);
shell.echo('>>> Decompressing...');
console.log('>>> Decompressing...');
let options = {
plugins: [unzip(), untargz(), untarbz2()],
};
@@ -120,14 +100,27 @@ exports.downloadUnzipAll = async (
}
const files = await decompress(data, targetDir, options);
if (files.length === 0) {
shell.echo('Error ocurred while decompressing the archive.');
shell.exit(1);
console.log('Error ocurred while decompressing the archive.');
process.exit(1);
}
shell.echo('<<< Decompressing succeeded.');
console.log('<<< Decompressing succeeded.');
if (!fs.existsSync(targetFile)) {
shell.echo(`Could not find file: ${targetFile}`);
shell.exit(1);
console.log(`Could not find file: ${targetFile}`);
process.exit(1);
}
shell.echo(`Done: ${targetFile}`);
console.log(`Done: ${targetFile}`);
};
/**
* @param {string} url
* @returns {Promise<import('node:buffer').Buffer>}
*/
async function download(url) {
const { default: download } = await import('@xhmikosr/downloader');
/** @type {import('node:buffer').Buffer} */
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const data = await download(url);
return data;
}

View File

@@ -3,22 +3,18 @@
(async () => {
const os = require('node:os');
const path = require('node:path');
const { mkdirSync, promises: fs } = require('node:fs');
const { exec } = require('./utils');
const glob = require('glob');
const { v4 } = require('uuid');
const shell = require('shelljs');
const protoc = path.dirname(require('protoc/protoc'));
const repository = path.join(os.tmpdir(), `${v4()}-arduino-cli`);
if (shell.mkdir('-p', repository).code !== 0) {
shell.exit(1);
}
const repository = await fs.mkdtemp(path.join(os.tmpdir(), 'arduino-cli-'));
const { owner, repo, commitish } = (() => {
const pkg = require(path.join(__dirname, '..', 'package.json'));
if (!pkg) {
shell.echo(`Could not parse the 'package.json'.`);
shell.exit(1);
console.log(`Could not parse the 'package.json'.`);
process.exit(1);
}
const defaultVersion = {
@@ -48,21 +44,21 @@
// We assume an object with `owner`, `repo`, commitish?` properties.
const { owner, repo, commitish } = version;
if (!owner) {
shell.echo(`Could not retrieve 'owner' from ${JSON.stringify(version)}`);
shell.exit(1);
console.log(`Could not retrieve 'owner' from ${JSON.stringify(version)}`);
process.exit(1);
}
if (!repo) {
shell.echo(`Could not retrieve 'repo' from ${JSON.stringify(version)}`);
shell.exit(1);
console.log(`Could not retrieve 'repo' from ${JSON.stringify(version)}`);
process.exit(1);
}
return { owner, repo, commitish };
})();
const url = `https://github.com/${owner}/${repo}.git`;
shell.echo(`>>> Cloning repository from '${url}'...`);
exec('git', ['clone', url, repository], shell);
shell.echo(`<<< Repository cloned.`);
console.log(`>>> Cloning repository from '${url}'...`);
exec('git', ['clone', url, repository], { logStdout: true });
console.log(`<<< Repository cloned.`);
const { platform } = process;
const resourcesFolder = path.join(
@@ -76,10 +72,12 @@
resourcesFolder,
`arduino-cli${platform === 'win32' ? '.exe' : ''}`
);
const versionJson = exec(cli, ['version', '--format', 'json'], shell).trim();
const versionJson = exec(cli, ['version', '--format', 'json'], {
logStdout: true,
}).trim();
if (!versionJson) {
shell.echo(`Could not retrieve the CLI version from ${cli}.`);
shell.exit(1);
console.log(`Could not retrieve the CLI version from ${cli}.`);
process.exit(1);
}
// As of today (28.01.2021), the `VersionString` can be one of the followings:
// - `nightly-YYYYMMDD` stands for the nightly build, we use the , the `commitish` from the `package.json` to check out the code.
@@ -103,45 +101,51 @@
version !== '0.0.0-git' &&
version !== 'git-snapshot'
) {
shell.echo(`>>> Checking out tagged version: '${version}'...`);
exec('git', ['-C', repository, 'fetch', '--all', '--tags'], shell);
console.log(`>>> Checking out tagged version: '${version}'...`);
exec('git', ['-C', repository, 'fetch', '--all', '--tags'], {
logStdout: true,
});
exec(
'git',
['-C', repository, 'checkout', `tags/${version}`, '-b', version],
shell
{ logStdout: true }
);
shell.echo(`<<< Checked out tagged version: '${version}'.`);
console.log(`<<< Checked out tagged version: '${version}'.`);
} else if (commitish) {
shell.echo(
console.log(
`>>> Checking out commitish from 'package.json': '${commitish}'...`
);
exec('git', ['-C', repository, 'checkout', commitish], shell);
shell.echo(
exec('git', ['-C', repository, 'checkout', commitish], { logStdout: true });
console.log(
`<<< Checked out commitish from 'package.json': '${commitish}'.`
);
} else if (versionObject.Commit) {
shell.echo(
console.log(
`>>> Checking out commitish from the CLI: '${versionObject.Commit}'...`
);
exec('git', ['-C', repository, 'checkout', versionObject.Commit], shell);
shell.echo(
exec('git', ['-C', repository, 'checkout', versionObject.Commit], {
logStdout: true,
});
console.log(
`<<< Checked out commitish from the CLI: '${versionObject.Commit}'.`
);
} else {
shell.echo(`WARN: no 'git checkout'. Generating from the HEAD revision.`);
console.log(`WARN: no 'git checkout'. Generating from the HEAD revision.`);
}
shell.echo('>>> Generating TS/JS API from:');
exec('git', ['-C', repository, 'rev-parse', '--abbrev-ref', 'HEAD'], shell);
console.log('>>> Generating TS/JS API from:');
exec('git', ['-C', repository, 'rev-parse', '--abbrev-ref', 'HEAD'], {
logStdout: true,
});
const rpc = path.join(repository, 'rpc');
const out = path.join(__dirname, '..', 'src', 'node', 'cli-protocol');
shell.mkdir('-p', out);
mkdirSync(out, { recursive: true });
const protos = await new Promise((resolve) =>
glob('**/*.proto', { cwd: rpc }, (error, matches) => {
if (error) {
shell.echo(error.stack ?? error.message);
console.log(error.stack ?? error.message);
resolve([]);
return;
}
@@ -149,12 +153,11 @@
})
);
if (!protos || protos.length === 0) {
shell.echo(`Could not find any .proto files under ${rpc}.`);
shell.exit(1);
console.log(`Could not find any .proto files under ${rpc}.`);
process.exit(1);
}
// Generate JS code from the `.proto` files.
exec(
'grpc_tools_node_protoc',
[
@@ -164,7 +167,7 @@
rpc,
...protos,
],
shell
{ logStdout: true }
);
// Generate the `.d.ts` files for JS.
@@ -183,8 +186,8 @@
rpc,
...protos,
],
shell
{ logStdout: true }
);
shell.echo('<<< Generation was successful.');
console.log('<<< Generation was successful.');
})();

View File

@@ -3,24 +3,21 @@
const exec = (
/** @type {string} */ command,
/** @type {readonly string[]} */ args,
/** @type {import('shelljs')|undefined}*/ shell = undefined,
/** @type {import('node:child_process').ExecFileSyncOptionsWithStringEncoding|undefined} */ options = undefined
/** @type {Partial<import('node:child_process').ExecFileSyncOptionsWithStringEncoding> & { logStdout?: boolean }|undefined} */ options = undefined
) => {
try {
const stdout = require('node:child_process').execFileSync(
command,
args,
options ? options : { encoding: 'utf8' }
);
if (shell) {
shell.echo(stdout.trim());
const stdout = require('node:child_process').execFileSync(command, args, {
encoding: 'utf8',
...(options ?? {}),
});
if (options?.logStdout) {
console.log(stdout.trim());
}
return stdout;
} catch (err) {
if (shell) {
shell.echo(err instanceof Error ? err.message : String(err));
shell.exit(1);
}
console.log(
`Failed to execute ${command} with args: ${JSON.stringify(args)}`
);
throw err;
}
};
@@ -59,32 +56,31 @@ function buildFromGit(command, version, destinationPath, taskName) {
const fs = require('node:fs');
const path = require('node:path');
const temp = require('temp');
const shell = require('shelljs');
// We assume an object with `owner`, `repo`, commitish?` properties.
if (typeof version !== 'object') {
shell.echo(
console.log(
`Expected a \`{ owner, repo, commitish }\` object. Got <${version}> instead.`
);
}
const { owner, repo, commitish } = version;
if (!owner) {
shell.echo(`Could not retrieve 'owner' from ${JSON.stringify(version)}`);
shell.exit(1);
console.log(`Could not retrieve 'owner' from ${JSON.stringify(version)}`);
process.exit(1);
}
if (!repo) {
shell.echo(`Could not retrieve 'repo' from ${JSON.stringify(version)}`);
shell.exit(1);
console.log(`Could not retrieve 'repo' from ${JSON.stringify(version)}`);
process.exit(1);
}
const url = `https://github.com/${owner}/${repo}.git`;
shell.echo(
console.log(
`Building ${taskName} from ${url}. Commitish: ${
commitish ? commitish : 'HEAD'
}`
);
if (fs.existsSync(destinationPath)) {
shell.echo(
console.log(
`Skipping the ${taskName} build because it already exists: ${destinationPath}`
);
return;
@@ -97,48 +93,51 @@ function buildFromGit(command, version, destinationPath, taskName) {
'node',
'resources'
);
if (shell.mkdir('-p', resourcesFolder).code !== 0) {
shell.echo('Could not create resources folder.');
shell.exit(1);
}
fs.mkdirSync(resourcesFolder, { recursive: true });
const tempRepoPath = temp.mkdirSync();
shell.echo(`>>> Cloning ${taskName} source to ${tempRepoPath}...`);
exec('git', ['clone', url, tempRepoPath], shell);
shell.echo(`<<< Cloned ${taskName} repo.`);
console.log(`>>> Cloning ${taskName} source to ${tempRepoPath}...`);
exec('git', ['clone', url, tempRepoPath], { logStdout: true });
console.log(`<<< Cloned ${taskName} repo.`);
if (commitish) {
shell.echo(`>>> Checking out ${commitish}...`);
exec('git', ['-C', tempRepoPath, 'checkout', commitish], shell);
shell.echo(`<<< Checked out ${commitish}.`);
console.log(`>>> Checking out ${commitish}...`);
exec('git', ['-C', tempRepoPath, 'checkout', commitish], {
logStdout: true,
});
console.log(`<<< Checked out ${commitish}.`);
}
exec('git', ['-C', tempRepoPath, 'rev-parse', '--short', 'HEAD'], shell);
exec('git', ['-C', tempRepoPath, 'rev-parse', '--short', 'HEAD'], {
logStdout: true,
});
shell.echo(`>>> Building the ${taskName}...`);
exec(command, ['build'], shell, { cwd: tempRepoPath, encoding: 'utf8' });
shell.echo(`<<< Done ${taskName} build.`);
console.log(`>>> Building the ${taskName}...`);
exec(command, ['build'], {
cwd: tempRepoPath,
encoding: 'utf8',
logStdout: true,
});
console.log(`<<< Done ${taskName} build.`);
const binName = path.basename(destinationPath);
if (!fs.existsSync(path.join(tempRepoPath, binName))) {
shell.echo(
console.log(
`Could not find the ${taskName} at ${path.join(tempRepoPath, binName)}.`
);
shell.exit(1);
process.exit(1);
}
const binPath = path.join(tempRepoPath, binName);
shell.echo(
console.log(
`>>> Copying ${taskName} from ${binPath} to ${destinationPath}...`
);
if (shell.cp(binPath, destinationPath).code !== 0) {
shell.exit(1);
}
shell.echo(`<<< Copied the ${taskName}.`);
fs.copyFileSync(binPath, destinationPath);
console.log(`<<< Copied the ${taskName}.`);
shell.echo(`<<< Verifying ${taskName}...`);
console.log(`<<< Verifying ${taskName}...`);
if (!fs.existsSync(destinationPath)) {
shell.exit(1);
process.exit(1);
}
shell.echo(`>>> Verified ${taskName}.`);
console.log(`>>> Verified ${taskName}.`);
}