Automating Your App's Release Process Using Fastlane (Firebase Dev Summit 2017)

[MUSIC PLAYING] FELIX KRAUSE: Thank you so much for having us here I’m Felix, one of the engineers here at Google working on Fastlane as part of the Firebase team JOSH LIEBOWITZ: Hey, I’m Josh I work on open source software in Firebase, primarily on Fastlane with Felix And today we’re going to be showing you how you can build your own app integrations and make shipping app updates easier and reproducible FELIX KRAUSE: So we’re going to– Josh is going to start with a short introduction on what Fastlane is and how you can use it And then, after his presentation, we’re going to do a short live demo on how you can extend Fastlane to fit your needs JOSH LIEBOWITZ: Awesome OK, so how would you like to have two extra hours every single week? Well, our talk is all about saving time and automating tasks, so you can spend the time on the things you care about most So today, I’m going to talk about three key issues we as mobile developers face and how we can solve it using Fastlane I want this talk to be very practice-oriented so that everyone can learn something today and we can start using it So I’d be willing to bet that you’ve heard some of these quotes Brian is the only person who knows how to do a release and he’s on vacation so we’ll have to wait Or oh man, our provisioning profiles don’t contain the devices we actually need to be using now So we’re going to have to add them, regenerate the profile, redistribute it and then resign the build Or just our build is broken Also, sometimes the marketing team really wants those new screenshots for the app that you’ve been working on And that can be pretty tedious So these are all things that we’ve heard in the past And these are not things that we really want to hear And so that’s where Fastlane comes into play All right, so release day Super exciting day for all of us All of your hard work finally pays off You want to get your app into your users’ hands, but there are so many steps involved So first you thoroughly test your release candidate and then you take all of the screenshots of all the new features in all the languages and the devices that you support But then you go to build it and you run into signing issues So after you resolve the signing issues, you work on your push certificate if you use notifications So finally, you upload that new build to iTunes Connect or whatever beta service that you’re using, and you can finally, after that, submit it This can easily take an entire day, and that’s time we as developers have to invest I’m sure you prefer to be working on your app So that’s why Fastlane was built It’s a tool that helps you automate all of these tedious tasks like testing, and building, and signing, and deploying your application So Fastlane has a bunch of tools that you can use, but we can also combine them with various third-party tools into one workflow And we can easily automate many parts of our app deployment process with that As an added bonus, Fastlane is open source and available on GitHub All right, so what are we really talking about now? It’s continuous delivery with mobile apps, but what are the goals here? Well, first off, it should be automatic, like push a button and it takes care of everything for you And secondly, we want to store as much of that information about the build in version control And I can’t stress this enough We want the build scripts We want the build info This stuff should be in Git in more version control This way, you have a proper history, and by having everything in one place, it means that you can check out the repo and get started right away Also, everybody, even new developers on the first day of the job, should be able to build your app All you have to do is check out the Git repository And we really don’t want to have internal things like wikis pointing to various different documents describing exactly how we do that So keep it in Git And last, when Brian is on vacation, we still want to be able to deploy that app So we don’t have time to cover everything that Fastlane does, so I’m going to focus on three common problems you’ve probably experienced in the past and how you can solve them using Fastlane So first off, screenshots It’s a huge pain And then our favorite topic, I’m sure, code signing and provisioning profiles And then automation of your deployment process So every time you publish a new app, you have to generate screenshots and upload those to iTunes Connect And over time your app features change You have new designs, you have new languages,

