TeamCity Integration

     

Teamcity banner

Over the last couple sprints I’ve become my team’s informal DevOps subject matter expert. This was because we needed to implement Continuous Integration/Continuous Delivery we were fairly low on the backlog of our Company’s formal DevOps team. Over the course of teaching myself how GitHub, TeamCity, Slack, and HockeyApp can all plug into one another I wrote a pretty handy little tutorial. Enjoy.

TeamCity Installation

The guide below is based on the TeamCity Documentation. A note on the terminal commands: you must execute them from the root of the file otherwise the shell script may fail to run. For example, running /buildAgent/bin/agent.sh start will work, but trying to run agent.sh start from within the bin directory will fail.

  1. Download TeamCity for macOS
  2. Unzip the file and move the folder to /Library/
  3. Make sure it works if started from the command line with bin/teamcity-server.sh start
  4. Create the /Library/LaunchDaemons/jetbrains.teamcity.server.plist file with the following content:
<?xml version="1.0"encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN""http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">
<dict>
    <key>WorkingDirectory</key>
    <string>/Library/TeamCity</string>
    <key>Debug</key>
    <false/>
    <key>Label</key>
    <string>jetbrains.teamcity.server</string>
    <key>OnDemand</key>
    <false/>
    <key>KeepAlive</key>
    <true/>
    <key>ProgramArguments</key>
    <array>
        <string>bin/teamcity-server.sh</string>
        <string>run</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>StandardErrorPath</key>
    <string>logs/launchd.err.log</string>
    <key>StandardOutPath</key>
    <string>logs/launchd.out.log</string>
</dict>
</plist>
  1. Test your file by running launchctl load /Library/LaunchDaemons/jetbrains.teamcity.server.plist. This command should start the TeamCity server (you can see this from logs/teamcity-server.log and in your browser).
  2. TeamCity server will now start automatically when the machine starts. If you’re operating TeamCity from a headless server you will need to configure your mac to automatically login as the build user, as described here.
  3. You can access the Web UI by navigating to http://localhost:8111/ It may be necessary to restart your computer before accessing it for the first time.
  4. To change the server port, in the /conf/server.xml file, change the port number in the existing, uncommented, “” XML node
  5. When you access the Web UI there will be a TeamCity First Start page. Proceed through the prompts with the existing defaults.
  6. Accept the license agreement.
  7. Create an administrator account. This is the account that will be used to log into the TeamCity software.

Project Creation

