diff --git a/fastlane/Fastfile b/fastlane/Fastfile index f974370..2c28484 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -38,6 +38,60 @@ platform :ios do ) end + # Firebase arrives via SPM, so upload-symbols sits in DerivedData instead of + # the ./Pods path fastlane looks in by default. + def crashlytics_upload_symbols_binary + pattern = File.expand_path( + "~/Library/Developer/Xcode/DerivedData/MealMood-*/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/upload-symbols" + ) + found = Dir.glob(pattern) + if found.empty? + UI.user_error!("upload-symbols not found. Build the project once so SPM checks out firebase-ios-sdk.") + end + found.max_by { |path| File.mtime(path) } + end + + # Every dSYM (app + widget) of the most recently archived build. + def latest_archive_dsyms + pattern = File.expand_path("~/Library/Developer/Xcode/Archives/*/MealMood*.xcarchive/dSYMs/*.dSYM") + by_archive = Dir.glob(pattern).group_by { |path| path[/.*\.xcarchive/] } + newest = by_archive.max_by { |archive, _| File.mtime(archive) } + newest ? newest.last : [] + end + + # Safety net for the Xcode build phase, which only uploads the dSYM produced + # locally. Run it once App Store Connect has finished processing the build — + # `beta` uses skip_waiting_for_build_processing, so right after an upload the + # dSYMs are not there yet and this would download nothing. + desc "Download processed dSYMs from App Store Connect and send them to Crashlytics" + lane :refresh_dsyms do |options| + download_dsyms( + api_key: asc_api_key, + version: options[:version] || "latest", + build_number: options[:build] + ) + + dsyms = lane_context[SharedValues::DSYM_PATHS] || [] + if dsyms.empty? + # Expected for a post-bitcode app: Apple recompiles nothing, so it keeps + # no dSYM of its own. Fall back to the ones the local archive produced. + dsyms = latest_archive_dsyms + UI.important("App Store Connect has no dSYMs for this build; using the latest local archive.") + end + + if dsyms.empty? + UI.important("No dSYMs found either — nothing to upload.") + next + end + + upload_symbols_to_crashlytics( + gsp_path: "MealMood/Resources/GoogleService-Info.plist", + binary_path: crashlytics_upload_symbols_binary, + dsym_paths: dsyms + ) + clean_build_artifacts + end + desc "Upload metadata + localized screenshots for an existing TestFlight build (no rebuild, no submit)" lane :publish do |options| version = options[:version] || "1.2.0" diff --git a/fastlane/README.md b/fastlane/README.md index c777c46..e9ce1a6 100644 --- a/fastlane/README.md +++ b/fastlane/README.md @@ -23,6 +23,14 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do Push a new beta build to TestFlight +### ios refresh_dsyms + +```sh +[bundle exec] fastlane ios refresh_dsyms +``` + +Download processed dSYMs from App Store Connect and send them to Crashlytics + ### ios publish ```sh