Since Apple released Xcode 9 with inbuilt Xcode Server, the process for setting up Continuous Integration for iOS projects became the matter of few clicks. In my previous post on Xcode Server, I explained the detailed process of setting up CI with Xcode 9 and Xcode Server for iOS apps. In order to understand the code signing, you should watch WWDC 2017 session on What’s New in Signing for Xcode and Xcode Server. Xcode Server has an option to produce an installable product as part of bot configuration which means Xcode Server creates an archive build and IPA for integration which can be downloaded in the iOS Devices within the network. In this post, we will cover common mistakes and solutions to those mistakes while installing the builds on iOS Devices from Xcode Server.
As Apple hasn't finished the documentation of Xcode Server with Xcode 9 yet (at the time of writing this post), getting the installed build on the iOS devices can be tricky and time-consuming if we don't look at others' experiences on StackOverflow or the Apple Developers forum. There are some tips and tricks to be used in order to get the builds on iOS devices without any pain. The common mistakes that most of the iOS team members are as follows:
- Using IP address to access the Xcode Server, which can't download the build
- Lack of access control
- Forget to enable Xcode Server Certificate
- Using domain names to access Xcode Server
- Wrong code signing options during bot setup
- Wrong archive options during bot setup
Those are the top five common mistakes that iOS team members make while using the Xcode Server for OTA installation. Now we will see some quick solutions for these common problems.
Xcode Server Tips
Here are some tips and tricks that we can follow to avoid the common mistakes mentioned above. I have faced all of these myself while setting up Xcode Server with multiple Mac Mini servers. I hope this will be useful for others as well.
Use Canonical Hostname
As a normal user, it's quite common to use IP address to access any machine in the network. It might not be an issue if you use other self-hosted iOS continuous integration servers like Jenkins, TeamCity, etc. However, with Xcode Server, we can still access the Xcode Bots page, but we can't download an app on to iOS devices. You will get an error saying something like "For security reasons, you cannot install using IP address, please use canonical hostname." This means we have to find the canonical hostname of our Xcode Server.
Getting the canonical hostname is very easy; if you have access to Xcode Server, then SSH into Xcode Server machine and type "hostname" in the terminal.
$ ssh xcode_server_user@xcodeserver_ip $ hostname
Or, you can type the following in your local machine terminal.
$ curl -k https://YOUR_XCODE_SERVER_IP:20343/api/hostname
Both the above commands will return the canonical hostname of the Xcode Server. We have to type this hostname in the iOS devices in order to download the build; for example, if your hostname is ABCXYZ, then you have to type "https://abcxyz/xcode/bots" into your iOS devices. Ideally, you should have the server machine with a good hostname from DNS. Usually, local machines have hostnames like XYZ's MacBook Pro.local, which aren't a great idea. Always use the server's canonical name.
Install Xcode Server Profile and Certificate
Xcode Server comes up with its own SSL certificate and profiles that need to be installed on the iOS devices. The profile can be installed on the "Profile" tab integration page on iOS devices. Clicking on the "Profile" tab will take you to the iOS settings and you can follow the instructions to install a profile. You can also install a profile by visiting Xcode Server API by visiting https://xcode_server_hostname:20343/api/profiles/ota.mobileconfig from iOS devices. Now we have an Xcode Server profile installed, but it's not enough.
There is another very important step that most of us easily forget, which is enabling the Xcode Server certificate manually from the Certificates settings. We get an annoying error, "cannot connect to server," when we tap the Install button. Apple has made this change from iOS 10.3 onwards. You can read more about this on Apple's support page here. In summary, we have to follow these steps:
- Install self-signed certificate(s) from Xcode server's bots page on your iPhone.
- Go to iPhone's Settings->General->About->Certificate Trust Settings.
- Find your server's self-signed certificate(s) under section ENABLE FULL TRUST FOR ROOT CERTIFICATES and turn the switch ON.
- Visit bots page on Xcode Server, click install.
It would be a good idea to clear the safari cache and cookies, just in case you get the same error again. Sometimes Safari cookies confuse Xcode Server.
Xcode Server has an option to set permissions for who should access the server page. By default, everybody in the network can visit the bot page and trigger integrations. Ideally, having access control is a good idea so that only people with credentials can access the bots. We can set up that from Xcode Server permissions settings and add only those users who can access the Xcode Server bots.
Avoid Using Domain Names
Xcode Server can also be accessed by using the domain names such as "https://abcxyz.london.my_company.com," but using domain names, we can only access the Xcode Server page, but we can not install build on the iOS devices. As mentioned above, we just have to use the canonical hostname in the URL to access the Xcode Server page and download builds.
While setting up a bot with Xcode 9, we have a separate dedicated tab for Code Signing. In the bot configuration, we can add the server to the team so that Xcode Server can automatically handle the code signing by clicking Allow Xcode Server to manage my certificates and profiles but sometime you may get an Archive Failed error. It may be because Xcode Server doesn't have enough details about provisioning profiles needed to code sign an iOS app. There is a hack mentioned here where we need to turn off automatic code signing and download all the provisioning profiles using Fastlane sigh in the pre-integration script.
Xcode Server gives us multiple options while archiving an iOS app during the Bot setup. Some of the options are:
There are three different options to create an archive from your schemes. We have to choose which option is suitable for our Xcode Bot.
- Installable Product: This will create only one IPA file.
- Installable Products & Thinned Variants: This creates multiple IPA files and takes a lot of disk space.
- Use Custom Export Options Plist: This option needs our own Plist file.
It would be a great idea to select Installable Products for on commit builds and another option for release builds in order to save some disk space on the server.
Getting iOS builds on devices from Xcode Server is tricky at the moment, but following some tips, tricks, and other users' experience can make it possible. Well, it feels very nice to get those builds on devices from self-managed Xcode Servers rather than using third-party services like Fabric, HockeyApp, TestFairy, etc. What are your experiences using Xcode Server for Over the Air installation? OKish, Great, It Sucks- whatever it is, share your experiences in the comments.