diff --git a/packages/remix/package.json b/packages/remix/package.json index a92aa880c3fe..05b0854269a0 100644 --- a/packages/remix/package.json +++ b/packages/remix/package.json @@ -6,6 +6,9 @@ "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/remix", "author": "Sentry", "license": "MIT", + "bin": { + "upload-sourcemaps": "scripts/upload-sourcemaps.js" + }, "engines": { "node": ">=14" }, @@ -15,6 +18,7 @@ "types": "build/types/index.server.d.ts", "private": true, "dependencies": { + "@sentry/cli": "2.2.0", "@sentry/core": "7.3.1", "@sentry/hub": "7.3.1", "@sentry/integrations": "7.3.1", @@ -28,19 +32,12 @@ }, "devDependencies": { "@remix-run/node": "^1.4.3", - "@remix-run/react": "^1.4.3", - "@types/webpack": "^4.41.31" + "@remix-run/react": "^1.4.3" }, "peerDependencies": { "@remix-run/node": "^1.4.3", "@remix-run/react": "^1.4.3", - "react": "16.x || 17.x || 18.x", - "webpack": ">=4.0.0" - }, - "peerDependenciesMeta": { - "webpack": { - "optional": true - } + "react": "16.x || 17.x || 18.x" }, "scripts": { "build": "run-p build:rollup build:types", diff --git a/packages/remix/scripts/createRelease.js b/packages/remix/scripts/createRelease.js new file mode 100644 index 000000000000..4b71bb3bfd75 --- /dev/null +++ b/packages/remix/scripts/createRelease.js @@ -0,0 +1,21 @@ +const SentryCli = require('@sentry/cli'); +const sentry = new SentryCli(); + +async function createRelease(argv, DEFAULT_URL_PREFIX, DEFAULT_BUILD_PATH) { + const RELEASE = argv.release || (await sentry.releases.proposeVersion()); + const URL_PREFIX = argv.urlPrefix || DEFAULT_URL_PREFIX; + const BUILD_PATH = argv.buildPath || DEFAULT_BUILD_PATH; + + await sentry.releases.new(RELEASE); + + await sentry.releases.uploadSourceMaps(RELEASE, { + urlPrefix: URL_PREFIX, + include: [BUILD_PATH], + }); + + await sentry.releases.finalize(RELEASE); +} + +module.exports = { + createRelease, +}; diff --git a/packages/remix/scripts/upload-sourcemaps.js b/packages/remix/scripts/upload-sourcemaps.js new file mode 100755 index 000000000000..0d7a081ddc98 --- /dev/null +++ b/packages/remix/scripts/upload-sourcemaps.js @@ -0,0 +1,39 @@ +#!/usr/bin/env node +const yargs = require('yargs'); + +const { createRelease } = require('./createRelease'); + +const DEFAULT_URL_PREFIX = '~/build/'; +const DEFAULT_BUILD_PATH = 'public/build'; + +const argv = yargs(process.argv.slice(2)) + .option('release', { + type: 'string', + describe: + 'The release number\n' + + "If not provided, a new release id will be determined by Sentry CLI's `propose-version`.\n" + + 'See: https://docs.sentry.io/product/releases/suspect-commits/#using-the-cli\n', + }) + .option('urlPrefix', { + type: 'string', + describe: 'URL prefix to add to the beginning of all filenames', + default: DEFAULT_URL_PREFIX, + }) + .option('buildPath', { + type: 'string', + describe: 'The path to the build directory', + default: DEFAULT_BUILD_PATH, + }) + .usage( + 'Usage: $0\n' + + ' [--release RELEASE]\n' + + ' [--urlPrefix URL_PREFIX]\n' + + ' [--buildPath BUILD_PATH]\n\n' + + 'This CLI tool will upload sourcemaps to Sentry for the given release.\n' + + 'It has defaults for URL prefix and build path for Remix builds, but you can override them.\n\n' + + 'If you need a more advanced configuration, you can use `sentry-cli` instead.\n' + + 'https://github.com/getsentry/sentry-cli', + ) + .wrap(120).argv; + +createRelease(argv, DEFAULT_URL_PREFIX, DEFAULT_BUILD_PATH); diff --git a/packages/remix/test/scripts/upload-sourcemaps.test.ts b/packages/remix/test/scripts/upload-sourcemaps.test.ts new file mode 100644 index 000000000000..f7886c5380fb --- /dev/null +++ b/packages/remix/test/scripts/upload-sourcemaps.test.ts @@ -0,0 +1,77 @@ +const newMock = jest.fn(); +const uploadSourceMapsMock = jest.fn(); +const finalizeMock = jest.fn(); +const proposeVersionMock = jest.fn(() => '0.1.2.3.4'); + +jest.mock('@sentry/cli', () => { + return jest.fn().mockImplementation(() => { + return { + execute: jest.fn(), + releases: { + new: newMock, + uploadSourceMaps: uploadSourceMapsMock, + finalize: finalizeMock, + proposeVersion: proposeVersionMock, + }, + }; + }); +}); + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { createRelease } = require('../../scripts/createRelease'); + +beforeEach(() => { + newMock.mockClear(); + uploadSourceMapsMock.mockClear(); + finalizeMock.mockClear(); + proposeVersionMock.mockClear(); +}); + +describe('createRelease', () => { + it('should use release param when given', async () => { + await createRelease({ release: '0.1.2.3' }, '~/build/', 'public/build'); + + expect(proposeVersionMock).not.toHaveBeenCalled(); + expect(newMock).toHaveBeenCalledWith('0.1.2.3'); + expect(uploadSourceMapsMock).toHaveBeenCalledWith('0.1.2.3', { + urlPrefix: '~/build/', + include: ['public/build'], + }); + expect(finalizeMock).toHaveBeenCalledWith('0.1.2.3'); + }); + + it('should call `proposeVersion` when release param is not given.', async () => { + await createRelease({}, '~/build/', 'public/build'); + + expect(proposeVersionMock).toHaveBeenCalled(); + expect(newMock).toHaveBeenCalledWith('0.1.2.3.4'); + expect(uploadSourceMapsMock).toHaveBeenCalledWith('0.1.2.3.4', { + urlPrefix: '~/build/', + include: ['public/build'], + }); + expect(finalizeMock).toHaveBeenCalledWith('0.1.2.3.4'); + }); + + it('should use given buildPath and urlPrefix over the defaults when given.', async () => { + await createRelease( + { + urlPrefix: '~/build/subfolder', + buildPath: 'public/build/subfolder', + }, + '~/build/', + 'public/build', + ); + + expect(proposeVersionMock).toHaveBeenCalled(); + expect(newMock).toHaveBeenCalledWith('0.1.2.3.4'); + expect(uploadSourceMapsMock).toHaveBeenCalledWith('0.1.2.3.4', { + urlPrefix: '~/build/subfolder', + include: ['public/build/subfolder'], + }); + expect(finalizeMock).toHaveBeenCalledWith('0.1.2.3.4'); + }); +}); + +// To avoid `--isolatedModules` flag as we're not importing +// anything for these tests. +export {}; diff --git a/yarn.lock b/yarn.lock index 88fe2747ab02..e7683ac1d4c1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4420,6 +4420,18 @@ semver "7.3.2" semver-intersect "1.4.0" +"@sentry/cli@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.2.0.tgz#0cf4d529d87e290dea54d7e58fa5ff87ea200e4e" + integrity sha512-ywFtB8VHyWN248LuM67fsRtdMLif/SOHYY3zyef5WybvnAmRLDmGTWK//hSUCebsHBpehRIkmt4iMiyUXwgd5w== + dependencies: + https-proxy-agent "^5.0.0" + node-fetch "^2.6.7" + npmlog "^6.0.1" + progress "^2.0.3" + proxy-from-env "^1.1.0" + which "^2.0.2" + "@sentry/cli@^1.74.4": version "1.74.4" resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.74.4.tgz#7df82f68045a155e1885bfcbb5d303e5259eb18e" @@ -6353,11 +6365,19 @@ aproba@^1.0.3, aproba@^1.1.1: resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== -aproba@^2.0.0: +"aproba@^1.0.3 || ^2.0.0", aproba@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== +are-we-there-yet@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-3.0.0.tgz#ba20bd6b553e31d62fc8c31bd23d22b95734390d" + integrity sha512-0GWpv50YSOcLXaN6/FAKY3vfRbllXWV2xvfA/oKJF8pzFhWXPV+yjhJXDBbjscDYowv7Yw1A3uigpzn5iEGTyw== + dependencies: + delegates "^1.0.0" + readable-stream "^3.6.0" + are-we-there-yet@~1.1.2: version "1.1.5" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" @@ -9421,6 +9441,11 @@ color-string@^1.5.4: color-name "^1.0.0" simple-swizzle "^0.2.2" +color-support@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" + integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== + color@^3.0.0: version "3.1.3" resolved "https://registry.yarnpkg.com/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e" @@ -9651,7 +9676,7 @@ console-browserify@^1.1.0: resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== -console-control-strings@^1.0.0, console-control-strings@~1.1.0: +console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= @@ -13633,6 +13658,20 @@ functions-have-names@^1.2.2: resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== +gauge@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" + integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg== + dependencies: + aproba "^1.0.3 || ^2.0.0" + color-support "^1.1.3" + console-control-strings "^1.1.0" + has-unicode "^2.0.1" + signal-exit "^3.0.7" + string-width "^4.2.3" + strip-ansi "^6.0.1" + wide-align "^1.1.5" + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -19409,6 +19448,16 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1: gauge "~2.7.3" set-blocking "~2.0.0" +npmlog@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830" + integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg== + dependencies: + are-we-there-yet "^3.0.0" + console-control-strings "^1.1.0" + gauge "^4.0.3" + set-blocking "^2.0.0" + nth-check@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" @@ -23141,7 +23190,7 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== -signal-exit@^3.0.3: +signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -23983,6 +24032,15 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.2.2, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -23992,15 +24050,6 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.0.0, string-width@^4.2.2: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^4.1.0, string-width@^4.2.0: version "4.2.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" @@ -26359,6 +26408,13 @@ wide-align@1.1.3, wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2" +wide-align@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" + integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg== + dependencies: + string-width "^1.0.2 || 2 || 3 || 4" + widest-line@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" @@ -26668,6 +26724,11 @@ yargs-parser@^20.2.3: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a" integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw== +yargs-parser@^21.0.0: + version "21.0.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35" + integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg== + yargs-unparser@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" @@ -26741,6 +26802,19 @@ yargs@^16.1.1, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" +yargs@^17.5.1: + version "17.5.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.5.1.tgz#e109900cab6fcb7fd44b1d8249166feb0b36e58e" + integrity sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.0.0" + yauzl@^2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"