Setting up simple Continuous Integration server for iOS application

Ci featured image

In this blog post I will show how to set up a Continuous Integration server for iOS applications. It will run our Unit Tests and confirm that builds aren’t corrupted.

We will use:

  • TeamCity as our CI server – it provides really good (and official!) support for iOS projects, integration with AppCode and easy to use interface.
  • xctool as a replacement for Apple’s xcodebuild – it eases a lot of pains connected with building an application.
  • git as our VCS – you can easily follow this post even if you use a different VCS, but from now on I will assume that you use git

Installation

TeamCity

  1. Download TeamCity for Mac OS X from https://www.jetbrains.com/teamcity/download/
  2. Unpack the downloaded package with tar xfz <name of package>.tar.gz
  3. Run TeamCity server with one default agent with script sh <TeamCity home>/bin/runAll.sh start
  4. Open http://localhost:8111/ in your browser.
  5. Select Proceed on the welcome page:
    TeamCity welcome screen
  6. Select one of the available databases.1 Select Proceed when you are ready.
    TeamCity database tutorial
  7. Wait for TeamCity to finish the initialization.
  8. Read and accept the license agreement and then select Continue:
    TeamCity License
  9. Create your administrator account for TeamCity:
    TeamCity Create account
    Now your basic setup is ready. You can fill in the remaining data, but it is not necessary to continue.

xctool

The easiest way to install xctool is to use homebrew. Just type in your terminal brew install xctool and you are done. If you don’t use homebrew, I highly recommend you to start.

Build script

Why build script?

We will use a custom build script instead of built-in TeamCity tools. Although those tools are much easier to use, a custom script has few deciding advantages:

  • much more flexible – we are not restricted to running XCTests and builds. We can add Acceptance Tests and UI tests later on.
  • agnostic of your CI server – if you ever decide to use different technology than TeamCity you will be able to reuse it.
  • goes with the source files – you can run it on your local machine2 and changes to it doesn’t require you to go through the web page.

My build script

  1. Copy the script below to the main folder of your project and replace APPLICATION_NAME and TEST_SCHEME_NAME with your application data. Don’t forget to remove my footnotes from the build script :).
  2. Add executable permissions to your script with chmod +x SCRIPT_NAME.
    # Clean repository, DerivedData folder and simulator
    git reset --hard3
    git clean -fd4
    rm -rf ~/Library/Developer/Xcode/DerivedData/APPLICATION_NAME*5
    xcrun simctl erase all6
    # Unit tests
    xctool \
    -scheme TEST_SCHEME_NAME \7
    -workspace APPLICATION_NAME.xcworkspace \8
    -destination "platform=iOS Simulator,name=iPhone 6,OS=8.3" \9
    -sdk iphonesimulator \
    -reporter junit:test-results/TEST-UnitTests.xml \10
    -reporter pretty \11
    clean test

Adding a project to TeamCity

Now that we have everything installed and the build script is committed into our project we can finally configure our first task in TeamCity.

  1. Open http://localhost:8111/ in your browser and log in to your previously created account.
  2. Select Create Project:
    TeamCity getting started
    If you already created any project you need to select Administration/Projects/Create project.
  3. Fill in Name and Project ID12 fields and select Create:
    TeamCity New project
  4. The next thing we need to do is to create a build configuration. Select Create build configuration:
    TeamCity project settings
  5. Fill in Name and Build configuration ID12 fields and select Create:
    TeamCity Creating build configuration
  6. Next step is to configure the VCS for your project:
    TeamCity Version Control System

        a) Select

    git

        as type of your

    VCS

        .
        b) Type in the name for your

    VCS

        configuration.
        c) Type in your

    VCS

        ID

    12

        .
        d) Type in the URL for your repository.
        e) Change

    master

        to the name of the branch you want to test (but leave refs/heads/).
        f) Select the appropriate

    Authentication method

        . The easiest ones to configure are

    Anonymous

        (if your project is public) or

    Password

        (if it is private).
        g) You can test if the configuration is correct now.
        h) When you are ready, select

    Create

      .

     

  7. Next we need to add steps to our configuration. From the left menu select Build Steps:
    TeamCity Configuration Menu
  8. And then Add build step:
    TeamCity Build Steps
  9. From the list of available build steps select Command Line:
    TeamCity Build Steps Selection
  10. In the Custom script section, type in sh SCRIPT_NAME to run your script every build and select Save:
    TeamCity command line
  11. Now we have Continuous Integration up and running but we can’t see the results of the tests. Select Build Features13 from the left menu:
    TeamCity Configuration Menu
  12. And then Add build feature:
    TeamCity Build Features
  13. From the popup menu select XML report processing (you may need to scroll – it is at the bottom of the list):
    TeamCity Build Feature Selection
  14. And from the Report type select Ant JUnit:
    TeamCity Build Feature XML Type
  15. In Monitoring rules we type test-results/*.xml, to tell the parser to take all results from the test-results folder. After that select Save:
    TeamCity Build Feature JUnit parser
  16. Test if everything is working with Run command in the right upper corner of the page:
    TeamCity Run

Summary

In this post we were able to run a simple Continuous Integration server that will run Unit Tests every time you make a commit to git. But this is not over!. There are few more things worth adding:

  • Make our server notify us by email about build results
  • Change the authentication method to use deploy key instead of our credentials
  • Set up production database
  • Add Acceptance Tests step
  • Make our server automatically start after reset
  • Separate Agent and HTTP server
  • Set up automatic sending builds to our testers and/or clients

We will add them in future posts.

______________________________________________________

  1. For evaluation you can select Internal, but TeamCity‘s advice is to change it as soon you want to move to production.  
  2. TeamCity can do that for you also through integration with AppCode 
  3. Reset git repository before build. This step is not mandatory. 
  4. Clean git repository before build. This step is not mandatory. 
  5. Remove DerivedData folder for your application. This step is not mandatory. 
  6. Erase the simulator before running tests. This step is not mandatory and can be dangerous if you have more than one agent, but it solved few problems with builds. 
  7. Default scheme is named after your project and it contains test target. 
  8. Skip this part if you don’t use workspaces. 
  9. You can specify here on which simulator you want to test your application. You can remove this line if you want to use the default one. 
  10. Redirect test results in jUnit format to folder test-results. We will use them later to display test results in CI. 
  11. Display test results to console. Useful for debugging. 
  12. ID can contain only alpha-numeric characters and underscores, is restricted to 80 characters, starts with a Latin letter and must be unique across all other similar IDs. 
  13. Build Features are commands that are executed after the build is finished.