Teamcity est un serveur de build très puissant et assez flexible. Avec Jenkins et Travis, il fait partie des outils les plus utilisés pour faciliter la mise en place de pratiques d’intégration continue. Teamcity est implémenté en Java toutefois il s’adapte et peut facilement être utilisé pour de très nombreuses technologies comme, par exemple, .NET.
Contrairement à Travis et à Jenkins, Teamcity n’est pas entièrement gratuit, toutefois la licence permet de configurer gratuitement 20 configurations de builds (i.e. build configuration) et 3 agents, ce qui est suffisant pour la plupart des cas d’utilisation. Teamcity peut être installé sur Windows, Linux ou MacOS. Même si le serveur Teamcity est installé sur une machine avec un OS spécifique, il peut s’interfacer avec d’autres machines qui peuvent être dans des OS différents de façon à piloter des builds avec des technologies différentes. Un même serveur Teamcity peut donc effectuer des builds dans des technologies différentes.
Dans cet article, on se propose d’expliquer l’installation d’un serveur Teamcity. Dans un article futur, je présenterai les fonctionnalités principales de Teamcity de façon à être capable de configurer une chaine de build complète.
La documentation de Teamcity est bien faite et très complète. Le but de cet article n’est pas de paraphraser la documentation de l’éditeur mais de permettre de monter rapidement un serveur Teamcity, de comprendre rapidement les fonctionnalités les plus importantes et de se familiariser avec l’interface de Teamcity pour être capable de l’utiliser efficacement. Cet outil est facile à utiliser toutefois il possède énormément de fonctionnalités qui ne sont pas faciles à appréhender aux premiers abords.
Dans un premier temps, on indiquera une méthode pour installer un serveur Teamcity sur une machine Linux avec Docker, ensuite on configurera un build agent et enfin on indiquera quelques éléments de configuration intéressants sur le serveur de build.
L’intérêt d’installer Teamcity en utilisant l’image Docker, est d’avoir une procédure d’installation rapide qui permet une grande flexibilité puisqu’on peut facilement supprimer l’image et reprendre l’installation.
On peut aussi installer directement Teamcity sur d’autres OS comme Linux, Windows ou macOS. Dans le cas où on ne souhaite pas polluer son système d’exploitation avec une installation qui ne sert que pour effectuer un test, on peut aussi installer Debian sur une machine virtuelle VirtualBox et installer Teamcity sur la Debian.
Installation préalable de Docker
Executer l’image Teamcity
Relancer l’exécution du container
Stopper l’exécution du container
Configuration du serveur Teamcity
Versionner la configuration de Teamcity
Installation d’un agent Teamcity
Installation de JAVA
Configuration de l’agent
Démarrage de l’agent
Ajout de l’agent à la configuration Teamcity
Installation préalable de Docker
Avant d’installer Teamcity, il faut installer Docker pour pouvoir exécuter l’image.
Dans notre cas, on souhaite installer Docker Community Edition (i.e. Docker CE) sur un système Debian 9 (Stretch). On peut toutefois installer facilement Docker CE sur d’autres systèmes d’exploitation.
Sur Debian 9, il faut suivre les instructions suivantes: Get Docker CE for Debian.
Dans notre cas, Debian 9 (Stretch) concerne la partie “Jessie or newer” (Jessie correspond à Debian 8) dans la documentation de Teamcity.
Après l’installation, pour éviter d’exécuter l’image Docker avec l’utilisateur root, on peut créer un utilisateur simple qui aura l’autorisation d’exécuter une image Docker. Cette configuration est facultative mais permet de séparer les responsabilités.
On peut créer un utilisateur et l’ajouter au groupe docker
en exécutant en tant qu’utilisateur root la comande:
root@debian:~% adduser --ingroup docker dockeruser
On peut voir que l’utilisateur dockeruser
appartient au groupe docker en exécutant:
root@debian:~% groups dockeruser
L’utilisateur dockeruser
peut maintenant exécuter une commande docker
.
Si on tente d’exécuter une image Docker avec un utilisateur qui n’appartient pas au groupe docker
, on aura une erreur du type:
Got permission denied while trying to connect to the Docker daemon socket
at unix:///var/run/docker.sock
Ceci s’explique par le fait que la lecture ou l’écriture de /var/run/docker.sock
nécessite d’appartenir au groupe docker
. On peut s’en rendre en compte en exécutant:
root@debian:~% ls -al /var/run/docker.sock
On obtient:
srw-rw---- 1 root docker 0 Sep 12 00:04 /var/run/docker.sock
Pour résoudre ce problème, il suffit d’ajouter l’utilisateur au groupe docker
en exécutant:
root@debian:~% usermod -aG docker <alias de l'utilisateur>
Il faut ensuite redémarrer pour que l’ajout de l’utilisateur au groupe soit pris en compte:
root@debian:~% reboot
Executer l’image Teamcity
D’abord, on crée des répertoires pour partager avec le container des données relatives au serveur Teamcity:
dockeruser@debian:~% mkdir /home/dockeruser/teamcity
dockeruser@debian:~% mkdir /home/dockeruser/teamcity/data
dockeruser@debian:~% mkdir /home/dockeruser/teamcity/logs
Pour créer un container à partir de l’image Docker de Teamcity (sur docker hub) il faut exécuter la commande:
dockeruser@debian:~% docker run -it --name teamcity-server-instance \
-v /home/dockeruser/data:/data/teamcity_server/datadir \
-v /home/dockeruser/logs:/opt/teamcity/logs \
-p 8111:8111 \
jetbrains/teamcity-server
Le détail des options est:
-it
: permet de démarrer le processus dans le container en attachant la console de l’hôte de façon à ce que les entrées standard, les sorties standard et les erreurs de la console du container soient visibles dans la console de l’hôte.--name <nom du container>
: permet d’indiquer le nom du container dans lequel sera exécuté l’image Docker.-v /home/dockeruser/data:/data/teamcity_server/datadir
: permet de partager le contenu du répertoire/home/dockeruser/data
de l’hôte avec le répertoire/data/teamcity_server/datadir
du container. Le répertoire de données du container sera ainsi plus facilement accessible sur l’hôte.-v logs:/opt/teamcity/logs
: permet de partager le contenu du répertoire /home/dockeruser/logs de l’hôte avec le répertoire/opt/teamcity/logs
du container. Cette option permet d’accéder facilement au répertoire de logs du container à partir de l’hôte.-p 8111:8111
: indique que le port 8111 de l’hôte sera redirigé vers le port 8111 du container Docker.
On peut ouvrir un bash dans le container Docker en exécutant:
dockeruser@debian:~% docker exec –it teamcity-server-instance /bin/bash
Relancer l’exécution du container
Si l’image a déjà été exécutée dans un container avec le nom “teamcity-server-instance” et si on relance la commande précédente:
dockeruser@debian:~% docker run -it --name teamcity-server-instance ...
On peut obtenir une erreur du type:
docker: Error response from daemon: Conflict. The container name
"/teamcity-server-instance" is already in use by container
"ab19821b4d64fb0e221b0a2c898db1745703acb45b96d602caddc3f6b25bfa5c". You have to remove
(or rename) that container to be able to reuse that name.
See 'docker run --help'.
Cette erreur signifie que le container se nommant “teamcity-server-instance” existe déjà. Pour relancer l’exécution de ce container, il suffit d’exécuter la commande:
dockeruser@debian:~% docker start teamcity-server-instance
Si le serveur Teamcity est correctement démarré, on peut se connecter avec un browser à l’adresse suivante:
http://localhost:8111
Stopper l’exécution du container
De même pour stopper l’exécution du container et par suite du serveur Teamcity, il faut taper:
dockeruser@debian:~% docker stop teamcity-server-instance
Configuration du serveur Teamcity
On peut accéder à l’interface en se connectant avec un browser à l’adresse:
http://localhost:8111
On doit obtenir un écran du type:

