Всем привет, в этой статье я бы хотел поделиться опытом о том, как наша команда столкнулась со сложностями загрузки dSYM в Firebase Crashlytics, и как мы эти сложности решили. Важно сказать пару слов о нашем стеке: все зависимости установлены через Swift Package Manager, мы используем Xcode 14, а в качестве CI CD мы используем Xcode Cloud с первых дней его релиза.
Предыстория
Вся история началась с сообщения от CTO, в котором он спросил, почему ему, после последнего релиза в App Store, на почту приходит много писем такого рода:
Впрочем, помимо CTO такие письма получили все разработчики из разных команд, которые есть в нашем Firebase'e. Чтобы хоть как-то оперативно исправить ситуацию и перестать засорять коллегам почту, я решил отключить email уведомления об этой ошибке на время изучения проблемы. Тогда я узнал, что каждый участник Firebase'а должен самостоятельно отключить для себя эти уведомления.
Кажется, большое количество iOS разработчиков рано или поздно сталкивались с потерянными dSYM файлами, и, как правило, всё сводится к тому, чтобы перепроверить скрипт в Build phase или в CI и вручную догрузить недостающие dSYM файлы. Со скриптом всё было на первый взгляд нормально, поэтому я решил просто скачать из App Store Connect'a dSYM файлы вручную и загрузить их в Firebase Crashlytics, но тут возник нюанс - я не нашёл эти файлы для последних сборок.
Xcode 14 и Bitcode
Незадолго до релиза мы всем составом iOS команды обновились до Xcode 14, а также перевели версию IDE на такую же в нашем релизном workflow в Xcode Cloud. Очевидно, что копать нужно было куда-то туда, и я решил более внимательно изучить список того, что изменилось в последней версии Xcode. Вот что я обнаружил в release notes Xcode 14:
Deprecations
Starting with Xcode 14, bitcode is no longer required for watchOS and tvOS applications, and the App Store no longer accepts bitcode submissions from Xcode 14.
Xcode no longer builds bitcode by default and generates a warning message if a project explicitly enables bitcode: “Building with bitcode is deprecated. Please update your project and/or target settings to disable bitcode.” The capability to build with bitcode will be removed in a future Xcode release. IPAs that contain bitcode will have the bitcode stripped before being submitted to the App Store. Debug symbols can only be downloaded from App Store Connect / TestFlight for existing bitcode submissions and are no longer available for submissions made with Xcode 14. (86118779)
И да, действительно, я зашёл в App Store Connect и увидел, что в Build metadata для сборки, собранной на 13-ой версии, есть dSYM файлы, но для сборки, которая была собрана на последней, 14-ой версии - их нет.
Где и как скачать dSYM
Для того, чтобы скачать dSYM для сборки из Xcode Cloud, я перешёл в интересующую меня сборку в панели Xcode Cloud, и затем, в разделе Artifacts, я скачал iOS архив, который представляет из себя .xcarchive
файл. dSYM файлы я обнаружил, когда открыл .xcarchive
файл через Show Package Contents и перешёл в папку dSYM. Затем я успешно загрузил всё это в Firebase Crashlytics вручную, но осталась последняя, и самая интересная часть - это автоматизация процесса загрузки.
Автоматизация загрузки dSYM в Xcode Cloud
Для того, чтобы написать скрипт, который бы автоматизировал процесс загрузки dSYM в крашлитику, нужно было понять, как встроить эту логику в workflow нашего CI. Как известно, в Xcode Cloud существует 3 вида скриптов, каждый из которых будет выполнен в определённый момент времени. Подробно о custom builds scripts, и как их добавить в ваш workflow отлично описано в документации.
В нашем случае, интересует именно post-xcodebuild
скрипт, который будет выполнен после успешной сборки. Далее, нам необходимо понимать, как мы можем получить доступ к upload-symbols
скрипту от Firebase (документация), который и будет выгружать наши dSYM. В Xcode Cloud существует набор некоторых переменных, к которым мы можем обратиться в любом из скриптов – речь о Environment variables. Здесь я не буду разбирать каждую из переменных, они, впрочем, отлично описаны в самой документации. Для нашей задачи нам понадобиться всего лишь две:
CI_DERIVED_DATA_PATH
- это именно тот каталог, углубившись в который можно найтиupload-symbols
скрипт. * Аналогичный каталог вы можете найти и у себя локально в/Library/Developer/Xcode/DerivedData/Your build
;CI_ARCHIVE_PATH
- это путь к.xcarchive
файлу, про который я рассказывал выше. Это то самое место, откуда мы будем забирать свежие dSYM файлы.
Наш скрипт должен делать всего лишь одно действие: запускать upload-symbols
скрипт с правильными аргументами (валидный путь к .plist и dSYM). Вот, что у меня получилось:
#!/bin/sh
set -e
if [[ -n $CI_ARCHIVE_PATH ]];
then
echo "Archive path is available. Let's run dSYMs uploading script"
# Move up to parent directory
cd ..
# Debug
echo "Derived data path: $CI_DERIVED_DATA_PATH"
echo "Archive path: $CI_ARCHIVE_PATH"
# Crashlytics dSYMs script
$CI_DERIVED_DATA_PATH/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/upload-symbols -gsp /GoogleService-Info.plist -p ios $CI_ARCHIVE_PATH/dSYMs
else
echo "Archive path isn't available. Unable to run dSYMs uploading script."
fi
Впрочем вот и всё, давайте запустим workflow с этим скриптом и посмотрим на логи. Скрипт выполнен успешно и dSYM файлы загружены в крашлитику.
Дополнительно
Если вы столкнулись с подобным warning'ом, то обратите внимание на информацию из документации Apple:
Important
Xcode Cloud uses
zsh
as its default Unix shell. As a best practice, always include a shebang in the first line of your custom build script; for example#!/bin/sh
.
Обязательно измените тип вашего файла на исполняемый, это можно сделать с помощью команды:
chmod +x ci_post_xcodebuild.sh
На этом всё, наш скрипт готов. Благодарю за внимание и буду рад ответить на интересующие вопросы.