@sentry/webpack-plugin
Advanced tools
Comparing version 1.5.2 to 1.6.0
@@ -11,3 +11,3 @@ { | ||
"author": "Sentry", | ||
"version": "1.5.2", | ||
"version": "1.6.0", | ||
"license": "MIT", | ||
@@ -21,3 +21,3 @@ "repository": "git@github.com:getsentry/sentry-webpack-plugin.git", | ||
"dependencies": { | ||
"@sentry/cli": "^1.30.2" | ||
"@sentry/cli": "^1.35.5" | ||
}, | ||
@@ -24,0 +24,0 @@ "devDependencies": { |
@@ -65,3 +65,5 @@ <p align="center"> | ||
`sentry-cli releases propose-version` command which should always return the | ||
correct version | ||
correct version (**requires access to `git` CLI and root directory to be a valid | ||
repository**). Can use `[hash]` as a part of a string, which will be replaced | ||
with Webpack's compilation hash. | ||
* `include [required]` - `string` or `array`, one or more paths that Sentry CLI | ||
@@ -83,9 +85,11 @@ should scan recursively for sources. It will upload all `.map` files and match | ||
defaults from `~/.sentryclirc` are always loaded | ||
* `ext [optional]` - `string`, adds an additional file extension to be | ||
* `ext [optional]` - `array`, this sets the file extensions to be | ||
considered. By default the following file extensions are processed: js, map, | ||
jsbundle and bundle. | ||
* `urlPrefix [optional]` - `string`, this sets an URL prefix in front of all | ||
files. This defaults to `~/` but you might want to set this to the full URL. | ||
This is also useful if your files are stored in a sub folder. eg: | ||
* `urlPrefix [optional]` - `string`, this sets an URL prefix at the beginning | ||
of all files. This defaults to `~/` but you might want to set this to the | ||
full URL. This is also useful if your files are stored in a sub folder. eg: | ||
`url-prefix '~/static/js'` | ||
* `urlSuffix [optional]` - `string`, this sets an URL suffix at the end of all | ||
files. Useful for appending query parameters. | ||
* `validate [optional]` - `boolean`, this attempts sourcemap validation before | ||
@@ -107,4 +111,5 @@ upload when rewriting is not enabled. It will spot a variety of issues with | ||
environments) | ||
* `debug [optional]` - `boolean`, print some useful debug information | ||
You can find more information about these options in our official docs: | ||
https://docs.sentry.io/learn/cli/releases/#upload-source-maps |
@@ -53,2 +53,12 @@ /*eslint-disable*/ | ||
test('allows to provide debug mode', () => { | ||
let sentryCliPlugin = new SentryCliPlugin(); | ||
expect(sentryCliPlugin.debug).toEqual(false); | ||
sentryCliPlugin = new SentryCliPlugin({ | ||
debug: true, | ||
}); | ||
expect(sentryCliPlugin.debug).toEqual(true); | ||
}); | ||
test('sanitizes array options `include` and `ignore`', () => { | ||
@@ -82,10 +92,2 @@ const sentryCliPlugin = new SentryCliPlugin({ | ||
describe('CLI configuration', () => { | ||
test('does not create a SentryCLI instance in `dryRun` mode', () => { | ||
const sentryCliPlugin = new SentryCliPlugin({ | ||
dryRun: true, | ||
}); | ||
expect(SentryCliMock).not.toHaveBeenCalled(); | ||
}); | ||
test('passes the configuration file to CLI', () => { | ||
@@ -92,0 +94,0 @@ const sentryCliPlugin = new SentryCliPlugin({ |
149
src/index.js
const SentryCli = require('@sentry/cli'); | ||
const path = require('path'); | ||
const util = require('util'); | ||
@@ -21,2 +22,24 @@ const SENTRY_LOADER = path.resolve(__dirname, 'sentry.loader.js'); | ||
/** Deep copy of a given input */ | ||
function sillyClone(input) { | ||
try { | ||
return JSON.parse(JSON.stringify(input)); | ||
} catch (oO) { | ||
return undefined; | ||
} | ||
} | ||
/** Diffs two arrays */ | ||
function diffArray(prev, next) { | ||
// eslint-disable-next-line no-param-reassign | ||
prev = Array.isArray(prev) ? prev : [prev]; | ||
// eslint-disable-next-line no-param-reassign | ||
next = Array.isArray(next) ? next : [next]; | ||
return { | ||
removed: prev.filter(x => !next.includes(x)), | ||
added: next.filter(x => !prev.includes(x)), | ||
}; | ||
} | ||
/** | ||
@@ -46,9 +69,35 @@ * Ensures that the passed value is in an array or an array itself. | ||
/** | ||
* Pretty-prints debug information | ||
* | ||
* @param {string} label Label to be printed as a prefix for the data | ||
* @param {any} data Input to be pretty-printed | ||
*/ | ||
function outputDebug(label, data) { | ||
if (data !== undefined) { | ||
// eslint-disable-next-line no-console | ||
console.log( | ||
`[Sentry Webpack Plugin] ${label} ${util.inspect( | ||
data, | ||
false, | ||
null, | ||
true | ||
)}` | ||
); | ||
} else { | ||
// eslint-disable-next-line no-console | ||
console.log(`[Sentry Webpack Plugin] ${label}`); | ||
} | ||
} | ||
class SentryCliPlugin { | ||
constructor(options = {}) { | ||
this.debug = options.debug || false; | ||
// By default we want that rewrite is true | ||
this.options = Object.assign({ rewrite: true }, options); | ||
this.options.include = toArray(options.include); | ||
this.options.ignore = toArray(options.ignore); | ||
if (options.include) this.options.include = toArray(options.include); | ||
if (options.ignore) this.options.ignore = toArray(options.ignore); | ||
this.cli = this.getSentryCli(); | ||
@@ -65,9 +114,26 @@ this.release = this.getReleasePromise(); | ||
getSentryCli() { | ||
const cli = new SentryCli(this.options.configFile); | ||
if (this.isDryRun()) { | ||
outputDebug('DRY Run Mode'); | ||
return { | ||
releases: { | ||
proposeVersion: () => Promise.resolve('1.0.0-dev'), | ||
new: () => Promise.resolve(), | ||
uploadSourceMaps: () => Promise.resolve(), | ||
finalize: () => Promise.resolve(), | ||
proposeVersion: () => | ||
cli.releases.proposeVersion().then(version => { | ||
outputDebug('Proposed version:\n', version); | ||
return version; | ||
}), | ||
new: release => { | ||
outputDebug('Creating new release:\n', release); | ||
return Promise.resolve(release); | ||
}, | ||
uploadSourceMaps: (release, config) => { | ||
outputDebug('Calling upload-sourcemaps with:\n', config); | ||
return Promise.resolve(release, config); | ||
}, | ||
finalize: release => { | ||
outputDebug('Finalizing release:\n', release); | ||
return Promise.resolve(release); | ||
}, | ||
}, | ||
@@ -77,3 +143,3 @@ }; | ||
return new SentryCli(this.options.configFile); | ||
return cli; | ||
} | ||
@@ -152,6 +218,8 @@ | ||
loader: SENTRY_LOADER, | ||
options: { releasePromise: this.release }, | ||
options: { | ||
releasePromise: this.release, | ||
}, | ||
}; | ||
return loaders.concat([loader]); | ||
return (loaders || []).concat([loader]); | ||
} | ||
@@ -166,3 +234,5 @@ | ||
loader: SENTRY_LOADER, | ||
options: { releasePromise: this.release }, | ||
options: { | ||
releasePromise: this.release, | ||
}, | ||
}, | ||
@@ -172,3 +242,3 @@ ], | ||
return rules.concat([rule]); | ||
return (rules || []).concat([rule]); | ||
} | ||
@@ -179,18 +249,41 @@ | ||
const options = compilerOptions; | ||
if (typeof options === 'undefined') { | ||
// Gatekeeper because we are not running in webpack env, probably just tests | ||
return; | ||
} | ||
options.entry = this.injectEntry(options.entry, SENTRY_MODULE); | ||
const mod = ensure(options, 'module', Object); | ||
if (mod.loaders) { | ||
// Handle old `module.loaders` syntax | ||
mod.loaders = this.injectLoader(mod.loaders); | ||
if (options.module.loaders) { | ||
// Handle old `options.module.loaders` syntax | ||
options.module.loaders = this.injectLoader(options.module.loaders); | ||
} else { | ||
mod.rules = this.injectRule(mod.rules || []); | ||
options.module.rules = this.injectRule(options.module.rules); | ||
} | ||
} | ||
/** injectRelease with printable debug info */ | ||
injectReleaseWithDebug(compilerOptions) { | ||
const input = { | ||
loaders: sillyClone( | ||
compilerOptions.module.loaders || compilerOptions.module.rules | ||
).map(x => x.loader || x.use[0].loader), | ||
entry: sillyClone(compilerOptions.entry), | ||
}; | ||
this.injectRelease(compilerOptions); | ||
const output = { | ||
loaders: sillyClone( | ||
compilerOptions.module.loaders || compilerOptions.module.rules | ||
).map(x => x.loader || x.use[0].loader), | ||
entry: sillyClone(compilerOptions.entry), | ||
}; | ||
const loaders = diffArray(input.loaders, output.loaders); | ||
const entry = diffArray(input.entry, output.entry); | ||
outputDebug('DEBUG: Injecting release code'); | ||
outputDebug('DEBUG: Loaders:\n', output.loaders); | ||
outputDebug('DEBUG: Added loaders:\n', loaders.added); | ||
outputDebug('DEBUG: Removed loaders:\n', loaders.removed); | ||
outputDebug('DEBUG: Entry:\n', output.entry); | ||
outputDebug('DEBUG: Added entry:\n', entry.added); | ||
outputDebug('DEBUG: Removed entry:\n', entry.removed); | ||
} | ||
/** Creates and finalizes a release on Sentry. */ | ||
@@ -208,3 +301,3 @@ finalizeRelease(compilation) { | ||
.then(proposedVersion => { | ||
release = proposedVersion; | ||
release = proposedVersion.replace('[hash]', compilation.hash); | ||
return this.cli.releases.new(release); | ||
@@ -219,3 +312,11 @@ }) | ||
apply(compiler) { | ||
this.injectRelease(compiler.options); | ||
const compilerOptions = compiler.options || {}; | ||
ensure(compilerOptions, 'module', Object); | ||
if (this.debug) { | ||
this.injectReleaseWithDebug(compilerOptions); | ||
} else { | ||
this.injectRelease(compilerOptions); | ||
} | ||
attachAfterEmitHook(compiler, (compilation, cb) => { | ||
@@ -222,0 +323,0 @@ this.finalizeRelease(compilation).then(() => cb()); |
@@ -5,6 +5,5 @@ module.exports = function sentryLoader(content, map, meta) { | ||
releasePromise.then(version => { | ||
const newVersion = version; | ||
const sentryRelease = `global.SENTRY_RELEASE={};\nglobal.SENTRY_RELEASE.id="${newVersion}";`; | ||
const sentryRelease = `(window||global||self).SENTRY_RELEASE={id:"${version}"};`; | ||
callback(null, sentryRelease, map, meta); | ||
}); | ||
}; |
Sorry, the diff of this file is not supported yet
145116
668
113
Updated@sentry/cli@^1.35.5