Skip to content

Commit

Permalink
feat(extension): initialize Sentry
Browse files Browse the repository at this point in the history
* feat: initialize Sentry

* feat(extension): add sentry to CSP on build

---------

Co-authored-by: Michael Chappell <7581002+mchappell@users.noreply.github.com>
  • Loading branch information
rhyslbw and mchappell authored Oct 30, 2024
1 parent 8546d9a commit e1a7c7e
Show file tree
Hide file tree
Showing 13 changed files with 687 additions and 13 deletions.
21 changes: 21 additions & 0 deletions .github/shared/build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,23 @@ inputs:
description: 'WS url for sanchonet env'
required: false
default: 'wss://dev-sanchonet.lw.iog.io'
SENTRY_AUTH_TOKEN:
description: 'Authentication token for Sentry, used to publish source maps for releases'
required: false
default: ''
SENTRY_DSN:
description: 'Data Source Name for Sentry, AKA Client Key. This tells a Sentry SDK where to send events so the events are associated
with the correct project'
required: false
default: ''
SENTRY_ORG:
description: 'Organization identifier for Sentry'
required: false
default: ''
SENTRY_PROJECT:
description: 'Project identifier for Sentry'
required: false
default: ''
runs:
using: 'composite'
steps:
Expand Down Expand Up @@ -131,4 +148,8 @@ runs:
CARDANO_WS_SERVER_URL_PREPROD: ${{ inputs.CARDANO_WS_SERVER_URL_PREPROD }}
CARDANO_WS_SERVER_URL_PREVIEW: ${{ inputs.CARDANO_WS_SERVER_URL_PREVIEW }}
CARDANO_WS_SERVER_URL_SANCHONET: ${{ inputs.CARDANO_WS_SERVER_URL_SANCHONET }}
SENTRY_AUTH_TOKEN: ${{ inputs.SENTRY_AUTH_TOKEN }}
SENTRY_DSN: ${{ inputs.SENTRY_DSN }}
SENTRY_ORG: ${{ inputs.SENTRY_ORG }}
SENTRY_PROJECT: ${{ inputs.SENTRY_PROJECT }}
run: yarn browser build
1 change: 1 addition & 0 deletions .github/workflows/build-dev-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
LACE_EXTENSION_KEY: ${{ secrets.DEV_PREVIEW_MANIFEST_PUBLIC_KEY }}
CARDANO_SERVICES_URL_SANCHONET: 'https://live-sanchonet.lw.iog.io'
PRODUCTION_MODE_TRACKING: 'false'
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
- name: Check for linter issues
run: yarn lint
- name: Execute unit tests
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ jobs:
BLOCKFROST_PROJECT_ID_MAINNET: ${{ secrets.BLOCKFROST_PROJECT_ID_MAINNET }}
BLOCKFROST_PROJECT_ID_PREPROD: ${{ secrets.BLOCKFROST_PROJECT_ID_PREPROD }}
BLOCKFROST_PROJECT_ID_PREVIEW: ${{ secrets.BLOCKFROST_PROJECT_ID_PREVIEW }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}

- name: Upload build artifact
uses: actions/upload-artifact@v4
Expand Down
36 changes: 36 additions & 0 deletions .github/workflows/sentry-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Sentry Release

on:
workflow_dispatch:

permissions:
actions: read

jobs:
upload-source-maps:
name: Upload Source Maps to Sentry
runs-on: ubuntu-22.04

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Node.js and install dependencies
uses: ./.github/actions/install
with:
WALLET_PASSWORD: ${{ secrets.WALLET_PASSWORD_TESTNET }}
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}

- name: Build Lace and trigger Sentry plugin to upload source maps
uses: ./.github/shared/build
with:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
LACE_EXTENSION_KEY: ${{ secrets.MANIFEST_PUBLIC_KEY }}
BLOCKFROST_PROJECT_ID_MAINNET: ${{ secrets.BLOCKFROST_PROJECT_ID_MAINNET }}
BLOCKFROST_PROJECT_ID_PREPROD: ${{ secrets.BLOCKFROST_PROJECT_ID_PREPROD }}
BLOCKFROST_PROJECT_ID_PREVIEW: ${{ secrets.BLOCKFROST_PROJECT_ID_PREVIEW }}
BLOCKFROST_PROJECT_ID_SANCHONET: ${{ secrets.BLOCKFROST_PROJECT_ID_SANCHONET }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_ORG: ${{ vars.SENTRY_ORG }}
SENTRY_PROJECT: ${{ vars.SENTRY_PROJECT }}
5 changes: 5 additions & 0 deletions apps/browser-extension-wallet/.env.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ PRODUCTION_MODE_TRACKING=false

# Post Hog
POSTHOG_DEV_TOKEN=phc_gH96Lx5lEVXTTWEyytSdTFPDk3Xsxwi4BqG88mKObd1
# Sentry
SENTRY_AUTH_TOKEN=
SENTRY_DSN=
SENTRY_ORG=
SENTRY_PROJECT=

# Cardano Services
CARDANO_SERVICES_URL_MAINNET=https://dev-mainnet.lw.iog.io
Expand Down
2 changes: 1 addition & 1 deletion apps/browser-extension-wallet/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"permissions": ["webRequest", "storage", "tabs", "unlimitedStorage"],
"host_permissions": ["<all_urls>"],
"content_security_policy": {
"extension_pages": "default-src 'self' $LOCALHOST_DEFAULT_SRC; frame-src https://connect.trezor.io/ https://www.youtube-nocookie.com; script-src 'self' 'wasm-unsafe-eval' $LOCALHOST_SCRIPT_SRC; font-src 'self' https://use.typekit.net; object-src 'self'; connect-src $BLOCKFROST_URLS $CARDANO_SERVICES_URLS $CARDANO_WS_SERVER_URLS https://coingecko.live-mainnet.eks.lw.iog.io https://muesliswap.live-mainnet.eks.lw.iog.io $LOCALHOST_CONNECT_SRC $POSTHOG_HOST https://use.typekit.net data:; style-src * 'unsafe-inline'; img-src * data:;"
"extension_pages": "default-src 'self' $LOCALHOST_DEFAULT_SRC; frame-src https://connect.trezor.io/ https://www.youtube-nocookie.com; script-src 'self' 'wasm-unsafe-eval' $LOCALHOST_SCRIPT_SRC; font-src 'self' https://use.typekit.net; object-src 'self'; connect-src $BLOCKFROST_URLS $CARDANO_SERVICES_URLS $CARDANO_WS_SERVER_URLS $SENTRY_URL https://coingecko.live-mainnet.eks.lw.iog.io https://muesliswap.live-mainnet.eks.lw.iog.io $LOCALHOST_CONNECT_SRC $POSTHOG_HOST https://use.typekit.net data:; style-src * 'unsafe-inline'; img-src * data:;"
},
"content_scripts": [
{
Expand Down
2 changes: 2 additions & 0 deletions apps/browser-extension-wallet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
"@pdfme/generator": "^4.0.2",
"@react-rxjs/core": "^0.9.8",
"@react-rxjs/utils": "^0.9.5",
"@sentry/react": "^8.33.1",
"@sentry/webpack-plugin": "^2.22.6",
"@shiroyasha9/axios-fetch-adapter": "^1.0.3",
"antd": "^4.24.10",
"are-you-es5": "^2.1.2",
Expand Down
21 changes: 21 additions & 0 deletions apps/browser-extension-wallet/sentry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as Sentry from '@sentry/react';

Sentry.init({
environment: process.env.NODE_ENV,
dsn: process.env.SENTRY_DSN,
integrations: [Sentry.browserTracingIntegration(), Sentry.browserProfilingIntegration(), Sentry.replayIntegration()],
// Set `tracePropagationTargets` to control for which URLs trace propagation should be enabled
tracePropagationTargets: ['localhost', 'chrome-extension://gafhhkghbfjjkeiendhlofajokpaflmk'],
// .5%
tracesSampleRate: 0.05,
profilesSampleRate: 0.05,
// Since profilesSampleRate is relative to tracesSampleRate,
// the final profiling rate can be computed as tracesSampleRate * profilesSampleRate
// A tracesSampleRate of 0.05 and profilesSampleRate of 0.05 results in 2.5% of
// transactions being profiled (0.05*0.05=0.0025)

// Capture Replay for 0.05% of all sessions,
replaysSessionSampleRate: 0.005,
// ...plus for 100% of sessions with an error
replaysOnErrorSampleRate: 1.0
});
8 changes: 7 additions & 1 deletion apps/browser-extension-wallet/webpack-utils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
const constructSentryConnectSrc = (dsn) => {
if (/https:\/\/[^@]+@([^/]+).*/.test(dsn)) return dsn.replace(/https:\/\/[^@]+@([^/]+).*/, 'https://$1');
return '';
};

const transformManifest = (content, mode) => {
require('dotenv-defaults').config({
path: './.env',
Expand Down Expand Up @@ -32,7 +37,8 @@ const transformManifest = (content, mode) => {
? 'http://localhost:* http://127.0.0.1:* ws://localhost:3000 ws://0.0.0.0:3000/ws wss://localhost:3000 ws://localhost:3001 ws://0.0.0.0:3001/ws wss://localhost:3001'
: 'http://localhost:* http://127.0.0.1:*'
)
.replace('$POSTHOG_HOST', process.env.POSTHOG_HOST);
.replace('$POSTHOG_HOST', process.env.POSTHOG_HOST)
.replace('$SENTRY_URL', constructSentryConnectSrc(process.env.SENTRY_DSN));

if (process.env.LACE_EXTENSION_KEY) {
manifest.key = manifest.key.replace('$LACE_EXTENSION_KEY', process.env.LACE_EXTENSION_KEY);
Expand Down
12 changes: 8 additions & 4 deletions apps/browser-extension-wallet/webpack.common.app.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ require('dotenv-defaults').config({
defaults: process.env.BUILD_DEV_PREVIEW === 'true' ? './.env.developerpreview' : './.env.defaults'
});

const withMaybeSentry = (p) => ('SENTRY_DSN' in process.env ? [path.join(__dirname, 'sentry.js'), p] : p);

module.exports = () =>
merge(commonConfig(), {
entry: {
popup: path.join(__dirname, 'src/index-popup.tsx'),
options: path.join(__dirname, 'src/index-options.tsx'),
dappConnector: path.join(__dirname, 'src/index-dapp-connector.tsx'),
popup: withMaybeSentry(path.join(__dirname, 'src/index-popup.tsx')),
options: withMaybeSentry(path.join(__dirname, 'src/index-options.tsx')),
dappConnector: withMaybeSentry(path.join(__dirname, 'src/index-dapp-connector.tsx')),
['trezor-content-script']: path.join(__dirname, 'src/lib/scripts/trezor/trezor-content-script.ts'),
['trezor-usb-permissions']: path.join(__dirname, 'src/lib/scripts/trezor/trezor-usb-permissions.ts')
['trezor-usb-permissions']: withMaybeSentry(
path.join(__dirname, 'src/lib/scripts/trezor/trezor-usb-permissions.ts')
)
},
experiments: {
syncWebAssembly: true
Expand Down
18 changes: 13 additions & 5 deletions apps/browser-extension-wallet/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ const { SubresourceIntegrityPlugin } = require('webpack-subresource-integrity');
const commitHash = Buffer.from(require('child_process').execSync('git rev-parse HEAD')).toString();
const app_version = require('./manifest.json').version;

require('dotenv-defaults').config({
path: './.env',
encoding: 'utf8'
});

const envsToExpose = {
APP_VERSION: app_version,
COMMIT_HASH: commitHash
//'process.env': JSON.stringify(process.env)
};
if ('SENTRY_DSN' in process.env) envsToExpose['SENTRY_DSN'] = process.env.SENTRY_DSN;

module.exports = () => {
return {
output: {
Expand Down Expand Up @@ -91,11 +103,7 @@ module.exports = () => {
systemvars: true,
allowEmptyValues: true
}),
new EnvironmentPlugin({
APP_VERSION: app_version,
COMMIT_HASH: commitHash
//'process.env': JSON.stringify(process.env)
}),
new EnvironmentPlugin(envsToExpose),
new SubresourceIntegrityPlugin()
]
};
Expand Down
17 changes: 16 additions & 1 deletion apps/browser-extension-wallet/webpack.common.prod.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,31 @@ const TerserPlugin = require('terser-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const { transformManifest } = require('./webpack-utils');
const Dotenv = require('dotenv-webpack');
const { sentryWebpackPlugin } = require('@sentry/webpack-plugin');
require('dotenv-defaults').config({
path: './.env',
encoding: 'utf8',
defaults: process.env.BUILD_DEV_PREVIEW === 'true' ? './.env.developerpreview' : './.env.defaults'
});

const hasSentryReleaseConfig =
!!process.env.SENTRY_AUTH_TOKEN && !!process.env.SENTRY_ORG && !!process.env.SENTRY_PROJECT;

module.exports = () => ({
mode: 'production',
devtool: false,
devtool: hasSentryReleaseConfig ? 'source-map' : false,
plugins: [
...(hasSentryReleaseConfig
? [
sentryWebpackPlugin({
authToken: process.env.SENTRY_AUTH_TOKEN,
org: process.env.SENTRY_ORG,
project: process.env.SENTRY_PROJECT,
telemetry: false,
url: 'https://sentry.io/'
})
]
: []),
new Dotenv({
path: '.env',
safe: false,
Expand Down
Loading

0 comments on commit e1a7c7e

Please sign in to comment.