Automatically download and upload dSYM symbolication files from iTunes Connect for Bitcode iOS apps using fastlane

When submitting iOS apps to the App Store with Bitcode enabled, your app gets recompiled by Apple, to be optimized for specific devices and architectures. While Bitcode is optional, it’s more and more encouraged by Apple, and even required for watchOS and tvOS apps.

Due to the fact that recompiling happens on Apple’s servers, third party crash reporters don’t have access to the symbolication files, which are required to properly associate the crash stack trace with the exact files and line numbers in your source code.

The current solution to solve this for Bitcode enabled apps is to manually download the dSYM files from Apple and upload them to your crash reporting service. Downloading the files can be done either using Xcode or iTunes Connect. 

Download dSYM symbolication files using the Xcode OrganizerDownload dSYM symbolication files using the Xcode Organizer

Download dSYM symbolication files from iTunes ConnectDownload dSYM symbolication files from iTunes Connect

The problem with this approach is not only the time you spend doing this manually for every single release, but also the lack of automation. There was no way to automatically do this process after every release, or just periodically on every day, so you end up spending a lot of engineering time on repetitive tasks.

Introducing automatic fastlane dSYM download

With the latest version of fastlane, you can now easily download all available dSYM symbolication files from iTunes Connect and upload them straight to the crash reporting service of your choice.

lane :refresh_dsyms do
  download_dsyms                  # Download dSYM files from iTC
  upload_symbols_to_crashlytics   # Upload them to Crashlytics
  clean_build_artifacts           # Delete the local dSYM files
end

All you have to do is define a lane (as seen above) and run:

fastlane refresh_dsyms

It’s easy to just run this task on your existing CI infrastructure every day or so, however you’re totally free to trigger it whenever and wherever you want. 

dSYM download in action - click on the gif to start it from the beginning dSYM download in action

You can find more information about the available options in the fastlane docs.

Currently the dSYM upload is supported by Crashlytics, Sentry and HockeyApp. If your service is still missing and they provide an API, feel free to submit a PR to add it to fastlane.

Open Source

As always, everything described in this article is completely open source under the MIT license, check out the following source files:


Getting started

If you’re already using fastlane, just update your existing Fastfile and add the new refresh_dsyms lane to it.

Step 1: Install fastlane

If you haven’t yet had the change to try fastlane, now is the perfect time. To quickly get started:

[sudo] gem install fastlane --verbose
cd your/project
mkdir fastlane && touch fastlane/Fastfile fastlane/Appfile

Step 2: Update Appfile

Edit your Appfile to include your bundle identifier and iTunes Connect Apple ID.

Step 3: Update Fastfile

Update your Fastfile to include the refresh_dsyms lane (seen above). You’re all set, now you can run 

Step 4: Enjoy fastlane

fastlane refresh_dsyms

On the first run you’ll be asked for your password, which will be stored in your local Keychain. 

You wonder what else you can add to your Fastfile? Check out the available actions to see all 170 built-in fastlane integrations, you can already use today. 

Edit on GitHub

Our goal to unify fastlane tools

I’ve been working as an iOS developer for over 5 years for various companies around the world. During that time it became clear there was lots of room for improvements around mobile developer tools, and in particular, the deployment of apps. Because of that, I started implementing little tools to help me automate tedious tasks like uploading metadata for release builds or generating screenshots. Each of those tools had no connection with each other and ran as standalone commands. About 4 months after the initial release of deliver, snapshot and frameit, I noticed one common theme: All users of those tools developed their own shell scripts to trigger different deployment steps, pass on information, and ensure every step was successful.

I wanted to help developers connect all the tools they use into one simple workflow. That’s why I created fastlane.

But as the community grew and the architecture became more complex, I needed to think about how we could best build the foundation of fastlane to continue to be a tool you love to use. 

In its current setup, we ran into these problems:

  • When releasing a spaceship bugfix, it required us to do at least five releases just to roll out the change to all users
  • fastlane has its own repo just to manage the other repos called “countdown”
  • The fastlane organization has over 30 GitHub repositories
  • I added 360 commits whose only purpose was to update internal dependencies between fastlane tools
  • We ended up with a lot of duplicate issues across multiple repos
  • Having 20 different travis builds to keep green, instead of just one

  • Working on a new feature or big change required us to switch to a separate branch on three different repos, which all depended on each other. Not only is it very time consuming to work on three different repo’s feature branches, but also the release takes longer: You have to merge the first PR, then do a release, before you can update the dependency of the other tool, to turn the build green and merge the next one.

  • It’s hard to decide when to release an update for each of the tools, so we built a script to show which tool has the highest number of outstanding changes to be released. Switching to a mono repo allows us to switch to a more regular release cycle

Our goal to unify fastlane tools

To solve a lot of these problems, our team decided to move all fastlane tools into one main repository. Each tool will be in a subfolder enabling you easy access to its source code.

I wanted to make this change as seamless and hassle-free as possible for everyone. With this migration, you can still use all tools directly, so your setup will continue to work as normal.

This should not break any existing setups and doesn’t require any action from your side. 

Unifying fastlane means having one place for everything you need. Now, there will be one place to submit and search for issues on GitHub, one place for the documentation, one place to contribute to fastlane, and one tool to install :)

We’ll be making this move within the next couple of weeks.

Technical Details

I’d like to share some more technical information on how the switch will work and the challenges I faced.

