|
| 1 | +# 71. Mobile Sentry Source Maps & Native Symbols Automation |
| 2 | + |
| 3 | +Date: 2026-02-11 |
| 4 | + |
| 5 | +## Status |
| 6 | + |
| 7 | +Accepted |
| 8 | + |
| 9 | +## Context |
| 10 | + |
| 11 | +The `tmail-flutter` application utilizes Sentry for error monitoring. While the Web platform successfully uploads source maps for readable stack traces, the Mobile platforms (Android & iOS) currently lack this capability. |
| 12 | + |
| 13 | +Mobile crash reports on Sentry are currently unreadable due to platform-specific obfuscation: |
| 14 | + |
| 15 | +1. **Android (Java/Kotlin):** Native code is minified and obfuscated by R8/ProGuard (e.g., classes appear as `a.b.c`). |
| 16 | +2. **iOS (Obj-C/Swift):** Native crash reports contain raw memory addresses (hexadecimal) instead of symbols, requiring **dSYM** files to resolve. |
| 17 | +3. **Flutter (Dart - Both Platforms):** The compiled Dart native code (ARM64) lacks debug information, displaying raw memory addresses instead of file names and line numbers. |
| 18 | + |
| 19 | +This limitation makes debugging production crashes—whether they are `NullPointerExceptions` on Android, `EXC_BAD_ACCESS` on iOS, or logic errors deep within Dart code—nearly impossible. |
| 20 | + |
| 21 | +There is a requirement to automate the upload of **ProGuard Mapping** (Android), **dSYMs** (iOS), and **Dart Debug Symbols** (Both) to Sentry within the CI/CD pipeline for every release. |
| 22 | + |
| 23 | +## Decision |
| 24 | + |
| 25 | +We have decided to update the Android and iOS Build/Release workflows to support comprehensive de-obfuscation on Sentry. |
| 26 | + |
| 27 | +### 1. Build Configuration (Fastlane) |
| 28 | + |
| 29 | +We updated the `Fastfile` for both platforms to enforce code obfuscation and the separation of debug information. |
| 30 | + |
| 31 | +#### Android |
| 32 | + |
| 33 | +We modified the build command to use `--obfuscate` and `--split-debug-info`. |
| 34 | + |
| 35 | +| Parameter | Value | Purpose | |
| 36 | +| --- | --- | --- | |
| 37 | +| `--obfuscate` | `true` | Minifies code to reduce size and obfuscate logic. | |
| 38 | +| `--split-debug-info` | `../build/app/outputs/symbols` | Extracts debug info into a separate directory. | |
| 39 | + |
| 40 | +#### iOS (Hybrid Strategy) |
| 41 | + |
| 42 | +We adopted a **Hybrid Build Strategy** because the standard Fastlane `build_app` (gym) action does not natively support Flutter's obfuscation flags. |
| 43 | + |
| 44 | +1. **Compile & Archive:** We use `flutter build ipa` directly via shell to compile code with obfuscation flags and generate an `.xcarchive`. |
| 45 | +2. **Export:** We use Fastlane's `build_app` only to sign and export the pre-built archive into an `.ipa`. |
| 46 | + |
| 47 | +**iOS Command (Fastfile):** |
| 48 | + |
| 49 | +```ruby |
| 50 | +# Step 1: Compile with obfuscation and symbols |
| 51 | +sh "flutter", "build", "ipa", "--release", "--obfuscate", "--split-debug-info=../build/ios/outputs/symbols", "--export-method=app-store" |
| 52 | + |
| 53 | +# Step 2: Export IPA using Fastlane Gym |
| 54 | +build_app(..., skip_build_archive: true, archive_path: "../build/ios/archive/Runner.xcarchive") |
| 55 | + |
| 56 | +``` |
| 57 | + |
| 58 | +### 2. CI Pipeline Strategy (GitHub Actions) |
| 59 | + |
| 60 | +The GitHub Actions `release.yaml` workflow has been expanded to include a unified **Sentry Artifact Upload** step immediately following a successful build. |
| 61 | + |
| 62 | +The process flow is as follows: |
| 63 | + |
| 64 | +1. **Build App:** Fastlane generates the binaries (`.aab`/`.ipa`) and the debug artifacts (`mapping.txt`, `dSYMs`, `symbols/`). |
| 65 | +2. **Create Release:** A Sentry release is created, matching the version defined in `pubspec.yaml`. |
| 66 | +3. **Upload Native Artifacts:** |
| 67 | +* **Android:** Uploads `mapping.txt` (ProGuard). |
| 68 | +* **iOS:** Finds and uploads `Runner.app.dSYM` located inside the `.xcarchive`. |
| 69 | + |
| 70 | + |
| 71 | +4. **Upload Dart Artifacts:** The `.symbols` directories for both platforms are scanned and uploaded to de-obfuscate Flutter crashes. |
| 72 | +5. **Finalize:** The release is marked as final. |
| 73 | + |
| 74 | +### 3. Artifact Locations |
| 75 | + |
| 76 | +We standardized the artifact output locations in the CI environment: |
| 77 | + |
| 78 | +| Platform | Artifact Type | Path | Purpose | |
| 79 | +| --- | --- | --- | --- | |
| 80 | +| **Android** | ProGuard Mapping | `build/app/outputs/mapping/release/mapping.txt` | De-obfuscate Java/Kotlin | |
| 81 | +| **Android** | Dart Symbols | `build/app/outputs/symbols` | De-obfuscate Flutter (Android) | |
| 82 | +| **iOS** | Native dSYM | `build/ios/archive/Runner.xcarchive/dSYMs` | De-obfuscate Obj-C/Swift | |
| 83 | +| **iOS** | Dart Symbols | `build/ios/outputs/symbols` | De-obfuscate Flutter (iOS) | |
| 84 | + |
| 85 | +## Consequences |
| 86 | + |
| 87 | +### Benefits |
| 88 | + |
| 89 | +* **Full Stacktrace Visibility:** Sentry will accurately display filenames, function names, and line numbers for Dart, Java/Kotlin, and Swift/Obj-C crashes. |
| 90 | +* **Automated Workflow:** Eliminates manual upload steps, preventing "missing dSYM" errors common in iOS releases. |
| 91 | +* **Optimized App Size:** Using `--split-debug-info` reduces the final download size of the application for users on both platforms. |
| 92 | +* **Platform Parity:** Ensures debugging capabilities are consistent across Web, Android, and iOS. |
| 93 | + |
| 94 | +### Trade-offs |
| 95 | + |
| 96 | +* **Build Time:** Release build times increase slightly due to symbol separation and network upload time. |
| 97 | +* **Fastlane Complexity (iOS):** The iOS Fastfile is more complex due to the split between "Build Archive" and "Export IPA" steps. |
| 98 | +* **CI Configuration:** Requires careful management of pathing (`working-directory`) in GitHub Actions to distinguish between Android and iOS build artifacts. |
| 99 | + |
| 100 | +## Developer Guidelines |
| 101 | + |
| 102 | +### Verification |
| 103 | + |
| 104 | +To verify a successful upload: |
| 105 | + |
| 106 | +1. Navigate to Sentry Project > **Releases**. |
| 107 | +2. Select the recently built version. |
| 108 | +3. Check the **Artifacts** tab. You should see: |
| 109 | +* **Android:** `mapping.txt` (Type: *ProGuard*). |
| 110 | +* **iOS:** Files ending in `.dSYM` (Type: *Debug Information*). |
| 111 | +* **Both:** Files ending in `.symbols` (Type: *Debug Information*). |
| 112 | + |
| 113 | + |
| 114 | + |
| 115 | +### Troubleshooting |
| 116 | + |
| 117 | +* **iOS "Missing dSYM":** If Sentry says dSYMs are missing, ensure `Bitcode` is disabled in Xcode (standard for Flutter). Also, verify the CI script is looking inside the `.xcarchive`. |
| 118 | +* **"No such file or directory":** Ensure no `flutter clean` commands run between the **Build** and **Upload** steps. |
| 119 | +* **Sentry Auth:** Verify `SENTRY_AUTH_TOKEN`, `SENTRY_ORG`, and `SENTRY_PROJECT` secrets are active. |
0 commit comments