new devices come out It gets surprisingly difficult to do screenshots correctly And just to give you an idea, in iOS, if you’ve got five different screenshots for six devices in 10 languages, you can easily end up with 300 screenshots that you have to generate locally And the pain doesn’t stop there either You need to upload that to iTunes Connect and actually place them in the right place So there’s this one tool that we wrote called Snapshot And we built that to automate the whole process for you So to use it, you basically just tell Snapshot how to navigate into your app and where it takes screenshots It will then iterate through all the languages, all the devices and it’ll generate those screenshots for you And finally, it’ll collect them into a folder and upload them straight to iTunes Connect using another tool called Deliver Now, of course, we have the same tool for Android and that’s called Screengrab It works the same way It just uses Espresso tests, and you can upload all the screenshots straight to Google Play using a Fastlane tool called Supply OK, so that’s really cool, but how does this look in action? Well, if you already have Snapshots set up, all you have to do is enter Fastlane Snapshot in the command line, and Snapshot will automatically detect your project settings and start running UI tests You can already see the simulator jumping up right here So what’s really cool is that this can run in the background and concurrently, so you can do something else while your computer is generating screenshots for you And this is extremely useful because it collects all of these screenshots into a folder which you can then upload to iTunes Connect And what’s really, really nice is that when it’s done, it gives you this HTML report where you can see all the screenshots of all the languages on all the devices So you get a really great overview of how your app looks with all of these different combinations And a lot of companies actually use this to make sure everything looks great In particular, if you support languages like German, which tend to be long on the localizations OK, now onto our favorite We’re going to talk about some iOS specific stuff here– code signing and provisioning profiles I don’t know if you remember this dialogue, but it usually signaled the start of an afternoon of code signing troubles– painful So now, you can press the Fix Issue button here and sometimes that fixed the issue, but it also had a tendency to break things from time to time So I want to talk to you about what we can do to simplify code signing so that you don’t have the sense of dread whenever somebody mentions provisioning profiles or signing certs ever again All right, so Apple recommends that when you do code signing, each developer on the team has their own code signing identity, which means that you have one App ID for every app you have, one code signing identity for every engineer on your team, and then you have one provisioning profile for each engineer– or for each App ID and for each developer It’s confusing Additionally, for each environment, you have ad hoc developer App Store So that means if you have a few developers and a few apps you can easily end up with hundreds of provisioning profiles, and a developer portal that looks kind of like that It’s a little bit of a mess So when you have this, you have to think about things like how do we keep the valid profiles in sync? Or whenever we add a new device, how do we make sure everybody gets the right provisioning profiles? And how does onboarding a developer look? And what does her first day of work look like? So this isn’t exactly the most ideal setup, and that’s why we have a different approach What if, instead of having hundreds of profiles and certificates for each developer, we share a code signing identity across the entire team? And we use that one identity to deploy to the App Store And you can store that identity and its private key in a Git repository You already use Git to sync your source code, so you can use a separate Git repository with your code signing identity in it And additionally, you can encrypt it or you can just keep a really secure Git repository And with this, that’s enough to be able to onboard any new developer Surprise, we’ve got a tool called Match that implements this workflow Here’s what it looks like First thing you just run Match in it It’s going to ask you for a URL to this Git repository that you want to use And what’s really great about Git repos is that you’ve got some basic access control here, so you can decide which users have read access and which users have write access All right, so the first time you run it, you just run match appstore This will generate a new App Store provisioning

profile and certificate and that was it That’s the whole thing You just have to run this every time you want to run a build on a different machine And what’s really great about this is that you don’t need to access– you don’t need to grant access to the developer portal for all of your developers You just have to grant access to the Git repository and that’s it It’s that simple All right, so we’ve covered Snapshots, and we’ve covered code signing, but let’s talk about why you’d even want to automate deployment So think about the following situation Your boss or your project manager asks you for a new build for your clients, or for your designer maybe, so you can send that build over so they can check out those latest changes OK, so that process looks like this You go ahead and you bump the version And then you go and commit that version back and push it up to your repository You add the new devices to the provisioning profile, you then build, export, and upload It goes to either iTunes Connect or whatever beta service you’re using And then you add release notes And finally, you can distribute that It’s a ton of work, but that’s where Fastlane comes into play We can reduce all of this down to just the push of a button So first off, Fastlane uses a so-called fastfile, and this file contains all the information that is needed to deploy your app You just define which steps run and in what order and Fastlane makes sure to execute them A group of steps is called a lane And if one of these steps fails, the whole lane will fail It will just stop running And so how does this configuration look for the example we were just talking about here? OK, well, first you define the lane, and this one is beta And then you can see the next step is to increment the version number And then we commit that and push it to our Git repository And then we use match to ensure that we have the latest provisioning profiles and signing certs directly from that Git repository And then we use gym to build and sign So finally, we’re able to upload that IPA to whatever beta distribution service we use, like Fabric’s Beta or HockeyApp And after that, we can post a message directly to Slack So speaking of Slack, we’ve got many built-in integrations And I think at this point, it’s somewhere around 400 It’s kind of changing But these are things like HipChat, and Slack, Crashlytics, Hockey, email actions, Git actions, and so on If integration isn’t available yet, you can easily extend Fastlane to use your existing shell scripts, Ruby scripts, or you can build your own integration Or even build a plugin that can be shared by many others, which is what Felix is going to be demoing for you shortly All right, so how does this look in action? Well, that’s easy enough You just call Fastlane beta OK, so another example here Here we’re going to build a new release and we’re going to send it to the App Store, so we run Fastlane iOS release This will be the first build Sorry, here we’re actually first signing the build, and as you can see, Fastlane prints out every single command that it’s doing We try to be fully transparent about what we’re doing here And once it’s done, it’s going to upload the new build to iTunes Connect And for uploading, Fastlane actually uses a tool that’s built into Xcode called iTunes Transporter, and it’s done So if you look at this output, you can see we get this nice little summary table Actually, it’s kind of huge here But this includes all the parameters that are being used at this point And it’s really, really useful because you can go back into your CI system and see what was being used at any given time And above that, you can see the commands that were run And what that means is that if you have any problems and you need to debug the stuff, you can easily go back in, copy and paste, and execute them to see what happens All right, so that was just a small example of a really useful workflow Fastlane can help with uploading app metadata and builds to iTunes Connect, managing your push notification profiles, automating app creation in iTunes Connect and the dev portal, testing and syncing your profiles across your team using Git, and much, much more Many of the tools in Fastlane communicate with Apple in some way So how does this work? Well, there’s no official API, right? Of course not There is an open source tool called Spaceship which is part of Fastlane It takes care of communicating with Apple,

