Files
codeql-action/node_modules/@protobuf-ts/protoc/protoc.js
Angela P Wen a196a714b8 Bump artifact dependencies if CODEQL_ACTION_ARTIFACT_V2_UPGRADE enabled (#2482)
Co-authored-by: Andrew Eisenberg <aeisenberg@github.com>
Co-authored-by: Henry Mercer <henrymercer@github.com>
2024-10-01 09:59:05 -07:00

138 lines
4.8 KiB
JavaScript
Executable File

#!/usr/bin/env node
// Automatically installs protoc if not found on $PATH, then
// runs it transiently.
const {spawnSync} = require('child_process');
const path = require('path');
const fs = require('fs');
const os = require('os');
const {findProtocVersionConfig, listInstalled, findProtocPlugins, findProtobufTs, unzip, makeReleaseName, httpGetRedirect, httpDownload, mkDirRecursive, findProtocInPath, standardInstallDirectory} = require('./util');
main().catch(err => {
console.error((err instanceof Error) ? err.message : err);
process.exit(1);
});
async function main() {
// the full path to the protoc executable
let command;
// the full path to the include files of a protoc release (well-known-types)
let includePath;
// does the nearest package.json have a config.protocVersion?
const configuredVersion = findProtocVersionConfig(process.cwd());
if (configuredVersion) {
// we prefer the configured protoc version and install it
let release = await ensureInstalled(configuredVersion);
command = release.protocPath;
includePath = release.includePath;
} else {
// there is no configured protoc version. do we have protoc in the $PATH?
command = findProtocInPath(process.env.PATH)
if (!command) {
// no protoc in $PATH, install the latest version
let release = await ensureInstalled(configuredVersion);
command = release.protocPath;
includePath = release.includePath;
}
}
let args = [
// pass all arguments to the process
...process.argv.slice(2),
];
if (includePath) {
// add the "include" directory of the installed protoc to the proto path
// do this last, otherwise it can shadow a user input
args.push("--proto_path", includePath);
}
// search for @protobuf-ts/plugin in node_modules and add --proto_path argument
let protobufTs = findProtobufTs(process.cwd());
if (protobufTs) {
args.push("--proto_path", protobufTs);
}
// search for any protoc-gen-xxx plugins in .bin and add --plugin arguments for them
for (let plugin of findProtocPlugins(process.cwd())) {
args.unshift("--plugin", plugin);
}
let child = spawnSync(command, args, {
// protoc accepts stdin for some commands, pipe all IO
stdio: [process.stdin, process.stdout, process.stderr],
shell: false
});
if (child.error) {
throw new Error("@protobuf-ts/protoc was unable to spawn protoc. " + child.error);
}
process.exit(child.status);
}
async function ensureInstalled(version) {
// resolve the latest release version number if necessary
if (version === "latest" || version === undefined) {
let latestLocation;
try {
latestLocation = await httpGetRedirect("https://github.com/protocolbuffers/protobuf/releases/latest");
} catch (e) {
throw new Error(`@protobuf-ts/protoc failed to retrieve latest protoc version number: ${e}`);
}
version = latestLocation.split("/v").pop();
}
// make the release name for the current platform and the requested version number
let releaseName = makeReleaseName({
platform: os.platform(),
arch: os.arch(),
version: version
});
// if this release is already installed, we are done here
let alreadyInstalled = listInstalled().find(i => i.name === releaseName);
if (alreadyInstalled) {
return alreadyInstalled;
}
// download the release
let archive;
try {
archive = await httpDownload(`https://github.com/protocolbuffers/protobuf/releases/download/v${version}/${releaseName}.zip`);
} catch (e) {
throw new Error(`@protobuf-ts/protoc failed to download protoc v${version}. \nDid you misspell the version number? The version number must look like "3.0.12", without a leading "v".\n${e}`);
}
// unzip the archive
let archivePath = path.join(standardInstallDirectory, releaseName);
try {
unzip(archive, (data, header) => {
let filename = path.join(archivePath, header.filename);
mkDirRecursive(path.dirname(filename));
fs.writeFileSync(filename, data, {
mode: header.filename.includes("bin/") ? 0o755 : 0o666
});
});
} catch (e) {
throw new Error(`@protobuf-ts/protoc failed unzip the downloaded protoc release v${version}: ${e}`);
}
// sanity check
let installed = listInstalled().find(i => i.name === releaseName);
if (!installed) {
throw new Error(`@protobuf-ts/protoc failed to install protoc v${version}.`);
}
// finished
console.info(`@protobuf-ts/protoc installed protoc v${installed.version}.`);
return installed;
}