Read how we managed to distribute a beta version of our iOS app using an Apple Enterprise Developer Program and GitHub Pages.
During the last year I worked in the team Lynch at lastminute.com group
on a big “app relaunch” project where we basically rewrote some sections of our main mobile apps using React Native
and we did a general restyle of them with a more modern and engaging design.
During one of the last sprint before the release we started to think about putting in place an internal beta testing
program to have more testing data and eventually discover more bugs before the release on the App Store (we really
wanted to eat our food ). We thought about using the TestFlight environment with
external testers. But this solution didn’t work for us because:
So what do we did? We put in place our custom Beta distribution program using Apple Enterprise Developer Program.
By enrolling into this program you have the ability to distribute you app inside your company without the need of the
App Store. You can basically create your own Company App Store!!
I worked on the creation of this custom internal Beta distribution program with my colleague
Giordano Tamburrelli. Giordano is
the Team Leader of the Lynch Team, the agile team where I work at lastminute.com group. He has a Phd in Computer
Science at Politecnico di Milano university and a master degree in Computer Science at the University of Illinois.
He is one of the most skilled person I ever met, both from a technical and managerial point of view (yes you know, I’m just
kissing his ass
). Obviously, he is also one of the biggest nerd you could
ever met
.
So how did we decide to proceed? We basically did the following operation to put in place our beta program:
To show you the details and some screenshots of the operation we made I will use a sample project SampleBetaApp
with bundle identifier it.chicio.SampleBetaApp.
Let’s start from the first step: configuration on the Apple developer account for our new enterprise program. As
already explained before, we decided to create a new bundle identifier for the beta app and obviously a new provisioning profile. The procedure is
basically the same of the standard program for both the bundle identifier and the provisioning profile. We just need
to follow the instruction in the Apple Developer Account site in the section “Certificates, Identities & Profiles”.
After that we created in our iOS project a new Beta configuration by duplicating the release one. In this way we were able to generate an ipa similar to the release one and were also able to customize some settings of our app.
The Build Setting that we customized are:
Then we created the scripts needed to automatize the build on Jenkins and the upload of our artifacts repository to Nexus. As I said before we were already using Fastlane to automatize the releases of our app to the store. For the beta publishing process we decided to create a new lane in our Fastfile where we launch a custom script to do all the operation needed to publish our beta.
lane :create_beta_ipa do |options|
sh './scripts/build_beta.sh'
endAs you can see below, in the script build_beta.sh we do three things:
xcodebuild archive command using the Beta configuration we
created before. We customized some other options. For example the archive path. At the end of this command we obtain a
file named SampleBetaApp.xcarchive in the folder <project root>/DerivedData/Beta.xcodebuild -exportArchive command. This command needs and
exportOptionsPlist file that contains some exporting options, including the provisioning profile name that must
corresponds to the name of the provisioning profile we created at the beginning in the Apple Enterprise Developer
account. Below the script you can find the exportOptions-SampleBetaApp.plist sample file for the SampleBetaApp project.#!/usr/bin/env bash
TARGET="SampleBetaApp"
DERIVED_DATA_BETA_PATH="../DerivedData/Beta/"
BETA_TARGET_PATH=$DERIVED_DATA_BETA_PATH$TARGET
XARCHIVE="${BETA_TARGET_PATH}/${TARGET}.xcarchive"
IPA="${BETA_TARGET_PATH}/${TARGET}.ipa"
xcodebuild -workspace ../Container.xcworkspace
-scheme "$TARGET"
-sdk iphoneos
-configuration Beta
archive -archivePath "$XARCHIVE"
xcodebuild -exportArchive
-archivePath "$XARCHIVE"
-exportOptionsPlist "exportOptions-${TARGET}.plist"
-exportPath "$BETA_TARGET_PATH"
mvn deploy:deploy-file -DgroupId="<group id project identifier>"
-DartifactId="$TARGET"
-Dversion=1
-DgeneratePom=false
-DrepositoryId=nexus
-Durl="<nexus repository url>"
-Dfile="$IPA"<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>enterprise</string>
<key>signingCertificate</key>
<string>iOS Distribution</string>
<key>provisioningProfiles</key>
<dict>
<key>it.chicio.BETA.SampleBetaApp</key>
<string>SampleApp Beta Distribution</string>
</dict>
</dict>
</plist>At this moment we were ready to create the new Jenkins job to build our beta. We decided to trigger it using Jenkins
webhook triggers. In this way we were able to trigger the build and release of a new beta by just calling an url. This
job basically clone our app repository and then execute the lane create_beta_ipa that we defined before in the
Fastlane Fastfile.
So in the end with all this steps above we obtained an ipa reachable at a public url (on Nexus). We decided to publish
our beta using Github Pages. Why? Because we needed a server with HTTPS
already configured. Github pages let us create the beta website really fast. So we created a new account and
published a new html that contains the following code:
<html>
<head> </head>
<body>
<p>
<br />
<br />
<a
href="itms-services://?action=download-manifest&url=<a base url>manifest.plist"
>
<p>Install the SampleAppBeta app</p>
</a>
</p>
</body>
</html>As you can see above, in this html there’s a special link with the protocol itms-services. If a user clicks on this
link from Safari browser on a iOS device, the download and the installation of the app will starts. If you look
carefully at the content of the link above, you will notice there’s a reference to a url of a manifest.plist
file. This is a file generated by Xcode if you export an archive with an enteprise certificate and contains some
metadata for the ipa, including the location/url of the ipa to be downloaded. In our case this url was the Nexus
link to the ipa. This file can be generated the first time and eventually edited if there’s any change. This is a
sample manifest file that could be used for our SampleBetaApp.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>items</key>
<array>
<dict>
<key>assets</key>
<array>
<dict>
<key>kind</key>
<string>software-package</string>
<key>url</key>
<string>http://www.example-url-to-where-the-ipa-is.com/SampleBetaApp.ipa</string>
</dict>
<dict>
<key>kind</key>
<string>display-image</string>
<key>url</key>
<string>https://www.example.com/image.57x57.png</string>
</dict>
<dict>
<key>kind</key>
<string>full-size-image</string>
<key>url</key>
<string>https://www.example.com/image.512x512.png</string>
</dict>
</array>
<key>metadata</key>
<dict>
<key>bundle-identifier</key>
<string>it.chicio.SampleBetaApp</string>
<key>bundle-version</key>
<string>1.0.0</string>
<key>kind</key>
<string>software</string>
<key>title</key>
<string>beta-sample.com</string>
</dict>
</dict>
</array>
</dict>
</plist>Now we were ready to distribute our beta app, and you know everything is needed to create your own beta program. One last thing: you will need to explain to the less experienced user that they need to accept the enterprise provisioning profile from Settings -> Profiles & Device Management. If they don’t do it they will see the alert contained in the screenshot below.
That’s it!!! This is how we created our internal beta testing program. Let us know what do you think about it in the comments below.
Compliance checkboxes don't change behaviour. Here's how we used RIOT's AI-powered platform to run real phishing simulations, deliver contextual micro-training via Slack, and cut our vulnerability index by more than half across 1,700 employees. [...]