The requirements:

  • All individual tools (like deliver, snapshot, etc.) have to be moved into the main fastlane repo
  • We want to preserve the complete history, meaning all commits across all repositories
  • All existing issues on the repositories need to be migrated to the main repo, both open and closed ones
  • I wanted to be sure that every person who contributed to fastlane in the past shows up in the Contribution Graph. fastlane wouldn’t be possible without the great community around it.

To implement all this I created a new repo (ironically) that contains all the scripts used to make the switch. You can find all the source code on fastlane/monorepo.

Moving the tools to the main repo

To move all source code to the main repo and still preserve the history with all commits, we used standard git features. You can check out the full source code on GitHub. Using this technique, all previous commits are still available, and the Contribution Graph shows all developers who ever contributed to fastlane.

Copying the GitHub issues to the main repo

There is no built-in way to migrate or merge issues to another repo. GitHub provides a great API which we used to copy over all existing issues. However the newly copied issues are not created by the original author, but by our fastlane bot instead. On the newly created issue we always mention the original authors, resulting in them being subscribed to the new issue. 

You can check out the full source code on GitHub. With this we worked on a lot of little tricks to make sure users are subscribed to the newly migrated issue and the original author is still visible. The GitHub API doesn’t allow us to post issues as the original author (for good reasons), so we solved this problem by posting the user’s information right inside the actual issue.

Ruby Gems

There are no changes with the way you install fastlane, you can still install tools e.g. using gem install deliver.

What happens to the other GitHub repositories

For SEO reasons we will keep the other repositories around, however the long term plan is to remove them and have everything in the main repo. The old repos will link to the new mono repo, therefore all issues and pull requests will be closed and moved over to the fastlane main repo.

Upgrading fastlane support to the next level 🚀

We took this opportunity to also improve the way we handle issues as a team. Our goal is to be faster and better at responding to all incoming GitHub issues and reviewing pull requests. 

Up until a few months ago, I was managing everything alone, resulting in my not responding to everyone in a timely matter. Thanks to Twitter & Fabric, the fastlane team has grown tremendously in the last few weeks, allowing us to offer world-class help for our thriving community. We want to treat support as a first class citizen and provide the best experience possible.

We’re just getting started: being part of Fabric means a passionate dedicated team to offer the best support & future experience for fastlane customers. We’re just getting started: being part of Fabric means a passionate dedicated team to offer the best support & future experience for fastlane customers.

With that in mind, we have a lot of inactive issues and pull requests spanning the last year when I was still working on this project in my free-time. Out of the 829 open issues across all repos, 273 issues haven’t had any activity within the last 3 months. 

After the migration, we will be constantly looking at all issues to make sure the process is improving. We’ll also be commenting on those inactive issues to see if the problem is still happening for those of you who submitted pull requests. This enables us to be much more responsive to new issues and have a better overview on what to focus our time on. 

The Future

This is one of the most impactful changes to fastlane yet. While there’s a lot of information, it’s very important to the entire team to communicate what we are up to. This migration shows our commitment to innovation and creating the future of fastlane.

I’m confident that this change will make yours and our lives much easier and will save us all a ton of time in the future. We’d love your feedback on this, Tweet at us at any time! :) 

Edit on GitHub

Introducing screengrab, the next big fastlane tool for Android

Before fastlane became part of Twitter, fastlane was only available for iOS applications. This year, at Twitter Flight, we announced Android support for fastlane. We started by helping you ship your app to Google Play using supply. Of course, we also integrated with the tools you already love, like Gradle.

Today, we’re excited to announce screengrab, a new tool to automate taking localised screenshots on different Android devices. It’s similar to snapshot, but for Android apps.

Check out the Fabric Blog Post for more information.

Open on GitHub

Edit on GitHub

Introducing fastlane 'match': A new approach to code signing

A little over a month ago, fastlane officially joined the Fabric team to help even more developers address pain points within mobile development. Since then, I’ve released several new tools to fastlane, including WatchBuild. But one of the biggest pain points I’ve had for years (together with the developer community and my Fabric colleagues), is the headache of code signing when working with teams. This has been an issue since day one of iOS mobile development.

Today, together with the Fabric team, I’m thrilled to introduce match — a new tool that helps automate the code signing process.

When deploying an app to the App Store, a beta testing service or even installing it on your own device, most development teams have separate code signing identities for every member. This results in dozens of profiles including a lot of duplicates.

To solve this, you can share one code signing identity with your team to simplify your setup, but here’s the catch: there’s no simple way to keep the profiles and keys between the various machines in sync . You would have to manually export those keys using Xcode and transfer them between the machines every time you change something in your app. It’s especially frustrating when all you want is to run the app on your phone to test!

This is why we rethought a whole new declarative approach to solve this, with match.

Once you create your own private Git repo, your certificates and profiles are stored there so you can have one code signing identity for the whole team. When you run fastlane, match automatically fetches the latest certificates from the remote Git repo and installs them on your local machine. 

If a profile is missing, fastlane will automatically generate one for you and upload it to your Git repo. 

To use match, all you have to do is specify:

  • the type of the profile (App Store, Ad Hoc or Development)
  • your app’s bundle identifier

Once you provide a separate, private git repo, match will store the iOS certificates provisioning profiles. Additionally, the files are encrypted using openssl.

While app development requires care throughout the deployment process, the goal for match was to make it easier to deal with the complexities of code signing when working with a team. With match, fastlane automatically pre-fills environment variables to enable proper code signing with multiple targets.  

To learn more about the concept open  codesigning.guide.

To get access to the source code and more technical information, visit the GitHub repo.

Open on GitHub

Edit on GitHub