and all of our tools are built on top of it so you know it’s battle hardened And you can use it to build your own workflows For example, like syncing new LDAP users with the developer portal anytime your company adds a new engineer So one thing we built that can show you how useful it is to have an API framework is this project we call Boarding So Boarding is this really cool Ruby on Rails project that gives you a landing page for users that want to beta test your app using TestFlight And I think that’s really cool because you don’t have to go into iTunes Connect manually and add people anymore Originally this project, Boarding, was just built to demonstrate what you can do with Spaceship, and it only took a weekend to build Now, lots of people use it and it’s maintained by the community So feel free to use it with your own apps You can deploy it on Linux, which is also pretty awesome It’s open source and you can also find that on GitHub OK, so I want to jump back into Fastlane Some of us using third-party crash reporters, like Crashlytics, have probably run into this problem if we enable bitcode You build your app and then you upload it to iTunes Connect It gets approved and released At some point, it crashes So you open up your crash reporter’s dashboard, and you note that nothing shows up You don’t see a stack trace Ah, right And that’s because your app supports bitcode, just as suggested by Apple Good job That means they can recompile your app on the fly and generate new dSYMs, which is exactly what happened here So Apple recompiled your app, and the crash reporting tool doesn’t have those new dSYMs So you’ve got to log into iTunes Connect, find the builds, then download the dSYMs, then log into your crash reporter, find where to upload those dSYMs– that’s kind of a pain Well, surprise We have Fastlane here and it can get your back and take care of that for you Here, Fastlane will download your dSYMs from Apple, and then it’ll upload those dSYMs to Crashlytics, or whatever tool you want to use, and then it will clean up after itself And that’s it That’s all of the code You can find more information in the Fastlane Docs about this at And so these are some of the things that you can do with Fastlane out of the box, but let’s say you want to build your own integrations with your own APIs That’s where Fastlane plugins come in handy And for that, I’ll hand you off to Felix FELIX KRAUSE: All right, thanks, Josh This was a really great introduction of how you can use Fastlane to optimize your app deployment process And best of all, as Josh already mentioned, all of this is open source available on GitHub As you may have noticed, much of Fastlane is highly optimized for iOS developers, but as Josh mentioned, it supports both platforms– iOS and Android So all right, let’s say you set up Fastlane successfully and you use it to build and deploy your application, but then you decide you want to do something more Let’s say you want to run a code style [INAUDIBLE] Let’s say you want to run Swift things This is where the Fastlane Docs page comes in handy We have a list of all the building actions over there that you can easily use using Fastlane Currently, we have about 400 actions available But what if you want Fastlane to do this one specific thing for your setup, this one thing that is missing? This is where the Fastlane community comes into play, because more than half of the actions that are available are actually provided by the Fastlane community in the form of Fastlane plugins So just like with the actions, we can find the list of all available plugins on the Docs page, and we make it very easy to find the plugins that are most useful for you So we introduced the Fastlane plugin scoring system that shows you the popularity of a plugin based on certain metrics, like the number of downloads, the number of active users, the number of contributors, and the number of matchable requests And for the distribution for those plugins, we make use of RubyGems So this is kind of like CocoaPods, but for Ruby projects At the same time as RubyGems, we also make use of Bundler, which allows us to define dependencies in a configuration file, and therefore, make the build reproducible And we’re going to see a lot more of that in our demo, because every time you want to use Bundler in RubyGems, you need to prefix a command with bundle exec So all right, we’re going to see all of this in action We have a sample iOS app that has multiple schemes to choose from, but we don’t want to specify this scheme every time manually We want to define what scheme to use as part of a JSON configuration file