A project in TeamCity is a collection of build configurations. Build configurations are settings edited in the Web UI which are used to start a build. The settings include VCS, run procedure (build steps and environment parameters), and triggers (when to start a new build). Examples of build configurations are distribution, integration tests, prepare release distribution, “nightly” build, deploy to QA. The project has a name, an ID, and an optional description. In TeamCity, user roles and permissions are managed on per-project basis.

  1. Access the Web UI by navigating to http://localhost:8111/
  2. Click the Projects button in the upper-left-hand corner.
  3. Select Create project and then Pointing to repository URL
  4. Copy and paste the github project address into repository URL field (i.e. https://github.com/SC-TechDev/lcv3-ios).
  5. Input your GitHub username and password and click Proceed
  6. Keep the auto-populated fields and click Proceed When Auto-detected Build Steps appears check the schemes (iOS) or buildTypes (Android) that you want to use for the build and click Use selected (NOTE: If deployed on a TeamCity Server you will need to make sure xCode and Android Studio are installed).
  7. Add any build triggers that you want under the Triggers section
  8. Add any failure conditions you want under the Failure Conditions section (highly recommended: Fail build on metric change > Fail build if: its percentage of class/method/line coverage > compared to constant value > is less than 50) (NOTE: Read this Apple Developer Guide and this Android Studio Guide on the code coverage reporting as they are implemented in Xcode and Android Studio)
  9. Build Features, Dependencies, Parameters, and Agent Requirements can be safely skipped for now.

Build Agent Installation

A Build Agent is a piece of software which listens for the commands from the TeamCity server and starts the actual build processes. It is installed and configured separately from the TeamCity Server. It can be installed on the same computer as TeamCity or a different computer. (NOTE: This tutorial assumes the build agent is located on the same machine that the code was developed on. If it’s not paths will need to be adjusted to accommodate the build agent’s output directory)

  1. Make sure a JDK (JRE) 1.6+ (1.8 is recommended) is properly installed on the agent computer from the command line with java -version
  2. In the TeamCity Web UI, navigate to the Agents tab along the top.
  3. Click the Zip file distribution under the Install Build Agents section to download the archive.
  4. Unzip the downloaded file into the desired directory.
  5. Navigate to the /buildAgent/conf directory, locate the file called buildAgent.dist.properties and rename it to buildAgent.properties
  6. Edit the buildAgent.properties file to specify:
    • The TeamCity server URL (i.e. serverUrl=http://localhost:8111/)
    • The name of the agent. (i.e name=lcv-ios)
    • The path to the android SDK (i.e. env.ANDROID_HOME=/Users/jtaylor/Library/Android/sdk)
  7. Now you can start the agent manually by executing /buildAgent/bin/agent.sh start, or stop by executing /buildAgent/bin/agent.sh stop
  8. To run the buildAgent automatically at startup, enter the command line interface and execute the following commands:
    • /buildAgent/ mkdir logs
    • sh /buildAgent/bin/mac.launchd.sh load (It will take several minutes for the build agent to auto-upgrade)
    • When the build agent is upgraded and connects to TeamCity, stop it with sh /buildAgent/bin/mac.launchd.sh unload
  9. Copy /buildAgent/bin/jetbrains.teamcity.BuildAgent.plist file to $HOME/Library/LaunchAgents/
  10. If you’re operating the build agent from a headless server you will need to configure your mac to automatically login as the build user, as described here. Reboot afterwards.
  11. If you want to start several build agents on the Mac, repeat the procedure of installing and starting build agent with the following changes
    • Install the second build agent in a different director7 In /buildAgent/conf/buildAgent.properties, you should specify an unique name for the build agent
    • Start and upgrade second agent via the /buildAgent/bin/agent.sh script
    • In /buildAgent/bin/jetbrains.teamcity.BuildAgent.plist file, you should specify unique “Label” parameter (jetbrains.teamcity.BuildAgent by default)
    • When copying jetbrains.teamcity.BuildAgent.plist file to LaunchAgents, you should give it a different name
  12. When the newly installed agent connects to the server for the first time, it appears on the Agents page, Unauthorized agents tab visible to administrators/users with the permissions to authorize it. Agents will not run builds until they are authorized in the TeamCity web UI. The agent running on the same computer as the server is authorized by default.

Slack Integration

In order to receive build status updates in a slack channel:

  1. Download the TeamCity Slack plugin zip file.
  2. In the TeamCity Web UI, navigate to the Administration tab along the top.
  3. Select Plugins List from the bottom left.
  4. Select Upload plugin zip and select the slack plugin zip file when the dialog box appears.
  5. Restart TeamCity server.
  6. In the TeamCity Web UI, navigate to the admin tab along the top.
  7. Select Notification Rules and then Slack Notifier
  8. Create an incoming webook (https://my.slack.com/services/new/incoming-webhook) in Slack
  9. Copy and paste the webhook URL given by slack in step 8 into the Slack Notifier notification rule from step 7.
  10. Pick a Slack username to use for automated notifications.
  11. Pick a Slack channel to notify on build events.
  12. Click Save
  13. Select Add new rule and then define what you want the TeamCity Slackbot to notify you of (build failed, build succeeded, etc.)

HockeyApp Integration

HockeyApp integration involves the addition of two build steps to both platforms.

  1. Access the Web UI by navigating to http://localhost:8111/
  2. Select Administration > Projects and select edit to the right of the ios project
  3. Under Build Configurations select edit for the Build
  4. Select Build Steps from the side bar and click Add build step and then select Command Line from the drop down menu.
  5. Name the step “Archive and Export” and paste the code below into the Custom Script text box
    • xcodebuild -workspace .xcworkspace -scheme archive -archivePath /Users//Desktop/.xcarchive
    • (i.e. xcodebuild -workspace /Users/jtaylor/Desktop/GitHub\ Clones/lcv3-ios/lcv3.xcworkspace -scheme pa-proto archive -archivePath /Users/jtaylor/Desktop/lcv3.xcarchive)
    • xcodebuild -exportArchive -exportFormat ipa -archivePath /Users//Desktop/.xcarchive -exportPath -exportProvisioningProfile
    • (i.e. xcodebuild -exportArchive -exportFormat ipa -archivePath /Users/jtaylor/Desktop/lcv3.xcarchive -exportPath /Users/jtaylor/Desktop/lcv3 -exportProvisioningProfile LCV3\ HockeyApp\ Ad\ Hoc)
  6. Click Save
  7. Under your Project Settings (the level above your Build Configuration) click Create build Configuration.
  8. You should not have a need to add your code repository
  9. Under Dependencies select Add new artifact dependency
    • For Depend on, select the Build Configuration we created in the previous steps
    • For Get artifacts from, select Last successful build
    • For Artifact rules enter the Artifact Paths field of the previous Build Configuration (i.e. .ipa)
    • Make sure to check Clean destination paths before downloading artifacts
  10. Click Add build step and then select Command Line from the drop down menu.
  11. Name the step “Deploy to HockeyApp” and paste the code below into the Custom Script text box (Read more about the HockeyApp API method calls here.
  12. Click Save
  13. Select Administration > Projects and select edit to the right of the Android project
  14. Under Build Configurations select edit for the Build
  15. Select Build Steps from the side bar
  16. Make sure the starting step is a Gradle task, NOT the command line that it auto-populates with. If it states Command Line under the Parameters Description delete it and create the Gradle task (make sure Use gradle wrapper to build project is checked).
  17. Click Add build step and then select Command Line from the drop down menu.
  18. Name the step “Archive and Export” and paste the code below into the Custom Script text box
    • ./gradlew assemble
  19. Click Saveß
  20. Under your Project Settings (the level above your Build Configuration) click Create build Configuration.
  21. You should not have a need to add your code repository
  22. Under Dependencies select Add new artifact dependency
    • For Depend on, select the Build Configuration we created in the previous steps
    • For Get artifacts from, select Last successful build
    • For Artifact rules enter the Artifact Paths field of the previous Build Configurationß (i.e. .ipa)
    • Make sure to check Clean destination paths before downloading artifacts
  23. Click Add build step and then select Command Line from the drop down menu.
  24. Name the step “Deploy to HockeyApp” and paste the code below into the Custom Script text box (Read more about the HockeyApp API method calls here.
    • set -x curl -F “status=2” -F “notify=0” -F “notes=Build %build.counter%” -F “notes_type=0” -F “ipa=@.apk”-H “X-HockeyAppToken: <API_Token_From_HockeyApp>” https://rink.hockeyapp.net/api/2/apps/upload
    • (i.e. set -x curl -F “status=2” -F “notify=0” -F “notes=Build %build.counter%” -F “notes_type=0” -F “ipa=@/Users/jtaylor/Desktop/GitHub Clones/lcv3-aos/app/build/outputs/apk/app-release-unsigned.apk” -H “X-HockeyAppToken: b2f7b3b1158f4c3faf62ccff9a6a9cb0” https://rink.hockeyapp.net/api/2/apps/upload)

Production Configuration

Out-of-the-box TeamCity server installation is suitable for evaluation purposes. For production use you will need to perform additional configuration which typically includes:

  1. Configuring correct server port) (and access via https)
  2. Make sure server URL, email and (optionally) Jabber server settings are specified and are correct
  3. Configuring the server process for OS-dependent autostart on machine reboot
  4. Using reliable storage for TeamCity Data Directory
  5. Using external databases
  6. Configuring recommended memory settings, use “maximum settings” for active or growing servers
  7. Reviewing server security notes
  8. Planning for regular backups
  9. Planning for regular upgrades to the latest TeamCity releases (since TeamCity 10.0.3) Consider adding the “teamcity.installation.completed=true” line into the \conf\teamcity-startup.properties file - this will prevent the server from creating an administrator user if no such user is found

comments powered by Disqus