@sentry/wizard
Version:
Sentry wizard helping you to configure your project
196 lines • 10.1 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.runAppleWizard = void 0;
/* eslint-disable max-lines */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unused-vars */
// @ts-ignore - clack is ESM and TS complains about that. It works though
const prompts_1 = __importDefault(require("@clack/prompts"));
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const xcode_manager_1 = require("./xcode-manager");
const codeTools = __importStar(require("./code-tools"));
const bash = __importStar(require("../utils/bash"));
const SentryUtils = __importStar(require("../utils/sentrycli-utils"));
const Sentry = __importStar(require("@sentry/node"));
const telemetry_1 = require("../telemetry");
const cocoapod = __importStar(require("./cocoapod"));
const fastlane = __importStar(require("./fastlane"));
/* eslint-enable @typescript-eslint/no-unused-vars */
const clack_utils_1 = require("../utils/clack-utils");
async function runAppleWizard(options) {
return (0, telemetry_1.withTelemetry)({
enabled: options.telemetryEnabled,
integration: 'ios',
wizardOptions: options,
}, () => runAppleWizardWithTelementry(options));
}
exports.runAppleWizard = runAppleWizard;
async function runAppleWizardWithTelementry(options) {
(0, clack_utils_1.printWelcome)({
wizardName: 'Sentry Apple Wizard',
promoCode: options.promoCode,
});
await (0, clack_utils_1.confirmContinueIfNoOrDirtyGitRepo)();
const hasCli = bash.hasSentryCLI();
Sentry.setTag('has-cli', hasCli);
if (!hasCli) {
if (!(await (0, telemetry_1.traceStep)('Ask for SentryCLI', () => (0, clack_utils_1.askToInstallSentryCLI)()))) {
prompts_1.default.log.warn("Without sentry-cli, you won't be able to upload debug symbols to Sentry. You can install it later by following the instructions at https://docs.sentry.io/cli/");
Sentry.setTag('CLI-Installed', false);
}
else {
await bash.installSentryCLI();
Sentry.setTag('CLI-Installed', true);
}
}
const projectDir = process.cwd();
const xcodeProjFiles = searchXcodeProject(projectDir);
if (!xcodeProjFiles || xcodeProjFiles.length === 0) {
prompts_1.default.log.error('No Xcode project found. Please run this command from the root of your project.');
await (0, clack_utils_1.abort)();
return;
}
let xcodeProjFile;
if (xcodeProjFiles.length === 1) {
xcodeProjFile = xcodeProjFiles[0];
Sentry.setTag('multiple-projects', false);
}
else {
Sentry.setTag('multiple-projects', true);
xcodeProjFile = (await (0, telemetry_1.traceStep)('Choose Xcode project', () => (0, clack_utils_1.askForItemSelection)(xcodeProjFiles, 'Which project do you want to add Sentry to?'))).value;
}
const pbxproj = path.join(projectDir, xcodeProjFile, 'project.pbxproj');
if (!fs.existsSync(pbxproj)) {
prompts_1.default.log.error(`No pbxproj found at ${xcodeProjFile}`);
await (0, clack_utils_1.abort)();
return;
}
const { project, apiKey } = await getSentryProjectAndApiKey(options);
const xcProject = new xcode_manager_1.XcodeProject(pbxproj);
const availableTargets = xcProject.getAllTargets();
if (availableTargets.length == 0) {
prompts_1.default.log.error(`No suitable target found in ${xcodeProjFile}`);
Sentry.setTag('No-Target', true);
await (0, clack_utils_1.abort)();
return;
}
const target = availableTargets.length == 1
? availableTargets[0]
: (await (0, telemetry_1.traceStep)('Choose target', () => (0, clack_utils_1.askForItemSelection)(availableTargets, 'Which target do you want to add Sentry to?'))).value;
SentryUtils.createSentryCLIRC(projectDir, { auth_token: apiKey.token });
prompts_1.default.log.info('We created a ".sentryclirc" file in your project directory in order to provide an auth token for Sentry CLI.\nIt was also added to your ".gitignore" file.\nAt your CI enviroment, you can set the SENTRY_AUTH_TOKEN environment variable instead. See https://docs.sentry.io/cli/configuration/#auth-token for more information.');
let hasCocoa = cocoapod.usesCocoaPod(projectDir);
Sentry.setTag('cocoapod-exists', hasCocoa);
if (hasCocoa) {
const pm = (await (0, telemetry_1.traceStep)('Choose a package manager', () => (0, clack_utils_1.askForItemSelection)(['Swift Package Manager', 'CocoaPods'], 'Which package manager would you like to use to add Sentry?'))).value;
hasCocoa = pm === 'CocoaPods';
if (hasCocoa) {
const podAdded = await (0, telemetry_1.traceStep)('Add CocoaPods reference', () => cocoapod.addCocoaPods(projectDir));
Sentry.setTag('cocoapod-added', podAdded);
if (!podAdded) {
prompts_1.default.log.warn("Could not add Sentry pod to your Podfile. You'll have to add it manually.\nPlease follow the instructions at https://docs.sentry.io/platforms/apple/guides/ios/#install");
}
}
}
Sentry.setTag('package-manager', hasCocoa ? 'cocoapods' : 'SPM');
(0, telemetry_1.traceStep)('Update Xcode project', () => {
xcProject.updateXcodeProject(project, target, !hasCocoa, true);
});
const codeAdded = (0, telemetry_1.traceStep)('Add code snippet', () => {
const files = xcProject.filesForTarget(target);
if (files === undefined || files.length == 0)
return false;
return codeTools.addCodeSnippetToProject(projectDir, files, project.keys[0].dsn.public);
});
Sentry.setTag('Snippet-Added', codeAdded);
if (!codeAdded) {
prompts_1.default.log.warn('Added the Sentry dependency to your project but could not add the Sentry code snippet. Please add the code snipped manually by following the docs: https://docs.sentry.io/platforms/apple/guides/ios/#configure');
}
const hasFastlane = fastlane.fastFile(projectDir);
Sentry.setTag('fastlane-exists', hasFastlane);
if (hasFastlane) {
const addLane = await prompts_1.default.confirm({
message: 'Found a Fastfile in your project. Do you want to configure a lane to upload debug symbols to Sentry?',
});
Sentry.setTag('fastlane-desired', addLane);
if (addLane) {
const added = await (0, telemetry_1.traceStep)('Configure fastlane', () => fastlane.addSentryToFastlane(projectDir, project.organization.slug, project.slug));
Sentry.setTag('fastlane-added', added);
if (added) {
prompts_1.default.log.step('A new step was added to your fastlane file. Now and you build your project with fastlane, debug symbols and source context will be uploaded to Sentry.');
}
else {
prompts_1.default.log.warn('Could not edit your fastlane file to upload debug symbols to Sentry. Please follow the instructions at https://docs.sentry.io/platforms/apple/guides/ios/dsym/#fastlane');
}
}
}
prompts_1.default.log.success('Sentry was successfully added to your project! Run your project to send your first event to Sentry. Go to Sentry.io to see whether everything is working fine.');
}
//Prompt for Sentry project and API key
async function getSentryProjectAndApiKey(options) {
const { selectedProject, authToken } = await (0, clack_utils_1.getOrAskForProjectData)(options);
return { project: selectedProject, apiKey: { token: authToken } };
}
function searchXcodeProject(at) {
const projs = findFilesWithExtension(at, '.xcodeproj');
if (projs.length > 0) {
return projs;
}
const workspace = findFilesWithExtension(at, '.xcworkspace');
if (workspace.length == 0) {
return [];
}
const xsworkspacedata = path.join(at, workspace[0], 'contents.xcworkspacedata');
if (!fs.existsSync(xsworkspacedata)) {
return [];
}
const groupRegex = /location *= *"group:([^"]+)"/gim;
const content = fs.readFileSync(xsworkspacedata, 'utf8');
let matches = groupRegex.exec(content);
while (matches) {
const group = matches[1];
const groupPath = path.join(at, group);
if (!group.endsWith('Pods.xcodeproj') &&
group.endsWith('.xcodeproj') &&
fs.existsSync(groupPath)) {
projs.push(group);
}
matches = groupRegex.exec(content);
}
return projs;
}
//find files with the given extension
function findFilesWithExtension(dir, extension) {
const files = fs.readdirSync(dir);
return files.filter((file) => file.endsWith(extension));
}
//# sourceMappingURL=apple-wizard.js.map