so we don’t have to update our Fastlane configuration every single time we want to use the scheme So this sounds like a great candidate for our first Fastlane plugin So we’re going to build one on stage right now All right, beautiful So we are in this demo directory And inside this demo directory, we have our application called myApp And if we open this up in our text editor, we can see that we have a working Fastlane setup So inside our Fastlane directory, we have our fastfile And this is a very simple fastfile All it does, it builds our application using Gym and then it distributes the beta build on Crashlytics So if we run this now in our terminal, we have to run bundle exec fastlane and then the name of the lane, which in this case, is build So we’re running this It will detect our Xcode project And as mentioned before, we have multiple schemes And of course, Fastlane asks us what scheme we want to run it for So I’m going to cancel this for now, because as mentioned, we want to have a JSON configuration file So how can we start a new plugin? Well, let’s go back to the root of the demo folder, and I can show you that the git status is clean We have no changes here for now And to generate this plugin now, we’re going to run bundle exec fastlane new_plugin And Fastlane makes it very easy for us to build new plugins So it will ask for the name of our plugin, which we’re going to call parse_json It’s going to ask us for a description of what this plugin does– parse a JSON file– and it asks us for more information We’re going to provide that later on All right, what actually happened here? Let’s run get status again We’ll see that we have a new directory which is our plugin So let’s see what’s inside this directory All right, you can see that we have a directory It’s already full of files It might be a little small to read, but it should be fine One thing that stands out is that we already have a fastfile, but this is not the fastfile of our Xcode project It’s the fastfile of our plugin And it already calls parse_json We just created that, so it seems like something already happened there And since it is a fastfile, we can try just running it So we are inside our plugin, and we’re going to run bundle exec fastlane, and then again, the name of the lane In this case, it is test All right, a lot of green text That’s usually a good sign So we see the short summary of what plugins were successfully loaded, so that is good And then we see the parse_json plugin is working All right, interesting So something’s already happening here And so when we generated our plugin, it also generated a default implementation So if we go inside the actual source code of the plugin, we will see that we have the action implementation here And there is a lot of methods you can implement Many of them are more advanced, so we’re not going to talk too much about them For example, one method describes what platforms you support– if it’s iOS or Android or both In this case, parsing a JSON works on any platform Available_options we’re going to talk about in a bit Details– we don’t provide for now The return_value of this plugin is the content of the JSON file And then as an author name, you can choose to use your GitHub or Twitter username And here we see the actual message we saw before, “The parse_json plugin is working!” All right, so we need to parse the JSON file, and it is very easy to do that in Ruby All you have to do is return JSON.parse and then parse the file content To get the file contents, we just call, and we access the file path And for the path, we’re just going to assume a dummy JSON file for now and see if it actually works So we’re going to create a dummy.json file inside our plugin directory, and within that, we want to define the scheme to say Themoji CustomScheme This is just a dummy scheme to see if it’s actually working All right, so we load, we defined the path, we load the content, we parsed the JSON file Let’s actually give this a try So we’re going to run the same command again, fastlane test, and we see there is some output is missing There’s nothing in between here anymore And the reason for that is that if we look at the example fastfile, we call our plugin, but we don’t use the return value So we’re going to say file_content equals parse_json And then to print out something, you just

