Continuous Integration With Xcode Server

Updated 19 Feb 2016: Some minor updates to the process for Xcode 7 and OS X El Capitan

Xcode Server was introduced with Xcode 5 to provide a way to perform continuous integration through the creation of bots that automate the building, analysing, testing and archiving of projects. The bots can be created in Xcode on a development Mac and then run on the server. Since this requires OS X server it is a great way to use a spare Mac you have gathering dust.

This post collects together my notes on installing and setting up the Xcode service on an OS X Server. My simple objective was to have my unit tests run each time I make a commit to a project hosted in a GitHub repository.

Installing OS X Server

To install Xcode Server you first need a Mac running OS X Server. There is nothing to stop you from turning your development Mac into a server and using it to run Xcode Server. However it is also a great way to use an old Mac as long as it is capable of running Yosemite.

If you are a member of the iOS developer program you probably know that you are entitled to use Mac OS X Server free of charge. To redeem your copy you need to login to the iOS Dev Center, find OS X Server in the downloads section and request a download code:

OS X Redeem Code

The current version is OS X Server v5.0.15 and supports OS X Yosemite v10.10.5 and OS X El Capitan systems.

If you are already on the Mac where you want to install the server you can just click on the redeem code in the iOS Dev Center to directly launch the Mac App Store, redeem the code and start the download. If you need to enter the code manually the Redeem link is listed under Quick Links in the Mac App Store. The Server application downloads to the Applications folder and needs to be run to complete the setup.

Server Icon

Click the continue button, enter your password for admin access and let the install complete. Once the Server app is displayed you should the list of services that you can now run on the server in the sidebar (none of which are currently enabled).

Services

Remotely Managing A Server (Optional)

If you have multiple Mac’s and want to administer the server remotely you can download the Server app from the Mac App Store to another machine. To allow remote management you need to check the server settings and ensure that the “Allow remote administration using Server” is enabled:

Server settings

Now when you run the Server app on the remote Mac select “Other Mac” and enter the host name or IP Address of the server together with the Administrator name and password to connect.

Server setup

Since the server is running with a self-signed certificate that was generated during the installation you will most likely get a warning. You can either just accept the certificate this time by clicking “Continue” or select “Show Certificate” to modify the trust. You can choose to always trust “com.apple.servermgrd” or only this certificate:

Verify Certificate

Turning On Caching Service (Optional)

One other tip you can take advantage of is to turn on the Caching service. This speeds up software downloads and updates by caching Mac and iOS system updates and App Store downloads on the server. To enable click on the Caching service in the Server app and switch it on. You can optionally select the disk volume and cache size. Once the service is running any clients (Mac or iOS) on the same local network will automatically use the caching service.

Server caching

Configuring the Xcode Service

With OS X Server installed and running we can turn our attention to the Xcode Service. If you have not already done so you should download and install Xcode on the server from the Mac App Store (assuming you are developing with the released version of Xcode). If you have just installed Xcode on the server you will need to run it before configuring the Xcode service to accept the software license agreement and let it finish installing components.

Click on the Xcode service in the sidebar of the Server app and then use the “Choose Xcode” button to find the version of Xcode you want to use (for example: /Applications/Xcode):

Once the setup finishes you will need to slide the switch to start the service:

We now have a running Xcode service but before we look at using it from a project there are a few extra server configuration steps:

  • To allow Xcode Server to access provisioning profiles you need to add a developer team from the Apple Developer program. Use the Add… button and enter your Apple Developer credentials to confirm you want to add this server to your team.

  • Any test devices you attach to the server should show up in the devices list. If this is the first time you have used the device for development click the “Use for Development” button and then “Add to team” to add it to the Apple developer team. If the device shows as not supported check you have removed any passcode lock.

  • You can also configure Xcode server to host code repositories on the server but since I am going to be using a remote repository hosted on GitHub I will skip this step.

Configure Xcode Development Environment

The following steps are performed on the development machine. I am assuming you already have a project with unit tests.

Add Server Account

On your development Mac add a server account to Xcode so that you can check the status of the remote bots from Xcode. In the Xcode preferences Account tab use the Add button and add a server. The server should show up in the list, enter your user name and password to connect to the server.

Share The Scheme

