Publish to App Store with fastlane

Three years ago at the Pragma Conference in Florence, Italy, I heard about a tool to help streamline iOS app development and publishing to the App Store: fastlane.tools. It is only recently I decided to give it a closer look. And it is great, really great and really simplify releasing apps to Apple and Google app stores.

Automation. One word I’m always after when it comes to software development. Having to do the same tedious tasks twice is painful and developers want to avoid this, I want to avoid this.

In one of my previous jobs, we used to have a set of batch files here and there to deliver the product. It was a small startup, and one developer had this magic script to build the Java archive and then this JAR file could be sent to clients. I converted the batch file to Ant (this was in the early 2000s), from compilation to the generation of installers. And then because it did not make sense to expect one single developer to be in charge of running a script, CruiseControl, a CI/CD platform, was added into the fix. Everything was automated, build, documentation, tests, installers.

Since that time, I chase these automatable tasks and whenever I get a chance, just write the script that will save me precious time that can be spent on more valuable tasks.

These days I have an idea for an app and I started working on it. Few years ago I published an app to the App Store. Everything was done manually, building the app from XCode, capturing screenshots from the simulator, formatting the screenshots, updating the app description in all languages from the iTunes Connect website, uploading the build, submitting for review. A lot of pain and error prone. So this is a very good opportunity to try out fastlane.

fastlane is an open source platform aimed at simplifying Android and iOS deployment. fastlane lets you automate every aspect of your development and release workflow.

fastlane includes several tools to achieve its goal: match, pilot, deliver to name of few, together with a set of plugins - like one to generate icons for all device sizes from one large PNG image. What I really missed was a step-by-step guide to integrate everything. It is not difficult but you have to read from several web pages to get to a point where you can start working on your app and not worry anymore about how to deliver your release. Going through the process, I captured all my steps and here they are.

Prereqs

  1. Make sure the XCode command line tools are installed
    xcode-select --install
    
  2. Connect to your Apple developer account, ensure you have accepted all the latest agreements - otherwise fastlane may fail and ask you to go approve those

Start with a new project

  1. Create a new project in XCode.
  2. Set CFBundleIconName to AppIcon in the bundle Info.plist key as described in this Apple article.
  3. Set ITSAppUsesNonExemptEncryption to false - you may change it later if you plan to use any encryption.
  4. Commit the project to a new Git repository

Enable Cocoapods

  1. Install Cocoapods:
    gem install cocoapods
    
  2. Initialize the project:
    pod init
    pod install
    
  3. Cocoapods creates a new workspace. From now own, use the workspace when working on the app.
  4. Commit the new files

Fastlane

  1. Install fastlane:
    gem install fastlane -NV
    
  2. Initialize the project with fastlane:
    fastlane init
    
  3. When prompted, pick Automate beta upload to TestFlight.
  4. Open the app workspace in XCode and enable automatic version and build numbers following the instructions in this Apple article.
  5. Create resources/beta-changelog.txt to hold information targeted to beta users about what has changed
  6. Create resources/beta-app.json with
    {
      "description": "First beta build",
      "feedbackEmail": "[email protected]"
    }
    
  7. Open Fastfile and change the beta lane to
    lane :beta do
      changelog = File.read("../resources/beta-changelog.txt")
      beta = JSON.parse(File.read("../resources/beta-app.json"))
    
      ensure_git_status_clean # comment if not using git
      increment_build_number # automatically increment the build number
      commit_version_bump # comment if not using git
      add_git_tag # comment if not using git
      push_to_git_remote # comment if not using git
         
      build_app(workspace: "myapp.xcworkspace", scheme: "myapp")
      upload_to_testflight(
        changelog: changelog,
        beta_app_description: beta["description"],
        beta_app_feedback_email: beta["feedbackEmail"]
      )
    end
    
  8. Commit the files

Certificate Management

fastlane simplifies the management of app certificates with match.

  1. Create a Git repo to host the certificates. Make note of the repo Git url and make sure you will be able to commit to this repo
  2. Enable fastlane match to handle certificates
    bundle exec fastlane match init
    

    This will prompt for the certificate repository

  3. Setup certificates for the different stages:
    1. bundle exec fastlane match development
    2. bundle exec fastlane match appstore
    3. bundle exec fastlane match adhoc
  4. Confirm that new files have been created in the certificates Git repo
  5. Edit the XCode workspace and uncheck “Automatically manage signing” in the project “General” tab
  6. Select the provisioning profile created above (match for development as example)
  7. Commit all changes

App Icon generation

fastlane has a nice plugin to generate all different icon sizes from one master icon.

  1. Create a large version (1024x1024) of your app icon
  2. Add the icon plugin
    bundle exec fastlane add_plugin appicon
    
  3. Add a new lane in Fastfile to generate all icons
    lane :icon do
      appicon(
        appicon_image_file: 'resources/AppIcon.png',
        appicon_devices: [ :ipad, :iphone, :ios_marketing,  :watch, :watch_marketing ],
        appicon_path: 'myapp/Assets.xcassets')
    end
    
  4. Generate the icons
    bundle exec fastlane icon
    
  5. Commit all changes

First Beta Build

  1. Build and push the first beta
    bundle exec fastlane beta
    

    The build may prompt from your mac password to access the keychain.

  2. Wait and don’t interrupt the script
  3. After a while the build is available in TestFlight for users

The end

You should read about fastlane to understand how it works and all the options. Of course, you could also decide to not use fastlane. Everything fastlane does could be done directly with the Apple tools like XCode. fastlane is mainly wrapping all the commands for you - this also means fastlane has to catch up with Apple whenever they change an API or make a new parameter required.