Using Fastlane to create iOS Ad-Hoc distribution on Amazon S3

Dmitry Fink
July 25, 2017

This tutorial is a revised tutorial we've published earlier, called iOS Ad-Hoc distribution using Amazon S3. The original tutorial achieved the desired effect using s3cmd and a bunch of bash scripts. However, since its publication, Fastlane gained a lot of popularity and gathered quite a following around it, including the ecosystem of plugins. If you are not familair with Fastlane, you should definitely spend some time to get familiar with it, and see how it can help you automate your iOS and Android builds. In the following article we will only focus on one specific task - creating an Ad-Hoc distribution on Amazon S3, and will use one Fastlane plugin for that purpose, called aws_s3.

The new Fastlane solution is much easier to implement than the original one, yet it comes with a price. It is less flexible, if the look and feel of the html needs to be tweaked, the plugin itself needs to be copied and modified.

Why?

Every iOS developer at some point in their life is challenged with a task to distribute their awesome app to a group of loyal beta testers. Apple does not make it easy. The reasons for this are clear. We all care about security and greatly appreciate the fact that iOS platform is much more secure than its main competitor, but it is still a problem that needs to be solved.  There are services out there that try to automate the ad-hoc distribution process, but sometimes it is not desirable or even possible to use them. Thus, there is a need to bake an in-house distribution system.

To make the ad-hoc distribution work, one must:

  • Upload the IPA file to a place where it can be downloaded
  • Generate a special plist xml file, referring to the IPA above. This file must be accessible over https!
  • Generate an html file with a special Download link, pointing to the plist file above. This is the page users will see

Throughout this tutorial, we are going to use an application called Dishero as an example. We will host it directly on S3, without spinning up machines or configuring http servers. The result will look similar to this:

Prerequisites

Create an Ad-hoc distribution profile

First of all you will need to create a distribution profiles in iTunes Connect.

Ad-Hoc distribution limits the the ability to install your application only on specific devices that have to be pre-registered. Instruct your beta users to visit http://whatsmyudid.com/ and to follow the instructions there to obtain UDID (Unique Device ID) for their device and send it to you.

Follow the pictures below to create an Ad-Hoc provisioning profile, and add all the devices to it. Download it once ready and install in your local keychain by double-clicking on it.

Create a bucket on S3 and enable web hosting on it

You will also need a dedicated bucket on S3 for this. Make sure you enable Web Hosting on your bucket as shown in the picture below.

Bonus: If you want to have your download page to be at a nice URL (we are using download.dishero.com for this example), you have to do a few tricks:
  1. Name your bucket accordingly - download.dishero.com
  2. In your DNS, configure a CNAME record download.dishero.com to point to download.dishero.com.s3.amazonaws.com.

Install and set up Fastlane

If you don't have yet fastlane installed, install it using one of the official methods.

Navigate to your project folder and run:

fastlane init

You'll be asked for your Apple ID, and fastlane will automatically generate a fastlane configuration for you, based on the information provided. The most interesting file is fastlane/Fastfile, which contains the main configuration that needs to be edited.

Install the aws_s3 plugin:

fastlane add_plugin aws_s3

Now lets edit the fastlane/Fastlane file and add our beta lane for both building and distributing our application:

# More documentation about how to customize your build
# can be found here:
# https://docs.fastlane.tools
fastlane_version "1.109.0"
# This value helps us track success metrics for Fastfiles
# we automatically generate. Feel free to remove this line
# once you get things running smoothly!
generated_fastfile_id "c23be0f6-7e21-4d16-916b-f3c75c71046a"
default_platform :ios
lane :beta do
  gym(
        scheme: "Dishero Beta"
        export_method: "ad-hoc"
  )
  aws_s3(
        access_key: ENV['S3_ACCESS_KEY'],
        secret_access_key: ENV['S3_SECRET_ACCESS_KEY'],
        bucket: "download.dishero.com",
        region: "us-west-2",
        ipa: "Dishero.ipa",
        app_directory: "beta"
  ) 
end

We need to make sure the build is actually signed with the Ad-Hoc provisioning profile we've created, thats why explicitly instruct the gym task to change export method to ad-hoc.

export_method: "ad-hoc"

It is considered a very dangerous practice to store the actual credentials in the code base, and since fastlane/Fastane file is going to be checked in, we take them from the environment instead.

Where the magic happens

Actually, all the magic has already happened. Now all we need is to run fastlane to build and upload our application to S3.

fastlane beta

The command above will make the download page available at http://download.dishero.com/beta. Alternatively, if DNS is not under your control and you can't do CNAME tricks to get a proper hostname, you will have to point your users to https://s3-us-west-2.amazonaws.com/bucketname/path/

Can my app check for updates?

The aws_s3 has another nifty feature under its hood, it automatically generates and uploads to the same location a JSON file containing the version metadata:

{
    "latestVersion": "2.5.0.1826",
    "updateUrl": "itms-services://?action=download-manifest&url=https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fdownload.dishero.com%2Fbeta%2Fv2.5.0_b1826%2FDishero.plist"
}

Now our application can poll http://download.dishero.com/beta/version.json to check if new update is available and automatically redirect to the provided URL, when it is. Stay tuned, as we will be covering it in one of our next tutorials.