xcodebuild: Deploy iOS app from Command Line

The deployment of an iOS app to iTunes Connect involves various things and it’s time-consuming and fragile activity.  It’s very common practice for iOS developers use Xcode to build, test, archive and upload the app to iTunes Connect.  Fortunately, Apple has command line tools to do all these things and one of the most popular utility is xcodebuild.  There is a fancy wrapper on Apple Developer tools called Fastlane which can be used for scripting deployment of an iOS application. You might be wondering why we need to use the command line to deploy the iOS application. Can you imagine a day without Xcode?  Or Can you think of deploying an app from the server where you don’t have GUI access? Or What if you don’t have scripting skills in Ruby to use Fastlane?

We must know what’s happening behind the scene when we build, test, archive and upload an app. We should aware of the native Apple developer tools used for all these activities. By learning command line interaction, we can get following benefits

  • In-Depth knowledge of underlying Apple technologies used while building, deploying an iOS application.
  • Ease of automating iOS development task for continuous integration or cloud-based servers
  • Better understanding of what tools like  Fastlane are doing in the background.

In this post, we will see how we can build, test, archive and deploy a sample iOS app to iTunes Connect.

Pre-requisite

In order to understand the command line deployment process, we should have following things setup in advance.

  • Sample app with Xcode workspace. e.g CLI.xcworkspace 
  • Xcode Scheme with Release configuration: CLI-Release 
  • Certificates, AppID, Provisioning profiles setup for production in iTunes Connect. Use Apple’s documentation to setup all the things. We will assume provisioning profile CLI Distribution profile  for this tutorial.
  • macOS with Distribution certificate in the keychain

We will cover the cycle of the iOS app from analysing app till deploying to iTunes Connect using xcodebuild.

Analysing

One of the sensible things to do before we build and test an iOS app is performing static analysis of the source code. The xcodebuild has an ability to clean and analyse the source code for any common syntax errors.  We can pass our Xcode project e.g CLI.xcodeproj

Building

We can build an iOS app using xcodebuild  ‘build’ action which generates the derived data for our iOS app. Once the app is built, it can run inside the simulator or can be used by test bundle.

build for running

We can simply build our app to run inside simulators by using simple command

This will create a derived data inside ~/Library/Developer/Xcode/DerivedData/  directory. Thre are various options that we can  pass to override the default settings so that we can control the artefact e.g  -destination or  -derivedDataPath  etc

build for testing

Xcode 8 has introduced this nice feature to allow building once and use the derived data .xctestrun file to test multiple time on different destinations.

We can build for testing using the command:

Now that, we can use test-without-building action to run tests without building an app.

Testing

Apple has XCTest framework to perform unit and UI testing of an iOS app. We can update our release scheme to include a suite of tests. Assuming our ‘CLI’ scheme is configured to run tests, then we can run tests associated with scheme using

This will build our scheme and start executing tests for that particular tests.

test-without-building

If you have build app using ‘build-for-testing’ option mentioned above, we can perform testing on multiple destinations using same derived data.

This will execute tests for iPhone as well as on iPad. We don’t have to build app twice to run the tests on different destinations.

Archiving

The most of the iOS engineers find the process of archiving an iOS app is very painful as it involves dealing with provisioning profiles, certificates and build configurations. In order to upload the app to iTunes Connect or deploy it on to the provisioned devices, we need to build and app for generic iOS device destination as well as export it in IPA format.

Let’s build our app with release configuration scheme ‘CLI’ with generic iOS device destination.

xcodebuild has a new -exportArchive option to create an IPA that works more like Xcode Organizer.

There are two steps

  1. build an archive with xcodebuild archive
  2. create the .ipa with xcodebuild -exportArchive

We now build the archive like this:

We now export the .ipa like this:

This two command create the file  build/myApp.xcarchive and build/myApp.ipa

Note that above command requires a -exportOptionsPlist argument that points to a .plist file with export options. For a complete list of what you can put in that plist, run xcodebuild -help . The minimal contents of the file look like this:

 

we run this command successfully, we will have IPA file created using provisioning profile ‘CLI Distribution Profile’. At the end, we will have our IPA, CLI.ipa  binary ready to upload to iTunes Connect.

Uploading IPA to iTunes Connect

The last step of the deploying our app is to upload the binary to iTunes Connect. Usually Xcode has ‘Application Loader‘  app to perform this task. Fortunately, we have command line interface for the Application loader app called ‘altool’. The binary file for altool comes up with Xcode so no need to download it separately. The binary is usually located at the path

It would be a great idea to export that binary to $PATH so that it can be accessed from anywhere. We can use this binary to upload our IPA to iTunes Connect. We need our Apple ID username and password to upload, assuming we have those credentials in the keychain or have it as ENV Variables $USERNAME and $PASSWORD

You can explore other command line options for ‘altool’ on the Apple official documentation. It will take a huge amount of time to upload but be patient and enjoy your IPA uploaded to iTunes Connect.

What Next

Now that, we have successfully uploaded an IPA to iTunes Connect, we can distribute to testFlight for internal testing or submit it to Apple for review from iTunes Connect

At this stage, you might have a brief idea about the internal tools that Apple use to build, archive and deploy an iOS app to iTunes Connect. There are various other open-source wrappers available to make our life easy like Fastlane, ios-deploy  etc. Please comment if you think something is missing

Happy Continuous delivery!