Continuous Integration for iOS [CI iOS] — Autobuild Guideline

Continuous Integration for iOS [CI iOS] — Autobuild Guideline

Continuous Integration for iOS [CI iOS] — Autobuild Guideline

The problem of continuous integration is quite particular for iOS, it is particularly sensitive in significant enterprises and is not-so-critical in small outsourcing companies. Of course, there is already a whole bunch of ready-made solutions, the most popular of which is diawi.comtestflight, but there are many others. If you're interested in mobile apps development, also take a look on the article about Firebase platform.

Consider the basic pros and cons of these three application distribution platforms.

For fabric.io

Pros

  • simple outbox user-friendly settings.
  • one-click distribution archives.
  • particular delivery for email.

Cons

  • need to install profiles on devices.
  • client/tester email required.
  • frequent installation errors.
  • impossibility of re-distribution of one build.
  • if you do not have an enterprise account, you need to register a UDID of the device.

For diawi.com

Pros

  • three-stage scheme for collecting-download-access link.
  • by distribution of links, you can regulate which group of users receives which build.
  • re-distribution with p. 1, the links will be different.
  • no email and additional profiles needed.
  • no installation errors "almost ;-)"
  • developer.apple.com profiles only, no advanced settings needed.

Cons

  • links can expire (weekly no use life).
  • no one-click integration.
  • If a user suddenly receives a link that was not intended for him, he will still be able to install the build, because this device is in the profile list from developer.apple.com.
  • if you do not have an enterprise account, you need to register a UDID of the device.

For TestFlight

Pros

  • public testing opportunity.
  • no need for registration of devices.
  • simple XCode build distribution.
  • automatic Apple primary machine review.

Cons

  • client/tester internal/external list registration needed.
  • client/tester one-time email invite confirmation required.
  • TestFlight application download required.
  • One time application invite received needed.

So, it is necessary to make a system that will be flexible and will include the pros of the previous two systems.

Let's make up some functional requirements for it:

  • Downloaded via a direct link from the Safari browser, it can be attached and sent by email or any messenger to the customer. In such way, we protect downloads from most of the errors.
  • The links should not expire but can be deleted.
  • The links can be grouped to separate lists.
  • One-click or even automatic build creation.
  • No need for additional profiles installation.

The system can be built by Jenkins and file hosting.

Let's look how we use this method in UKAD

Create an archive from changes in the repository (git push-based build):

  • For the operation, you need a valid xcodeproj or xcodeworkplace with an installed appID and signature certificates.
  • Transfer all the signature keys to the buildMac-machine.
  • Install fastlane оn the build server, you need to and configure it so that it is available from the console.

Continuous Integration

  • Don’t mind the report и readme files; these are the inbuilt guide and the final log of the deployment, report.xml is automatically filled via logs.
  • Fastfile is an example of deployment through fastlane (you can find more information about its structure and additional commands in the official guides of fastlane).

Continuous Integration 2

When your fastlane is configured you can get build with just one command:

fastlane lane_name

Jenkins Setup

  • brew install Jenkins.
  • add the Jenkins-user to the git repository and configure ssh-keys.
  • Add custom target in Jenkins.
  • Setup script (Execute shell).

Continuous Integration 3

The Build script window looks like that

and the script

cd source_path &&
git fetch --all && git reset --hard origin/master && git pull origin master &&
fastlane lane_name &&
mv source_path/scheme_name.ipa export_path/export_build_name${BUILD_ID}.ipa
iosOTAGenerator -ipaPath export_path/export_build_name${BUILD_ID}.ipa
-config source_path/build_config_name.plist -buildNumber ${BUILD_ID} -htmlPath some_html_path

where

  • source_path - is the path to the git repository.
  • lane_name - is the name of the lane in the fastlane file.
  • sheme_name - schema name in xcodeproj or xcodeworkspace.
  • export_path - the path to the public folder (where the static hosting file will be configured).
  • export_build_name - is the build public name.
  • $ {BUILD_ID} - Jenkins variable, indicating the build serial number.
  • build_config_name.plist - configuration file name for the iosOTAGenerator utility.
  • some_html_path - is the path to the html file, where the successful build links added.

Creating the link for downloading in Safari

Quick OTA guide

OTA files creation tool

The tool creates a folder and generates files, which are necessary for distribution via OTA.

iosOTAGenerator -ipaPath SchemeName-${BUILD_ID}.ipa -config config_path.plist -buildNumber ${BUILD_ID} -htmlPath some_html_path

  • ipaPath - absolute path to the build.
  • config - is the path to the plist configuration file that tells how the build is called, its version (not the build number) and where it will be on the web (a secure https hosting is needed since OTA is accessible only from a valid "green" https address).
  • buildNumber - build number (variable Jenkins).
  • htmlPath - path to the html file with specified identifier div (OTA_URLS_TABLE) where the links will be added to builds.

The example - config.plist (can be opened via xcode)

Continuous Integration 4

<?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>bundleId</key>
    <string>com.some.SomeProj</string>
    <key>version</key>
    <string>2.2.0</string>
    <key>webUrl</key>
    <string>https://somesite.com/SomeProj/</string>
    <key>appName</key>
    <string>SomeProjName</string>
</dict>
</plist>

appName, bundleId, version, and webUrl are used for correct generation of .OTA files (used to distribute applications through direct web links)
A folder under the name of the build is created, containing three files: the build, index.html and manifest.plist
Using the link in index.html, you can download the build through web

Examples

index.html

<a href="itms-services://?action=download-manifest&url=https://somsite.com/SomeProjName/manifest.plist">Install App SomeProjName v2.2.0</a>

manifest.plist

<?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>https://somsite.com/SomeProjName/build_name.ipa</string>
          </dict>
        </array>
        <key>metadata</key>
        <dict>
          <key>bundle-identifier</key>
          <string>se.some.SomeProj</string>
          <key>bundle-version</key>
          <string>2.2.0</string>
          <key>kind</key>
          <string>software</string>
          <key>title</key>
          <string>SomeProjName</string>
        </dict>
      </dict>
    </array>
  </dict>
</plist>

Conclusion

The main thing is not to violate the correct type of cross-references index.html to manifest.plist and the absolute path to the build (export_path export_name) on web hosting.

Thus, all the work is based on writing the fastline team into Jenkins, creating the OTA files and correct files positioning on the web.

Further, the level of customization of a system depends only on you; this link can be added to the web portal, chat, send via email, etc. (both in automatic and manual mode).

  • Continuous Integration
  • CI iOS
  • Jenkins
Back to Articles

It's time to talk!