Apple has very comprehensive documentation on Xcode Servers and Continuous Integration with the OSX server (app) and Xcode server (Xcode within the server app). You might be wondering what the point of this post is if everything is documented in the guide. Apple's guide still reads as the OSX server rather than the MacOS Server, but Apple has released the new MacOS Server (5.2) with some improvements in the Automated Xcode Builds.
This small tutorial aims to set up a Mac to run as a MacOS server with Xcode service and to set up basic Xcode bots for the MacOS Server with Xcode 8 to perform Continuous Integration. We will cover:
- MacOS server basics and setup.
- Configure Xcode to use the Xcode service of the MacOS server.
- Set up development Xcode to use Xcode Server on the MacOS server.
- Create an Xcode bot with an example of the XCFit Swift Package on GitHub.
- Run bot integrations and analyze results.
In order to set up Continuous Integration using MacOS Server and Xcode Service, we need:
- Mac or Mac Mini with the MacOS Server 5.2 app. (Download it from the App Store.)
- Xcode 8 on the server. (Download it from the App Store.)
- Swift 3.
- The Xcode project repository hosted on GitHub (optional for the tutorial).
- Another development Mac from which we can trigger Xcode bots (optional for this tutorial).
What's New in MacOS Server (5.2)
Apple has renamed their old OSX server as MacOS server. It has a lot of new things, like profile manager, a caching server, NFS, Xsan 5, etc., but let's focus on what's new for the Xcode service.
- The MacOS server isn't supporting old Xcode versions. It supports Xcode 8+.
- The MacOS server isn't supporting old Swift versions. It supports Swift 3+. Read more here.
- Xcode bots running on the OSX server or Xcode server are broken when server app is upgraded to 5.2, i.e., MacOS server. Read customer reviews of the server app.
This means using there are some significant changes in this release that can affect the current CI system with Xcode Server. The new macOS server will have following features.
Custom Environment Variable
This isn’t new, but Xcode 8 will now allow us a set of environmental variables without the creation of extra schemes.
Advance Trigger Editing
The MacOS server will now have two types of triggers: script triggers and email triggers. We will have control over how to set email containers.
Issue Tracking and Blaming
The Xcode server will send an email to the person who broke the build. We can now configure bots instead of changing code.
The Xcode server now re-integrate your project if it fails using same revision. It also prevents blaming for the broken build.
Configurable Integration Users
The Xcode server will have now its own user called "Xcode Server," which gives you full control with password as any normal MacOS user. Setting a new user seems fairly easy in the Xcode server.
Now, we will see how to set up the MacOS server for our fresh Mac or Mac Mini.
Set Up MacOS Server
This is assuming that you have already downloaded Xcode 8 on the Mac and have also downloaded the MacOS Server (5.2) app (which might cost some money, but if you already have a developer account, then you might able to redeem it for free).
Start Server App
Once downloaded, we can launch the server app.
Once launched for the first time, it will show you the entire tutorial for how to use the new MacOS server for all services.
It's worth spending some time reading this tutorial about some of the other services to see what's new there.
Next, the MacOS Server will say Choose a Mac. Select This Mac, as we are setting the same Mac for the Xcode server.
Select User to Run Integrations
The next step is to select the user to run Xcode bot integrations. We can use the same user who is logged in, but we have the option to use another user Xcode server. There will be an option to create a new user.
We will use the same user to run the test to avoid user swapping. My username is shashi.
Now, the MacOS server will take some time configuring, and then we will be able to connect to the MacOS Server.
Configure Xcode for Xcode Service
The MacOS server has lots of other services, but we need a Xcode service, which is a Continuous Integration service to automate the static analysis of code, build apps, run tests, archive apps, report code coverage, report test results, send notifications, etc. Now, developers working on Git repositories can trigger integrations by creating Xcode bots. Xcode integrations can be triggered manually, after code changes, or periodically.
Now we have various settings like choosing Xcode, setting up user permissions, and configuring development team and development devices.
The next step is to configure Xcode service from MacOS server to run our integrations. Now, select Xcode service from the server app and choose the Xcode 8 app installed on the Mac.
Choose User to Run Test
Now, we can select here to run our test or integrations triggered from the Xcode bot. We have already created an Xcode server user, but it can be any user. We can switch users if we wish to. It isn't a good idea to give that user Administrative rights because it's not required.
Choose Development Team and Devices
Now it's time to configure details of our development team with our Apple ID. We need provisioning profiles, certificated to configure this. We can add real devices to the Server as well. Once provisioned devices connected to the Mac it will start appearing in the device list.
Add Your Git Repo
Assuming you are a team of developers working on the GitHub repo, we can add a GitHub repo to our Xcode service. We can set up repository access with SSH or HTTP. There is a button to add multiple repositories to be hosted on the Xcode server. You can do it from XcodeBot Setup, as well, which we will cover later in this post. Let's add a Swift package called XCFit as the Git Repo.
Turn On Xcode Service
Turn on Xcode service by clicking on the button once we have everything set up. You should see it as shown in the screenshot below.
At this stage, our Mac with a MacOS server will accept any integrations triggered by the Xcode bot. Now, developers can create bots as per their needs and our Mac will be capable of running those integrations.
Share Server Details With Team
We have just completed all the necessary setups to run Xcode bot on our Mac. It's time to share the server details to the development team so that they can configure the MacOS server on individual Xcode servers installed on the Mac. The details are on the main server tab. Details will be:
- Host name and IP address.
- SSH access with username and password.
- Network to be used.
The developers will use these details to configure the local development Xcode to connect to the Xcode server.
Configure Xcode to Use Xcode Server
Now, we have our MacOS server fully set up for running our Xcode bots. We need to configure the local development Xcode to connect to the Xcode Service installed on the MacOS Server. We have all the details of the server to configure. We will configure the same Mac to connect to the local Xcode server, but ideally, there will other development Macs connecting to the Xcode server.
In order to add the MacOS server to Xcode, launch the Xcode project you are working on and Select Xcode > Preference > Account > click on + > Add Server.
There will an option to select a server or connect to a host. Select the server that we have just configured.
Add Integration User
On the next screen, we will see the option to log into the user on the MacOS server. We have to log in with the user we have set up to run integrations. Otherwise, the Xcode server will show an error. We have configured my user shashi to run integrations so lets log into the server with that user.
Once the user is successfully added, we should see a screen with Server status "on." It should look like this:
At this stage, we have configured our local Xcode to use the MacOS Server. We should now able to create Xcode bots.
Create Xcode Bots
Xcode Bots are similar to the Jobs in Jenkins or Projects in TravisCI. We have to configure a set of automated instructions to checkout source code, build, test, and notify, etc. The benefit of the Xcode bot is that we can configure the bot straight from the Xcode. We can see all the created bots in the Test Navigator of the Xcode. We will use the XCFit GitHub repository to configure bots.
Clone the project from the GitHub and open the project in the Xcode.
$ git clone email@example.com:Shashikant86/XCFit.git $ open XCFit.xcodeproj
This will open the project in Xcode. Go to Product > Create Bot and name the bot XCFit Bot.
Add Repository With SSH Credentials
The next step is to add GitHub repo to the bot. We have to add Git repo with SSH. Xcode will ask you to trust the identity repository. You have to select Trust and use credentials for the existing SSH Key.
Once successfully authorized, we should able to configure the build.
Add Build Configuration
The build configuration is the main stage to configure what we want to perform as part of the build. The Xcode bot has some options like:
- Scheme: This is the Xcode scheme we will build.
- Actions: We have to tick Perform Static Analysis and Perform Test Action with code coverage enabled. At this stage, we don't need Perform Archive Action, as it's just a Swift Package.
- Cleaning and configuration: Keep this default to "Never" and "Use Scheme Setting"
We can then schedule the build whenever we want to build the Xcode bot. There are three major options to build or integrate the Xcode bot.
- Periodically: This has the option to integrate Xcode bot daily, weekly, or hourly at a specific time.
- On commit: After Every commit to Git Repository this Xcode Bot will be integrated.
- Manual: We have to manually click Integrate to perform the Xcode Bot integration.
There is an option to select the device to run an integration on. We can run tests on a real device or on simulators. The provisioned devices attached to the Xcode servers will appear on the list. We have various OS combinations to run integrations on such as MacOS, iOS, tvOS, and watchOS.
We don't an iOS device or simulator, as its Swift package and can be run on a Mac just in case we are using iOS app and want to select a specific device or iOS simulator. We will select MacOS for this bot.
There is an option to use custom environment variables or use predefined variables to perform integrations. A full list of Xcode server environmental variable is here. In our case, we don't need to select a variable.
Triggers are set of actions to be performed before or after Xcode bot integration. The Xcode bot has following available triggers:
- Pre-integration script: We can add bash scripts to run before integration starts.
- Post-integration script: This involves the bash script being executed after integration is finished.
- Emails about new issues: Receive email notifications when a new issue comes up.
- Periodic email reports: Receive email notifications after regular intervals.
We don't need to select any trigger for our XCFit Bot. You should now see the message that we have successfully configured our bot.
Run Integrations and Analyze Results
Once the Xcode bot is configured, it will automatically start integration. The typical integration will check out the source code and perform all the actions defined in the build configurations. At the end of the integration, we will see a summary.
We will also have the option to view tests, code coverage, and logs.
Xcode Bot in Action
Let's watch everything we described in action. You can watch a YouTube video about this here or watch this animated GIF:
Congratulations! You have successfully configured the Xcode bot and performed integrations.
WWDC Tips for Xcode Server Users
- Dedicate a new user to run integrations from the Xcode bot.
- Avoid using administrative accounts for the Xcode server user.
- Stay logged in with fast user switching.
- Disable screen lock in order to avoid UI tests failing unnecessarily.
- Customize needs such as simulators, networks, and advanced provisioning.