From df42b36194c67c0acdc14f4ab89d80c97f511a73 Mon Sep 17 00:00:00 2001 From: nicolas Date: Fri, 30 Oct 2020 16:55:40 -0300 Subject: [PATCH] Add Sentry config and ErrorBoundary Component (#1528) * Add Sentry config and ErrorBoundary Component * Update travis file to upload sentry sourcemaps * Add design implementation for ErrorBoundary * Add Sentry DSN configuration for all networks * Push sourcemaps to sentry only on staging/production build * move isProdction to constants file * change Button for Link * fix redirect when safeAddress is provided but not a subpath for it. Co-authored-by: Daniel Sanchez --- .env.example | 1 + .travis.yml | 26 +++- config/travis/build.sh | 10 -- package.json | 8 +- src/components/GlobalErrorBoundary/index.tsx | 103 +++++++++++++++ src/components/Root/index.tsx | 9 +- src/index.tsx | 10 ++ src/routes/safe/container/index.tsx | 2 +- src/utils/constants.ts | 2 + yarn.lock | 124 +++++++++++++++++-- 10 files changed, 266 insertions(+), 29 deletions(-) delete mode 100755 config/travis/build.sh create mode 100644 src/components/GlobalErrorBoundary/index.tsx diff --git a/.env.example b/.env.example index 1e81bb2a..33d8a508 100644 --- a/.env.example +++ b/.env.example @@ -6,6 +6,7 @@ REACT_APP_GOOGLE_ANALYTICS= REACT_APP_INFURA_TOKEN= REACT_APP_IPFS_GATEWAY=https://ipfs.io/ipfs PUBLIC_URL=/app/ +REACT_APP_SENTRY_DSN= # For production environments REACT_APP_BLOCKNATIVE_KEY= diff --git a/.travis.yml b/.travis.yml index ff284b09..5141ae8f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,27 +10,38 @@ matrix: include: - env: - REACT_APP_NETWORK='mainnet' - - REACT_APP_GOOGLE_ANALYTICS=${REACT_APP_GOOGLE_ANALYTICS_ID_MAINNET} - STAGING_BUCKET_NAME=${STAGING_MAINNET_BUCKET_NAME} + - REACT_APP_SENTRY_DSN=${SENTRY_DSN_MAINNET} + - SENTRY_PROJECT=${SENTRY_PROJECT_MAINNET} + - REACT_APP_GOOGLE_ANALYTICS=${REACT_APP_GOOGLE_ANALYTICS_ID_MAINNET} - REACT_APP_GNOSIS_APPS_URL=${REACT_APP_GNOSIS_APPS_URL_PROD} if: (branch = master AND NOT type = pull_request) OR tag IS present - env: - REACT_APP_NETWORK='rinkeby' + - REACT_APP_SENTRY_DSN=${SENTRY_DSN_RINKEBY} + - SENTRY_PROJECT=${SENTRY_PROJECT_RINKEBY} - REACT_APP_GOOGLE_ANALYTICS=${REACT_APP_GOOGLE_ANALYTICS_ID_RINKEBY} - REACT_APP_GNOSIS_APPS_URL=${REACT_APP_GNOSIS_APPS_URL_STAGING} - env: - REACT_APP_NETWORK='xdai' - - REACT_APP_GOOGLE_ANALYTICS=${REACT_APP_GOOGLE_ANALYTICS_ID_XDAI} - STAGING_BUCKET_NAME=${STAGING_XDAI_BUCKET_NAME} + - REACT_APP_SENTRY_DSN=${SENTRY_DSN_XDAI} + - SENTRY_PROJECT=${SENTRY_PROJECT_XDAI} + - REACT_APP_GOOGLE_ANALYTICS=${REACT_APP_GOOGLE_ANALYTICS_ID_XDAI} if: (branch = master AND NOT type = pull_request) OR tag IS present - env: - REACT_APP_NETWORK='volta' - - REACT_APP_GOOGLE_ANALYTICS=${REACT_APP_GOOGLE_ANALYTICS_ID_VOLTA} - STAGING_BUCKET_NAME=${STAGING_VOLTA_BUCKET_NAME} + - REACT_APP_SENTRY_DSN=${SENTRY_DSN_VOLTA} + - SENTRY_PROJECT=${SENTRY_PROJECT_VOLTA} + - REACT_APP_GOOGLE_ANALYTICS=${REACT_APP_GOOGLE_ANALYTICS_ID_VOLTA} + if: (branch = master AND NOT type = pull_request) OR tag IS present - env: - REACT_APP_NETWORK='energy_web_chain' - - REACT_APP_GOOGLE_ANALYTICS=${REACT_APP_GOOGLE_ANALYTICS_ID_EWC} - STAGING_BUCKET_NAME=${STAGING_EWC_BUCKET_NAME} + - REACT_APP_SENTRY_DSN=${SENTRY_DSN_EWC} + - SENTRY_PROJECT=${SENTRY_PROJECT_EWC} + - REACT_APP_GOOGLE_ANALYTICS=${REACT_APP_GOOGLE_ANALYTICS_ID_EWC} if: ((branch = master OR branch = release/v2.14.0) AND NOT type = pull_request) OR tag IS present cache: @@ -48,7 +59,12 @@ script: - yarn prettier:check - yarn test:coverage - yarn build - #- bash ./config/travis/build.sh + - if [[ $TRAVIS_BRANCH == "master" && $TRAVIS_PULL_REQUEST == "false" ]] || [ -n "$TRAVIS_TAG" ]; then + echo "Upload sentry source maps" + yarn sentry-upload-sourcemaps; + else + echo "Skip source map upload"; + fi; after_success: # Pull Request - Deploy it to a review environment # Travis doesn't do deploy step with pull requests builds diff --git a/config/travis/build.sh b/config/travis/build.sh deleted file mode 100755 index 96e41851..00000000 --- a/config/travis/build.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -export NODE_ENV=production; - -if [[ -n "$TRAVIS_TAG" ]]; then export REACT_APP_ENV='production'; fi - -yarn lint:check -yarn prettier:check -yarn test:coverage -yarn build \ No newline at end of file diff --git a/package.json b/package.json index ec64735d..e61c8ddb 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,8 @@ "test:coverage": "yarn test --coverage --watchAll=false", "coveralls": "cat ./coverage/lcov.info | coveralls", "storybook": "start-storybook -p 9009 -s public", - "build-storybook": "build-storybook -s public" + "build-storybook": "build-storybook -s public", + "sentry-upload-sourcemaps": "sentry-cli --auth-token $SENTRY_AUTH_TOKEN releases -o $SENTRY_ORG -p $SENTRY_PROJECT files $npm_package_version upload-sourcemaps ./build/static/js/" }, "husky": { "hooks": { @@ -167,13 +168,15 @@ "dependencies": { "@gnosis.pm/safe-apps-sdk": "https://github.com/gnosis/safe-apps-sdk.git#3f0689f", "@gnosis.pm/safe-contracts": "1.1.1-dev.2", - "@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#70e57bdd1e0fd5dfdf5768076577c1e000b5fe28", + "@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#8d8508e", "@gnosis.pm/util-contracts": "2.0.6", "@ledgerhq/hw-transport-node-hid": "5.26.0", "@material-ui/core": "4.11.0", "@material-ui/icons": "4.9.1", "@material-ui/lab": "4.0.0-alpha.56", "@openzeppelin/contracts": "3.1.0", + "@sentry/react": "^5.27.1", + "@sentry/tracing": "^5.27.1", "@truffle/contract": "4.2.26", "async-sema": "^3.1.0", "axios": "0.20.0", @@ -232,6 +235,7 @@ "web3-utils": "^1.2.11" }, "devDependencies": { + "@sentry/cli": "^1.58.0", "@storybook/addon-actions": "^5.3.19", "@storybook/addon-links": "^5.3.19", "@storybook/addons": "^5.3.19", diff --git a/src/components/GlobalErrorBoundary/index.tsx b/src/components/GlobalErrorBoundary/index.tsx new file mode 100644 index 00000000..7b8d96f2 --- /dev/null +++ b/src/components/GlobalErrorBoundary/index.tsx @@ -0,0 +1,103 @@ +import React from 'react' +import styled from 'styled-components' +import { Text, Link, Icon, FixedIcon, Title } from '@gnosis.pm/safe-react-components' + +import { IS_PRODUCTION } from 'src/utils/constants' + +const Wrapper = styled.div` + width: 100%; + margin-top: 50px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; +` + +const Content = styled.div` + width: 400px; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + + > * { + margin-top: 10px; + } +` + +const LinkWrapper = styled.div` + display: inline-flex; + margin-bottom: 10px; + + > :first-of-type { + margin-right: 5px; + } +` + +const LinkContent = styled.div` + display: flex; + align-items: center; + + > span { + margin-right: 5px; + } +` + +type Props = { + error: Error + componentStack: string + resetError: () => void +} + +const GlobalErrorBoundaryFallback = ({ error, componentStack }: Props): React.ReactElement => { + return ( + + + Something went wrong, please try again. + + {IS_PRODUCTION && ( +
+ + In case the problem persists, please reach out to us via{' '} + + + + + Email + + + + + or{' '} + + + + Discord + + + + +
+ )} + {!IS_PRODUCTION && ( + <> + + {error.toString()} + + + {componentStack} + + + )} + + + + Go to Home + + +
+
+ ) +} + +export default GlobalErrorBoundaryFallback diff --git a/src/components/Root/index.tsx b/src/components/Root/index.tsx index cffb2ac6..4c5937d0 100644 --- a/src/components/Root/index.tsx +++ b/src/components/Root/index.tsx @@ -4,10 +4,11 @@ import { ConnectedRouter } from 'connected-react-router' import React from 'react' import { Provider } from 'react-redux' import { ThemeProvider } from 'styled-components' +import * as Sentry from '@sentry/react' import Loader from 'src/components/Loader' import App from 'src/components/App' - +import GlobalErrorBoundary from 'src/components/GlobalErrorBoundary' import AppRoutes from 'src/routes' import { history, store } from 'src/store' import theme from 'src/theme/mui' @@ -20,7 +21,11 @@ const Root = (): React.ReactElement => ( - {{wrapInSuspense(, )}} + + + {wrapInSuspense(, )} + + diff --git a/src/index.tsx b/src/index.tsx index 052bcbb0..745f223c 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,6 +1,8 @@ import { BigNumber } from 'bignumber.js' import React from 'react' import ReactDOM from 'react-dom' +import * as Sentry from '@sentry/react' +import { Integrations } from '@sentry/tracing' import Root from 'src/components/Root' import loadCurrentSessionFromStorage from 'src/logic/currentSession/store/actions/loadCurrentSessionFromStorage' @@ -8,6 +10,7 @@ import loadActiveTokens from 'src/logic/tokens/store/actions/loadActiveTokens' import loadDefaultSafe from 'src/logic/safe/store/actions/loadDefaultSafe' import loadSafesFromStorage from 'src/logic/safe/store/actions/loadSafesFromStorage' import { store } from 'src/store' +import { SENTRY_DSN } from './utils/constants' BigNumber.set({ EXPONENTIAL_AT: [-7, 255] }) @@ -16,6 +19,13 @@ store.dispatch(loadSafesFromStorage()) store.dispatch(loadDefaultSafe()) store.dispatch(loadCurrentSessionFromStorage()) +Sentry.init({ + dsn: SENTRY_DSN, + release: `safe-react@${process.env.REACT_APP_APP_VERSION}`, + integrations: [new Integrations.BrowserTracing()], + sampleRate: 1, +}) + const root = document.getElementById('root') if (root !== null) { diff --git a/src/routes/safe/container/index.tsx b/src/routes/safe/container/index.tsx index d90de961..f0008b30 100644 --- a/src/routes/safe/container/index.tsx +++ b/src/routes/safe/container/index.tsx @@ -101,7 +101,7 @@ const Container = (): React.ReactElement => { path={`${matchSafeWithAddress?.path}/address-book`} render={() => wrapInSuspense(, null)} /> - + {modal.isOpen && } diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 4a9e2bb0..0828f8a9 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -1,8 +1,10 @@ export const APP_ENV = process.env.REACT_APP_ENV export const NODE_ENV = process.env.NODE_ENV +export const IS_PRODUCTION = process.env.NODE_ENV === 'production' export const NETWORK = process.env.REACT_APP_NETWORK?.toUpperCase() || 'RINKEBY' export const INTERCOM_ID = APP_ENV === 'production' ? process.env.REACT_APP_INTERCOM_ID : 'plssl1fl' export const GOOGLE_ANALYTICS_ID = process.env.REACT_APP_GOOGLE_ANALYTICS || '' +export const SENTRY_DSN = process.env.REACT_APP_SENTRY_DSN || '' export const PORTIS_ID = process.env.REACT_APP_PORTIS_ID ?? '852b763d-f28b-4463-80cb-846d7ec5806b' export const FORTMATIC_KEY = process.env.REACT_APP_FORTMATIC_KEY ?? 'pk_test_CAD437AA29BE0A40' export const BLOCKNATIVE_KEY = process.env.REACT_APP_BLOCKNATIVE_KEY ?? '7fbb9cee-7e97-4436-8770-8b29a9a8814c' diff --git a/yarn.lock b/yarn.lock index 06f2f7f4..804a92f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1484,9 +1484,9 @@ solc "0.5.14" truffle "^5.1.21" -"@gnosis.pm/safe-react-components@https://github.com/gnosis/safe-react-components.git#70e57bdd1e0fd5dfdf5768076577c1e000b5fe28": +"@gnosis.pm/safe-react-components@https://github.com/gnosis/safe-react-components.git#8d8508e": version "0.4.0" - resolved "https://github.com/gnosis/safe-react-components.git#70e57bdd1e0fd5dfdf5768076577c1e000b5fe28" + resolved "https://github.com/gnosis/safe-react-components.git#8d8508ea01bf660bfd75a95ed7fff277caa9ac30" dependencies: classnames "^2.2.6" polished "3.6.5" @@ -1997,6 +1997,92 @@ resolved "https://registry.yarnpkg.com/@restless/sanitizers/-/sanitizers-0.2.5.tgz#96a5cfa3edb52abd8fa14e77798738f3a067dbec" integrity sha512-utsOFwv5owNnbj8HijF7uML/AURgUl5YvY4S2gpxQsrp2D1EP/4rQU/HSyYdIQaL89BoZ/5NHveRJrcFyuHo/w== +"@sentry/browser@5.27.1": + version "5.27.1" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.27.1.tgz#67da0cb9680ed54ecdb56a66abd8183b5a8ee174" + integrity sha512-OPBtKKJDgpJOJILaXntGp0z5KT2I1fmtePnHDdgPd7uNqXfTw0E6bvSjY9bR0pSJSooSwqZAAnsAZg8t4772ow== + dependencies: + "@sentry/core" "5.27.1" + "@sentry/types" "5.27.1" + "@sentry/utils" "5.27.1" + tslib "^1.9.3" + +"@sentry/cli@^1.58.0": + version "1.58.0" + resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.58.0.tgz#b1609f10e71539951499866502b13bf3a270fe79" + integrity sha512-bUBKBYyKVzjNhQpAfPJ3XAvAyNNvrD2Rtpo6B0MR3Okw3prdLFgv9Ta8TN19IXT7u9w13B2EdMnNA6dQDtrD4g== + dependencies: + https-proxy-agent "^5.0.0" + mkdirp "^0.5.5" + node-fetch "^2.6.0" + progress "^2.0.3" + proxy-from-env "^1.1.0" + +"@sentry/core@5.27.1": + version "5.27.1" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.27.1.tgz#489604054d821e1de155f80fe650085b37cad235" + integrity sha512-n5CxzMbOAT6HZK4U4cOUAAikkRnnHhMNhInrjfZh7BoiuX1k63Hru2H5xk5WDuEaTTr5RaBA/fqPl7wxHySlwQ== + dependencies: + "@sentry/hub" "5.27.1" + "@sentry/minimal" "5.27.1" + "@sentry/types" "5.27.1" + "@sentry/utils" "5.27.1" + tslib "^1.9.3" + +"@sentry/hub@5.27.1": + version "5.27.1" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.27.1.tgz#c95faaf18257c365acc09246fafd27276bfd6a2f" + integrity sha512-RBHo3T92s6s4Ian1pZcPlmNtFqB+HAP6xitU+ZNA48bYUK+R1vvqEcI8Xs83FyNaRGCgclp9erDFQYyAuxY4vw== + dependencies: + "@sentry/types" "5.27.1" + "@sentry/utils" "5.27.1" + tslib "^1.9.3" + +"@sentry/minimal@5.27.1": + version "5.27.1" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.27.1.tgz#d6ce881ba3c262db29520177a4c1f0e0f5388697" + integrity sha512-MHXCeJdA1NAvaJuippcM8nrWScul8iTN0Q5nnFkGctGIGmmiZHTXAYkObqJk7H3AK+CP7r1jqN2aQj5Nd9CtyA== + dependencies: + "@sentry/hub" "5.27.1" + "@sentry/types" "5.27.1" + tslib "^1.9.3" + +"@sentry/react@^5.27.1": + version "5.27.1" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-5.27.1.tgz#1accad75dd7302d6486b8d4657673d56ebfb7fa7" + integrity sha512-iKJgF3ZfIbKC9pCTip+xnu7JYAYryDgobknj/NmT7nbfeSE2oJHFZYsMk+BzxxKaEFcYfMeJvtm3Ijq1Nm1Khw== + dependencies: + "@sentry/browser" "5.27.1" + "@sentry/minimal" "5.27.1" + "@sentry/types" "5.27.1" + "@sentry/utils" "5.27.1" + hoist-non-react-statics "^3.3.2" + tslib "^1.9.3" + +"@sentry/tracing@^5.27.1": + version "5.27.1" + resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.27.1.tgz#198cd97514363369d29eef9b597be9332ab170c4" + integrity sha512-GBmdR8Ky/nv4KOa6+DEnOSBkFOFhM+asR8Y/gw2qSUWCwzKuWHh9BEnDwxtSI8CMvgUwOIZ5wiiqJGc1unYfCw== + dependencies: + "@sentry/hub" "5.27.1" + "@sentry/minimal" "5.27.1" + "@sentry/types" "5.27.1" + "@sentry/utils" "5.27.1" + tslib "^1.9.3" + +"@sentry/types@5.27.1": + version "5.27.1" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.27.1.tgz#031480a4cf8f0b6e6337fb03ee884deedcef6f40" + integrity sha512-g1aX0V0fz5BTo0mjgSVY9XmPLGZ6p+8OEzq3ubKzDUf59VHl+Vt8viZ8VXw/vsNtfAjBHn7BzSuzJo7cXJJBtA== + +"@sentry/utils@5.27.1": + version "5.27.1" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.27.1.tgz#0ed9d9685aae6f4ef9eb6b9ebb81e361fd1c5452" + integrity sha512-VIzK8utuvFO9EogZcKJPgmLnlJtYbaPQ0jCw7od9HRw1ckrSBc84sA0uuuY6pB6KSM+7k6EjJ5IdIBaCz5ep/A== + dependencies: + "@sentry/types" "5.27.1" + tslib "^1.9.3" + "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -3780,6 +3866,13 @@ aes-js@3.1.2, aes-js@^3.1.1: resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -7213,6 +7306,13 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6. dependencies: ms "2.0.0" +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + dependencies: + ms "2.1.2" + debug@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" @@ -7234,13 +7334,6 @@ debug@^3.0.0, debug@^3.1.1, debug@^3.2.5: dependencies: ms "^2.1.1" -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" - integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== - dependencies: - ms "2.1.2" - decamelize-keys@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -10666,6 +10759,14 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + human-signals@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" @@ -15728,6 +15829,11 @@ proxy-addr@~2.0.5: forwarded "~0.1.2" ipaddr.js "1.9.1" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476"