diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 17419c7d..c8907bd4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -63,39 +63,14 @@ jobs: EOF - name: Build APKs - run: flutter build apk --release --split-per-abi --dart-define=ENABLE_UPDATE_CHECK=true ${{ env.SENTRY_DART_DEFINE }} ${{ env.GIT_COMMIT_DART_DEFINE }} ${{ env.SENTRY_ENV_DART_DEFINE }} ${{ env.DONATIONS_DART_DEFINE }} --obfuscate --split-debug-info=debug-info/android-apk + run: flutter build apk --release --split-per-abi --dart-define=ENABLE_UPDATE_CHECK=true ${{ env.SENTRY_DART_DEFINE }} ${{ env.GIT_COMMIT_DART_DEFINE }} ${{ env.SENTRY_ENV_DART_DEFINE }} --dart-define=SENTRY_DIST=github-android-apk ${{ env.DONATIONS_DART_DEFINE }} --obfuscate --split-debug-info=debug-info/android-apk --extra-gen-snapshot-options=--save-obfuscation-map=debug-info/android-apk/obfuscation.map.json - - name: Stage symbols for upload + - name: Upload symbols to bugs.plezy.app if: github.repository == 'edde746/plezy' - continue-on-error: true - run: | - SYMBOL_ROOT="symbol-inputs/android-apk" - rm -rf "$SYMBOL_ROOT" - mkdir -p "$SYMBOL_ROOT" - - if [ -d "debug-info/android-apk" ]; then - mkdir -p "$SYMBOL_ROOT/debug-info" - cp -R "debug-info/android-apk" "$SYMBOL_ROOT/debug-info/" - fi - - if [ -d "build/app/intermediates/merged_native_libs" ]; then - while IFS= read -r -d '' file; do - mkdir -p "$SYMBOL_ROOT/$(dirname "$file")" - cp "$file" "$SYMBOL_ROOT/$file" - done < <(find build/app/intermediates/merged_native_libs -name '*.so' -type f -print0) - fi - - find "$SYMBOL_ROOT" -type f -print -quit | grep -q . - - - name: Upload symbols artifact - if: github.repository == 'edde746/plezy' - continue-on-error: true - uses: actions/upload-artifact@v4 - with: - name: symbols-android-apk - path: symbol-inputs/android-apk - retention-days: 3 - if-no-files-found: error + env: + BUGS_ADMIN_TOKEN: ${{ secrets.BUGS_ADMIN_TOKEN }} + SENTRY_DIST: github-android-apk + run: ./scripts/upload-symbols.sh android-apk - name: Clean up keystore if: always() @@ -162,39 +137,14 @@ jobs: run: flutter pub get --enforce-lockfile --no-example - name: Build iOS (no codesign) - run: flutter build ios --release --no-codesign --dart-define=ENABLE_UPDATE_CHECK=true ${{ env.SENTRY_DART_DEFINE }} ${{ env.GIT_COMMIT_DART_DEFINE }} ${{ env.SENTRY_ENV_DART_DEFINE }} ${{ env.DONATIONS_DART_DEFINE }} --split-debug-info=debug-info/ios + run: flutter build ios --release --no-codesign --dart-define=ENABLE_UPDATE_CHECK=true ${{ env.SENTRY_DART_DEFINE }} ${{ env.GIT_COMMIT_DART_DEFINE }} ${{ env.SENTRY_ENV_DART_DEFINE }} --dart-define=SENTRY_DIST=github-ios ${{ env.DONATIONS_DART_DEFINE }} --split-debug-info=debug-info/ios - - name: Stage symbols for upload + - name: Upload symbols to bugs.plezy.app if: github.repository == 'edde746/plezy' - continue-on-error: true - run: | - SYMBOL_ROOT="symbol-inputs/ios" - rm -rf "$SYMBOL_ROOT" - mkdir -p "$SYMBOL_ROOT" - - if [ -d "debug-info/ios" ]; then - mkdir -p "$SYMBOL_ROOT/debug-info" - cp -R "debug-info/ios" "$SYMBOL_ROOT/debug-info/" - fi - - if [ -d "build/ios" ]; then - while IFS= read -r -d '' file; do - mkdir -p "$SYMBOL_ROOT/$(dirname "$file")" - cp "$file" "$SYMBOL_ROOT/$file" - done < <(find build/ios -path '*.dSYM/Contents/Resources/DWARF/*' -type f -print0) - fi - - find "$SYMBOL_ROOT" -type f -print -quit | grep -q . - - - name: Upload symbols artifact - if: github.repository == 'edde746/plezy' - continue-on-error: true - uses: actions/upload-artifact@v4 - with: - name: symbols-ios - path: symbol-inputs/ios - retention-days: 3 - if-no-files-found: error + env: + BUGS_ADMIN_TOKEN: ${{ secrets.BUGS_ADMIN_TOKEN }} + SENTRY_DIST: github-ios + run: ./scripts/upload-symbols.sh ios - name: Create IPA run: | @@ -251,39 +201,14 @@ jobs: run: flutter pub get --enforce-lockfile --no-example - name: Build macOS - run: flutter build macos --release --dart-define=ENABLE_UPDATE_CHECK=true ${{ env.SENTRY_DART_DEFINE }} ${{ env.GIT_COMMIT_DART_DEFINE }} ${{ env.SENTRY_ENV_DART_DEFINE }} ${{ env.DONATIONS_DART_DEFINE }} --split-debug-info=debug-info/macos + run: flutter build macos --release --dart-define=ENABLE_UPDATE_CHECK=true ${{ env.SENTRY_DART_DEFINE }} ${{ env.GIT_COMMIT_DART_DEFINE }} ${{ env.SENTRY_ENV_DART_DEFINE }} --dart-define=SENTRY_DIST=github-macos ${{ env.DONATIONS_DART_DEFINE }} --split-debug-info=debug-info/macos - - name: Stage symbols for upload + - name: Upload symbols to bugs.plezy.app if: github.repository == 'edde746/plezy' - continue-on-error: true - run: | - SYMBOL_ROOT="symbol-inputs/macos" - rm -rf "$SYMBOL_ROOT" - mkdir -p "$SYMBOL_ROOT" - - if [ -d "debug-info/macos" ]; then - mkdir -p "$SYMBOL_ROOT/debug-info" - cp -R "debug-info/macos" "$SYMBOL_ROOT/debug-info/" - fi - - if [ -d "build/macos/Build/Products/Release" ]; then - while IFS= read -r -d '' file; do - mkdir -p "$SYMBOL_ROOT/$(dirname "$file")" - cp "$file" "$SYMBOL_ROOT/$file" - done < <(find build/macos/Build/Products/Release -path '*.dSYM/Contents/Resources/DWARF/*' -type f -print0) - fi - - find "$SYMBOL_ROOT" -type f -print -quit | grep -q . - - - name: Upload symbols artifact - if: github.repository == 'edde746/plezy' - continue-on-error: true - uses: actions/upload-artifact@v4 - with: - name: symbols-macos - path: symbol-inputs/macos - retention-days: 3 - if-no-files-found: error + env: + BUGS_ADMIN_TOKEN: ${{ secrets.BUGS_ADMIN_TOKEN }} + SENTRY_DIST: github-macos + run: ./scripts/upload-symbols.sh macos - name: Import Code Signing Certificate env: @@ -439,47 +364,15 @@ jobs: run: flutter pub get --enforce-lockfile --no-example - name: Build Windows x64 - run: flutter build windows --release --dart-define=ENABLE_UPDATE_CHECK=true ${{ env.SENTRY_DART_DEFINE }} ${{ env.GIT_COMMIT_DART_DEFINE }} ${{ env.SENTRY_ENV_DART_DEFINE }} ${{ env.DONATIONS_DART_DEFINE }} --split-debug-info=debug-info/windows-x64 + run: flutter build windows --release --dart-define=ENABLE_UPDATE_CHECK=true ${{ env.SENTRY_DART_DEFINE }} ${{ env.GIT_COMMIT_DART_DEFINE }} ${{ env.SENTRY_ENV_DART_DEFINE }} --dart-define=SENTRY_DIST=github-windows-x64 ${{ env.DONATIONS_DART_DEFINE }} --split-debug-info=debug-info/windows-x64 - - name: Stage symbols for upload + - name: Upload symbols to bugs.plezy.app if: github.repository == 'edde746/plezy' shell: pwsh - continue-on-error: true - run: | - $symbolRoot = 'symbol-inputs/windows-x64' - Remove-Item -Path $symbolRoot -Recurse -Force -ErrorAction SilentlyContinue - New-Item -ItemType Directory -Path $symbolRoot -Force | Out-Null - - $debugInfo = 'debug-info/windows-x64' - if (Test-Path $debugInfo) { - $debugInfoRoot = Join-Path $symbolRoot 'debug-info' - New-Item -ItemType Directory -Path $debugInfoRoot -Force | Out-Null - Copy-Item -Path $debugInfo -Destination $debugInfoRoot -Recurse -Force - } - - $pdbRoot = 'build/windows/x64/runner/Release' - if (Test-Path $pdbRoot) { - Get-ChildItem -Path $pdbRoot -Filter '*.pdb' -Recurse | ForEach-Object { - $relative = [System.IO.Path]::GetRelativePath((Get-Location).Path, $_.FullName) - $destination = Join-Path $symbolRoot $relative - New-Item -ItemType Directory -Path (Split-Path -Parent $destination) -Force | Out-Null - Copy-Item -Path $_.FullName -Destination $destination -Force - } - } - - if (-not (Get-ChildItem -Path $symbolRoot -File -Recurse)) { - throw 'No symbol files staged' - } - - - name: Upload symbols artifact - if: github.repository == 'edde746/plezy' - continue-on-error: true - uses: actions/upload-artifact@v4 - with: - name: symbols-windows-x64 - path: symbol-inputs/windows-x64 - retention-days: 3 - if-no-files-found: error + env: + BUGS_ADMIN_TOKEN: ${{ secrets.BUGS_ADMIN_TOKEN }} + SENTRY_DIST: github-windows-x64 + run: .\scripts\upload-symbols.ps1 windows-x64 - name: Upload x64 build uses: actions/upload-artifact@v4 @@ -525,47 +418,15 @@ jobs: run: flutter pub get --no-example - name: Build Windows arm64 - run: flutter build windows --release --dart-define=ENABLE_UPDATE_CHECK=true ${{ env.SENTRY_DART_DEFINE }} ${{ env.GIT_COMMIT_DART_DEFINE }} ${{ env.SENTRY_ENV_DART_DEFINE }} ${{ env.DONATIONS_DART_DEFINE }} --split-debug-info=debug-info/windows-arm64 + run: flutter build windows --release --dart-define=ENABLE_UPDATE_CHECK=true ${{ env.SENTRY_DART_DEFINE }} ${{ env.GIT_COMMIT_DART_DEFINE }} ${{ env.SENTRY_ENV_DART_DEFINE }} --dart-define=SENTRY_DIST=github-windows-arm64 ${{ env.DONATIONS_DART_DEFINE }} --split-debug-info=debug-info/windows-arm64 - - name: Stage symbols for upload + - name: Upload symbols to bugs.plezy.app if: github.repository == 'edde746/plezy' shell: pwsh - continue-on-error: true - run: | - $symbolRoot = 'symbol-inputs/windows-arm64' - Remove-Item -Path $symbolRoot -Recurse -Force -ErrorAction SilentlyContinue - New-Item -ItemType Directory -Path $symbolRoot -Force | Out-Null - - $debugInfo = 'debug-info/windows-arm64' - if (Test-Path $debugInfo) { - $debugInfoRoot = Join-Path $symbolRoot 'debug-info' - New-Item -ItemType Directory -Path $debugInfoRoot -Force | Out-Null - Copy-Item -Path $debugInfo -Destination $debugInfoRoot -Recurse -Force - } - - $pdbRoot = 'build/windows/arm64/runner/Release' - if (Test-Path $pdbRoot) { - Get-ChildItem -Path $pdbRoot -Filter '*.pdb' -Recurse | ForEach-Object { - $relative = [System.IO.Path]::GetRelativePath((Get-Location).Path, $_.FullName) - $destination = Join-Path $symbolRoot $relative - New-Item -ItemType Directory -Path (Split-Path -Parent $destination) -Force | Out-Null - Copy-Item -Path $_.FullName -Destination $destination -Force - } - } - - if (-not (Get-ChildItem -Path $symbolRoot -File -Recurse)) { - throw 'No symbol files staged' - } - - - name: Upload symbols artifact - if: github.repository == 'edde746/plezy' - continue-on-error: true - uses: actions/upload-artifact@v4 - with: - name: symbols-windows-arm64 - path: symbol-inputs/windows-arm64 - retention-days: 3 - if-no-files-found: error + env: + BUGS_ADMIN_TOKEN: ${{ secrets.BUGS_ADMIN_TOKEN }} + SENTRY_DIST: github-windows-arm64 + run: .\scripts\upload-symbols.ps1 windows-arm64 - name: Upload arm64 build uses: actions/upload-artifact@v4 @@ -708,41 +569,16 @@ jobs: run: flutter pub get --enforce-lockfile --no-example - name: Build Linux x64 - run: flutter build linux --release --dart-define=ENABLE_UPDATE_CHECK=true ${{ env.SENTRY_DART_DEFINE }} ${{ env.GIT_COMMIT_DART_DEFINE }} ${{ env.SENTRY_ENV_DART_DEFINE }} ${{ env.DONATIONS_DART_DEFINE }} --split-debug-info=debug-info/linux-x64 + run: flutter build linux --release --dart-define=ENABLE_UPDATE_CHECK=true ${{ env.SENTRY_DART_DEFINE }} ${{ env.GIT_COMMIT_DART_DEFINE }} ${{ env.SENTRY_ENV_DART_DEFINE }} --dart-define=SENTRY_DIST=github-linux-x64 ${{ env.DONATIONS_DART_DEFINE }} --split-debug-info=debug-info/linux-x64 env: PKG_CONFIG_PATH: ${{ github.workspace }}/libmpv-prefix/lib/pkgconfig:${{ github.workspace }}/libmpv-prefix/lib/x86_64-linux-gnu/pkgconfig - - name: Stage symbols for upload + - name: Upload symbols to bugs.plezy.app if: github.repository == 'edde746/plezy' - continue-on-error: true - run: | - SYMBOL_ROOT="symbol-inputs/linux-x64" - rm -rf "$SYMBOL_ROOT" - mkdir -p "$SYMBOL_ROOT" - - if [ -d "debug-info/linux-x64" ]; then - mkdir -p "$SYMBOL_ROOT/debug-info" - cp -R "debug-info/linux-x64" "$SYMBOL_ROOT/debug-info/" - fi - - if [ -d "build/linux" ]; then - while IFS= read -r -d '' file; do - mkdir -p "$SYMBOL_ROOT/$(dirname "$file")" - cp "$file" "$SYMBOL_ROOT/$file" - done < <(find build/linux -path '*/release/bundle/plezy' -type f -print0) - fi - - find "$SYMBOL_ROOT" -type f -print -quit | grep -q . - - - name: Upload symbols artifact - if: github.repository == 'edde746/plezy' - continue-on-error: true - uses: actions/upload-artifact@v4 - with: - name: symbols-linux-x64 - path: symbol-inputs/linux-x64 - retention-days: 3 - if-no-files-found: error + env: + BUGS_ADMIN_TOKEN: ${{ secrets.BUGS_ADMIN_TOKEN }} + SENTRY_DIST: github-linux-x64 + run: ./scripts/upload-symbols.sh linux-x64 - name: Build Linux Packages run: ARCH_SUFFIX=x64 OUTPUT_DIR=$GITHUB_WORKSPACE python3 linux/packaging/build-packages.py @@ -847,41 +683,16 @@ jobs: run: flutter pub get --no-example - name: Build Linux arm64 - run: flutter build linux --release --dart-define=ENABLE_UPDATE_CHECK=true ${{ env.SENTRY_DART_DEFINE }} ${{ env.GIT_COMMIT_DART_DEFINE }} ${{ env.SENTRY_ENV_DART_DEFINE }} ${{ env.DONATIONS_DART_DEFINE }} --split-debug-info=debug-info/linux-arm64 + run: flutter build linux --release --dart-define=ENABLE_UPDATE_CHECK=true ${{ env.SENTRY_DART_DEFINE }} ${{ env.GIT_COMMIT_DART_DEFINE }} ${{ env.SENTRY_ENV_DART_DEFINE }} --dart-define=SENTRY_DIST=github-linux-arm64 ${{ env.DONATIONS_DART_DEFINE }} --split-debug-info=debug-info/linux-arm64 env: PKG_CONFIG_PATH: ${{ github.workspace }}/libmpv-prefix/lib/pkgconfig:${{ github.workspace }}/libmpv-prefix/lib/aarch64-linux-gnu/pkgconfig - - name: Stage symbols for upload + - name: Upload symbols to bugs.plezy.app if: github.repository == 'edde746/plezy' - continue-on-error: true - run: | - SYMBOL_ROOT="symbol-inputs/linux-arm64" - rm -rf "$SYMBOL_ROOT" - mkdir -p "$SYMBOL_ROOT" - - if [ -d "debug-info/linux-arm64" ]; then - mkdir -p "$SYMBOL_ROOT/debug-info" - cp -R "debug-info/linux-arm64" "$SYMBOL_ROOT/debug-info/" - fi - - if [ -d "build/linux" ]; then - while IFS= read -r -d '' file; do - mkdir -p "$SYMBOL_ROOT/$(dirname "$file")" - cp "$file" "$SYMBOL_ROOT/$file" - done < <(find build/linux -path '*/release/bundle/plezy' -type f -print0) - fi - - find "$SYMBOL_ROOT" -type f -print -quit | grep -q . - - - name: Upload symbols artifact - if: github.repository == 'edde746/plezy' - continue-on-error: true - uses: actions/upload-artifact@v4 - with: - name: symbols-linux-arm64 - path: symbol-inputs/linux-arm64 - retention-days: 3 - if-no-files-found: error + env: + BUGS_ADMIN_TOKEN: ${{ secrets.BUGS_ADMIN_TOKEN }} + SENTRY_DIST: github-linux-arm64 + run: ./scripts/upload-symbols.sh linux-arm64 - name: Find bundle directory id: find-bundle @@ -944,51 +755,6 @@ jobs: plezy-linux-arm64.rpm plezy-linux-arm64.pkg.tar.zst - upload-symbols: - if: github.repository == 'edde746/plezy' - needs: [build-android, build-ios, build-macos, build-windows-x64, build-windows-arm64, build-linux-x64, build-linux-arm64] - runs-on: ${{ matrix.os }} - permissions: - contents: read - strategy: - fail-fast: false - matrix: - include: - - platform: android-apk - os: ubuntu-latest - command: ./scripts/upload-symbols.sh android-apk symbol-inputs/android-apk - - platform: ios - os: ubuntu-latest - command: ./scripts/upload-symbols.sh ios symbol-inputs/ios - - platform: macos - os: ubuntu-latest - command: ./scripts/upload-symbols.sh macos symbol-inputs/macos - - platform: windows-x64 - os: windows-latest - command: ./scripts/upload-symbols.ps1 windows-x64 symbol-inputs/windows-x64 - - platform: windows-arm64 - os: windows-latest - command: ./scripts/upload-symbols.ps1 windows-arm64 symbol-inputs/windows-arm64 - - platform: linux-x64 - os: ubuntu-latest - command: ./scripts/upload-symbols.sh linux-x64 symbol-inputs/linux-x64 - - platform: linux-arm64 - os: ubuntu-latest - command: ./scripts/upload-symbols.sh linux-arm64 symbol-inputs/linux-arm64 - steps: - - uses: actions/checkout@v4 - - - name: Download symbols artifact - uses: actions/download-artifact@v4 - with: - name: symbols-${{ matrix.platform }} - path: symbol-inputs/${{ matrix.platform }} - - - name: Upload symbols to bugs.plezy.app - env: - BUGS_ADMIN_TOKEN: ${{ secrets.BUGS_ADMIN_TOKEN }} - run: ${{ matrix.command }} - create-release: needs: [build-android, build-ios, build-macos, package-windows, build-linux-x64, build-linux-arm64] runs-on: ubuntu-latest diff --git a/android/fastlane/Fastfile b/android/fastlane/Fastfile index f20a6f58..bf8948a5 100644 --- a/android/fastlane/Fastfile +++ b/android/fastlane/Fastfile @@ -1,5 +1,10 @@ require 'dotenv/load' -Dotenv.load("../../.env") +require 'shellwords' + +PROJECT_ROOT = File.expand_path("../..", __dir__) +PROJECT_ROOT_ARG = Shellwords.escape(PROJECT_ROOT) + +Dotenv.load(File.join(PROJECT_ROOT, ".env")) default_platform(:android) @@ -7,7 +12,7 @@ platform :android do desc "Build and deploy to Google Play Store" lane :release do # Get version from pubspec.yaml - pubspec_path = "#{ENV['PWD']}/../pubspec.yaml" + pubspec_path = File.join(PROJECT_ROOT, "pubspec.yaml") pubspec_content = File.read(pubspec_path) version_match = pubspec_content.match(/version:\s*(.+)\+(\d+)/) @@ -19,11 +24,11 @@ platform :android do UI.user_error!("Could not extract version from pubspec.yaml") end - git_commit = `git rev-parse --short HEAD`.strip + git_commit = `git -C #{PROJECT_ROOT_ARG} rev-parse --short HEAD`.strip # Build the Flutter app - sh("cd #{ENV['PWD']}/.. && flutter build appbundle --dart-define=ENABLE_SENTRY=true --dart-define=GIT_COMMIT=#{git_commit} --dart-define=SENTRY_ENVIRONMENT=play-store --obfuscate --split-debug-info=debug-info/android-aab") - sh("cd #{ENV['PWD']}/.. && ./scripts/upload-symbols.sh android-aab") + sh("cd #{PROJECT_ROOT_ARG} && flutter build appbundle --dart-define=ENABLE_SENTRY=true --dart-define=GIT_COMMIT=#{git_commit} --dart-define=SENTRY_ENVIRONMENT=play-store --dart-define=SENTRY_DIST=play-store --obfuscate --split-debug-info=debug-info/android-aab --extra-gen-snapshot-options=--save-obfuscation-map=debug-info/android-aab/obfuscation.map.json") + sh("cd #{PROJECT_ROOT_ARG} && SENTRY_DIST=play-store ./scripts/upload-symbols.sh android-aab") upload_to_play_store( track: "production", @@ -33,8 +38,8 @@ platform :android do ) # Build universal APK for Amazon Appstore (doesn't accept AABs, excludes x86 via env var) - sh("cd #{ENV['PWD']}/.. && AMAZON=1 flutter build apk --release --dart-define=ENABLE_SENTRY=true --dart-define=GIT_COMMIT=#{git_commit} --dart-define=SENTRY_ENVIRONMENT=amazon --obfuscate --split-debug-info=debug-info/android-apk") - sh("cd #{ENV['PWD']}/.. && ./scripts/upload-symbols.sh android-apk") + sh("cd #{PROJECT_ROOT_ARG} && AMAZON=1 flutter build apk --release --dart-define=ENABLE_SENTRY=true --dart-define=GIT_COMMIT=#{git_commit} --dart-define=SENTRY_ENVIRONMENT=amazon --dart-define=SENTRY_DIST=amazon --obfuscate --split-debug-info=debug-info/android-apk --extra-gen-snapshot-options=--save-obfuscation-map=debug-info/android-apk/obfuscation.map.json") + sh("cd #{PROJECT_ROOT_ARG} && SENTRY_DIST=amazon ./scripts/upload-symbols.sh android-apk") upload_to_amazon_appstore( apk_paths: [ diff --git a/ios/fastlane/Fastfile b/ios/fastlane/Fastfile index e696fe4a..31f110e1 100644 --- a/ios/fastlane/Fastfile +++ b/ios/fastlane/Fastfile @@ -1,18 +1,23 @@ require 'dotenv/load' -Dotenv.load("../../.env") +require 'shellwords' + +PROJECT_ROOT = File.expand_path("../..", __dir__) +PROJECT_ROOT_ARG = Shellwords.escape(PROJECT_ROOT) + +Dotenv.load(File.join(PROJECT_ROOT, ".env")) default_platform(:ios) platform :ios do desc "Build and deploy to App Store" lane :deploy_appstore do - git_commit = `git rev-parse --short HEAD`.strip + git_commit = `git -C #{PROJECT_ROOT_ARG} rev-parse --short HEAD`.strip # Build the Flutter app - sh("cd #{ENV['PWD']}/.. && flutter build ipa --dart-define=ENABLE_SENTRY=true --dart-define=GIT_COMMIT=#{git_commit} --dart-define=SENTRY_ENVIRONMENT=app-store --split-debug-info=debug-info/ios") + sh("cd #{PROJECT_ROOT_ARG} && flutter build ipa --dart-define=ENABLE_SENTRY=true --dart-define=GIT_COMMIT=#{git_commit} --dart-define=SENTRY_ENVIRONMENT=app-store --dart-define=SENTRY_DIST=app-store --split-debug-info=debug-info/ios") # Upload debug symbols - sh("cd #{ENV['PWD']}/.. && ./scripts/upload-symbols.sh ios") + sh("cd #{PROJECT_ROOT_ARG} && SENTRY_DIST=app-store ./scripts/upload-symbols.sh ios") # Upload to App Store upload_to_app_store( diff --git a/lib/main.dart b/lib/main.dart index cc001f25..315ca6d1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -80,6 +80,7 @@ import 'package:package_info_plus/package_info_plus.dart'; const bool _enableSentry = bool.fromEnvironment('ENABLE_SENTRY', defaultValue: false); const String gitCommit = String.fromEnvironment('GIT_COMMIT'); const String _sentryEnvironment = String.fromEnvironment('SENTRY_ENVIRONMENT'); +const String _sentryDist = String.fromEnvironment('SENTRY_DIST'); // Workaround for Flutter bug #177992: iPadOS 26.1+ misinterprets fake touch events // at (0,0) as barrier taps, causing modals to dismiss immediately. @@ -130,6 +131,7 @@ Future main() async { ? 'plezy@${gitCommit.substring(0, 7)}' : 'plezy@${packageInfo.version}+${packageInfo.buildNumber}'; if (_sentryEnvironment.isNotEmpty) options.environment = _sentryEnvironment; + if (_sentryDist.isNotEmpty) options.dist = _sentryDist; options.tracesSampleRate = 0; options.attachStacktrace = true; options.enableAutoSessionTracking = false; diff --git a/pubspec.lock b/pubspec.lock index 14fb511e..874307a0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -506,6 +506,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.3" + globbing: + dependency: transitive + description: + name: globbing + sha256: "4f89cfaf6fa74c9c1740a96259da06bd45411ede56744e28017cc534a12b6e2d" + url: "https://pub.dev" + source: hosted + version: "1.0.0" graphs: dependency: transitive description: @@ -570,6 +578,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.0" + injector: + dependency: transitive + description: + name: injector + sha256: ed389bed5b48a699d5b9561c985023d0d5cc88dd5ff2237aadcce5a5ab433e4e + url: "https://pub.dev" + source: hosted + version: "3.0.0" intl: dependency: "direct main" description: @@ -884,6 +900,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.5" + properties: + dependency: transitive + description: + name: properties + sha256: "333f427dd4ed07bdbe8c75b9ff864a1e70b5d7a8426a2e8bdd457b65ae5ac598" + url: "https://pub.dev" + source: hosted + version: "2.1.1" provider: dependency: "direct main" description: @@ -1013,6 +1037,14 @@ packages: url: "https://github.com/edde746/sentry-dart" source: git version: "9.16.0" + sentry_dart_plugin: + dependency: "direct dev" + description: + name: sentry_dart_plugin + sha256: "2c5f263f8d5aea3cf387a7e03f77e355d35c71bd9a429474d633fbc085b86ceb" + url: "https://pub.dev" + source: hosted + version: "3.3.0" sentry_flutter: dependency: "direct main" description: @@ -1211,6 +1243,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.1" + system_info2: + dependency: transitive + description: + name: system_info2 + sha256: b937736ecfa63c45b10dde1ceb6bb30e5c0c340e14c441df024150679d65ac43 + url: "https://pub.dev" + source: hosted + version: "4.1.0" term_glyph: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 3480442b..eb5514f5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -79,6 +79,7 @@ dev_dependencies: build_runner: ^2.13.0 json_serializable: ^6.7.1 slang_build_runner: ^4.14.0 + sentry_dart_plugin: ^3.3.0 dart_code_linter: ^4.0.2 drift_dev: ^2.28.3 shared_preferences_platform_interface: ^2.4.0 @@ -117,6 +118,13 @@ dependency_overrides: url: https://github.com/edde746/material_symbols_icons ref: 1d8cd83 +sentry: + org: plezy + project: plezy + url: https://bugs.plezy.app + upload_sources: true + commits: false + flutter: uses-material-design: true assets: diff --git a/scripts/upload-symbols.ps1 b/scripts/upload-symbols.ps1 old mode 100644 new mode 100755 index 889906fc..21375392 --- a/scripts/upload-symbols.ps1 +++ b/scripts/upload-symbols.ps1 @@ -1,6 +1,7 @@ #!/usr/bin/env pwsh # Usage: upload-symbols.ps1 [source-root] -# Env: BUGS_ADMIN_TOKEN (required unless BUGS_UPLOAD_DRY_RUN is set), BUGS_URL (default https://bugs.plezy.app) +# Env: SENTRY_AUTH_TOKEN or BUGS_ADMIN_TOKEN (required unless BUGS_UPLOAD_DRY_RUN is set) +# SENTRY_URL or BUGS_URL (default https://bugs.plezy.app) # Platforms: windows-x64 | windows-arm64 param( [Parameter(Mandatory = $true)] @@ -10,15 +11,6 @@ param( $ErrorActionPreference = 'Stop' -$Token = $env:BUGS_ADMIN_TOKEN -$DryRun = -not [string]::IsNullOrEmpty($env:BUGS_UPLOAD_DRY_RUN) -if (-not $DryRun -and [string]::IsNullOrEmpty($Token)) { - Write-Error 'BUGS_ADMIN_TOKEN env var required' - exit 1 -} - -$Url = if ([string]::IsNullOrEmpty($env:BUGS_URL)) { 'https://bugs.plezy.app' } else { $env:BUGS_URL } - $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition $Root = Split-Path -Parent $ScriptDir Set-Location $Root @@ -30,62 +22,118 @@ elseif ([System.IO.Path]::IsPathRooted($SourceRoot)) { $SearchRoot = $SourceRoot } else { - $SearchRoot = Join-Path $Root $SourceRoot + $SearchRoot = [System.IO.Path]::GetFullPath((Join-Path $Root $SourceRoot)) } -$Release = "plezy@$(git rev-parse --short HEAD)" -$Stage = New-Item -ItemType Directory -Path ([System.IO.Path]::GetTempPath()) -Name ([System.IO.Path]::GetRandomFileName()) -Force -$Zip = $null +$BuildRoot = Join-Path $SearchRoot 'build' +$SymbolRoot = Join-Path (Join-Path $SearchRoot 'debug-info') $Platform +$DryRun = -not [string]::IsNullOrEmpty($env:BUGS_UPLOAD_DRY_RUN) -try { - $DebugInfoDir = Join-Path $SearchRoot "debug-info\$Platform" - if (Test-Path $DebugInfoDir) { - Copy-Item -Path "$DebugInfoDir\*" -Destination $Stage -Recurse -Force +$SearchRoots = [System.Collections.Generic.List[string]]::new() +function Add-ExistingRoot([string]$Path) { + if (Test-Path -Path $Path -PathType Container) { + $SearchRoots.Add($Path) } +} - switch ($Platform) { - { $_ -eq 'windows-x64' -or $_ -eq 'windows-arm64' } { - $Arch = $Platform -replace '^windows-', '' - $PdbRoot = Join-Path $SearchRoot "build\windows\$Arch\runner\Release" - if (Test-Path $PdbRoot) { - Get-ChildItem -Path $PdbRoot -Filter '*.pdb' -Recurse | ForEach-Object { - Copy-Item $_.FullName -Destination $Stage -Force - } - } - } - default { - Write-Error "unknown platform: $Platform" - exit 2 +Add-ExistingRoot $SymbolRoot + +switch ($Platform) { + { $_ -eq 'windows-x64' -or $_ -eq 'windows-arm64' } { + Add-ExistingRoot (Join-Path $BuildRoot 'windows') + } + default { + Write-Error "unknown platform: $Platform" + exit 2 + } +} + +function Has-SymbolFile { + foreach ($RootPath in $SearchRoots) { + $First = Get-ChildItem -Path $RootPath -File -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 + if ($null -ne $First) { + return $true } } - - $Files = Get-ChildItem -Path $Stage -File -Recurse - if (-not $Files) { - Write-Error "no symbols found for platform $Platform" - exit 3 - } - - if ($DryRun) { - Write-Host "dry-run: would upload $($Files.Count) symbol file(s) for $Platform release $Release" - $Files | ForEach-Object { Write-Host "dry-run: $_" } - return - } - - $Zip = Join-Path ([System.IO.Path]::GetTempPath()) "symbols-$([System.IO.Path]::GetRandomFileName()).zip" - Compress-Archive -Path (Join-Path $Stage '*') -DestinationPath $Zip -Force - - $Headers = @{ 'Authorization' = "Bearer $Token" } - $Form = @{ - file = Get-Item $Zip - release = $Release - } - - Invoke-RestMethod -Method Post -Uri "$Url/api/0/projects/plezy/plezy/files/dsyms/" ` - -Headers $Headers -Form $Form + return $false } -finally { - Remove-Item -Path $Stage -Recurse -Force -ErrorAction SilentlyContinue - if ($Zip -and (Test-Path $Zip)) { - Remove-Item -Path $Zip -Force -ErrorAction SilentlyContinue + +if (-not (Has-SymbolFile)) { + Write-Error "no symbols found for platform $Platform" + exit 3 +} + +if ([string]::IsNullOrEmpty($env:SENTRY_URL)) { + $env:SENTRY_URL = if ([string]::IsNullOrEmpty($env:BUGS_URL)) { 'https://bugs.plezy.app' } else { $env:BUGS_URL } +} + +if ([string]::IsNullOrEmpty($env:SENTRY_RELEASE)) { + $env:SENTRY_RELEASE = "plezy@$(git rev-parse --short HEAD)" +} + +if ([string]::IsNullOrEmpty($env:SENTRY_LOG_LEVEL)) { + $env:SENTRY_LOG_LEVEL = 'info' +} + +if ([string]::IsNullOrEmpty($env:SENTRY_AUTH_TOKEN) -and -not [string]::IsNullOrEmpty($env:BUGS_ADMIN_TOKEN)) { + $env:SENTRY_AUTH_TOKEN = $env:BUGS_ADMIN_TOKEN +} + +if (-not $DryRun -and [string]::IsNullOrEmpty($env:SENTRY_AUTH_TOKEN)) { + Write-Error 'SENTRY_AUTH_TOKEN or BUGS_ADMIN_TOKEN env var required' + exit 1 +} + +$DartSymbolMapPath = $env:SENTRY_DART_SYMBOL_MAP_PATH +if ([string]::IsNullOrEmpty($DartSymbolMapPath)) { + $Candidates = @( + (Join-Path $SymbolRoot 'obfuscation.map.json'), + (Join-Path (Join-Path $BuildRoot 'app\obfuscation') "$Platform.map.json"), + (Join-Path (Join-Path $BuildRoot 'app') 'obfuscation.map.json') + ) + + foreach ($Candidate in $Candidates) { + if (Test-Path -Path $Candidate -PathType Leaf) { + $DartSymbolMapPath = $Candidate + break + } } } + +$PluginArgs = @( + "--sentry-define=release=$($env:SENTRY_RELEASE)", + "--sentry-define=url=$($env:SENTRY_URL)", + "--sentry-define=build_path=$BuildRoot" +) + +if (-not [string]::IsNullOrEmpty($env:SENTRY_DIST)) { + $PluginArgs += "--sentry-define=dist=$($env:SENTRY_DIST)" +} + +if (Test-Path -Path $SymbolRoot -PathType Container) { + $PluginArgs += "--sentry-define=symbols_path=$SymbolRoot" +} + +if (-not [string]::IsNullOrEmpty($DartSymbolMapPath)) { + $PluginArgs += "--sentry-define=dart_symbol_map_path=$DartSymbolMapPath" +} + +if ($DryRun) { + Write-Host "dry-run: would upload symbols for $Platform" + Write-Host "dry-run: release=$($env:SENTRY_RELEASE)" + Write-Host "dry-run: dist=$($env:SENTRY_DIST)" + Write-Host "dry-run: source_root=$SearchRoot" + Write-Host "dry-run: build_path=$BuildRoot" + Write-Host "dry-run: symbols_path=$SymbolRoot" + Write-Host "dry-run: dart_symbol_map_path=$DartSymbolMapPath" + foreach ($RootPath in $SearchRoots) { + Get-ChildItem -Path $RootPath -File -Recurse -ErrorAction SilentlyContinue | ForEach-Object { Write-Host $_.FullName } + } + exit 0 +} + +Write-Host "uploading symbols for $Platform release $($env:SENTRY_RELEASE) dist $($env:SENTRY_DIST)" +& dart run sentry_dart_plugin @PluginArgs +if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE +} diff --git a/scripts/upload-symbols.sh b/scripts/upload-symbols.sh index dab15093..2a2d14f5 100755 --- a/scripts/upload-symbols.sh +++ b/scripts/upload-symbols.sh @@ -1,20 +1,13 @@ #!/usr/bin/env bash # Usage: upload-symbols.sh [source-root] -# Env: BUGS_ADMIN_TOKEN (required unless BUGS_UPLOAD_DRY_RUN is set), BUGS_URL (default https://bugs.plezy.app) +# Env: SENTRY_AUTH_TOKEN or BUGS_ADMIN_TOKEN (required unless BUGS_UPLOAD_DRY_RUN is set) +# SENTRY_URL or BUGS_URL (default https://bugs.plezy.app) # Platforms: macos | ios | android-apk | android-aab | linux-x64 | linux-arm64 set -euo pipefail PLATFORM="${1:?platform arg required}" -URL="${BUGS_URL:-https://bugs.plezy.app}" -MAX_ATTEMPTS="${BUGS_UPLOAD_ATTEMPTS:-5}" DRY_RUN="${BUGS_UPLOAD_DRY_RUN:-}" -if [ -z "$DRY_RUN" ]; then - TOKEN="${BUGS_ADMIN_TOKEN:?BUGS_ADMIN_TOKEN env var required}" -else - TOKEN="${BUGS_ADMIN_TOKEN:-}" -fi - SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" cd "$ROOT" @@ -24,109 +17,45 @@ if [[ "$SOURCE_ROOT" != /* ]]; then SOURCE_ROOT="$ROOT/$SOURCE_ROOT" fi -RELEASE="plezy@$(git rev-parse --short HEAD)" -ENDPOINT="${URL}/api/0/projects/plezy/plezy/files/dsyms/" -FILES=() +BUILD_ROOT="$SOURCE_ROOT/build" +SYMBOL_ROOT="$SOURCE_ROOT/debug-info/$PLATFORM" +DART_SYMBOL_MAP_PATH="${SENTRY_DART_SYMBOL_MAP_PATH:-}" -add_matches() { - local path - while IFS= read -r -d '' path; do - FILES+=("$path") - done < <(find "$@" -print0 2>/dev/null || true) -} - -add_debug_info() { - if [ -d "${SOURCE_ROOT}/debug-info/${PLATFORM}" ]; then - add_matches "${SOURCE_ROOT}/debug-info/${PLATFORM}" -type f - fi -} - -file_size() { - wc -c < "$1" | tr -d '[:space:]' -} - -curl_fail_arg() { - if curl --help all 2>/dev/null | grep -q -- '--fail-with-body'; then - printf '%s\n' '--fail-with-body' - else - printf '%s\n' '--fail' - fi -} - -upload_file() { - local file="$1" - local index="$2" - local total="$3" - local size - local body - local attempt - local delay - local fail_arg - - size="$(file_size "$file")" - - if [ -n "$DRY_RUN" ]; then - echo "dry-run: would upload symbols ${index}/${total}: ${file} (${size} bytes)" - return 0 - fi - - body="$(mktemp)" - fail_arg="$(curl_fail_arg)" - - echo "uploading symbols ${index}/${total}: ${file} (${size} bytes)" - - attempt=1 - delay=2 - while [ "$attempt" -le "$MAX_ATTEMPTS" ]; do - if curl "$fail_arg" --silent --show-error \ - --connect-timeout 20 \ - --max-time 600 \ - -o "$body" \ - -X POST \ - -H "Authorization: Bearer ${TOKEN}" \ - -F "file=@${file}" \ - -F "release=${RELEASE}" \ - "$ENDPOINT"; then - rm -f "$body" - return 0 +if [ -z "$DART_SYMBOL_MAP_PATH" ]; then + for candidate in \ + "$SYMBOL_ROOT/obfuscation.map.json" \ + "$BUILD_ROOT/app/obfuscation/$PLATFORM.map.json" \ + "$BUILD_ROOT/app/obfuscation.map.json"; do + if [ -f "$candidate" ]; then + DART_SYMBOL_MAP_PATH="$candidate" + break fi - - if [ "$attempt" -lt "$MAX_ATTEMPTS" ]; then - echo "symbol upload failed for ${file}; retrying in ${delay}s (${attempt}/${MAX_ATTEMPTS})" >&2 - sleep "$delay" - delay=$((delay * 2)) - fi - attempt=$((attempt + 1)) done +fi - echo "symbol upload failed after ${MAX_ATTEMPTS} attempts" >&2 - echo "platform=${PLATFORM}" >&2 - echo "release=${RELEASE}" >&2 - echo "file_count=${total}" >&2 - echo "failed_file=${file}" >&2 - echo "failed_file_size=${size}" >&2 - if [ -s "$body" ]; then - echo "response_body:" >&2 - sed 's/^/ /' "$body" >&2 +SEARCH_ROOTS=() + +add_existing_root() { + if [ -d "$1" ]; then + SEARCH_ROOTS+=("$1") fi - rm -f "$body" - return 1 } -add_debug_info +add_existing_root "$SYMBOL_ROOT" case "$PLATFORM" in macos) - add_matches "${SOURCE_ROOT}/build/macos/Build/Products/Release" -path '*.dSYM/Contents/Resources/DWARF/*' -type f + add_existing_root "$BUILD_ROOT/macos" ;; ios) - add_matches "${SOURCE_ROOT}/build/ios" -path '*.dSYM/Contents/Resources/DWARF/*' -type f + add_existing_root "$BUILD_ROOT/ios" + add_existing_root "$SOURCE_ROOT/ios/build" ;; linux-x64|linux-arm64) - add_matches "${SOURCE_ROOT}/build/linux" -path '*/release/bundle/plezy' -type f + add_existing_root "$BUILD_ROOT/linux" ;; android-apk|android-aab) - add_matches "${SOURCE_ROOT}/build/app/intermediates/merged_native_libs" -name '*.so' -type f + add_existing_root "$BUILD_ROOT/app" ;; *) echo "unknown platform: $PLATFORM" >&2 @@ -134,15 +63,63 @@ case "$PLATFORM" in ;; esac -if [ "${#FILES[@]}" -eq 0 ]; then +found_symbol_file() { + local first + if [ "${#SEARCH_ROOTS[@]}" -eq 0 ]; then + return 1 + fi + + first="$(find "${SEARCH_ROOTS[@]}" -type f -print -quit 2>/dev/null || true)" + [ -n "$first" ] +} + +if ! found_symbol_file; then echo "no symbols found for platform ${PLATFORM}" >&2 exit 3 fi -echo "uploading ${#FILES[@]} symbol file(s) for ${PLATFORM} release ${RELEASE}" +export SENTRY_URL="${SENTRY_URL:-${BUGS_URL:-https://bugs.plezy.app}}" +export SENTRY_RELEASE="${SENTRY_RELEASE:-plezy@$(git rev-parse --short HEAD)}" +export SENTRY_LOG_LEVEL="${SENTRY_LOG_LEVEL:-info}" -index=1 -for file in "${FILES[@]}"; do - upload_file "$file" "$index" "${#FILES[@]}" - index=$((index + 1)) -done +if [ -z "${SENTRY_AUTH_TOKEN:-}" ] && [ -n "${BUGS_ADMIN_TOKEN:-}" ]; then + export SENTRY_AUTH_TOKEN="$BUGS_ADMIN_TOKEN" +fi + +if [ -z "$DRY_RUN" ] && [ -z "${SENTRY_AUTH_TOKEN:-}" ]; then + echo "SENTRY_AUTH_TOKEN or BUGS_ADMIN_TOKEN env var required" >&2 + exit 1 +fi + +PLUGIN_ARGS=( + "--sentry-define=release=${SENTRY_RELEASE}" + "--sentry-define=url=${SENTRY_URL}" + "--sentry-define=build_path=${BUILD_ROOT}" +) + +if [ -n "${SENTRY_DIST:-}" ]; then + PLUGIN_ARGS+=("--sentry-define=dist=${SENTRY_DIST}") +fi + +if [ -d "$SYMBOL_ROOT" ]; then + PLUGIN_ARGS+=("--sentry-define=symbols_path=${SYMBOL_ROOT}") +fi + +if [ -n "$DART_SYMBOL_MAP_PATH" ]; then + PLUGIN_ARGS+=("--sentry-define=dart_symbol_map_path=${DART_SYMBOL_MAP_PATH}") +fi + +if [ -n "$DRY_RUN" ]; then + echo "dry-run: would upload symbols for ${PLATFORM}" + echo "dry-run: release=${SENTRY_RELEASE}" + echo "dry-run: dist=${SENTRY_DIST:-}" + echo "dry-run: source_root=${SOURCE_ROOT}" + echo "dry-run: build_path=${BUILD_ROOT}" + echo "dry-run: symbols_path=${SYMBOL_ROOT}" + echo "dry-run: dart_symbol_map_path=${DART_SYMBOL_MAP_PATH}" + find "${SEARCH_ROOTS[@]}" -type f -print 2>/dev/null || true + exit 0 +fi + +echo "uploading symbols for ${PLATFORM} release ${SENTRY_RELEASE} dist ${SENTRY_DIST:-}" +dart run sentry_dart_plugin "${PLUGIN_ARGS[@]}"