UNPKG

@bugsplat/symbol-upload

Version:
194 lines 7.92 kB
#! /usr/bin/env node "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const js_api_client_1 = require("@bugsplat/js-api-client"); const command_line_args_1 = __importDefault(require("command-line-args")); const command_line_usage_1 = __importDefault(require("command-line-usage")); const glob_1 = require("glob"); const node_crypto_1 = require("node:crypto"); const node_fs_1 = require("node:fs"); const promises_1 = require("node:fs/promises"); const node_path_1 = require("node:path"); const fs_1 = require("../src/fs"); const info_1 = require("../src/info"); const preload_1 = require("../src/preload"); const sym_1 = require("../src/sym"); const tmp_1 = require("../src/tmp"); const upload_1 = require("../src/upload"); const command_line_definitions_1 = require("./command-line-definitions"); (async () => { let { help, database, application, version, user, password, clientId, clientSecret, remove, files, directory, dumpSyms, localPath, } = await getCommandLineOptions(command_line_definitions_1.argDefinitions); if (help) { logHelpAndExit(); } database = database ?? process.env.BUGSPLAT_DATABASE; user = user ?? process.env.SYMBOL_UPLOAD_USER; password = password ?? process.env.SYMBOL_UPLOAD_PASSWORD; clientId = clientId ?? process.env.SYMBOL_UPLOAD_CLIENT_ID; clientSecret = clientSecret ?? process.env.SYMBOL_UPLOAD_CLIENT_SECRET; if (!database && !localPath) { logMissingArgAndExit('database'); } if (!application && !localPath) { logMissingArgAndExit('application'); } if (!version && !localPath) { logMissingArgAndExit('version'); } if (!localPath && !validAuthenticationArguments({ user, password, clientId, clientSecret, })) { logMissingAuthAndExit(); } console.log(`Symbol upload working directory: ${process.cwd()}`); let bugsplat = null; if (!localPath) { console.log('About to authenticate...'); bugsplat = await createBugSplatClient({ user, password, clientId, clientSecret, }); console.log('Authentication success!'); } if (remove && bugsplat) { try { const versionsApiClient = new js_api_client_1.VersionsApiClient(bugsplat); console.log(`About to delete symbols for ${database}-${application}-${version}...`); await versionsApiClient.deleteSymbols(database, application, version); console.log('Symbols deleted successfully!'); } catch (error) { console.error(error); process.exit(1); } finally { return; } } directory = normalizeDirectory(directory); if (!(0, node_fs_1.existsSync)(tmp_1.tmpDir)) { await (0, promises_1.mkdir)(tmp_1.tmpDir); } const globPattern = `${directory}/${files}`; let symbolFilePaths = await (0, glob_1.glob)(globPattern); if (!symbolFilePaths.length) { throw new Error(`Could not find any files to upload using glob ${globPattern}!`); } console.log(`Found files:\n ${symbolFilePaths.join('\n')}`); if (dumpSyms) { let nodeDumpSyms; try { nodeDumpSyms = (await (0, preload_1.importNodeDumpSyms)()).dumpSyms; } catch (cause) { throw new Error("Can't import dump_syms! Please ensure node-dump-syms is installed https://github.com/BugSplat-Git/node-dump-syms", { cause }); } const newSymbolFilePaths = []; for (const file of symbolFilePaths) { console.log(`Dumping syms for ${file}...`); const symFile = (0, node_path_1.join)(tmp_1.tmpDir, (0, node_crypto_1.randomUUID)(), (0, sym_1.getNormalizedSymFileName)((0, node_path_1.basename)(file))); (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(symFile), { recursive: true }); try { nodeDumpSyms(file, symFile); } catch (error) { console.warn(`Failed to dump syms for ${file}: ${error?.message || error}`); continue; } newSymbolFilePaths.push(symFile); } symbolFilePaths = newSymbolFilePaths; } if (!symbolFilePaths.length) { throw new Error('No valid symbol files found!'); } const symbolFileInfos = await Promise.all(symbolFilePaths.map(async (symbolFilePath) => await (0, info_1.createSymbolFileInfos)(symbolFilePath))).then((array) => array.flat()); if (localPath) { await copyFilesToLocalPath(symbolFileInfos, localPath); } if (bugsplat) { await (0, upload_1.uploadSymbolFiles)(bugsplat, database, application, version, symbolFileInfos); } await (0, tmp_1.safeRemoveTmp)(); process.exit(0); })().catch(async (error) => { await (0, tmp_1.safeRemoveTmp)(); console.error(error.message); process.exit(1); }); async function copyFilesToLocalPath(symbolFileInfos, localPath) { console.log(`Copying files to ${localPath}...`); for (const symbolFileInfo of symbolFileInfos) { if (!symbolFileInfo.dbgId) { console.warn(`Failed to parse UUID for ${symbolFileInfo.path}, skipping...`); continue; } const localFilePath = (0, node_path_1.join)(localPath, symbolFileInfo.moduleName, symbolFileInfo.dbgId, (0, node_path_1.basename)(symbolFileInfo.path)); (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(localFilePath), { recursive: true }); await (0, promises_1.copyFile)(symbolFileInfo.path, localFilePath); } const symSrvMarkerFilePath = (0, node_path_1.join)(localPath, 'index.txt'); await (0, promises_1.writeFile)(symSrvMarkerFilePath, '.'); } async function createBugSplatClient({ user, password, clientId, clientSecret, }) { const host = process.env.BUGSPLAT_HOST; if (user && password) { return js_api_client_1.BugSplatApiClient.createAuthenticatedClientForNode(user, password, host); } return js_api_client_1.OAuthClientCredentialsClient.createAuthenticatedClient(clientId, clientSecret, host); } async function getCommandLineOptions(argDefinitions) { const options = (0, command_line_args_1.default)(argDefinitions); let { database, application, version } = options; let packageJson; if (!database || !application || !version) { const packageJsonPath = './package.json'; packageJson = (await (0, fs_1.fileExists)(packageJsonPath)) ? JSON.parse((await (0, promises_1.readFile)(packageJsonPath)).toString()) : null; } if (!database && packageJson) { database = packageJson.database; } if (!application && packageJson) { application = packageJson.name; } if (!version && packageJson) { version = packageJson.version; } return { ...options, database, application, version, }; } function logHelpAndExit(code = 0) { const help = (0, command_line_usage_1.default)(command_line_definitions_1.usageDefinitions); console.log(help); process.exit(code); } function logMissingArgAndExit(arg) { console.log(`\nMissing argument: -${arg}\n`); logHelpAndExit(1); } function logMissingAuthAndExit() { console.log('\nInvalid authentication arguments: please provide either a user and password, or a clientId and clientSecret\n'); logHelpAndExit(1); } function normalizeDirectory(directory) { return directory.replace(/\\/g, '/'); } function validAuthenticationArguments({ user, password, clientId, clientSecret, }) { return !!(user && password) || !!(clientId && clientSecret); } //# sourceMappingURL=index.js.map