From 825f07fb9d554ffe3f93ed1e79213c40be124d34 Mon Sep 17 00:00:00 2001 From: Michal Urbanek Date: Mon, 4 May 2026 10:01:34 +0200 Subject: [PATCH 1/2] feat: Archive symbols for obfuscation when creating iOS release --- .../flutter-template-release-builds/SKILL.md | 26 ++++++++++++++----- .../scripts/archive_ios_ipa.sh | 16 ++++++++++++ 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/ai/skills/flutter-template-release-builds/SKILL.md b/ai/skills/flutter-template-release-builds/SKILL.md index f3c4723..edf0cba 100644 --- a/ai/skills/flutter-template-release-builds/SKILL.md +++ b/ai/skills/flutter-template-release-builds/SKILL.md @@ -1,6 +1,6 @@ --- name: flutter-template-release-builds -description: Run post-merge release build steps for this repository, including Android tag-driven releases and sequential iOS IPA generation with archival for Transporter upload. Use after the release PR has been merged. +description: Run post-merge release build steps for this repository, including Android tag-driven releases and sequential iOS IPA generation with archival for Transporter upload and Crashlytics deobfuscation. Use after the release PR has been merged. --- # Flutter Template Release Builds @@ -23,6 +23,7 @@ It covers: - Android release triggering by tags - iOS IPA generation - archiving IPA files outside the cleaned build folder for Transporter upload +- archiving Flutter obfuscation symbols from `build/app/outputs/symbols` for Crashlytics Dart stack-trace deobfuscation ## Android Release Flow Android releases are triggered by tags after the release branch work is merged. @@ -45,7 +46,7 @@ iOS release builds are manual and should be done one flavor at a time. Why: - each make target runs `make clean` - each build clears the `build/` directory -- IPA files must be copied out of `build/ios/ipa/` before the next build if you want to keep all generated artifacts +- IPA files and Flutter obfuscation symbols must be copied out of `build/` before the next build if you want to keep all generated artifacts ## iOS Build Commands - develop: @@ -55,8 +56,8 @@ Why: - production: - `make generateIosProductionIpa` -## IPA Archival Workflow -Immediately after each IPA build, archive the IPA out of `build/ios/ipa/` before starting the next build. +## iOS Artifact Archival Workflow +Immediately after each IPA build, archive the IPA out of `build/ios/ipa/` and Flutter obfuscation symbols out of `build/app/outputs/symbols` before starting the next build. Use: @@ -77,18 +78,29 @@ release_artifacts/ios-ipa// and renames it to include the flavor plus the full `pubspec.yaml` version token, including the build number, so multiple release IPAs can coexist even when only the build number changes. +It also copies the Flutter obfuscation symbols into: + +```text +release_artifacts/flutter-symbols/// +``` + +These are the `--split-debug-info` Dart symbol files used for Flutter Crashlytics deobfuscation. They are separate from iOS dSYMs and Android R8/ProGuard `mapping.txt`. + ## Recommended iOS Sequence 1. Build one flavor. -2. Archive the IPA with the helper script. +2. Archive the IPA and Flutter obfuscation symbols with the helper script. 3. Build the next flavor. -4. Archive that IPA too. +4. Archive that IPA and its symbols too. 5. Repeat until all required IPA files are archived. 6. After all IPA files are safely archived, upload them manually through Transporter. +7. Keep the archived Flutter obfuscation symbols with the release artifacts for Crashlytics deobfuscation. ## Watch Outs - Do not run multiple iOS make targets back-to-back without archiving. - Do not assume the last-built IPA still exists in `build/ios/ipa/`. +- Do not assume the last-built Flutter obfuscation symbols still exist in `build/app/outputs/symbols`. - The archival helper expects exactly one IPA in `build/ios/ipa/` and fails loudly if multiple files are present. +- The archival helper also expects `build/app/outputs/symbols` to exist and contain at least one file. - Transporter is the handoff point to App Store Connect. - Android and iOS release flows are intentionally different in this repo. - Transporter delivery is currently a manual step in this workflow, not an automated repo-integrated step. @@ -97,5 +109,7 @@ and renames it to include the flavor plus the full `pubspec.yaml` version token, - Android tags match the intended workflows - each iOS IPA is generated one-at-a-time - each iOS IPA is copied out of the build folder +- each iOS build's Flutter obfuscation symbols are copied out of the build folder - archived IPA filenames include flavor and the full app version token +- archived Flutter obfuscation symbols are grouped by version and flavor - the team has a clean handoff path into Transporter diff --git a/ai/skills/flutter-template-release-builds/scripts/archive_ios_ipa.sh b/ai/skills/flutter-template-release-builds/scripts/archive_ios_ipa.sh index 039f25d..80d8215 100644 --- a/ai/skills/flutter-template-release-builds/scripts/archive_ios_ipa.sh +++ b/ai/skills/flutter-template-release-builds/scripts/archive_ios_ipa.sh @@ -45,8 +45,24 @@ ipa_path="$ipa_matches" ipa_name="$(basename "$ipa_path" .ipa)" destination_dir="release_artifacts/ios-ipa/$version" destination_path="$destination_dir/${ipa_name}-${flavor}-${version}.ipa" +symbols_source_dir="build/app/outputs/symbols" +symbols_destination_dir="release_artifacts/flutter-symbols/$version/$flavor" + +if [ ! -d "$symbols_source_dir" ]; then + echo "No Flutter obfuscation symbols directory found at $symbols_source_dir" >&2 + exit 1 +fi + +if [ -z "$(find "$symbols_source_dir" -type f -maxdepth 1 | head -n 1)" ]; then + echo "No Flutter obfuscation symbol files found in $symbols_source_dir" >&2 + exit 1 +fi mkdir -p "$destination_dir" cp "$ipa_path" "$destination_path" +rm -rf "$symbols_destination_dir" +mkdir -p "$symbols_destination_dir" +cp "$symbols_source_dir"/* "$symbols_destination_dir"/ echo "Archived IPA to $destination_path" +echo "Archived Flutter obfuscation symbols to $symbols_destination_dir" From 5374ac5a84c96e724e7ccbd9e27514cf1a211b0e Mon Sep 17 00:00:00 2001 From: Michal Urbanek Date: Wed, 6 May 2026 14:05:31 +0200 Subject: [PATCH 2/2] fix: AI PR review --- .../scripts/archive_ios_ipa.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ai/skills/flutter-template-release-builds/scripts/archive_ios_ipa.sh b/ai/skills/flutter-template-release-builds/scripts/archive_ios_ipa.sh index 80d8215..11bf2d1 100644 --- a/ai/skills/flutter-template-release-builds/scripts/archive_ios_ipa.sh +++ b/ai/skills/flutter-template-release-builds/scripts/archive_ios_ipa.sh @@ -53,7 +53,7 @@ if [ ! -d "$symbols_source_dir" ]; then exit 1 fi -if [ -z "$(find "$symbols_source_dir" -type f -maxdepth 1 | head -n 1)" ]; then +if [ -z "$(find "$symbols_source_dir" -maxdepth 1 -type f | head -n 1)" ]; then echo "No Flutter obfuscation symbol files found in $symbols_source_dir" >&2 exit 1 fi @@ -62,7 +62,7 @@ mkdir -p "$destination_dir" cp "$ipa_path" "$destination_path" rm -rf "$symbols_destination_dir" mkdir -p "$symbols_destination_dir" -cp "$symbols_source_dir"/* "$symbols_destination_dir"/ +find "$symbols_source_dir" -maxdepth 1 -type f -exec cp {} "$symbols_destination_dir"/ \; echo "Archived IPA to $destination_path" echo "Archived Flutter obfuscation symbols to $symbols_destination_dir"