UNPKG

@sentry/wizard

Version:

Sentry wizard helping you to configure your project

290 lines (286 loc) 13 kB
"use strict"; 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.configureCI = exports.runSourcemapsWizard = void 0; // @ts-ignore - clack is ESM and TS complains about that. It works though const prompts_1 = __importDefault(require("@clack/prompts")); const chalk_1 = __importDefault(require("chalk")); const Sentry = __importStar(require("@sentry/node")); const clack_utils_1 = require("../utils/clack-utils"); const is_unicorn_supported_1 = require("../utils/vendor/is-unicorn-supported"); const vite_1 = require("./tools/vite"); const sentry_cli_1 = require("./tools/sentry-cli"); const webpack_1 = require("./tools/webpack"); const tsc_1 = require("./tools/tsc"); const rollup_1 = require("./tools/rollup"); const esbuild_1 = require("./tools/esbuild"); const create_react_app_1 = require("./tools/create-react-app"); const sdk_version_1 = require("./utils/sdk-version"); const telemetry_1 = require("../telemetry"); const other_wizards_1 = require("./utils/other-wizards"); const angular_1 = require("./tools/angular"); const detect_tool_1 = require("./utils/detect-tool"); const nextjs_1 = require("./tools/nextjs"); const remix_1 = require("./tools/remix"); const package_manager_1 = require("../utils/package-manager"); const url_1 = require("../utils/url"); async function runSourcemapsWizard(options) { return (0, telemetry_1.withTelemetry)({ enabled: options.telemetryEnabled, integration: 'sourcemaps', wizardOptions: options, }, () => runSourcemapsWizardWithTelemetry(options)); } exports.runSourcemapsWizard = runSourcemapsWizard; async function runSourcemapsWizardWithTelemetry(options) { (0, clack_utils_1.printWelcome)({ wizardName: 'Sentry Source Maps Upload Configuration Wizard', message: `This wizard will help you upload source maps to Sentry as part of your build. Thank you for using Sentry :)${options.telemetryEnabled ? ` (This setup wizard sends telemetry data and crash reports to Sentry. You can turn this off by running the wizard with the '--disable-telemetry' flag.)` : ''}`, promoCode: options.promoCode, }); const moreSuitableWizard = await (0, telemetry_1.traceStep)('check-framework-wizard', other_wizards_1.checkIfMoreSuitableWizardExistsAndAskForRedirect); if (moreSuitableWizard) { await (0, telemetry_1.traceStep)('run-framework-wizard', () => moreSuitableWizard(options)); return; } await (0, clack_utils_1.confirmContinueIfNoOrDirtyGitRepo)(); await (0, telemetry_1.traceStep)('check-sdk-version', sdk_version_1.ensureMinimumSdkVersionIsInstalled); const { selfHosted, selectedProject, sentryUrl, authToken } = await (0, clack_utils_1.getOrAskForProjectData)(options); const wizardOptionsWithPreSelectedProject = { ...options, preSelectedProject: { project: selectedProject, authToken, selfHosted, }, }; const selectedTool = await (0, telemetry_1.traceStep)('select-tool', askForUsedBundlerTool); Sentry.setTag('selected-tool', selectedTool); if (selectedTool === 'no-tool') { prompts_1.default.log.info("No Problem! But in this case, there's nothing to configure :)"); await (0, clack_utils_1.abort)('Exiting, have a great day!', 0); return; } await (0, telemetry_1.traceStep)('tool-setup', () => startToolSetupFlow(selectedTool, { orgSlug: selectedProject.organization.slug, projectSlug: selectedProject.slug, selfHosted, url: sentryUrl, authToken, }, wizardOptionsWithPreSelectedProject)); await (0, telemetry_1.traceStep)('ci-setup', () => configureCI(selectedTool, authToken)); (0, telemetry_1.traceStep)('outro', () => printOutro(sentryUrl, selectedProject.organization.slug, selectedProject.id)); } async function askForUsedBundlerTool() { const selectedTool = await (0, clack_utils_1.abortIfCancelled)(prompts_1.default.select({ message: 'Which framework, bundler or build tool are you using?', options: [ { label: 'Angular', value: 'angular', hint: 'Select this option if you are using Angular.', }, { label: 'Create React App', value: 'create-react-app', hint: 'Select this option if you set up your app with Create React App.', }, { label: 'Next.js', value: 'nextjs', hint: 'Select this option if you want to set up source maps in a Next.js project.', }, { label: 'Remix', value: 'remix', hint: 'Select this option if you want to set up source maps in a Remix project.', }, { label: 'Webpack', value: 'webpack', hint: 'Select this if you are using Webpack and you have access to your Webpack config.', }, { label: 'Vite', value: 'vite', hint: 'Select this if you are using Vite and you have access to your Vite config.', }, { label: 'esbuild', value: 'esbuild', hint: 'Select this if you are using esbuild and you have access to your esbuild config.', }, { label: 'Rollup', value: 'rollup', hint: 'Select this if you are using Rollup and you have access to your Rollup config.', }, { label: 'tsc', value: 'tsc', hint: 'Configure source maps when using tsc as build tool', }, { label: 'I use another tool', value: 'sentry-cli', hint: 'This will configure source maps upload for you using sentry-cli', }, { label: "I don't minify, transpile or bundle my code", value: 'no-tool', hint: 'This will exit the wizard', }, ], initialValue: await (0, detect_tool_1.detectUsedTool)(), })); return selectedTool; } async function startToolSetupFlow(selctedTool, options, wizardOptions) { switch (selctedTool) { case 'webpack': await (0, webpack_1.configureWebPackPlugin)(options); break; case 'vite': await (0, vite_1.configureVitePlugin)(options); break; case 'esbuild': await (0, esbuild_1.configureEsbuildPlugin)(options); break; case 'rollup': await (0, rollup_1.configureRollupPlugin)(options); break; case 'tsc': await (0, sentry_cli_1.configureSentryCLI)(options, tsc_1.configureTscSourcemapGenerationFlow); break; case 'create-react-app': await (0, sentry_cli_1.configureSentryCLI)(options, create_react_app_1.configureCRASourcemapGenerationFlow); break; case 'angular': await (0, sentry_cli_1.configureSentryCLI)(options, angular_1.configureAngularSourcemapGenerationFlow); break; case 'nextjs': await (0, nextjs_1.configureNextJsSourceMapsUpload)(options, wizardOptions); break; case 'remix': await (0, remix_1.configureRemixSourceMapsUpload)(options, wizardOptions); break; default: await (0, sentry_cli_1.configureSentryCLI)(options); break; } } async function configureCI(selectedTool, authToken) { const isUsingCI = await (0, clack_utils_1.abortIfCancelled)(prompts_1.default.select({ message: `Are you using a CI/CD tool to build and deploy your application?`, options: [ { label: 'Yes', hint: 'I use a tool like GitHub Actions, GitLab, CircleCI, TravisCI, Jenkins, Vercel, ...', value: true, }, { label: 'No', hint: 'I build and deploy my application manually', value: false, }, ], initialValue: true, })); Sentry.setTag('using-ci', isUsingCI); const isCliBasedFlowTool = [ 'sentry-cli', 'tsc', 'angular', 'create-react-app', ].includes(selectedTool); const authTokenFile = isCliBasedFlowTool ? clack_utils_1.SENTRY_CLI_RC_FILE : clack_utils_1.SENTRY_DOT_ENV_FILE; if (!isUsingCI) { prompts_1.default.log.info(`No Problem! Just make sure that the Sentry auth token from ${chalk_1.default.cyan(authTokenFile)} is available whenever you build and deploy your app.`); return; } if (isCliBasedFlowTool) { await (0, telemetry_1.traceStep)('ci-npm-script-setup', sentry_cli_1.setupNpmScriptInCI); } await (0, telemetry_1.traceStep)('ci-auth-token-setup', () => setupAuthTokenInCI(authToken)); } exports.configureCI = configureCI; async function setupAuthTokenInCI(authToken) { prompts_1.default.log.step('Add the Sentry authentication token as an environment variable to your CI setup:'); // Intentially logging directly to console here so that the code can be copied/pasted directly // eslint-disable-next-line no-console console.log(chalk_1.default.greenBright(` SENTRY_AUTH_TOKEN=${authToken} `)); prompts_1.default.log.warn(chalk_1.default.yellow('DO NOT commit this auth token to your repository!')); const addedEnvVarToCI = await (0, clack_utils_1.abortIfCancelled)(prompts_1.default.select({ message: 'Did you configure CI as shown above?', options: [ { label: 'Yes, continue!', value: true }, { label: "I'll do it later...", value: false, hint: chalk_1.default.yellow('You need to set the auth token to upload source maps in CI'), }, ], initialValue: true, })); Sentry.setTag('added-env-var-to-ci', addedEnvVarToCI); if (!addedEnvVarToCI) { prompts_1.default.log.info("Don't forget! :)"); } } function printOutro(url, orgSlug, projectId) { const packageManager = (0, package_manager_1.detectPackageManger)(); const buildCommand = packageManager?.buildCommand ?? 'npm run build'; const issueStreamUrl = (0, url_1.getIssueStreamUrl)({ url, orgSlug, projectId }); const arrow = (0, is_unicorn_supported_1.isUnicodeSupported)() ? '→' : '->'; prompts_1.default.outro(`${chalk_1.default.green("That's it - everything is set up!")} ${chalk_1.default.cyan(`Test and validate your setup locally with the following Steps: 1. Build your application in ${chalk_1.default.bold('production mode')}. ${chalk_1.default.gray(`${arrow} For example, run ${chalk_1.default.bold(buildCommand)}.`)} ${chalk_1.default.gray(`${arrow} You should see source map upload logs in your console.`)} 2. Run your application and throw a test error. ${chalk_1.default.gray(`${arrow} The error should appear in Sentry:`)} ${chalk_1.default.gray(`${arrow} ${issueStreamUrl}`)} 3. Open the error in Sentry and verify that it's source-mapped. ${chalk_1.default.gray(`${arrow} The stack trace should show your original source code.`)} `)} ${chalk_1.default.dim(`If you encounter any issues, please refer to the Troubleshooting Guide: https://docs.sentry.io/platforms/javascript/sourcemaps/troubleshooting_js If the guide doesn't help or you encounter a bug, please let us know: https://github.com/getsentry/sentry-javascript/issues`)} `); } //# sourceMappingURL=sourcemaps-wizard.js.map