Today we will be configuring an Xcode server that can be accessed from anywhere and configuring a bot to see that everything works. The work of setting up an Xcode server locally has been very well covered by Honza Dvorsky at https://honzadvorsky.com/pages/xcode_server_tutorials/. Rather than cover all of the same material we will just go over the changes that should be made to run the server on a remote machine (even if it’s sitting next to the machine you write your code on).
Things you will need:
- A Mac running 10.11, with Xcode 7 (development machine)
- A Mac running 10.11, with Xcode 7, and Server 5 (build machine)
- A paid Apple Developer account (for on device testing)
- A router capable of port forwarding (Apple routers make it super easy, but most allow for it somehow)
Enabling Remote Access
Before we get to setting up the Xcode portion of the server we need to make the server machine reachable from outside our home network. Most servers on the internet have a static IP address and that address is in a Domain Name Server (DNS) that takes the domain name entered into a browser (or any other app accessing the internet) and looks up the IP address that goes with it. If you are setting up a machine in your house or small company it is unlikely that you have a static IP address, you have an address that is assigned as needed (machine boots up, router restarts, internet connection is re-established, etc). This makes it impossible for a DNS to reliably connect us to the right place in the long run. Luckily there are some Dynamic DNS (DDNS) providers out there, some are even free. One of those free services is Duck DNS, their service is also super easy to setup and they aren’t out to sell you to advertisers so we will use them in this article. (Feel free to pick your own provider if you prefer the steps should be pretty similar once you have an account).
Start by navigating to duckdns.org and picking a way to log in (it’s safe enough to use Facebook as they don’t post to your wall or contact your friends). Once you are in you will see a screen that looks much like the one below.
Start by making note of the token as you will need it later. Then in the field near the bottom that says “sub domain” enter whatever you want (perhaps if you work for ACME Software you would enter “amceSoftware”) and click on add domain. That is all that needs to happen on their site, the rest happens on your build machine.
The server side instructions here come straight from the duckpins.org site but I’ve rephrased them and included them here so you don’t have to look for them (though if you need to setup anything other than a Mac, or if you are using home-brew on OS X, you should look at their instructions for your OS or router):
The basic idea is that there will be a script that gets run every few minutes, it will connect to their servers so the IP address can be updated as needed. Create a folder to store the script and log file (that will only ever say “OK” or “KO”) in. In this example we will be keeping it at the root level of our user folder but feel free to change the location just make sure to use the correct path later.
Within this new folder create a new file called duckdns.sh, this will be a shell script so you can use a command line tool like vi or a GUI tool like TextEdit as long as you set it to plain text. The contents of this file are pretty simple:
;&;token= &ip=" | curl -k -o /Users/ /duckdns/duck.log -K -
Where it says <yourSubDomain> enter the same thing you entered in the text field on the Duck DNS site and put the token you made note of earlier in the spot that says <token>, and of course substitute the appropriate username where is says <yourUsername> (or alter the path to correctly lead to your duckdns folder).
Next the script needs to be executable. Enter the following in terminal making sure you are in the duckdns directory:
chmod 700 duck.sh
The last thing is to set a cron task to fire the script on a regular basis. To edit the cron file enter the following on the command line:
This will launch vi with all the current tasks, if there are any. Below any existing lines enter the following (press ‘i’ to switch to insert mode):
*/5 * * * * /Users/<yourUsername>/duckdns/duck.sh >/dev/null 2>&1
Again enter the correct username or other modified path to the script where noted. Save the file and exit vi (CTRL+o then CTRL+x).
To test things out and get things started without having wait enter the following on the command line:
You should just get returned to the prompt after a second or so (depending on network speed). To see if it worked check the file named “duckdns.log” (you can quick look it, use cat on the command line, etc). The log should just say “OK”, if it says “KO” instead check that your token and domain are both correct in the script as that is the most likely issue.
The IP address that Duck DNS gets will typically lead it as far as your router which will need to forward the necessary ports to your build machine. If you are using an Apple router we will take care of port forwarding later, if however you aren’t using an Apple router then check out portforward.com for more information.
If you are doing port forwarding on your own you’ll need to know that Xcode uses TCP ports 20300, 20343, 20344, & 20345. You will also need to forward the standard HTTP, HTTPS, and SSH ports. Again with Apple routers you don’t need to worry about this.
At this point you won’t really get anything if you try loading the full domain name in a browser since we haven’t even installed Server yet.
Basic Server Setup
At this point you should open up Honza Dvorsky’s Xcode Server Tutorials: 1. Getting Started. Follow his article through the end of step 2 “Enabling Xcode Server” completing the steps on your build machine.
In the Repositories tab of the Xcode service pane make sure repos can be accessed as well as created. This will allow you to have your build machine host all your repos if you want (even if just as a secondary remote).
If you are using an Apple router this is the point to deal with port forwarding. On the left pick the second item, it should be your network name. In that pane you will find a single column table labeled “Public Services”. click the plus below that table, select Xcode from the popup menu in the sheet that appears and click Add. You can also add any other services you want available over the internet (proceed with caution, you may open yourself up to attacks so don’t turn on stuff you aren’t going to use). I have the Websites service accessible along with custom ones for Git (port 9418) and Dringend (port 5461), but you may want more or less ports forwarded.
Return to Honza’s tutorial and go through section 4 “Adding Server to Xcode” completing the steps on your development machine. When you get to the point of actually adding the server instead of using the IP address he provides (127.0.0.1) or selecting your server from the list of available servers enter <yourSubDomain>.duckdns.org. From there follow his instructions for the rest of the step.
Before you create a bot the server needs to have a copy of the repo to work with (as soon as you create a bot it will get run once, if there isn’t a copy or the repo yet it will just get confused and do nothing). In Honza’s tutorial the development and build machines are one in the same so the server already has a copy, that is not the case for us. To resolve this we need to add a new remote to our working copy and then push to that remote.
In Xcode with the XCSTutorialProject1 project selected goto Source Control -> XCSTutorialProject1 – master -> Configure XCSTutorialProject1… and select Remotes. At the bottom of the window click the plus button and select Create New Remote…. In the sheet the appears select your server if it isn’t already, enter a name for the remote and click Create. Click Done on the sheet that has the remotes listed. Then select Push… from the Source Control menu and push to your new remote (it will likely say “create” in parentheses after you remote name and the branch).
From here you can move on through the rest of the steps following them on your development machine remembering that your server name will be different from the ones he references. In step 5 of Honza’s tutorial you can save yourself the trouble of closing and re-opening the project when you get to the instruction to switch to the step 2 branch (git checkout step2) you can use Source Control -> XCSTutorialProject1 – master -> Switch to branch… and select the correct branch from there.
Now you can move onto his next tutorial, Xcode Server Tutorials: 2. Integrations. All of the instructions should be completed on your development machine. With the exception of step 2 you can follow the instructions just as he has them listed.
In step 2 substitute https://127.0.0.1/xcode for your *.duckdns.org/xcode or go to your server in Xcode’s preferences and click on the little arrow beside the server name.
Next up is Xcode Server Tutorials: 3. Prebuild & Postbuild Scripts. Before getting started with Honza’s tutorial make sure Cocoapods and fastlane are installed on both the development and build machines. I recommend starting with Cocoapods first as it is a one line install unless you want to avoid using sudo…
$ sudo gem install cocoapods
If you want to avoid using sudo or need more install information the install guide is here.
Next you can move onto fastlane, it is also pretty easy to install…
Start by installing the Xcode command line tools by entering the following in Terminal:
This will trigger the OS to download and install the correct package for you and will bring up a system dialog to confirm you want to install the tools. Once that is done you need to accept the license with the following command:
sudo xcodebuild -license accept
Finally, you can install fastlane itself:
sudo gem install fastlane --verbose
At this point you should go make a cup of tea (it will be a few minutes).
Once both machines are taken care of you can start following Honza’s tutorial completing step 1 & 2 on your development machine (remember you can have Xcode change branches for you rather than closing the project, switching to the command line and re-opening the project). Don’t forget to push the new branch to the server remote before moving on.
Steps 3 & 4 should be done on you build machine as your development machine doesn’t have a user named _xcsbuildd and the SSH keys you add should be for your build machine (if you haven’t added SSH keys for your development machine to GitHub, or whatever cloud based repo you are using follow those instructions on your development machine too so everything is set).
Steps 5 & 6 can be done from your development machine and followed as is.
The last of the tutorials is Xcode Server Tutorials: 4. Certificates and Provisioning as the name suggests it deals with certificates and provisioning profiles which means this is the part you need a paid developer account for. When I went through it I had to add an app identifier to my developer account before I got things to work properly.
With the exception of the small part in step 3 when Honza mentions the certificates needing to go to the server machine everything can happen on your development machine. Keep in mind that you will only be able to use the wifi install of archives when on you home network, it wont work over the internet.
That’s All Folks
At this point your server is ready for action and you have the framework for how to create bots to automate tests. You should be alright as far as certificates go until your current ones expire or if you add new certificates. As long as you remember to transfer any certificates you make in the Apple developer portal over to your build machine along with their private keys things will keep working.
Honza has a couple other related articles here that may also be of interest if you want to dig deeper in to Xcode Server (I’ll be reading them very soon). As he adds new tutorials I will likely either update this post or add new ones if there are any differences to deal with for a multi machine setup.
The last thing to do is to write some tests for your other projects so your server has something to do. To learn more about writing tests you might want to have a look at Cate Huston’s iOS Unit Testing: Beyond the Model I’ve just bought it so I can’t say for sure that it’s useful but it looks very promising and is only $20. It is written for Objective-C code currently but translating it to Swift shouldn’t be too difficult, I know Natasha the Robot is working through it in Swift and posting about it so you can get some hints from her posts if you need them.