The Xcode project scheme defines the settings to use when a project is built, run, tested, profiled, analysed or archived. To allow these settings to be accessed by the Xcode server they need to be checked into the source code repository which requires that they be shared. In Xcode on the development machine use Product > Scheme > Manage Schemes to view the available schemes. In my case I have only a single scheme to mark as shared:

This creates the xcshareddata directory containing the scheme configuration that I can then check into the Git repository for the project.

Setting Up SSH Keys For Repository Access

To allow the Xcode server to access the GitHub repository it needs to know the SSH keys to use. GitHub has detailed instructions on generating SSH keys that you can follow if you need to create keys. In brief to create a new pair of keys from the command-line:

$ ssh-keygen -t rsa -C “your_email@example.com”

You will prompted for a file name and then a passphrase. By default this will create two files in the .ssh subdirectory of your home directory named id_rsa and id_rsa.pub but you can use some other value when prompted. You need to copy the contents of the id_rsa.pub file to the SSH keys section of your GitHub account. If in doubt refer to the detailed GitHub instructions.

A quick tip that I always forget: The pbcopy command is a quick way to copy the contents of a file to the clipboard making it easy to paste into a window:

$ pbcopy < ~/.ssh/id_rsa.pub

Add Remote Repository to Xcode Accounts

To allow the Xcode Server to access the remote code repository you first need to add it to the Xcode Account settings on your development Mac. In the Xcode preferences Account tab use the Add button to add the repository. In my case I want to access a repository on GitHub using the SSH public/private keys I created above. The SSH URL for the repository is as follows:

git@github.com:kharrison/UYLPasswordManager.git

Select SSH keys for the authentication method and then select your private key (in my case stored in ~/.ssh/github):

Xcode will pickup the public key and then attempt to authenticate with the remote repository.

Create a Bot

To create a bot to run our unit tests, use Product > Create Bot and check the scheme and server name are correct:

At this point the Xcode Server will check if it can access the source code repository which in my case will fail as I have not given Xcode any credentials:

Use the Change button and select Existing SSH Keys for the type and paste in the public (id_rsa.pub) and private (id_rsa) keys into the correct fields

Clicking Next will cause Xcode to validate the credentials and if all went well you should see the options to schedule and configure the bot:

Configure the Bot

A bot can be configured to run hourly, daily, weekly or when there is a new commit to the repository. When run the bot can perform static analysis, testing and product archiving actions. You can also specify if and when the bot should clean the build products and intermediates. To fit my requirements to run the tests on each commit I selected the following options:

  • Schedule: On Commit - the bot will check for new commits every 5 minutes
  • Actions: Perform analyze action, Perform test action
  • Cleaning: Once a day

I don’t archive every build and I only clean the build products once a day to keep the builds fast. Since you can have multiple bots you could also for example schedule a bot to run once a day that did a clean build and archive.

Next you can specify which devices and simulators should run the tests. Any devices you want to specify must be connected to the server. If you select Specific Devices and Simulators you are presented with a list of attached devices and the long list of simulators for each version of the iOS SDK.

Finally you can add an email notification or shell script trigger before and after a bot runs if you need some custom actions. By default an email notification is generated when a test fails or a build has errors:

With the bot configuration complete, use the Create button.

Monitoring Bots

There are several ways to view and manage a bot:

Report Navigator

You can manage the bots you have created from the Report Navigator in Xcode on your development Mac:

Right-clicking the bot in the navigator pane allows you to edit or delete the bot or run it immediately. Selecting the bot will show a summary of the bot integrations in the editor area of Xcode. Clicking on the entry in the navigator pane for a specific integration run will show detailed results:

Web Browser

Each bot is also accessible via a web browser at the URL: <hostname>/xcode/ where <hostname> is the address of the OS X Server. This view is less useful than the Xcode reporting interface but it does provide a quick summary of the most recent integrations. You can also switch to the big screen mode either by clicking the button on the bots homepage or using the URL: <hostname>/xcode/bigscreen.

Closing Summary

If you have never used a continuous integration server to run your tests you should give Xcode Server a try. It is a little bit of work if you are not already running OS X Server but for the most part it is simple to get started. Alternatives such as Travis CI are free for open source projects but will cost you money for private repositories so it is worth trying Xcode first to see if it will meet your needs.