Using TeamCity with Xamarin
This guide will discuss the steps involved with using TeamCity to compile mobile applications and then submit them to App Center Test.
As discussed in the Introduction to Continuous Integration guide, continuous integration (CI) is a useful practice when developing quality mobile applications. There are many viable options for continuous integration server software; this guide will focus on TeamCity from JetBrains.
There are several different permutations of a TeamCity installation. The following list describes some of these permutations:
Windows Service – In this scenario, TeamCity starts up when Windows boots as a Windows Service. It must be paired with a Mac Build Host to compile any iOS applications.
Launch Daemon on OS X – Conceptually, this is similar to running as a Windows Service described in the previous step. By default the builds will be run under the root account.
User Account on OS X – It's possible to run TeamCity under a user account that starts up each time the user logs in.
Of the previous scenarios, running TeamCity under a user account on OS X is the simplest and easiest to set up.
There are several steps involved with setting up TeamCity:
Installing TeamCity – The installation of TeamCity isn't covered in this guide. This guide assumes that TeamCity is installed and running under a user account. Instructions on installing TeamCity can be found in the TeamCity 8 documentation by JetBrains.
Preparing the Build Server – This step involves installing the necessary software, tools, and certificates required to build mobile applications and prepare them for distribution.
Creating A Build Script – This step isn't strictly necessary, but a build script is a useful aid to building applications unattended. Using a build script will help with troubleshooting build issues that may arise and provides a consistent, repeatable way to create the binaries for distribution, even if continuous integration isn't practiced.
Creating A TeamCity Project – Once the previous three steps are completed, we must create a TeamCity project that will contain all of the meta-data necessary to retrieve the source code, compile the projects, and submit the tests to App Center Test.
Experience with App Center Test is required.
Familiarity with TeamCity 8.1 is required. The installation of TeamCity is beyond the scope of this document. It's assumed that TeamCity is installed on OS X Mavericks and is running under a regular user account and not the root account.
The build server should be a stand-alone computer, running OS X, that is dedicated to continuous integration. Ideally, the build server won't be responsible for any other roles, such as a database server, web server, or developer workstation.
This guide does not cover a "headless" installation of Xamarin.
In order for tests to be submitted to Xamarin Test Cloud, the computer submitting the tests must be able to communicate with the Test Cloud servers. Firewalls must be configured to allow network traffic to and from the servers located at testcloud.xamarin.com on ports 80 and 443. This endpoint is managed by DNS and the IP address is subject to change.
In some situations, a test (or a device running the test) must communicate with web servers protected by a firewall. In this scenario the firewall must be configured to allow traffic from the following IP addresses:
Preparing the Build Server
A crucial step in configuring a build server is to install all of the necessary tools, software, and certificates to build the mobile applications. It's important that the build server can compile the mobile solution and run any tests. To minimize configuration issues, the software and tools should be installed in the same user account that is hosting TeamCity. The following list details what's required:
- Visual Studio for Mac – This includes Xamarin.iOS and Xamarin.Android.
- Log in to the Xamarin Component Store – This step is optional and only required if your application uses Components from the Xamarin Component store. Proactively logging into the Component store at this point will prevent any issues when a TeamCity build tries to compile the application.
- Xcode – Xcode is required to compile and sign iOS applications.
- Xcode Command-Line Tools – This is described in step 1 of the Installation section of the Updating Ruby with rbenv guide.
- Signing Identity & Provisioning Profiles – Import the certificates and provisioning profile via XCode. See Apple’s guide on Exporting Signing Identities and Provisioning Profiles for more details.
- Android Keystores – Copy the required Android keystores to a directory the TeamCity user has access to, i.e.
- Calabash – This is an optional step if your application has tests written using Calabash. See the Installing Calabash on OS X Mavericks guide and the Updating Ruby with rbenv guide for more information.
The following diagram illustrates all of these components:
Once all of the software is installed, log in to the user account and confirm that all of the software is properly installed and working. This should involve compiling the solution and submitting the application to App Center Test. This can be simplified by running the build script, as described in the next section.
Create a Build Script
Although it's possible for TeamCity to handle all aspects of compiling and submitting mobile applications to App Center Test by itself; it's recommended to create a build script. A build script provides the following advantages:
- Documentation – A build script serves as a form of documentation on how the software is built. This removes some of the “magic” that is associated with deploying the application and allows developers to concentrate on functionality.
- Repeatability – A build script ensures that each time the application is compiled and deployed, it happens in the same way, regardless of who or what does the work. This repeatable consistency removes any issues or errors that might appear because of an incorrectly executed build or human error.
- Versioning – A build script can be included in the source control system. This means that changes to the build script can be tracked, monitored, and corrected if errors or inaccuracies are found.
- Prepare the Environment – A build script can include logic to install any required 3rd party dependencies. This will ensure that the applications are built with the proper components.
The build script can be as simple as a PowerShell file (on Windows) or a bash script (on OS X). When creating the build script, there are several choices for scripting languages:
Rake – this is a Domain-Specific Language (DSL) for building projects, based on Ruby. Rake has the advantage of popularity and a rich ecosystem of libraries.
psake – this is a Windows PowerShell library for building software
FAKE – this is a DSL based in F# which makes it possible to use existing .NET libraries if necessary.
Which scripting language is used depends on your preferences and requirements.
It's possible to use an XML based build system such as MSBuild or NAnt, but these lack the expressiveness and maintainability of a DSL that is dedicated to building software.
Parameterizing The Build Script
The process of building and testing software requires information that should be kept secret. Creating an APK may require a password for the keystore and/or the key alias in the keystore. Likewise, App Center Test requires an API key that is unique to a developer. These types of values shouldn't be hard-coded in the build script. Instead they should be passed as variables to the build script.
Less sensitive are values such as the iOS device ID or the Android device ID that identify what devices App Center should use for test runs. These aren't values that need to be protected, but they may change from build to build.
Storing these types of variables outside of the build script also makes it easier to share the build script within an organization, with developers for example. Developers may use the exact same script as the build server, but can use their own keystores and API keys.
There are two possible options for storing these sensitive values:
A configuration file – To protect the API key this value shouldn't be checked into version control. The file can be created for each machine. How values are read from this file depends on the scripting language used.
Environment variables – these can be easily set on a per-machine basis and are independent of the underlying scripting language.
There are advantages and disadvantages to each of these choices. TeamCity works nicely with environment variables, so this guide will recommend this technique when creating build scripts.
The build script must do the following steps:
Compile the Application – This includes signing the application with the correct provisioning profile.
Submit the Application to Xamarin Test Cloud – This includes signing and zip aligning the APK with the appropriate keystore.
These two steps will be explained in more detail below.
Compiling a Xamarin.iOS Application
The following command line to specify a Release build of the solution SOLUTION_FILE.sln for the iPhone. The location of the IPA can be set by specifying the
IpaPackageDir property on the command line:
On the Mac, using xbuild:
xbuild /p:Configuration="Release" \ /p:Platform="iPhone" \ /p:IpaPackageDir="$HOME/Builds" \ /t:Build MyProject.sln
The xbuild command is typically found in the directory /Library/Frameworks/Mono.framework/Commands.
On Windows, using msbuild:
msbuild /p:Configuration="Release" /p:Platform="iPhone" /p:IpaPackageDir="%USERPROFILE%\Builds" /p:ServerAddress="192.168.1.3" /p:ServerUser="macuser" /t:Build MyProject.sln
msbuild will not automatically expand
$( ) expressions passed in by the command line. For this reason it is recommended to use a full path when setting the
IpaPackageDir at the command line.
See the Release Notes for iOS 9.8 for more details about the
Compiling a Xamarin.Android Application
To compile an Android application, use xbuild (or msbuild on Windows):
/Library/Frameworks/Mono.framework/Commands/xbuild /t:SignAndroidPackage /p:Configuration=Release /path/to/android.csproj
Compiling the Android application xbuild uses the project, while the iOS application xbuild uses the solution.
Submitting Xamarin.UITests to App Center
UITests are submitted using the App Center CLI, as shown in the following snippet:
appcenter test run uitest --app <TEAM-NAME/APP-NAME> --devices <DEVICE_SET> --token <API_KEY> --app-path <appname.APK-or-appname.IPA> --merge-nunit-xml report.xml --build-dir pathToUITestBuildDir
When the test is run, the test results will be returned in the form of an NUnit style XML file called report.xml. TeamCity will display the information in the Build Log.
Submitting Calabash Tests to App Center
Calabash tests are submitted using the App Center CLI, as shown in the following snippet:
appcenter test run calabash --app <TEAM-NAME/APP-NAME> --devices <DEVICE_SET> --token <API_KEY> --app-path <appname.APK-or-appname.IPA> --project-dir pathToProjectDir
To submit an Android application to App Center Test, it's necessary to first rebuild the APK test server using calabash-android:
$ calabash-android build </path/to/signed/APK> $ appcenter test run calabash --app <TEAM-NAME/APP-NAME> --devices <DEVICE_SET> --token <API_KEY> --app-path <appname.APK> --project-dir pathToProjectDir
For more information on submitting Calabash tests, consult Xamarin’s guide on Submitting Calabash Tests to Test Cloud.
Creating a TeamCity Project
Once TeamCity is installed and Visual Studio for Mac can build your project, it's time to create a project in TeamCity to build the project and submit it to App Center.
Started by logging into TeamCity via the web browser. Navigate to the Root Project:
Underneath the Root Project, create a new subproject:
Once the subproject is created, add a new Build Configuration:
Attach a VCS project to the Build Configuration. This is done via the Version Control Setting screen:
If there's no VCS project created, you can create one from the New VCS Root page shown below:
Once the VCS root has been attached, TeamCity will check out the project and try to auto detect build steps. If you're familiar with TeamCity, then you can select one of the detected build steps. It's safe to ignore the detected build steps for now.
Next, configure a Build Trigger. This will queue up a build when certain conditions are met, such as when a user commits code to the repository. The following screenshot shows how to add a build trigger:
An example of configuring a build trigger can be seen in the following screenshot:
The previous section, Parameterizing the Build Script, suggested storing some values as environment variables. These variables can be added to the build configuration via the Parameters screen. Add the variables for the App Center API Key, the iOS device ID, and the Android Device ID as shown in the screenshot below:
The final step is to add a build step that will invoke the build script to compile the application and enqueue the application to App Center Test. The following screenshot is an example of a build step that uses a Rakefile to build an application:
At this point, the build configuration is complete. It's a good idea to trigger a build to confirm that the project is properly configured. A good way to do this is to commit a small, insignificant change to the repository. TeamCity should detect the commit and start a build.
Once the build has completed, inspect the build log and see if there are any problems or warnings with the build that require attention.
This guide covered how to use TeamCity to build Xamarin Mobile applications and then submit them to App Center Test. We discussed creating a build script to automate the build process. The build script takes care of compiling the application, submitting to App Center Test, and waiting for the results.
Then we covered how to create a project in TeamCity that will queue a build each time a developer commits code and will call the build script.