Skip to content

Commit

Permalink
feat: adds configurable dev environments for source map upload plugins (
Browse files Browse the repository at this point in the history
  • Loading branch information
subzero10 authored Oct 22, 2024
1 parent fb25688 commit cae080b
Show file tree
Hide file tree
Showing 14 changed files with 81 additions and 34 deletions.
3 changes: 3 additions & 0 deletions packages/esbuild-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ These plugin parameters correspond to the Honeybadger [Source Map Upload API](ht
<dd>The name of the user that triggered this deploy, for example, "Jane"</dd>
</dl>
</dd>

<dt><code>developmentEnvironments</code> (optional &mdash; default: ["dev", "development", "test"])</dt>
<dd>Used to decide whether source maps should be uploaded or not.</dd>
</dl>

### esbuild.config.js
Expand Down
10 changes: 7 additions & 3 deletions packages/esbuild-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class HoneybadgerSourceMapPlugin {
return {
name: PLUGIN_NAME,
setup(build: PluginBuild) {
if (self.isNonProdEnv()) {
if (self.isDevEnv(self.options.developmentEnvironments)) {
return
}

Expand Down Expand Up @@ -95,8 +95,12 @@ class HoneybadgerSourceMapPlugin {
return assets
}

private isNonProdEnv(): boolean {
return !!process.env.NODE_ENV && process.env.NODE_ENV !== 'production'
private isDevEnv(devEnvironments: string[]): boolean {
if (!process.env.NODE_ENV || process.env.NODE_ENV === '') {
return false
}

return devEnvironments.includes(process.env.NODE_ENV)
}

private handleError(error: Error): Message {
Expand Down
7 changes: 7 additions & 0 deletions packages/plugin-core/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const DEFAULT_DEPLOY = false
export const DEFAULT_DEPLOY_ENDPOINT = 'https://api.honeybadger.io/v1/deploys'
export const DEFAULT_IGNORE_PATHS = []
export const DEFAULT_IGNORE_ERRORS = false
export const DEFAULT_DEVELOPMENT_ENVIRONMENTS = ['dev', 'development', 'test'];

const required = [
'apiKey',
Expand All @@ -27,6 +28,7 @@ const defaultOptions = {
ignorePaths: DEFAULT_IGNORE_PATHS,
ignoreErrors: DEFAULT_IGNORE_ERRORS,
workerCount: DEFAULT_WORKER_COUNT,
developmentEnvironments: DEFAULT_DEVELOPMENT_ENVIRONMENTS
}

export function cleanOptions(
Expand All @@ -44,6 +46,11 @@ export function cleanOptions(
throw new Error('ignorePaths must be an array')
}

// Validate developmentEnvironments
if (options.developmentEnvironments && !Array.isArray(options.developmentEnvironments)) {
throw new Error('developmentEnvironments must be an array')
}

// Don't allow excessive retries
if (options.retries && options.retries > MAX_RETRIES) {
if (!options.silent) {
Expand Down
1 change: 1 addition & 0 deletions packages/plugin-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type HbPluginOptions = {
ignorePaths: Array<string>;
ignoreErrors: boolean;
workerCount: number;
developmentEnvironments: Array<string>;
}

// Options passed in by a user
Expand Down
4 changes: 3 additions & 1 deletion packages/plugin-core/test/options.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
DEFAULT_IGNORE_ERRORS,
DEFAULT_WORKER_COUNT,
MIN_WORKER_COUNT,
DEFAULT_DEVELOPMENT_ENVIRONMENTS,
} from '../src/options';

describe('Options', () => {
Expand Down Expand Up @@ -41,7 +42,7 @@ describe('Options', () => {
workerCount: 0
})
expect(result.workerCount).to.equal(MIN_WORKER_COUNT)
})
})

it('should merge in default options', () => {
const result = cleanOptions({
Expand All @@ -62,6 +63,7 @@ describe('Options', () => {
ignorePaths: [],
ignoreErrors: DEFAULT_IGNORE_ERRORS,
workerCount: DEFAULT_WORKER_COUNT,
developmentEnvironments: DEFAULT_DEVELOPMENT_ENVIRONMENTS,
})
})
});
Expand Down
3 changes: 3 additions & 0 deletions packages/rollup-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ These plugin parameters correspond to the Honeybadger [Source Map Upload API](ht
<dd>The name of the user that triggered this deploy, for example, "Jane"</dd>
</dl>
</dd>

<dt><code>developmentEnvironments</code> (optional &mdash; default: ["dev", "development", "test"])</dt>
<dd>Used to decide whether source maps should be uploaded or not.</dd>
</dl>

### rollup.config.js
Expand Down
4 changes: 2 additions & 2 deletions packages/rollup-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { extractSourcemapDataFromBundle, isNonProdEnv } from './rollupUtils'
import { extractSourcemapDataFromBundle, isDevEnv } from './rollupUtils'
import { sendDeployNotification, uploadSourcemaps, cleanOptions, Types } from '@honeybadger-io/plugin-core'
import type { OutputBundle, Plugin, NormalizedOutputOptions } from 'rollup'

Expand All @@ -13,7 +13,7 @@ export default function honeybadgerRollupPlugin(
outputOptions: NormalizedOutputOptions,
bundle: OutputBundle
) => {
if (isNonProdEnv()) {
if (isDevEnv(hbOptions.developmentEnvironments)) {
if (!hbOptions.silent) {
console.info('Honeybadger will not upload sourcemaps in non-production environment.')
}
Expand Down
8 changes: 6 additions & 2 deletions packages/rollup-plugin/src/rollupUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ function formatSourcemapData(
* In Rollup without Vite, it may or may not be available,
* so if it's missing we'll assume prod
*/
export function isNonProdEnv(): boolean {
return !!process.env.NODE_ENV && process.env.NODE_ENV !== 'production'
export function isDevEnv(devEnvironments: string[]): boolean {
if (!process.env.NODE_ENV || process.env.NODE_ENV === '') {
return false
}

return devEnvironments.includes(process.env.NODE_ENV)
}
16 changes: 10 additions & 6 deletions packages/rollup-plugin/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import * as td from 'testdouble'
describe('Index', () => {
let honeybadgerRollupPlugin
let core, rollupUtils
const options = { apiKey: 'test_key', assetsUrl: 'https://foo.bar' }
const options = {
apiKey: 'test_key',
assetsUrl: 'https://foo.bar',
developmentEnvironments: ['dev', 'development', 'test']
}

beforeEach(async () => {
core = td.replace('@honeybadger-io/plugin-core')
Expand Down Expand Up @@ -35,7 +39,7 @@ describe('Index', () => {
const sourcemapData = [{ sourcemapFilename: 'index.map.js' }]

it('should upload sourcemaps', async () => {
td.when(rollupUtils.isNonProdEnv()).thenReturn(false)
td.when(rollupUtils.isDevEnv(options.developmentEnvironments)).thenReturn(false)
td.when(rollupUtils.extractSourcemapDataFromBundle(outputOptions, bundle, undefined)).thenReturn(sourcemapData)
td.when(core.cleanOptions(options)).thenReturn(options)

Expand All @@ -48,7 +52,7 @@ describe('Index', () => {

it('should send deploy notification if deploy is true', async () => {
const deployTrueOpt = { ...options, deploy: true }
td.when(rollupUtils.isNonProdEnv()).thenReturn(false)
td.when(rollupUtils.isDevEnv(options.developmentEnvironments)).thenReturn(false)
td.when(rollupUtils.extractSourcemapDataFromBundle({ outputOptions, bundle })).thenReturn(sourcemapData)
td.when(core.cleanOptions(deployTrueOpt)).thenReturn(deployTrueOpt)

Expand All @@ -61,7 +65,7 @@ describe('Index', () => {

it('should send deploy notification if deploy is an object', async () => {
const deployObjOpt = { ...options, deploy: { localUsername: 'me' } }
td.when(rollupUtils.isNonProdEnv()).thenReturn(false)
td.when(rollupUtils.isDevEnv(options.developmentEnvironments)).thenReturn(false)
td.when(rollupUtils.extractSourcemapDataFromBundle({ outputOptions, bundle })).thenReturn(sourcemapData)
td.when(core.cleanOptions(deployObjOpt)).thenReturn(deployObjOpt)

Expand All @@ -74,7 +78,7 @@ describe('Index', () => {

it('should not send deploy notification if deploy is false', async () => {
const deployFalseOpt = { ...options, deploy: false }
td.when(rollupUtils.isNonProdEnv()).thenReturn(false)
td.when(rollupUtils.isDevEnv(options.developmentEnvironments)).thenReturn(false)
td.when(rollupUtils.extractSourcemapDataFromBundle({ outputOptions, bundle })).thenReturn(sourcemapData)
td.when(core.cleanOptions(deployFalseOpt)).thenReturn(deployFalseOpt)

Expand All @@ -87,7 +91,7 @@ describe('Index', () => {
})

it('should do nothing in non-prod environments', async () => {
td.when(rollupUtils.isNonProdEnv()).thenReturn(true)
td.when(rollupUtils.isDevEnv(options.developmentEnvironments)).thenReturn(true)
td.when(core.cleanOptions(options)).thenReturn(options)

const plugin = honeybadgerRollupPlugin(options)
Expand Down
16 changes: 11 additions & 5 deletions packages/rollup-plugin/test/rollupUtils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from 'chai'
import { extractSourcemapDataFromBundle, isNonProdEnv } from '../src/rollupUtils';
import { extractSourcemapDataFromBundle, isDevEnv } from '../src/rollupUtils';
import bundle from './fixtures/bundle'
import path from 'node:path'
import { NormalizedOutputOptions } from 'rollup';
Expand Down Expand Up @@ -91,7 +91,8 @@ describe('extractSourcemapDataFromBundle', () => {
})
})

describe('isNonProdEnv', () => {
describe('isDevEnv', () => {
const developmentEnvironments = ['dev', 'development', 'test']
let restore

beforeEach(() => {
Expand All @@ -104,16 +105,21 @@ describe('isNonProdEnv', () => {

it('returns true if NODE_ENV is non-prod', () => {
process.env.NODE_ENV = 'development'
expect(isNonProdEnv()).to.equal(true)
expect(isDevEnv(developmentEnvironments)).to.equal(true)
})

it('returns false if NODE_ENV is non-prod but not in developmentEnvironments array', () => {
process.env.NODE_ENV = 'staging'
expect(isDevEnv(developmentEnvironments)).to.equal(false)
})

it('returns false if NODE_ENV is missing', () => {
delete process.env.NODE_ENV
expect(isNonProdEnv()).to.equal(false)
expect(isDevEnv(developmentEnvironments)).to.equal(false)
})

it('returns false if NODE_ENV is prod', () => {
process.env.NODE_ENV = 'production'
expect(isNonProdEnv()).to.equal(false)
expect(isDevEnv(developmentEnvironments)).to.equal(false)
})
})
11 changes: 8 additions & 3 deletions packages/rollup-plugin/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@
"extends": "../../tsconfig.base.json",
"include": [
"src/**/*.ts"
],
],
"compilerOptions": {
"rootDir": "./",
"rootDir": "./",
"allowSyntheticDefaultImports": true
},
}
"references": [
{
"path": "../plugin-core"
}
]
}
3 changes: 3 additions & 0 deletions packages/webpack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ These plugin parameters correspond to the Honeybadger [Source Map Upload API](ht
<dd>The name of the user that triggered this deploy, for example, "Jane"</dd>
</dl>
</dd>

<dt><code>developmentEnvironments</code> (optional &mdash; default: ["dev", "development", "test"])</dt>
<dd>Source maps upload will be skipped when the environment matches any of the values in this array or the webpack dev server is running.</dd>
</dl>

### Vanilla webpack.config.js
Expand Down
10 changes: 7 additions & 3 deletions packages/webpack/src/HoneybadgerSourceMapPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class HoneybadgerSourceMapPlugin {
}

async afterEmit (compilation) {
if (this.isDevServerRunning()) {
if (this.isDevEnv(this.options.developmentEnvironments)) {
if (!this.options.silent) {
console.info('\nHoneybadgerSourceMapPlugin will not upload source maps because webpack-dev-server is running.')
}
Expand All @@ -41,8 +41,12 @@ class HoneybadgerSourceMapPlugin {
}
}

isDevServerRunning () {
return process.env.WEBPACK_DEV_SERVER === 'true'
isDevEnv (devEnvironments) {
if (process.env.WEBPACK_DEV_SERVER === 'true') {
return true
}

return !!(devEnvironments && devEnvironments.includes(process.env.NODE_ENV));
}

apply (compiler) {
Expand Down
19 changes: 10 additions & 9 deletions packages/webpack/test/HoneybadgerSourceMapPlugin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe('HoneybadgerSourceMapPlugin', function () {

const options = {
apiKey: 'abcd1234',
assetsUrl: 'https://cdn.example.com/assets',
assetsUrl: 'https://cdn.example.com/assets',
endpoint: `${TEST_ENDPOINT}${SOURCEMAP_PATH}`,
deployEndpoint: `${TEST_ENDPOINT}${DEPLOY_PATH}`,
}
Expand Down Expand Up @@ -62,6 +62,7 @@ describe('HoneybadgerSourceMapPlugin', function () {
revision: 'main',
silent: false,
workerCount: 5,
developmentEnvironments: ['dev', 'development', 'test']
})
})
})
Expand Down Expand Up @@ -91,13 +92,13 @@ describe('HoneybadgerSourceMapPlugin', function () {
id: 0,
names: ['app'],
files: ['app.5190.js', 'app.5190.js.map']
},
},
]
const assets = [{
const assets = [{
sourcemapFilePath: '/fake/output/path/app.5190.js.map',
sourcemapFilename: 'app.5190.js.map',
jsFilePath: '/fake/output/path/app.5190.js',
jsFilename: 'app.5190.js',
jsFilename: 'app.5190.js',
}]
const outputPath = '/fake/output/path'

Expand Down Expand Up @@ -141,7 +142,7 @@ describe('HoneybadgerSourceMapPlugin', function () {
}
sinon.stub(plugin, 'uploadSourceMaps')
sinon.stub(plugin, 'sendDeployNotification')

await plugin.afterEmit(compilation)
expect(plugin.sendDeployNotification.callCount).to.eq(1)
expect(plugin.sendDeployNotification.calledWith(plugin.options)).to.equal(true)
Expand Down Expand Up @@ -209,7 +210,7 @@ describe('HoneybadgerSourceMapPlugin', function () {
id: 0,
names: ['app'],
files: ['app.5190.js', 'app.5190.js.map']
},
},
{
id: 1,
names: ['foo'],
Expand All @@ -220,17 +221,17 @@ describe('HoneybadgerSourceMapPlugin', function () {
const compilation = {
getStats: () => ({
toJson: () => ({ chunks })
}),
}),
compiler: { outputPath },
getPath: () => outputPath,
}

const expectedAssets = [
{
{
sourcemapFilePath: '/fake/output/path/app.5190.js.map',
sourcemapFilename: 'app.5190.js.map',
jsFilePath: '/fake/output/path/app.5190.js',
jsFilename: 'app.5190.js',
jsFilename: 'app.5190.js',
}
]

Expand Down

0 comments on commit cae080b

Please sign in to comment.