Skip to content

Commit

Permalink
fix(astro): Adjust Vite plugin config to upload server source maps (#…
Browse files Browse the repository at this point in the history
…9541)

For some reason our automatic assets detection in the Vite plugin
doesn't work well in Astro builds. While client files were picked up and
uploaded correctly, server-side source and map files were not uploaded.

This fix ensures we search for files to be uploaded in the entire output
directory by building an `assets` glob from the output directory stored
in the `config` object. Once again Astro's integrations API comes in
super handy here as this already gives us a custom output directory if
users overwrote the default (`/dist`) one.
  • Loading branch information
Lms24 authored Nov 13, 2023
1 parent 569e5b5 commit d80e27b
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 15 deletions.
23 changes: 21 additions & 2 deletions packages/astro/src/integration/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable no-console */
import { sentryVitePlugin } from '@sentry/vite-plugin';
import type { AstroIntegration } from 'astro';
import type { AstroConfig, AstroIntegration } from 'astro';
import * as fs from 'fs';
import * as path from 'path';

Expand All @@ -13,7 +13,8 @@ export const sentryAstro = (options: SentryOptions = {}): AstroIntegration => {
return {
name: PKG_NAME,
hooks: {
'astro:config:setup': async ({ updateConfig, injectScript }) => {
// eslint-disable-next-line complexity
'astro:config:setup': async ({ updateConfig, injectScript, config }) => {
// The third param here enables loading of all env vars, regardless of prefix
// see: https://main.vitejs.dev/config/#using-environment-variables-in-config

Expand All @@ -40,6 +41,10 @@ export const sentryAstro = (options: SentryOptions = {}): AstroIntegration => {
project: uploadOptions.project ?? env.SENTRY_PROJECT,
authToken: uploadOptions.authToken ?? env.SENTRY_AUTH_TOKEN,
telemetry: uploadOptions.telemetry ?? true,
sourcemaps: {
assets: [getSourcemapsAssetsGlob(config)],
},
debug: options.debug ?? false,
}),
],
},
Expand Down Expand Up @@ -79,3 +84,17 @@ function findDefaultSdkInitFile(type: 'server' | 'client'): string | undefined {
.map(ext => path.resolve(path.join(process.cwd(), `sentry.${type}.config.${ext}`)))
.find(filename => fs.existsSync(filename));
}

function getSourcemapsAssetsGlob(config: AstroConfig): string {
// paths are stored as "file://" URLs
const outDirPathname = config.outDir && path.resolve(config.outDir.pathname);
const rootDirName = path.resolve((config.root && config.root.pathname) || process.cwd());

if (outDirPathname) {
const relativePath = path.relative(rootDirName, outDirPathname);
return `${relativePath}/**/*`;
}

// fallback to default output dir
return 'dist/**/*';
}
48 changes: 35 additions & 13 deletions packages/astro/test/integration/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ process.env = {
SENTRY_AUTH_TOKEN: 'my-token',
};

const updateConfig = vi.fn();
const injectScript = vi.fn();
const config = {
root: new URL('file://path/to/project'),
outDir: new URL('file://path/to/project/out'),
};

describe('sentryAstro integration', () => {
afterEach(() => {
vi.clearAllMocks();
Expand All @@ -28,12 +35,10 @@ describe('sentryAstro integration', () => {
const integration = sentryAstro({
sourceMapsUploadOptions: { enabled: true, org: 'my-org', project: 'my-project', telemetry: false },
});
const updateConfig = vi.fn();
const injectScript = vi.fn();

expect(integration.hooks['astro:config:setup']).toBeDefined();
// @ts-expect-error - the hook exists and we only need to pass what we actually use
await integration.hooks['astro:config:setup']({ updateConfig, injectScript });
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config });

expect(updateConfig).toHaveBeenCalledTimes(1);
expect(updateConfig).toHaveBeenCalledWith({
Expand All @@ -51,32 +56,52 @@ describe('sentryAstro integration', () => {
org: 'my-org',
project: 'my-project',
telemetry: false,
debug: false,
sourcemaps: {
assets: ['out/**/*'],
},
});
});

it('falls back to default output dir, if out and root dir are not available', async () => {
const integration = sentryAstro({
sourceMapsUploadOptions: { enabled: true, org: 'my-org', project: 'my-project', telemetry: false },
});
// @ts-expect-error - the hook exists and we only need to pass what we actually use
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config: {} });

expect(sentryVitePluginSpy).toHaveBeenCalledTimes(1);
expect(sentryVitePluginSpy).toHaveBeenCalledWith({
authToken: 'my-token',
org: 'my-org',
project: 'my-project',
telemetry: false,
debug: false,
sourcemaps: {
assets: ['dist/**/*'],
},
});
});

it("doesn't enable source maps if `sourceMapsUploadOptions.enabled` is `false`", async () => {
const integration = sentryAstro({
sourceMapsUploadOptions: { enabled: false },
});
const updateConfig = vi.fn();
const injectScript = vi.fn();

expect(integration.hooks['astro:config:setup']).toBeDefined();
// @ts-expect-error - the hook exists and we only need to pass what we actually use
await integration.hooks['astro:config:setup']({ updateConfig, injectScript });
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config });

expect(updateConfig).toHaveBeenCalledTimes(0);
expect(sentryVitePluginSpy).toHaveBeenCalledTimes(0);
});

it('injects client and server init scripts', async () => {
const integration = sentryAstro({});
const updateConfig = vi.fn();
const injectScript = vi.fn();

expect(integration.hooks['astro:config:setup']).toBeDefined();
// @ts-expect-error - the hook exists and we only need to pass what we actually use
await integration.hooks['astro:config:setup']({ updateConfig, injectScript });
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config });

expect(injectScript).toHaveBeenCalledTimes(2);
expect(injectScript).toHaveBeenCalledWith('page', expect.stringContaining('Sentry.init'));
Expand All @@ -89,12 +114,9 @@ describe('sentryAstro integration', () => {
serverInitPath: 'my-server-init-path.js',
});

const updateConfig = vi.fn();
const injectScript = vi.fn();

expect(integration.hooks['astro:config:setup']).toBeDefined();
// @ts-expect-error - the hook exists and we only need to pass what we actually use
await integration.hooks['astro:config:setup']({ updateConfig, injectScript });
await integration.hooks['astro:config:setup']({ updateConfig, injectScript, config });

expect(injectScript).toHaveBeenCalledTimes(2);
expect(injectScript).toHaveBeenCalledWith('page', expect.stringContaining('my-client-init-path.js'));
Expand Down

0 comments on commit d80e27b

Please sign in to comment.