Skip to content

Instantly share code, notes, and snippets.

@rbsgn
Last active October 25, 2020 21:25
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rbsgn/0d7473a2692bdf6e0ef7 to your computer and use it in GitHub Desktop.
Save rbsgn/0d7473a2692bdf6e0ef7 to your computer and use it in GitHub Desktop.
TeamCity build agent as a launchd service done right
<?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>Debug</key>
<false/>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>jetbrains.teamcity.BuildAgent</string>
<key>OnDemand</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>launcher/bin/TeamCityAgentService-macosx-universal-32</string>
<string>-c</string>
<string>../conf/wrapper.conf</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StandardErrorPath</key>
<string>logs/launchd.err.log</string>
<key>StandardOutPath</key>
<string>logs/launchd.out.log</string>
<key>WorkingDirectory</key>
<string>/Users/teamcity/buildAgent</string>
<key>EnvironmentVariables</key>
<dict>
<key>LC_CTYPE</key>
<string>en_US.UTF-8</string>
</dict>
<key>LimitLoadToSessionType</key>
<array>
<string>Aqua</string>
</array>
</dict>
</plist>

There are several complaints regarding TeamCity build agent can't run tests in iOS Simulator all gathered in issue TW-38954 Agent started automatically on Yosemite could not launch iOS simulator.

Official workaround from JetBrains found on StackOverflow for this issue looks like this:

$ sh buildAgent/bin/agent.sh start

This means we should convert from automatic launch by launchd to manual via Terminal.app. Side effect of this is no relaunch on agent crash or system reboot.

Further investigation on that issue has led me to the Apple Developer Forums topic where Apple engineer claims following about xcodebuild:

  • There needs to be a user logged in with a window server / Aqua session, and
  • Commands should be invoked via launchd for that user, as LaunchAgents, or something more direct:

launchctl submit -l com.foo.test -- xcodebuild test -workspace ~/path/to/Foo.xcworkspace -scheme Foo -destination 'platform=iOS Simulator,name=iPhone 5s'

Which correlates with the excerpt from DTS incident cited on StackOverflow:

The context provided by LaunchDaemons is not supported for running GUI applications. The SSH service, and the default setup for Jenkins, are both implemented as LaunchDaemons. In earlier versions of Xcode 5 xcodebuild could run tests on the iOS simulator in this context, but that was never a supported configuration, and as you have noted that is no longer working as of Xcode 6.

Unlike LaunchDaemons, LaunchAgents provide a context where you can run GUI applications - if the user is logged in at the time, with a window server / Aqua session. Converting your Jenkins configuration from being a LaunchDaemon to being a LaunchAgent would avoid the reported issue. You can also use launchd for running tests on the iOS simulator from a SSH session, either by crafting a LaunchAgent and manually loading / starting that, or by using "launchctl submit”.

Summing up two facts one can make following conclusion: In order to be able to run tests in iOS Simulator while running automatically TeamCity build agent must be registered as launch agent limited to the UI session. You can achieve that by putting attached agent configuration file to ~/Library/LaunchAgents/ (create this directory unless it exists) and then loading it in a following way:

$ launchctl load ~/Library/LaunchAgents/jetbrains.teamcity.BuildAgent.plist

Having LimitLoadToSessionType defined ensures that this launch agent will not be started from SSH session by accident.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment