From a56eea6b3fa7fc2021b9cd69fee42b907827e849 Mon Sep 17 00:00:00 2001 From: Tomasz Lesniakiewicz Date: Wed, 29 Oct 2025 16:33:45 +0100 Subject: [PATCH 01/19] feat: enable sentry source maps for web --- .env.example | 2 + config/webpack/webpack.common.ts | 13 ++ package-lock.json | 345 +++++++++++++++++++++++++++++++ package.json | 1 + 4 files changed, 361 insertions(+) diff --git a/.env.example b/.env.example index 31f963dd3925..a5a499737521 100644 --- a/.env.example +++ b/.env.example @@ -40,3 +40,5 @@ FB_PROJECT_ID=YOUR_PROJECT_ID GITHUB_TOKEN=YOUR_TOKEN OPENAI_API_KEY=YOUR_TOKEN + +SENTRY_AUTH_TOKEN=SENTRY_AUTH_TOKEN diff --git a/config/webpack/webpack.common.ts b/config/webpack/webpack.common.ts index ad3124aed049..198771d16e67 100644 --- a/config/webpack/webpack.common.ts +++ b/config/webpack/webpack.common.ts @@ -1,3 +1,4 @@ +import {sentryWebpackPlugin} from '@sentry/webpack-plugin'; import {CleanWebpackPlugin} from 'clean-webpack-plugin'; import CopyPlugin from 'copy-webpack-plugin'; import dotenv from 'dotenv'; @@ -169,6 +170,18 @@ const getCommonConfiguration = ({file = '.env', platform = 'web'}: Environment): }), ...(isDevelopment ? [] : [new MiniCssExtractPlugin()]), + // Upload source maps to Sentry + ...(isDevelopment + ? [] + : ([ + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + sentryWebpackPlugin({ + authToken: process.env.SENTRY_AUTH_TOKEN as string | undefined, + org: 'expensify', + project: 'app', + }), + ] as WebpackPluginInstance[])), + // This allows us to interactively inspect JS bundle contents ...(process.env.ANALYZE_BUNDLE === 'true' ? [new BundleAnalyzerPlugin()] : []), ], diff --git a/package-lock.json b/package-lock.json index d4d1709f5835..6c1a1db8737c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -187,6 +187,7 @@ "@rock-js/platform-ios": "0.11.5", "@rock-js/plugin-metro": "0.11.5", "@rock-js/provider-github": "0.11.5", + "@sentry/webpack-plugin": "^4.6.0", "@storybook/addon-a11y": "^8.6.9", "@storybook/addon-essentials": "^8.6.9", "@storybook/addon-webpack5-compiler-babel": "^3.0.5", @@ -12220,6 +12221,298 @@ "node": ">=18" } }, + "node_modules/@sentry/bundler-plugin-core": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-4.6.0.tgz", + "integrity": "sha512-Fub2XQqrS258jjS8qAxLLU1k1h5UCNJ76i8m4qZJJdogWWaF8t00KnnTyp9TEDJzrVD64tRXS8+HHENxmeUo3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.18.5", + "@sentry/babel-plugin-component-annotate": "4.6.0", + "@sentry/cli": "^2.57.0", + "dotenv": "^16.3.1", + "find-up": "^5.0.0", + "glob": "^9.3.2", + "magic-string": "0.30.8", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/babel-plugin-component-annotate": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-4.6.0.tgz", + "integrity": "sha512-3soTX50JPQQ51FSbb4qvNBf4z/yP7jTdn43vMTp9E4IxvJ9HKJR7OEuKkCMszrZmWsVABXl02msqO7QisePdiQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli": { + "version": "2.57.0", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.57.0.tgz", + "integrity": "sha512-oC4HPrVIX06GvUTgK0i+WbNgIA9Zl5YEcwf9N4eWFJJmjonr2j4SML9Hn2yNENbUWDgwepy4MLod3P8rM4bk/w==", + "dev": true, + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.57.0", + "@sentry/cli-linux-arm": "2.57.0", + "@sentry/cli-linux-arm64": "2.57.0", + "@sentry/cli-linux-i686": "2.57.0", + "@sentry/cli-linux-x64": "2.57.0", + "@sentry/cli-win32-arm64": "2.57.0", + "@sentry/cli-win32-i686": "2.57.0", + "@sentry/cli-win32-x64": "2.57.0" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-darwin": { + "version": "2.57.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.57.0.tgz", + "integrity": "sha512-v1wYQU3BcCO+Z3OVxxO+EnaW4oQhuOza6CXeYZ0z5ftza9r0QQBLz3bcZKTVta86xraNm0z8GDlREwinyddOxQ==", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-arm": { + "version": "2.57.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.57.0.tgz", + "integrity": "sha512-uNHB8xyygqfMd1/6tFzl9NUkuVefg7jdZtM/vVCQVaF/rJLWZ++Wms+LLhYyKXKN8yd7J9wy7kTEl4Qu4jWbGQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-arm64": { + "version": "2.57.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.57.0.tgz", + "integrity": "sha512-Kh1jTsMV5Fy/RvB381N/woXe1qclRMqsG6kM3Gq6m6afEF/+k3PyQdNW3HXAola6d63EptokLtxPG2xjWQ+w9Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-i686": { + "version": "2.57.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.57.0.tgz", + "integrity": "sha512-EYXghoK/tKd0zqz+KD/ewXXE3u1HLCwG89krweveytBy/qw7M5z58eFvw+iGb1Vnbl1f/fRD0G4E0AbEsPfmpg==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-linux-x64": { + "version": "2.57.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.57.0.tgz", + "integrity": "sha512-CyZrP/ssHmAPLSzfd4ydy7icDnwmDD6o3QjhkWwVFmCd+9slSBMQxpIqpamZmrWE6X4R+xBRbSUjmdoJoZ5yMw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-win32-arm64": { + "version": "2.57.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.57.0.tgz", + "integrity": "sha512-wji/GGE4Lh5I/dNCsuVbg6fRvttvZRG6db1yPW1BSvQRh8DdnVy1CVp+HMqSq0SRy/S4z60j2u+m4yXMoCL+5g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-win32-i686": { + "version": "2.57.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.57.0.tgz", + "integrity": "sha512-hWvzyD7bTPh3b55qvJ1Okg3Wbl0Km8xcL6KvS7gfBl6uss+I6RldmQTP0gJKdHSdf/QlJN1FK0b7bLnCB3wHsg==", + "cpu": [ + "x86", + "ia32" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/@sentry/cli-win32-x64": { + "version": "2.57.0", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.57.0.tgz", + "integrity": "sha512-QWYV/Y0sbpDSTyA4XQBOTaid4a6H2Iwa1Z8UI+qNxFlk0ADSEgIqo2NrRHDU8iRnghTkecQNX1NTt/7mXN3f/A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/unplugin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz", + "integrity": "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.8.1", + "chokidar": "^3.5.3", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.5.0" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/webpack-virtual-modules": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", + "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", + "dev": true, + "license": "MIT" + }, "node_modules/@sentry/cli": { "version": "2.56.1", "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.56.1.tgz", @@ -12450,6 +12743,58 @@ "node": ">=18" } }, + "node_modules/@sentry/webpack-plugin": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sentry/webpack-plugin/-/webpack-plugin-4.6.0.tgz", + "integrity": "sha512-i9Yy2kXCbFKlRST09fV1HsI0naJAfeXxoiUPyh5iCgSo2w7ZwEUlk0tJhupnHZzfSa3OSg01+vVNeeyLYM4tdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sentry/bundler-plugin-core": "4.6.0", + "unplugin": "1.0.1", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "webpack": ">=4.40.0" + } + }, + "node_modules/@sentry/webpack-plugin/node_modules/unplugin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz", + "integrity": "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.8.1", + "chokidar": "^3.5.3", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.5.0" + } + }, + "node_modules/@sentry/webpack-plugin/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@sentry/webpack-plugin/node_modules/webpack-virtual-modules": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", + "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", + "dev": true, + "license": "MIT" + }, "node_modules/@shopify/flash-list": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@shopify/flash-list/-/flash-list-2.0.3.tgz", diff --git a/package.json b/package.json index 1cc3cc12b12a..c50fcbd52ed4 100644 --- a/package.json +++ b/package.json @@ -257,6 +257,7 @@ "@rock-js/platform-ios": "0.11.5", "@rock-js/plugin-metro": "0.11.5", "@rock-js/provider-github": "0.11.5", + "@sentry/webpack-plugin": "^4.6.0", "@storybook/addon-a11y": "^8.6.9", "@storybook/addon-essentials": "^8.6.9", "@storybook/addon-webpack5-compiler-babel": "^3.0.5", From d252967dff68eae4abefd881724d03f7611502d0 Mon Sep 17 00:00:00 2001 From: Tomasz Lesniakiewicz Date: Thu, 30 Oct 2025 13:45:14 +0100 Subject: [PATCH 02/19] feat: enable sentry source map for ios --- ios/NewExpensify.xcodeproj/project.pbxproj | 15 +++++++++++++++ ios/sentry.properties | 3 +++ src/pages/home/ReportScreen.tsx | 9 +++++++++ 3 files changed, 27 insertions(+) create mode 100644 ios/sentry.properties diff --git a/ios/NewExpensify.xcodeproj/project.pbxproj b/ios/NewExpensify.xcodeproj/project.pbxproj index 236658039a3b..ec64317006ce 100644 --- a/ios/NewExpensify.xcodeproj/project.pbxproj +++ b/ios/NewExpensify.xcodeproj/project.pbxproj @@ -384,6 +384,7 @@ D687A4E020266C9380167930 /* [CP] Copy Pods Resources */, 072FAC2AE1685E6A5862C00A /* [CP-User] [RNFB] Core Configuration */, 31A7E8E60AE02E9F7F5A917A /* [CP-User] [RNFB] Crashlytics Configuration */, + AAB7A3D7B518487FA9F9E0EE /* Upload Debug Symbols to Sentry */, ); buildRules = ( ); @@ -785,6 +786,20 @@ shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\nexport RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > `$NODE_BINARY --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/.packager.env'\"`\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open `$NODE_BINARY --print \"require('path').dirname(require.resolve('expo/package.json')) + '/scripts/launchPackager.command'\"` || echo \"Can't start packager automatically\"\n fi\nfi\n"; showEnvVarsInLog = 0; }; + AAB7A3D7B518487FA9F9E0EE /* Upload Debug Symbols to Sentry */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + name = "Upload Debug Symbols to Sentry"; + inputPaths = ( + ); + outputPaths = ( + ); + shellPath = /bin/sh; + shellScript = "/bin/sh ../node_modules/@sentry/react-native/scripts/sentry-xcode-debug-files.sh"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/ios/sentry.properties b/ios/sentry.properties new file mode 100644 index 000000000000..fccb72fe02f7 --- /dev/null +++ b/ios/sentry.properties @@ -0,0 +1,3 @@ +defaults.org=expensify +defaults.project=app +defaults.url=https://expensify.sentry.io/ diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index 47a592bde947..4b3eddcd0428 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -1,6 +1,7 @@ import {PortalHost} from '@gorhom/portal'; import {useFocusEffect, useIsFocused} from '@react-navigation/native'; import {accountIDSelector} from '@selectors/Session'; +import * as Sentry from '@sentry/react-native'; import {deepEqual} from 'fast-equals'; import React, {memo, useCallback, useEffect, useMemo, useRef, useState} from 'react'; import type {FlatList, ViewStyle} from 'react-native'; @@ -11,6 +12,7 @@ import {Animated, DeviceEventEmitter, InteractionManager, View} from 'react-nati import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import Banner from '@components/Banner'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; +import Button from '@components/Button'; import DragAndDropProvider from '@components/DragAndDrop/Provider'; import * as Expensicons from '@components/Icon/Expensicons'; import MoneyReportHeader from '@components/MoneyReportHeader'; @@ -955,6 +957,13 @@ function ReportScreen({route, navigation}: ReportScreenProps) { shouldShowButton /> )} + {/* TODO: REMOVE BEFORE MERGING, ONLY FOR TESTING */} +