2015/10/15

Moving TeamCity Build to Remote Agent


As we added more build configuration to our TeamCity server, it was soon too much for the machine hosting it. Having a spare machine we decided to move some build to this new machine to lift the burden from our TeamCity's shoulders.

It was also opportunity to look at TeamCity plugins in general an specifically at so called agent tools.

Pre-requisities

  • fresh installation of the Linux distribution of your choice
  • JDK
  • OpenSSH daemon for remote access  

Agent Push

On the target machine create an account for teamcity, e.g. teamcity - to make the maintenance easier use the same user/group name and id as on the machine hosting TeamCity.

I wanted to use password-based authentication but avoid to disclose root password so I used the same  credentials "push agent" as used for  "run under". It worked up to the "su" point -- see below.

Problem: push fails with "Algorithm negotiation fail"

This is cause by the removal of unsafe algorithms from OpenSSH default configuration. Unfortunately the JSCH library used by TeamCity still tries to use them and is refused.

To make JSCH happy, you can enable weak key-exchage algorithms by adding following line to the /etc/ssh/sshd_config file (diffie-hellman-group1-sha1 stands for 1024 bit DH with SHA1, diffie-hellman-group-exchange-sha1 for custom DH with SHA1):

KexAlgorithms diffie-hellman-group1-sha1, diffie-hellman-group-exchange-sha1

Please enable this line only for the agent push and make sure it is removed after that. It is broken in current TeamCity 9.1.3.

Problem: "su: must be run from a terminal"

The whole error message looks similar to this:

Remote agent installation failed: Command '[./bootstrapper.sh "http://myteamcity:8111" "/home/teamcity/BuildAgent" "some_security_token" "user" "password"]' was executed with error message(s): su: must be run from a terminal.

There are several issues associated with this error and I am not sure what is the proper solution at the time being - addding user teamcity to group sudo did not work.  As I installed only one agent, I "solved" it by logging to the agent machine as the teamcity user, editing name in buildAgent.properties  and executing "agent.sh start".

The last thing to do its to go to the Agents tab in TeamCity, check the agent's status, authorize it if it is not authorized and set compatible configuration so no build is run on the agent until it is really ready.

Agent Tools

TeamCity plugins can have both server and agent side. The agent-side plugins that do not load any classes into the runtime are called agent tools - it is TeamCity way for distribution of binary files to agents.

In your .BuildServer/plugins directory (default value) create directory .tools, if it is not there yet. Each agent plugin then can put either zip file or directory with the tools to distribute to all agents. The distribution starts in about 2 minutes. It is possible that a build configuration asociated with the agent is required to trigger the process.

Create directory .BuildServer/plugins/.tools/my_plugin and put your scripts inside. The files  should be accompanied with plugin descriptor teamcity-plugin.xml . If you do not create it,  an empty one is created on the agent side. The distribution process removes executable bit from all files put into the directory -- to prevent it you have to list your executable in the descriptor under "executable-files":

<?xml version="1.0" encoding="UTF-8"?>
 <teamcity-agent-plugin xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        xsi:noNamespaceSchemaLocation="urn:schemas-jetbrains-com:teamcity-agent-plugin-v1-xml">
   <tool-deployment>
      <layout>
         <executable-files>
           <include name='path_to_executable'/>
         </executable-files>
      </layout>
   </tool-deployment>
 </teamcity-agent-plugin>

The path is relative to the plugin directorty and you do not have to start it with "./".

Calling Your Agent Tools Script


Create a build step of runner type "Command line" and set working directory of the step to %teamcity.tool.my_plugin% . Then you can execute scripts relative to the plugin directory, .e.g. with "Command executable" set to "./helloWorld.py" .