Skip to content

fix(crashlytics): resolve SPM run script for Flutter 3.44+ and custom -derivedDataPath#444

Open
phuongta-pi wants to merge 1 commit into
invertase:mainfrom
phuongta-pi:fix/spm-crashlytics-derived-data-path
Open

fix(crashlytics): resolve SPM run script for Flutter 3.44+ and custom -derivedDataPath#444
phuongta-pi wants to merge 1 commit into
invertase:mainfrom
phuongta-pi:fix/spm-crashlytics-derived-data-path

Conversation

@phuongta-pi
Copy link
Copy Markdown

Description

Fixes #443.

flutterfire configure injects an Xcode Run Script Build Phase that spawns firebase-ios-sdk/Crashlytics/run to upload dSYMs. With Swift Package Manager the binary lives at <derivedDataPath>/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run, but the previous implementation hardcoded a regex that only matches Xcode's standalone DerivedData layout:

DERIVED_DATA_PATH=$(echo "$BUILD_ROOT" | sed -E 's|(.*DerivedData/[^/]+).*|\1|')

This breaks two real-world layouts:

  1. Flutter 3.44+ project-local builds (flutter build ios) place SourcePackages under <project>/build/ios/SourcePackages/..., which contains no DerivedData/ segment — sed leaves BUILD_ROOT untouched and the spawned path doesn't exist (ProcessException: No such file or directory).
  2. xcodebuild -derivedDataPath <custom> runs (e.g. fastlane gym with its per-run isolation directory) place SourcePackages under <custom>/SourcePackages/..., again no DerivedData/ segment.

Fix

Replace the regex with a resolve_spm_run_script helper that strips /Build/... from BUILD_DIR (then BUILT_PRODUCTS_DIR / BUILD_ROOT as fallbacks) to recover the derived-data root. Xcode build settings guarantee BUILD_DIR has the shape <derivedDataPath>/Build/... across all three layouts (Xcode standalone, Flutter project-local, custom -derivedDataPath), so the strip-based anchor is reliable everywhere the previous regex was, plus the two cases it missed.

Also fall back to exit 0 with a warning if no candidate run file exists, so a misconfigured project surfaces a clear message instead of killing the archive with ProcessException.

Type of Change

  • feat -- New feature (non-breaking change which adds functionality)
  • 🛠️ fix -- Bug fix (non-breaking change which fixes an issue)
  • ! -- Breaking change (fix or feature that would cause existing functionality to change)
  • 🧹 refactor -- Code refactor
  • ci -- Build configuration change
  • 📝 docs -- Documentation
  • 🗑️ chore -- Chore

Test plan

The existing integration test Validate flutterfire upload-crashlytics-symbols script is ran when building app (test/configure_test.dart:585) exercises the new resolver end-to-end via flutter build ios --simulator --debug after switching the project to SPM. On Flutter 3.44, that test reproduces #443 with the old regex (flutter build outputs to build/ios, not ~/Library/.../DerivedData/Runner-X) and passes with this fix.

Verified manually against all three layouts:

  • Xcode standalone build (~/Library/Developer/Xcode/DerivedData/Runner-XXXXX)
  • flutter build ios Flutter 3.44.0 (<project>/build/ios/SourcePackages/...)
  • xcodebuild -derivedDataPath custom (fastlane gym per-run dir)

Allow edits by maintainers

  • Edits from maintainers allowed.

… -derivedDataPath

Fixes invertase#443.

`flutterfire configure` injects an Xcode Run Script Build Phase that
spawns `firebase-ios-sdk/Crashlytics/run` to upload dSYMs. With Swift
Package Manager, the binary lives at
`<derivedDataPath>/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run`,
but the previous implementation hardcoded a regex that only matches
Xcode's standalone DerivedData layout:

    DERIVED_DATA_PATH=$(echo "$BUILD_ROOT" | sed -E 's|(.*DerivedData/[^/]+).*|\1|')

This breaks two real-world layouts:

  1. **Flutter 3.44+ project-local builds** (`flutter build ios`) place
     SourcePackages under `<project>/build/ios/SourcePackages/...`, which
     contains no `DerivedData/` segment - sed leaves `BUILD_ROOT`
     untouched and the spawned path doesn't exist
     (`ProcessException: No such file or directory`).
  2. **`xcodebuild -derivedDataPath <custom>`** runs (e.g. fastlane gym
     with its per-run isolation directory) place SourcePackages under
     `<custom>/SourcePackages/...`, again no `DerivedData/` segment.

Replace the regex with a `resolve_spm_run_script` helper that strips
`/Build/...` from `BUILD_DIR` (then `BUILT_PRODUCTS_DIR` /
`BUILD_ROOT` as fallbacks) to recover the derived-data root. Xcode
build settings guarantee `BUILD_DIR` has the shape
`<derivedDataPath>/Build/...` across all three layouts, so the
strip-based anchor is reliable everywhere the previous regex was, plus
the two cases it missed.

Also fall back to `exit 0` with a warning if no candidate `run` file
exists, so a misconfigured project surfaces a clear message instead of
killing the archive with `ProcessException`.

Verified by hand against:
- Xcode standalone DerivedData (`~/Library/.../DerivedData/Runner-X`)
- Flutter `build/ios` derived-data (Flutter 3.44.0, SPM enabled)
- fastlane gym custom `-derivedDataPath`
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug]: upload symbols fails with Flutter 3.44 because the SourcePackages have moved

3 participants