have to do UI.message file_content Let’s run it again and see what happens All right, scheme Themoji CustomScheme– beautiful So we are only interested in the scheme, so to access it we’re going to use the square bracket notation So we’re going to say selected_scheme equals file_content, and then say scheme And as a message, we’re going to say we’re going to use the scheme scheme– Selected_scheme All right, let’s see if that works as expected We’re going to use the scheme Themoji CustomScheme All right, so this is all working great We compiled the JSON file, we get the scheme One thing we haven’t done yet is we don’t allow the user of this plugin to choose what JSON file to load So if we look back, we are assuming dummy.json, and Fastlane makes it very easy to set those values So in the available app options method, you can just return an array of options you allowed to take, and you define the metadata of what kind of value to take So in this case, we’re going to call it path This is an environment variable we can set, so let’s call it PARSE_JSON_PATH And the description is just like path to the JSON file And to access it, all you have to do is say params square bracket path And if we go back to our fastfile, we can now pass the path here and then say dummy.json And this is really important because we don’t want people to have to modify the plugin, but we want people to be able to pass values that is working for the setup So let’s run it again and see if it works All right, it’s the same output We’re going to use the scheme Themoji CustomScheme– beautiful So we have this in our example fastfile How can we add the plugin to our application? So for that, we’re going to go back to our application MyApp And inside MyApp, we can make use of a command that is bundle exec fastlane add_plugin And it’s going to ask us what kind of plugin we want to install, so we’re going to say it’s called parse_json And one thing Fastlane just found out is that the plugin is not available on RubyGems, which as I mentioned before, is the system we use to distribute plugins And obviously, it’s not available yet because it’s only on my local machine We just started building it So we’re going to use the local path option, number two, and it’s asking us for the relative path So we’re going to say dot dot, dot dot, and then the name, fastlane-plugin-parse_json So it asks us if we can modify our gemfile and our plugin file Again, this is all Bundler doing all the magic for us It’s just, again, Fastlane tries to be as transparent as possible And let’s look at what actually changed So looking at the getdiff, we’re going to see that it now attached a new file that is the so-called plugin file Again, we don’t have to understand how this works Fastlane does that for us, but it is important that you check that into your version control And so we successfully installed the plugin now, but we don’t use it yet So if we open up the fastfile of our application again, we can see that we have our Gym call here and our Crashlytics call here And let’s comment these two out for now and focus on selecting a scheme again So we’re going to copy the code we wrote in our example fastfile and insert it here And let’s see if it works again So we’re going to use the same configuration So we’re going to run fastlane and then build This doesn’t look too nice– big stack trace All right, let’s scroll up and see what happened here No such file or directory dummy.json All right, that looks valid, because the dummy.json is in the directory of the plugin, not of our application Either way, first, before we actually fix the path, we want to fix this error message We want our plugin to be more user-friendly And that is really easy in Fastlane also So as part of the config items, what you can do is you can pass a verify block And the verify block allows you to define a rule on how to verify that the value is valid So what we can do is we can say– we can throw an exception using the UI.user_error and say couldn’t find given file Unless of course, the file exists using value All right, so let’s run this again, see how it looks like Couldn’t find given file This is a lot nicer– beautiful So now we are actually going to fix the path in our Fastlane fastfile So to fix it, we’re going to go one folder up and say fastlane-plugin-parse_json

And the great thing, of course, here is that the JSON file can now be named anything and can come from anywhere All right, so we were able to successfully load the scheme So let’s connect the things together We’re going to comment out Gym and Crashlytics again We’re going to pass the scheme parameter and select our scheme And in the dummy.json, we actually want to use the actual scheme, and in this case, for this app, it’s called Themoji So we’re doing everything now Load the file, select the scheme, print out the scheme, build our application, and upload to Crashlytics Let’s see what happens Same command again Loaded our plugin So it’s printed out that it’s going to use the scheme Themoji And these are all these nice little summaries Josh was talking about So it will show that it is using this scheme Themoji And then it started building our application So this is a basic Swift application So this is going to include the Swift standard library and it will also code sign application Building was successful We are now uploading to Crashlytics– to Crashlytics beta And there we go Fastlane tools finished successfully Beautiful So this all seems like it worked really well And one last thing we want to do now is we want to publish the plugin to RubyGems So this looks like it’s working well So we’re going to go back to our plugin And one thing, obviously, you would do is you would publish your source code on GitHub In this case, we are not going to do that and only focus on the RubyGems part And if we go back to our source code, one thing that you need to change is you have to provide a home page Very often, that’s just a GitHub page So we’re going to add my username here And to now be able to publish the plugin, I recommend running Bundler update to make sure you have all the latest dependencies installed And after doing that, you can run Rake Build, which will package up your plugin into a zip file And then to publish this, you can run gem push and then pass the path here, and it’s pushing to RubyGems Successfully registered gem 0.1.0 And we can now go to the RubyGems website and search for Fastlane plugin We will see that we have a lot of plugins here, so currently it’s 240 plugins And depending on how fast their cache is, we can actually find our plugin here fastlane-plugin-parse_json released today All right, we just successfully published a plugin here on stage [APPLAUSE] So to recap, we just saw how we can use Fastlane in action, how we can change the configuration and change Fastlane to fit our needs And then at the same time, we were able to prepare it as a package and provide it to other Fastlane users in form of the plugin And now back to Josh JOSH LIEBOWITZ: Awesome, Felix So this was a short introduction of what you can do with Fastlane and how it helps save a lot of time during development and deployment You can find more information on how to get started with Fastlane at You can also find us in the Ask Firebase lounge right after this talk Thank you [APPLAUSE] [MUSIC PLAYING]