@splunk/rum-cli
Version:
Tools for handling symbol and mapping files for symbolication
149 lines (148 loc) • 7.66 kB
JavaScript
;
/*
* Copyright Splunk Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.iOSCommand = void 0;
const commander_1 = require("commander");
const spinner_1 = require("../utils/spinner");
const constants_1 = require("../utils/constants");
const dsymClient_1 = require("../dsyms/dsymClient");
const logger_1 = require("../utils/logger");
const iOSdSYMUtils_1 = require("../dsyms/iOSdSYMUtils");
const userFriendlyErrors_1 = require("../utils/userFriendlyErrors");
const metadataFormatUtils_1 = require("../utils/metadataFormatUtils");
const inputValidations_1 = require("../utils/inputValidations");
const program = new commander_1.Command();
exports.iOSCommand = program.command('ios');
const shortDescription = 'Upload and list iOS symbolication files (dSYMs)';
const detailedHelp = `For each respective command listed below under 'Commands', please run 'splunk-rum ios <command> --help' for an overview of its usage and options`;
const iOSUploadDescription = 'This subcommand uploads dSYMs provided as either a zip file, or a dSYM or dSYMs directory.';
const iOSUploadSummary = 'Upload dSYMs, either by directory path or zip path, to the symbolication service';
const listdSYMsDescription = `This subcommand retrieves and shows a list of the uploaded dSYMs.
By default, it returns the last 100 dSYMs uploaded, sorted in reverse chronological order based on the upload timestamp.
`;
exports.iOSCommand
.description(shortDescription)
.usage('[command] [options]');
exports.iOSCommand.configureHelp({
commandDescription: (cmd) => {
return `${cmd.description()}\n\n${detailedHelp}`;
}
});
exports.iOSCommand
.command('upload')
.showHelpAfterError(inputValidations_1.COMMON_ERROR_MESSAGES.HELP_MESSAGE_AFTER_ERROR)
.usage('--path <dSYMs directory or zip file>')
.description(iOSUploadDescription)
.summary(iOSUploadSummary)
.requiredOption('--path <dSYMs dir or zip>', 'Path to the dSYM[s] directory or zip file.')
.requiredOption('--realm <value>', 'Realm for your organization (example: us0). Can also be set using the environment variable SPLUNK_REALM', process.env.SPLUNK_REALM)
.option('--token <value>', 'API access token. Can also be set using the environment variable SPLUNK_ACCESS_TOKEN')
.option('--debug', 'Enable debug logs')
.option('--dry-run', 'Perform a trial run with no changes made', false)
.action((options) => __awaiter(void 0, void 0, void 0, function* () {
const spinner = (0, spinner_1.createSpinner)();
const logger = (0, logger_1.createLogger)(options.debug ? 1 /* LogLevel.DEBUG */ : 2 /* LogLevel.INFO */, spinner);
try {
// Step 1: Validate and prepare the token
const token = (0, inputValidations_1.validateAndPrepareToken)(options);
// Step 2: Validate the input path and prepare the zipped files
const { zipFiles, uploadPath } = (0, iOSdSYMUtils_1.prepareUploadFiles)(options.path, logger);
// Step 3: Upload the files
yield (0, dsymClient_1.uploadDSYMZipFiles)({
zipFiles,
uploadPath,
realm: options.realm,
token,
logger,
spinner,
});
logger.info('All dSYM files uploaded successfully.');
}
catch (error) {
spinner.stop();
if (error instanceof userFriendlyErrors_1.UserFriendlyError) {
// UserFriendlyError.message already contains the formatted string from formatCLIErrorMessage
logger.error(error.message);
if (options.debug && error.originalError) {
logger.debug('Original error details:', error.originalError);
}
}
else {
logger.error(error instanceof Error ? error.message : `An unexpected error occurred: ${String(error)}`);
}
exports.iOSCommand.error(''); // ensure error exit code. process.exit(1) would also work.
}
}));
exports.iOSCommand
.command('list')
.summary('Retrieves list of metadata of all uploaded dSYM files')
.showHelpAfterError(inputValidations_1.COMMON_ERROR_MESSAGES.HELP_MESSAGE_AFTER_ERROR)
.description(listdSYMsDescription)
.option('--debug', 'Enable debug logs')
.requiredOption('--realm <value>', 'Realm for your organization (example: us0). Can also be set using the environment variable SPLUNK_REALM', process.env.SPLUNK_REALM)
.option('--token <value>', 'API access token. Can also be set using the environment variable SPLUNK_ACCESS_TOKEN')
.action((options) => __awaiter(void 0, void 0, void 0, function* () {
const logger = (0, logger_1.createLogger)(options.debug ? 1 /* LogLevel.DEBUG */ : 2 /* LogLevel.INFO */);
logger.info('Fetching dSYM file data...');
try {
const token = (0, inputValidations_1.validateAndPrepareToken)(options);
const url = (0, iOSdSYMUtils_1.generateUrl)({
apiPath: constants_1.IOS_CONSTANTS.PATH_FOR_METADATA,
realm: options.realm
});
const responseData = yield (0, dsymClient_1.listDSYMs)({
url,
token: token,
logger,
});
logger.info((0, metadataFormatUtils_1.formatIOSdSYMMetadata)(responseData));
}
catch (error) {
if (error instanceof userFriendlyErrors_1.UserFriendlyError) {
// The UserFriendlyError.message is already formatted by formatCLIErrorMessage
// and includes both user-friendly text and technical details.
// logger.error will prefix this with "ERROR " and handle colors.
logger.error(error.message);
if (options.debug && error.originalError) {
logger.debug('Original error details:', error.originalError);
}
}
else {
// For any other unexpected errors (e.g. non-Axios, such as in token validation)
logger.error('An unexpected error occurred during the iOS list command:');
if (error instanceof Error) {
logger.error(error.message);
if (options.debug && error.stack) {
logger.debug(error.stack);
}
}
else {
logger.error(String(error)); // catchall for other error types
}
}
exports.iOSCommand.error(''); // Error exit. Blank message because one was already logged.
}
}));