En cliquant sur “Proceed”, on peut choisir un type de base de données, dans notre cas, on choisit “Internal (HSQLDB)”:

Il faut ensuite répondre à quelques questions avant d’arriver à la création d’un utilisateur avec des droits d’administrateur:

On arrive ensuite sur l’interface principale de Teamcity:

Versionner la configuration de Teamcity
Teamcity a une fonctionnalité particulièrement intéressante qui permet de versionner la configuration des projets dans un gestionnaire de version (comme SVN ou Git). Cette étape est facultative. Avec cette fonctionnalité, la synchronisation se fait dans les 2 sens:
- Teamcity commit lui-même les changements dans le gestionnaire de versions à chaque changement de la configuration.
- Si on modifie la configuration dans le gestionnaire de versions en éditant les fichiers, Teamcity rechargera automatiquement sa configuration après le commit des modifications.
L’intérêt de cette fonctionnalité est de:
- Pouvoir revenir en arrière facilement dans la configuration si on a fait une erreur,
- Importer facilement une configuration sur on installe un nouveau serveur,
- Voir la configuration avec des outils comme Github.
- Editer directement la configuration dans les fichiers versionnés
Pour effectuer cette configuration à partir de l’interface de Teamcity, il faut cliquer sur “Administration”:

Puis sur “<Root project>”:

Dans le menu de gauche, il faut cliquer sur “VCS Roots” pour ajouter une configuration pour un gestionnaire de version (VCS signifie “Version Control System”):

On clique ensuite sur “Create VCS root” et on indique les paramètres d’accès au VCS:

Dans notre cas, on utilise GitHub. On a donc créé un compte sur GitHub puis un repository de façon à indiquer ces paramètres dans Teamcity.
Si à ce moment, on essaie d’effectuer un test de connexion en cliquant sur “Test connection”, on aura un message d’erreur:
Cannot find revision of the default branch 'refs/heads/master' of vcs root
"jetbrains.git" {instance id=10, parent internal id=-1, parent id=dummy_jetbrains.git,
description: "https://github.com/teamcitytest/teamcityconfig.git#refs/heads/master"}
Cette erreur est due au fait qu’il n’existe pas de branche “master” sur le repository. Pour créer une branche vide, il suffit de créer un fichier README.md
sur GitHub et la branche “master” sera créée.
Dans le cas présent, on a configuré un repository pour permettre de versionner la configuration de Teamcity. Le repository de la configuration est différent du repository d’un projet pour lequel on souhaiterait effectuer une build.
Le repository contenant la configuration de Teamcity est mis à jour directement par Teamcity. On peut le voir si on regarde dans GitHub dans le répertoire .teamcity
.
Dans notre cas, le repository est teamcityconfig.
Enfin dans Teamcity, il faut indiquer à Teamcity quel est le paramétrage de gestionnaire de version qui permet de stocker la configuration. On clique donc sur “Versioned Settings” dans le menu à gauche:

Puis:
- On sélectionne “Synchronization enabled”
- On sélectionne le paramétrage de VCS Root qui correspond à la configuration,
- On sélectionne “use settings from VCS”.
- On valide en cliquant sur “Apply”.
Ecran “Versioned Settings”
A la fin de cette étape, Teamcity effectue directement des modifications dans le repository GitHub et les commit.
Installation d’un agent Teamcity
Un agent Teamcity est une machine sur laquelle sera exécutée les différentes builds. Cette machine peut être différente de celle qui héberge le serveur Teamcity. Teamcity permet d’utiliser plusieurs agents avec des architectures différentes. L’intérêt d’avoir plusieurs agents est de:
- Pouvoir effectuer des builds dans des architectures et des technologies différentes,
- Paralléliser les builds sur plusieurs agents.
- Avoir un seul serveur Teamcity qui s’interface avec plusieurs agents, la configuration reste ainsi centralisée.
Comme indiqué plus haut, l’agent peut se trouver sur une autre machine que celle du serveur Teamcity. Dans notre cas, pour simplifier, l’agent se trouvera sur la même machine.
Pour installer l’agent Teamcity, il faut cliquer en haut de l’interface d’administration de Teamcity sur “Agents” puis à droite sur “Install Build Agents”:

On télécharge le fichier correspondant à l’architecture sur laquelle on veut installer l’agent. Dans notre cas, on cliquer sur “Zip file distribution” puisqu’on souhaite installer l’agent sur une machine Linux.
On décompresse le fichier en exécutant les commandes suivantes:
dockeruser@debian:~% mkdir /home/dockeruser/teamcity_agent
dockeruser@debian:~% unzip /home/dockeruser/buildAgent.zip -d /home/dockeruser/teamcity_agent
Ensuite, on copie le répertoire dans le répertoire /usr
en tant qu’utilisateur root:
root@debian:~% cp –r /home/dockeruser/teamcity_agent /usr
On change les autorisations du répertoire pour que l’utilisateur dockeruser
puisse exécuter l’agent:
root@debian:~% chown -r dockeruser:docker /usr/teamcity_agent
Pour plus d’informations sur l’installation d’un agent Teamcity, on peut se reporter à la documentation de JetBrains.
Installation de JAVA
Avant de lancer l’agent Teamcity, il faut installer une JRE sur la machine si ce n’est pas déjà fait.
On peut télécharger la JRE sur le site d’Oracle: http://www.oracle.com/technetwork/java/javase/downloads/index.html.
Dans notre cas, la version utilisée était la jdk1.8.0_151 pour linux en 64 bits.
On peut installer la JRE sur le disque en exécutant:
root@debian:~% tar zxvf jdk-8u151-linux-x64.tar.gz
Cette commande permet d’extraire les fichiers contenus dans l’archive en listant tous les fichiers extraits.
En tant qu’utilisateur root, il faut placer le répertoire résultant dans /usr/java
root@debian:~% mkdir /usr/java
root@debian:~% mv <nom du répertoire> /usr/java
Ensuite, il faut ajouter la variable d’environnement JRE_HOME
dans le PATH
en éditant le fichier /etc/profile
en tant qu’utilisateur root:
root@debian:~% vi /etc/profile
On ajoute ensuite les lignes suivantes à la fin du fichier (pour passer en mode édition dans vi, il faut appuyer sur la touche [i]):
export JRE_HOME="/usr/java/jdk1.8.0_151/jre"
export PATH=$JRE_HOME/bin:$PATH
On enregistre en tapant [Echap] puis :wq.
Configuration de l’agent
On configure l’agent Teamcity en tapant les commandes suivantes:
- On renomme le fichier
buildAgent.dist.properties
enbuildAgent.properties
:dockeruser@debian:~% mv /usr/teamcity_agent/conf/buildAgent.dist.properties /usr/teamcity_agent/conf/buildAgent.properties
- On édite, ensuite ce fichier en tapant:
dockeruser@debian:~% vi /usr/teamcity_agent/conf/buildAgent.properties
(Pour passer en mode édition dans vi, il faut appuyer sur la touche [i])
- Si on installe l’agent sur une machine différente de celle sur laquelle se trouve le serveur Teamcity, il faut modifier le paramètre
serverUrl
pour qu’il pointe vers le serveur Teamcity:serverUrl=http://<adresse IP du serveur Teamcity>:8111/
Dans le cas contraire, on peut laisser la valeur:
serverUrl=http://localhost:8111/
- Il faut ensuite indiquer le nom de l’agent avec le paramètre
name
:name=BuildAgent1
On enregistre en tapant [Echap] puis :wq.
Démarrage de l’agent
Une fois que la configuration est effectuée, on peut démarrer l’agent en exécutant:
dockeruser@debian:~% ./usr/teamcity_agent/bin/agent.sh start
Les logs sont consultables dans le répertoire:
/usr/teamcity_agent/logs
Si le démarrage s’est effectué correctement, on devrait voir dans le fichier /usr/teamcity_agent/logs/teamcity-agent.log
une phrase du type:
Updating agent parameters on the server
Ajout de l’agent à la configuration Teamcity
A la fin de l’étape précédente, après quelques secondes, l’agent doit apparaître dans l’interface de Teamcity en cliquant sur “Agents” en haut à gauche puis sur l’onglet “Unauthorized”:

Il faut cliquer sur le nom de l’agent puis sur “Authorize agent”:

Après cette étape, l’agent est connecté avec le serveur Teamcity.
Configurer les “clean-up rules”
Ce paramétrage est particulièrement traitre dans Teamcity car, par défaut, Teamcity conserve tous les fichiers résultats des builds sur le serveur. La conservation de ces fichiers saturent rapidement la mémoire du serveur en particulier si on effectue souvent des builds et si on possède beaucoup de configurations de build.
Les “clean-up rules” sont des règles permettant d’indiquer quand supprimer ces fichiers.
Pour accéder au paramétrage des “clean-up rules”, il faut:
- Cliquer sur “Administration”
- Puis cliquer sur <Root project>
- Cliquer dans le menu de gauche sur “Clean-up rules”
Cliquez sur “Clean-up rules” - Cliquer sur “Edit” pour affecter des règles valables pour tous les projets,
- Affecter des valeurs qui permettront de supprimer périodiquement les fichiers de builds, par exemple:
Exemple de paramètres “Clean-Up Rules”
En conclusion
Toutes ces étapes ont permis de paramétrer un serveur Teamcity de façon à ce qu’il soit opérationnel pour exécuter des builds. Dans un prochain article, on indiquera quelles sont les fonctionnalités principales de Teamcity pour paramétrer rapidement une configuration de build dans le cadre de .NET.
- Top 8 Continuous Integration Tools (2017 edition): https://www.codeproject.com/Articles/1080526/Top-Continuous-Integration-Tools
- Get Docker CE for Debian: https://docs.docker.com/engine/installation/linux/docker-ce/debian/
- TeamCity on Docker Hub – it’s official now!: https://blog.jetbrains.com/teamcity/2016/06/teamcity-on-docker-hub-its-official-now/
- How To Work with Docker Data Volumes on Ubuntu 14.04: https://www.digitalocean.com/community/tutorials/how-to-work-with-docker-data-volumes-on-ubuntu-14-04
- Docker run reference: https://docs.docker.com/engine/reference/run/
- Use volumes in Docker: https://docs.docker.com/engine/admin/volumes/volumes/
- Installing build agent via ZIP File: https://confluence.jetbrains.com/display/TCD10//Setting+up+and+Running+Additional+Build+Agents#SettingupandRunningAdditionalBuildAgents-InstallingviaZIPFile
- Teamcity server on Docker Hub: https://hub.docker.com/r/jetbrains/teamcity-server/