Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 39 additions & 39 deletions packages/bundler-plugin-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
} from "./sentry/telemetry";
import { Span, Transaction } from "@sentry/types";
import { createLogger, Logger } from "./sentry/logger";
import { InternalOptions, normalizeUserOptions, validateOptions } from "./options-mapping";
import { NormalizedOptions, normalizeUserOptions, validateOptions } from "./options-mapping";
import { getSentryCli } from "./sentry/cli";
import { makeMain } from "@sentry/node";
import os from "os";
Expand Down Expand Up @@ -70,18 +70,18 @@ const esbuildDebugIdInjectionFilePath = require.resolve(
*
* This release creation pipeline relies on Sentry CLI to execute the different steps.
*/
const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) => {
const internalOptions = normalizeUserOptions(options);
const unplugin = createUnplugin<Options, true>((userOptions, unpluginMetaContext) => {
const options = normalizeUserOptions(userOptions);

const allowedToSendTelemetryPromise = shouldSendTelemetry(internalOptions);
const allowedToSendTelemetryPromise = shouldSendTelemetry(options);

const { sentryHub, sentryClient } = makeSentryClient(
"https://[email protected]/6690737",
allowedToSendTelemetryPromise,
internalOptions.project
options.project
);

addPluginOptionInformationToHub(internalOptions, sentryHub, unpluginMetaContext.framework);
addPluginOptionInformationToHub(options, sentryHub, unpluginMetaContext.framework);

//TODO: This call is problematic because as soon as we set our hub as the current hub
// we might interfere with other plugins that use Sentry. However, for now, we'll
Expand All @@ -92,23 +92,23 @@ const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) =>

const logger = createLogger({
prefix: `[sentry-${unpluginMetaContext.framework}-plugin]`,
silent: internalOptions.silent,
debug: internalOptions.debug,
silent: options.silent,
debug: options.debug,
});

if (!validateOptions(internalOptions, logger)) {
if (!validateOptions(options, logger)) {
handleError(
new Error("Options were not set correctly. See output above for more details."),
logger,
internalOptions.errorHandler
options.errorHandler
);
}

const cli = getSentryCli(internalOptions, logger);
const cli = getSentryCli(options, logger);

const releaseNamePromise = new Promise<string>((resolve) => {
if (options.release) {
resolve(options.release);
if (userOptions.release) {
resolve(userOptions.release);
} else {
resolve(cli.releases.proposeVersion());
}
Expand Down Expand Up @@ -156,7 +156,7 @@ const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) =>
"Unable to determine a release name. Make sure to set the `release` option or use an environment that supports auto-detection https://docs.sentry.io/cli/releases/#creating-releases`"
),
logger,
internalOptions.errorHandler
options.errorHandler
);
}

Expand Down Expand Up @@ -211,13 +211,13 @@ const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) =>
// a windows style path to `releaseInjectionTargets`
const normalizedId = path.normalize(id);

if (internalOptions.releaseInjectionTargets) {
if (options.releaseInjectionTargets) {
// If there's an `releaseInjectionTargets` option transform (ie. inject the release varible) when the file path matches the option.
if (typeof internalOptions.releaseInjectionTargets === "function") {
return internalOptions.releaseInjectionTargets(normalizedId);
if (typeof options.releaseInjectionTargets === "function") {
return options.releaseInjectionTargets(normalizedId);
}

return internalOptions.releaseInjectionTargets.some((entry) => {
return options.releaseInjectionTargets.some((entry) => {
if (entry instanceof RegExp) {
return entry.test(normalizedId);
} else {
Expand Down Expand Up @@ -247,7 +247,7 @@ const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) =>
async transform(code, id) {
logger.debug('Called "transform":', { id });

if (!internalOptions.injectRelease) {
if (!options.injectRelease) {
return;
}

Expand All @@ -259,10 +259,10 @@ const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) =>
ms.append(
generateGlobalInjectorCode({
release: await releaseNamePromise,
injectReleasesMap: internalOptions.injectReleasesMap,
injectBuildInformation: internalOptions._experiments.injectBuildInformation || false,
org: internalOptions.org,
project: internalOptions.project,
injectReleasesMap: options.injectReleasesMap,
injectBuildInformation: options._experiments.injectBuildInformation || false,
org: options.org,
project: options.project,
})
);
} else {
Expand Down Expand Up @@ -314,12 +314,12 @@ const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) =>

try {
if (!unpluginMetaContext.watchMode) {
if (internalOptions._experiments.debugIdUpload) {
if (options.sourcemaps?.assets) {
const debugIdChunkFilePaths = (
await glob(internalOptions._experiments.debugIdUpload.include, {
await glob(options.sourcemaps.assets, {
absolute: true,
nodir: true,
ignore: internalOptions._experiments.debugIdUpload.ignore,
ignore: options.sourcemaps.ignore,
})
).filter((p) => p.endsWith(".js") || p.endsWith(".mjs") || p.endsWith(".cjs"));

Expand Down Expand Up @@ -363,15 +363,15 @@ const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) =>
);

tmpUploadFolder = await sourceFileUploadFolderPromise;
await uploadDebugIdSourcemaps(internalOptions, ctx, tmpUploadFolder, releaseName);
await uploadDebugIdSourcemaps(options, ctx, tmpUploadFolder, releaseName);
}

await createNewRelease(internalOptions, ctx, releaseName);
await cleanArtifacts(internalOptions, ctx, releaseName);
await uploadSourceMaps(internalOptions, ctx, releaseName);
await setCommits(internalOptions, ctx, releaseName);
await finalizeRelease(internalOptions, ctx, releaseName);
await addDeploy(internalOptions, ctx, releaseName);
await createNewRelease(options, ctx, releaseName);
await cleanArtifacts(options, ctx, releaseName);
await uploadSourceMaps(options, ctx, releaseName);
await setCommits(options, ctx, releaseName);
await finalizeRelease(options, ctx, releaseName);
await addDeploy(options, ctx, releaseName);
}
transaction?.setStatus("ok");
} catch (e: unknown) {
Expand All @@ -380,7 +380,7 @@ const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) =>
level: "error",
message: "Error during writeBundle",
});
handleError(e, logger, internalOptions.errorHandler);
handleError(e, logger, options.errorHandler);
} finally {
if (tmpUploadFolder) {
fs.rm(tmpUploadFolder, { recursive: true, force: true }, () => {
Expand All @@ -402,7 +402,7 @@ const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) =>
rollup: {
renderChunk(code, chunk) {
if (
options._experiments?.debugIdUpload &&
options.sourcemaps?.assets &&
[".js", ".mjs", ".cjs"].some((ending) => chunk.fileName.endsWith(ending)) // chunks could be any file (html, md, ...)
) {
return injectDebugIdSnippetIntoChunk(code);
Expand All @@ -414,7 +414,7 @@ const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) =>
vite: {
renderChunk(code, chunk) {
if (
options._experiments?.debugIdUpload &&
options.sourcemaps?.assets &&
[".js", ".mjs", ".cjs"].some((ending) => chunk.fileName.endsWith(ending)) // chunks could be any file (html, md, ...)
) {
return injectDebugIdSnippetIntoChunk(code);
Expand All @@ -424,7 +424,7 @@ const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) =>
},
},
webpack(compiler) {
if (options._experiments?.debugIdUpload) {
if (options.sourcemaps?.assets) {
// Cache inspired by https://github.com/webpack/webpack/pull/15454
const cache = new WeakMap<sources.Source, sources.Source>();

Expand Down Expand Up @@ -488,7 +488,7 @@ const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) =>
});

if (unpluginMetaContext.framework === "esbuild") {
if (internalOptions._experiments.debugIdUpload) {
if (options.sourcemaps?.assets) {
plugins.push({
name: "sentry-esbuild-debug-id-plugin",
esbuild: {
Expand All @@ -507,7 +507,7 @@ const unplugin = createUnplugin<Options, true>((options, unpluginMetaContext) =>
function handleError(
unknownError: unknown,
logger: Logger,
errorHandler: InternalOptions["errorHandler"]
errorHandler: NormalizedOptions["errorHandler"]
) {
if (unknownError instanceof Error) {
logger.error(unknownError.message);
Expand Down
12 changes: 9 additions & 3 deletions packages/bundler-plugin-core/src/options-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type OptionalInternalOptions = Partial<
| "deploy"
| "configFile"
| "headers"
| "sourcemaps"
>
>;

Expand All @@ -40,7 +41,7 @@ type NormalizedInternalOptions = {
include: InternalIncludeEntry[];
};

export type InternalOptions = RequiredInternalOptions &
export type NormalizedOptions = RequiredInternalOptions &
OptionalInternalOptions &
NormalizedInternalOptions;

Expand All @@ -62,7 +63,7 @@ export type InternalIncludeEntry = RequiredInternalIncludeEntry &

export const SENTRY_SAAS_URL = "https://sentry.io";

export function normalizeUserOptions(userOptions: UserOptions): InternalOptions {
export function normalizeUserOptions(userOptions: UserOptions) {
const options = {
// include is the only strictly required option
// (normalizeInclude needs all userOptions to access top-level include options)
Expand Down Expand Up @@ -94,6 +95,7 @@ export function normalizeUserOptions(userOptions: UserOptions): InternalOptions
injectReleasesMap: userOptions.injectReleasesMap ?? false,
injectRelease: userOptions.injectRelease ?? true,
uploadSourceMaps: userOptions.uploadSourceMaps ?? true,
sourcemaps: userOptions.sourcemaps,
_experiments: userOptions._experiments ?? {},

// These options and can also be set via env variables or the config file.
Expand Down Expand Up @@ -149,6 +151,10 @@ function normalizeReleaseInjectionTargets(
* @return an array of `InternalIncludeEntry` objects.
*/
function normalizeInclude(userOptions: UserOptions): InternalIncludeEntry[] {
if (!userOptions.include) {
return [];
}

return arrayify(userOptions.include)
.map((includeItem) =>
typeof includeItem === "string" ? { paths: [includeItem] } : includeItem
Expand Down Expand Up @@ -198,7 +204,7 @@ function normalizeIncludeEntry(
*
* @returns `true` if the options are valid, `false` otherwise
*/
export function validateOptions(options: InternalOptions, logger: Logger): boolean {
export function validateOptions(options: NormalizedOptions, logger: Logger): boolean {
if (options.injectReleasesMap && !options.org) {
logger.error(
"The `injectReleasesMap` option was set but it is only supported when the `org` option is also specified.",
Expand Down
4 changes: 2 additions & 2 deletions packages/bundler-plugin-core/src/sentry/cli.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import SentryCli, { SentryCliReleases } from "@sentry/cli";
import { InternalOptions } from "../options-mapping";
import { NormalizedOptions } from "../options-mapping";
import { Logger } from "./logger";

type SentryDryRunCLI = {
Expand All @@ -14,7 +14,7 @@ export type SentryCLILike = SentryCli | SentryDryRunCLI;
* In case, users selected the `dryRun` options, this returns a stub
* that makes no-ops out of most CLI operations
*/
export function getSentryCli(internalOptions: InternalOptions, logger: Logger): SentryCLILike {
export function getSentryCli(internalOptions: NormalizedOptions, logger: Logger): SentryCLILike {
const { silent, org, project, authToken, url, vcsRemote, headers } = internalOptions;
const cli = new SentryCli(internalOptions.configFile, {
url,
Expand Down
16 changes: 8 additions & 8 deletions packages/bundler-plugin-core/src/sentry/releasePipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
// - unnecessary functionality

import { logger } from "@sentry/utils";
import { InternalOptions } from "../options-mapping";
import { NormalizedOptions } from "../options-mapping";
import { BuildContext } from "../types";
import { addSpanToTransaction } from "./telemetry";

export async function createNewRelease(
options: InternalOptions,
options: NormalizedOptions,
ctx: BuildContext,
releaseName: string
): Promise<void> {
Expand All @@ -32,7 +32,7 @@ export async function createNewRelease(
}

export async function cleanArtifacts(
options: InternalOptions,
options: NormalizedOptions,
ctx: BuildContext,
releaseName: string
): Promise<void> {
Expand All @@ -57,7 +57,7 @@ export async function cleanArtifacts(
}

export async function uploadSourceMaps(
options: InternalOptions,
options: NormalizedOptions,
ctx: BuildContext,
releaseName: string
): Promise<void> {
Expand Down Expand Up @@ -88,7 +88,7 @@ export async function uploadSourceMaps(
}

export async function uploadDebugIdSourcemaps(
options: InternalOptions,
options: NormalizedOptions,
ctx: BuildContext,
folderPathToUpload: string,
releaseName: string
Expand Down Expand Up @@ -121,7 +121,7 @@ export async function uploadDebugIdSourcemaps(
}

export async function setCommits(
options: InternalOptions,
options: NormalizedOptions,
ctx: BuildContext,
releaseName: string
): Promise<void> {
Expand Down Expand Up @@ -154,7 +154,7 @@ export async function setCommits(
}

export async function finalizeRelease(
options: InternalOptions,
options: NormalizedOptions,
ctx: BuildContext,
releaseName: string
): Promise<void> {
Expand All @@ -180,7 +180,7 @@ export async function finalizeRelease(
}

export async function addDeploy(
options: InternalOptions,
options: NormalizedOptions,
ctx: BuildContext,
releaseName: string
): Promise<void> {
Expand Down
10 changes: 5 additions & 5 deletions packages/bundler-plugin-core/src/sentry/telemetry.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import SentryCli from "@sentry/cli";
import { defaultStackParser, Hub, makeNodeTransport, NodeClient, Span } from "@sentry/node";
import { InternalOptions, SENTRY_SAAS_URL } from "../options-mapping";
import { NormalizedOptions, SENTRY_SAAS_URL } from "../options-mapping";
import { BuildContext } from "../types";

const SENTRY_SAAS_HOSTNAME = "sentry.io";
Expand Down Expand Up @@ -81,7 +81,7 @@ export function addSpanToTransaction(
}

export function addPluginOptionInformationToHub(
options: InternalOptions,
options: NormalizedOptions,
hub: Hub,
bundler: "rollup" | "webpack" | "vite" | "esbuild"
) {
Expand All @@ -96,7 +96,7 @@ export function addPluginOptionInformationToHub(
errorHandler,
deploy,
include,
_experiments,
sourcemaps,
} = options;

hub.setTag("include", include.length > 1 ? "multiple-entries" : "single-entry");
Expand Down Expand Up @@ -125,7 +125,7 @@ export function addPluginOptionInformationToHub(
if (errorHandler) {
hub.setTag("error-handler", "custom");
}
if (_experiments.debugIdUpload) {
if (sourcemaps?.assets) {
hub.setTag("debug-id-upload", true);
}

Expand All @@ -140,7 +140,7 @@ export function addPluginOptionInformationToHub(
hub.setUser({ id: org });
}

export async function shouldSendTelemetry(options: InternalOptions): Promise<boolean> {
export async function shouldSendTelemetry(options: NormalizedOptions): Promise<boolean> {
const { silent, org, project, authToken, url, vcsRemote, headers, telemetry, dryRun } = options;

// `options.telemetry` defaults to true
Expand Down
Loading