Paramétrer la “build configuration” d’une application .NET Core avec Teamcity

Dans un article précédent, on avait indiqué une méthode pour installer Teamcity en utilisant Docker. Dans ce même article, on avait aussi installé et configuré un agent de build (i.e. build agent) de façon à mettre en place une configuration de build.

Pour faire suite à l’installation, le présent article a pour but de présenter les fonctionnalités principales de Teamcity pour être capable de configurer une chaine de build. La documentation de Teamcity est bien faite et est très complète. Comme pour l’article précédent, le but n’est pas de paraphraser la documentation de Jetbrains mais de comprendre rapidement les fonctionnalités pour les utiliser efficacement. Cet outil est ergonomique toutefois il possède énormément de fonctionnalités qui ne sont pas faciles à appréhender aux premiers abords.

On va donc expliquer quelques fonctionnalités en illustrant en configurant une build d’une application .NET Core.

Installation de .NET Core

Avant de rentrer dans les détails de Teamcity, il reste quelques installations à effectuer pour être capable de builder une application .NET Core:

  • Installer le SDK .NET Core
  • Installer le plugin Teamcity pour .NET Core

Installer le SDK .NET Core sur l’agent

Il faut, dans un premier temps, installer le SDK .NET Core sur l’agent qui exécutera la build. Il n’est pas nécessaire d’installer .NET Core sur la machine qui héberge le serveur Teamcity (dans notre cas, il s’agit d’un container Docker).

L’installation de .NET Core ne présente pas de difficulté particulière, il suffit de suivre les étapes présentes sur cette page: https://www.microsoft.com/net/core#linuxdebian.

En résumé, il faut réaliser les étapes suivantes:

  1. Ouvrir un terminal et se connecter en tant qu’utilisateur root en tapant:
    root@debianvm:~% su 
    
  2. Installer quelques outils comme curl en exécutant:
    root@debianvm:~% apt-get install curl libunwind8 gettext apt-transport-https 
    

    curl permettra le téléchargement de la clé publique des produits Microsoft.

  3. Télécharger la clé publique des produits Microsoft en faisant:
    root@debianvm:~% curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg 
    
  4. Déplacer la clé pour qu’elle soit considérée comme une clé de confiance par le système de packages APT:
    root@debianvm:~% mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg 
    
  5. On édite le fichier /etc/apt/sources.list.d/dotnetdev.list, par exemple avec vi en exécutant:
    root@debianvm:~% vi /etc/apt/sources.list.d/dotnetdev.list 
    

    Il faut ensuite aller à la dernière ligne du fichier, de passer en mode insertion en tapant [i] et ajouter la ligne suivante:

    deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-stretch-prod stretch main 
    

    On peut enregistrer le fichier en faisant [echap] et en tapant la commande suivante:
    :wq puis [entrée]

  6. On met à jour la liste des packages présents dans les différentes sources de APT en tapant:
    root@debianvm:~% apt-get update 
    
  7. Enfin, on installe le package correspondant au SDK .NET Core en tapant:
    root@debianvm:~% apt-get install dotnet-sdk-2.0.0 
    

A la fin de cette étape, on doit être capable d’exécuter la commande dotnet en tant qu’utilisateur normal:

dockeruser@debianvm:~% dotnet --version 

Installer le plugin Teamcity pour .NET Core

Le plugin permet au build agent de communiquer avec le serveur Teamcity. Pour l’installer, il faut effectuer les étapes suivantes:

  1. Cliquer sur “Administration” en haut à droite
  2. Cliquer sur “Plugins List”
  3. Cette liste contient la liste des plugins mais ne contient pas le plugin .NET Core.

  4. Cliquer sur “Available plugins” qui va rediriger sur la page suivante: https://plugins.jetbrains.com/teamcity
  5. Chercher et télécharger le plugin “.NET CLI Support”. Le plugin est sous la forme d’un fichier .ZIP.
  6. Il faut retourner sur la page des plugins de Teamcity et cliquer sur “Upload plugin zip”
  7. Indiquer le fichier .ZIP du plugin et cliquer sur “Save”.
    Le plugin doit apparaître dans la liste des fichiers:

    Plugin “.NET CLI Support”

    A ce moment, le plugin n’est pas exécuté. On peut s’en rendre compte en allant dans les paramètres de l’agent:

    • Cliquer sur “Agents” en haut de l’interface
    • Cliquer sur l’agent
    • Cliquer sur l’onglet “Agent Parameters”
    • Cliquer sur “Configuration Parameters”
      On peut voir que la liste de paramètres ne contient pas de paramètres liés à .NET Core:

      Paramètres liés à .NET Core sont absents
  8. Pour que le plugin soit exécuté, il faut redémarrer le serveur Teamcity en exécutant les commandes suivantes:
    dockeruser@debianvm:~% docker stop teamcity-server-instance 
    dockeruser@debianvm:~% docker start teamcity-server-instance 
    

A la fin du redémarrage du serveur, si on clique sur “Administration” ⇒ “Diagnostics” ⇒ Onglet “Browse Data Directory” et si on déplie le contenu du répertoire plugins, on s’aperçoit qu’il contient un répertoire .unpacked contenant le plugin .NET Core dézippé:

Plugin dézippé

Enfin si on consulte de nouveau les paramètres de l’agent dans “Agents” ⇒ <nom de l’agent> ⇒ Onglet “Agent parameters” ⇒ Onglet “Configuration Parameters”, on doit voir des paramètres relatifs à .NET Core:

Les paramètres liés à .NET Core sont présents

Familles d’interfaces

Dans Teamcity, il existe 3 familles d’interfaces qui sont accéssibles suivant les autorisations des utilisateurs:

  • La partie Administration accessible quand on clique en haut à droite sur “Administration”
  • La partie affichant les builds des projets configurés accessible en cliquant sur “Projects” en haut à gauche:
    Cliquer sur “Projects”
  • La partie permettant de configurer un projet. Cette partie est accessible en cliquant sur “Projects” puis en cliquant sur le nom du projet lui-même et enfin en cliquant sur “Edit Project Settings”:
    Cliquer sur “Edit Project Settings”

On entrera, par la suite, plus en détail pour expliquer toutes ces parties.

Configuration des utilisateurs

La configuration des utilisateurs est accessibles en cliquant sur “Administration” dans la partie “User Management”.

La configuration des utilisateurs est classique et s’articule autour de 3 notions:

  • Les rôles qui indiquent les droits dont un utilisateur dispose pour effectuer une action
  • Des groupes d’utilisateurs: on peut affecter des rôles à un groupe de façon à ce que tous les utilisateurs de ce groupe disposent des mêmes droits.
  • Les utilisateurs ont des rôles et peuvent appartenir à groupe. Si un utilisateur appartient à une groupe, il hérite des rôles de ce groupe.

Il existe 2 modes pour paramétrer les utilisateurs: un mode simple et un mode par projet.

Mode simple

Quand ce mode est actif, la partie “User Management” ne comporte que 2 parties “Users” et “Groups”.

Ce mode ne comprends que quelques rôles:

  • Administrateur qui accède à tous les écrans sans restrictions. Pour créer ce type d’utilisateur, il faut cocher “Give the user administrative privileges” sur l’écran de création d’un utilisateur.
  • Utilisateur authentifié (i.e. logged-in user) qui accède à la configuration de tous les projets mais pas à la partie Administration. Pour pouvoir créer ce type d’utilisateurs, il faut que les utilisateurs du groupe “All Users” ne soient pas des administrateurs. On peut le vérifier en cliquant sur “Groups” ⇒ “All Users” ⇒ Décocher “Group with administrative privileges…”.

    Enfin, au moment de créer un utilisateur, il faut que “Give the user administrative privileges” soit décoché.

  • Utilisateur invité (i.e. guest user) qui accède seulement à la partie affichant les builds des projets. Pour que les utilisateurs invités puissent se connecter, il faut l’autoriser en cliquant sur “Administration” ⇒ “Authentication” ⇒ Cocher “Allow login as guest user”.

Mode par projet

Pour activer ce mode, il faut aller dans “Administration” ⇒ “Authentication” ⇒ Cocher “Enable per-project permissions”.

Quand ce mode est actif, la partie “User Management” comporte 3 parties: “Users”, “Groups” et “Roles”. Il permet une gestion plus fine des rôles en permettant de configurer des accès pour chaque rôle. Par défaut, les rôles sont (visibles dans la partie “Roles” de “User management”):

  • “System administrator” qui accède à tous les écrans sans restriction.
  • “Project administrator” qui permet à un utilisateur de configurer tout ce qui est lié à un projet et aux projets enfant (gérer les utilisateurs du projet, paramétrer des configurations de build et configurer des agents).
  • “Project developer” qui permet à un utilisateur de voir des configurations de build et de lancer des builds.
  • “Project viewer” qui ne peut que voir les projets et les builds correspondantes.
  • “Agent manager” qui permet de gérer les paramètres liés à un agent.

Ces rôles peuvent être affectés à un groupe ou à un utilisateur par projet. D’autres parts, ils sont entièrement paramétrables dans l’écran “Roles” de la partie “User management”.

Pour plus de détails sur la gestion des utilisateurs: Role and Permission.

Configurer une “build”

Par la suite, lorsqu’on parlera de la configuration d’une build, on utilisera le terme “build configuration” qui correspondant davantage au terme utilisé dans la documentation de Teamcity.

Avant de rentrer dans les détails de la configuration d’une build, il convient d’avoir quelques éléments en tête:

  • Héritage des paramètres: Teamcity possède un système d’héritage des paramètres d’un projet à ses enfants. De ce fait, si des éléments de configuration sont définis pour un projet parent, les projets enfant hériteront de ces éléments. Les projets peuvent, toutefois, surcharger les valeurs de ces éléments. Ce principe est valable pour une grande partie des paramètres.
  • Le projet racine <Root project>: on peut avoir du mal à atteindre la configuration de ce projet car il n’est pas toujours affiché sur l’interface. Il faut évidemment que l’utilisateur ait le droit d’y accéder (en fonction des droits dont il dispose), ensuite pour y accéder il faut:
    1. Cliquer sur “Projects” en haut à gauche
    2. Cliquer sur un projet (peu importe le projet)
    3. Cliquer sur “Edit Project Settings”
    4. Cliquer sur “<Root project>”:
      Cliquer sur “<Root project>”

    A ce moment, on accède aux paramétrages du projet racine. Le fait de ne pas voir apparaître ce niveau de la hiérarchie sur tous les écrans peut prêter à confusion car on peut hériter de paramètres sans comprendre d’où ils proviennent.

  • Le seul endroit où on peut voir clairement l’héritage des projets est dans la partie “General Settings” d’un projet:
    Cliquer sur “General Settings” pour voir la hiérarchie des projets

    Si on clique sur “VCS Roots”, par exemple, on ne voit plus cet héritage, ce qui peut prêter à confusion.

On se propose, dans la suite, de configurer entièrement la build d’un projet de façon à voir toutes les étapes de la configuration.

Configurer un projet

Pour créer un projet il suffit d’aller dans le projet racine <Root project> puis dans la partie “General Settings” (comme explicité plus haut). On clique ensuite sur “Create subproject”:

Cliquer sur “Create subproject”

Dans notre exemple, on crée un projet s’appelant “Pizza Calculator”. Ce projet est disponible sur GitHub.

On clique ensuite sur le projet pour accéder à la configuration du projet.

VCS Root

Pour importer le projet à partir de GitHub, il faut configurer un VCS Root (VCS pour Version Control System). Pour ce faire, on clique sur “VCS Roots” dans les paramètres du projet:

Cliquer sur “Create VCS root”

On clique ensuite sur “Create VCS root” pour créer un VCS Root. On renseigne les paramètres liés au projet:

  • Type of VCS: Git
  • VCS root name: Pizza-calculator
  • VCS root ID: peu importe, il faut que l’ID soit unique
  • Fetch URL: https://github.com/teamcitytest/pizza-calculator.git
  • Push URL: <vide>
  • Default branch: refs/heads/master
  • Authentication method: Password
  • On indique ensuite le username et le mot de passe.

On peut tester en cliquant sur “Test connection”.

Configurer une “build configuration”

Cette partie permettra de configurer une build pour qu’elle apparaisse dans la partie affichant toutes les builds par projet (en cliquant sur “Projects” en haut à gauche).

On peut définir plusieurs build configurations par projet si on souhaite, par exemple, effectuer des builds pour des architectures différentes.

Pour créer une build configuration:

  1. On clique sur “Create build configuration”:
    Cliquer sur “Create build configuration”
  2. Cliquer sur “Manually” et indiquer les paramètres suivants:
    • Parent project: sélectionner Pizza Calculator
    • Name: Build AnyCpu
    • Build configuration ID: PizzaCalculator_BuildAnyCpu
    • Cliquer sur “Proceed”
  3. Dans l’écran suivant, pour le paramètre “Attach existing VCS root”, il faut sélectionner Pizza-calculator et cliquer sur “Attach”.

A ce moment Teamcity va détecter 4 étapes pour builder. Le terme utilisé pour désigner ces étapes est build step. Ces étapes sont exécutées successivement lors de l’exécution de la build:

  • Restore: permet de restaurer les packages NuGet dans le projet src/pizza-calculator.csproj
  • Build: permet de construire les assemblies dans le projet src/pizza-calculator.csproj
  • Restore Test: permet de restaurer les packages NuGet dans le projet de test tests/pizza-calculator.csproj
  • Test: exécute les tests dans le projet tests/pizza-calculator.csproj

Il faut sélectionner toutes les build steps puis cliquer sur “Use selected” pour qu’elles soient créées. On obtient alors une liste des build steps ordonnées.

On peut voir le paramétrage de chaque build step en cliquant sur “Edit”. On en profite pour renseigner un nom pour chaque build step en précisant le paramètre “Step name” de façon à avoir la configuration suivante:

Liste des build steps ordonnées

On peut compléter la configuration de la build step “Build” en ajoutant un paramètre après avoir cliqué sur “Show advanced options”:

Cliquer sur “Show advanced options”

Il faut compléter le paramètre “Configuration” avec la valeur “Release”.

Exécuter la “build configuration”

On peut à ce moment, exécuter la build en cliquant sur “Projects” en haut à gauche et en dépliant la nœud du projet “Pizza Calculator”. On clique ensuite sur le bouton “Run” correspondant à la build configuration “Build AnyCpu”:

Cliquer sur “Run”

Pour accéder aux détails de l’exécution de la build, il faut cliquer sur la build configuration “Build AnyCpu”, ensuite sur l’onglet “History” et enfin sur la build qui a été exécutée. On obtient un écran contenant tous les détails de l’exécution. Les onglets les plus intéressants sont:

  • Tests: qui permet d’indiquer les tests qui ont été exécutés. On peut voir notamment les tests qui ont éventuellement échoué.
  • Build log: cet écran est le plus intéressant car il permet de voir tous les détails de la build. Il est particulièrement utile quand on souhaite savoir pourquoi une build a échoué. Il faut cliquer sur la fléche du bas pour déplier tous les nœuds:
    Déplier tous les nœuds pour voir les détails d’une build
  • Parameters: cet écran présente tous les paramètres utilisés pendant la build. Ces données peuvent aussi être utiles en cas d’erreurs de façon à trouver le problème.
Répertoire où est effectué la build

Quand une build configuration est exécutée, le répertoire sur l’agent où le traitement est effectué se trouve dans le répertoire indiqué dans le fichier de configuration <répertoire d'installation de l'agent>/conf/buildAgent.properties avec le paramètre workDir.

Dans notre cas, le répertoire d’installation de l’agent est /usr/Teamcity et le répertoire de travail est /usr/Teamcity/work.

Pour une build configuration, le chemin du répertoire de travail sera complété par un nom aléatoire et différent pour chaque build configuration. Toutefois, il faut avoir en tête que le répertoire sera le même entre 2 exécutions de la même build configuration. Utilisé le même répertoire sans en vider le contenu peut parfois mener à des comportements étranges.

Détails de configuration d’une “build configuration”

Ils existent de nombreux autres paramètres dans une build configuration qui sont utiles pour des configurations plus complexes.

Artifacts

Ces éléments ne sont pas, à proprement parlé, des éléments de configuration. Ce sont des éléments qui sont générés par la build configuration. Ils se renseignent dans la partie “General Settings” d’une build configuration, et avec le paramètre “Artifact paths”:

Renseigner le paramètre “Artifact paths” d’une build configuration

Les artifacts sont importants quand on souhaite chainer plusieurs build configurations. Il faut avoir en tête un certain nombre de choses pour ne pas être surpris par certains comportements de Teamcity:

  • Quand une build configuration est exécutée, un certain nombre de traitements sont effectués. Par exemple, des assemblies sont buildées. Ces assemblies correspondent à des fichiers générés qui n’étaient pas présents au début de l’exécution de la build configuration.
  • Si une 2e build configuration dépend d’éléments générés par une autre build configuration, pour que ces éléments soient réellement accessibles par la 2e build configuration, il faut les indiquer dans les artifacts.
  • On indiquera dans la 1ère build configuration avec le paramètre “Artifact Paths” quelles sont les éléments qui ont été générés et qui doivent être transmis à la build configuration suivante.
  • On indiquera, ensuite, dans la 2e build configuration quelles sont les dépendances d’artifacts nécessaires à son exécution.

Ainsi, si on souhaite qu’une build configuration fournisse des éléments à une autre build configuration, il faut indiquer le répertoire ou le fichier à fournir en utilisant le paramètre “Artifact paths” avec une syntaxe du type:

  • +:bin/Debug=>assemblies: permet d’indiquer que le contenu du répertoire bin/Debug sera copié dans un répertoire assemblies pour les build configurations suivantes.
  • +:bin/Debug: indique que le contenu du répertoire bin/Debug sera copié dans un répertoire bin/Debug pour les build configurations suivantes.
  • -:bin/Debug/netcoreapp2.0=>bin/Debug: indique que le répertoire bin/Debug/netcoreapp2.0 ne sera pas copié dans bin/Debug pour les build configurations suivantes.

Triggers

Dans les paramètres d’une build configuration, la partie “Triggers” permet de configurer des conditions pour déclencher l’exécution d’une build:

  • VCS Trigger: déclenche une build quand un commit a été détecté dans le gestionnaire de versions (i.e. VCS).
  • Schedule Trigger: permet de déclencher le démarrage d’une build à un certaine heure.
  • Finish Build Trigger: déclenche la build quand une autre build s’est terminée.

Failure conditions

Il peut s’avérer nécessaire d’affiner certains critères pour considérer que l’exécution d’une build a echoué. Par exemple, si le temps d’exécution d’une build dépasse une certaine durée ou si un message particulier apparaît dans les logs.

Build features

Ce paramétrage permet d’effectuer des traitements très divers concernant des éléments assez différents. Par exemple, les build features les plus utiles peuvent être:

  • File Content Replacer: permet de remplacer un fragment de texte dans un fichier par un autre. Cette fonction est particulièrement utile quand on veut affecter une version particulière dans un fichier Version.cs ou quand on veut appliquer un paramétrage particulier dans un fichier App.config ou Web.config. La détection du fragment se fait par regex.
  • VCS labeling: permet de poser un tag dans le gestionnaire de version lorsqu’une build s’est exécuté et a réussi.
  • Automatic merge: merge des branches dans le gestionnaire de versions si la build a réussi.
  • Performance Monitor: permet de collecter quelques métriques (utilisation du CPU, de la mémoire du disque ou de la machine).

Un exemple présenté plus bas, permet d’illustrer l’utilisation d’une build feature (cf. Ajouter des “build features” pour créer un tag Git).

Dependencies

Ce paramétrage permet d’indiquer quelles sont les build configurations nécessaires à l’exécution de la build configuration courante. Ces dépendances peuvent être de 2 natures:

  • Snapshot dependencies: permet d’indiquer une condition qui doit être satisfaite quant à l’exécution d’une autre build configuration pour que la build configuration courante soit exécutée.
    Par exemple, on pourra:

    • Déterminer la build configuration qui doit être exécutée avant la build configuration courante
    • Indiquer le critère de réussite de l’exécution d’une autre build configuration
    • Préciser qu’on souhaite exécuter la build configuration courante sur le même agent qu’une autre build configuration.
    • Ajouter des critères d’échec de la build configuration courante en fonction du résultat de build configurations précédentes.
  • Artifact dependencies: ce paramètre permet d’indiquer quels sont les éléments générés par une autre build configuration qui sont nécessaires à l’exécution de la build configuration courante.

    Par exemple, une assembly compilée dans une autre build configuration peut être nécessaire à la compilation effectuée par la build configuration courante.

    La syntaxe utilisée pour indiquer le chemin des artifacts est similaire à celle utilisée pour le paramètre “Artifact Paths”:

    • +:<chemin dans la build config précédente> => <chemin dans la build config courante>
    • +:<chemin dans la build config précédente>: si on ne précise pas de répertoire d’arrivée alors c’est le même répertoire que celui d’origine.
    • -: <chemin dans la build config précédente> => <chemin dans la build config courante>: indique qu’on souhaite exclure un fichier ou un répertoire dans les artifacts utilisés pour la build configuration courante.

    L’élément de configuration “Clean destination paths before downloading artifacts” est assez important car il permet de supprimer le contenu du répertoire d’arrivée avant d’importer les artifacts d’une build précédente. Dans certains cas, si on exécute à plusieurs reprises une build configuration, on peut avoir des comportements étranges si le répertoire d’arrivée n’est pas vide.

Un exemple présenté plus bas, permet d’illustrer l’utilisation des dépendances (cf. Ajouter une “build configuration” avec une dépendance).

Parameters

Les paramètres sont particulièrement utiles car ils permettent de personnaliser certains éléments de configuration et de les rendre accessibles dans toute l’arborescence des projets. Comme pour la plupart des éléments de configuration, les paramètres sont héritables dans l’arborescence des projets. Cela signifie que:

  • Si on crée un paramètre au niveau d’un projet, ce paramètre sera accessible dans les projets sous-jacents (ou enfants), dans les build configurations de ce projet et dans les build templates de ce projet.
  • Si on crée un paramètre au niveau d’une build configuration, il sera accessible à tous les niveaux de cette build configuration.
  • Si on crée un paramètre dans un build template, il sera accessible automatiquement dans les build configurations qui implémentent le build template.

Les paramètres peuvent être utilisés dans n’importe quel écran de configuration d’un projet ou d’une build configuration si l’arborescence le permet avec la syntaxe:

%<nom du paramètre>% 

Par exemple, si le paramètre s’appelle build.counter, on pourra l’utiliser avec la syntaxe:

%build.counter% 

Il existe 3 types de paramètres:

  • Configuration parameter: ces paramètres peuvent être utilisés dans les éléments de configuration des projets et des build configurations. Ils sont spécifiques à Teamcity et ne seront pas accessibles à d’autres éléments que les commandes directement lancées par Teamcity. La documentation indique que ces variables ne sont pas injectées dans les builds.

    Par exemple, si un paramètre s’appelle %DotNetBuildConfiguration%, on peut l’utiliser pour lancer une commande à partir de Teamcity comme, par exemple, la commande suivante:

    dotnet build --configuration %DotNetBuildConfiguration% 
    

    En revanche, en dehors de Teamcity, la variable ne sera pas accessible comme pouvait l’être une variable d’environnement.

  • System Properties: ces variables sont injectées dans les builds et sont donc accessibles lorsque les commandes ne sont pas directement lancées par Teamcity. Ces variables peuvent être utilisées quand on ne veut pas utiliser de variables d’environnement (qui pourraient avoir une empreinte trop forte car elles modifient des éléments de configuration du serveur). En effet, les paramètres “system properties” sont spécifiques à une build ce qui permet de ne pas affecter d’autres builds exécutées en parallèle.
  • Environment variable: comme son nom l’indique, ce type de paramètre permet de définir des variables d’environnement. Ces variables sont accessibles dans la build mais aussi sur le serveur sur lequel la build est exécutée. Il faut donc, garder en tête que si 2 builds sont exécutées en même temps sur le même serveur et si elles utilisent des valeurs différentes d’une même variable, l’utilisation de ce type de paramètre peut occasionner des comportements inattendus.

Pour créer un paramètre, il suffit de cliquer sur “Add new parameter”:

Cliquer sur “Add new parameter”

Il faut préciser ensuite quelques éléments de configuration comme le nom, le type de paramètre et la valeur:

Configurer un paramètre

D’autres éléments de configuration sont disponibles en cliquant sur “Edit”:

  • Label: permet d’indiquer un identifiant qui sera présenté sur les écrans d’exécution des build configurations. Le but est d’afficher un identifiant différent du nom du paramètre et plus explicite.
  • Display: ce paramétrage est assez important car il indique où le paramètre sera affiché pour qu’on puisse compléter sa valeur:
    • Normal: c’est le paramétrage par défaut. La valeur du paramètre sera utilisée sans qu’on soit obligé de la remplir sur l’écran de lancement d’une build. Toutefois, la valeur peut être modifiée sur l’écran de lancement d’une build.
    • Hidden: le paramètre ne sera pas affiché sur l’écran de lancement d’une build. Une modification de la valeur n’est possible que dans la configuration.
    • Prompt: ce paramétrage permet de forcer à remplir une valeur sur l’écran de lancement d’une build.
  • Type: permet d’affiner le type de paramétrage:
    • Password: les paramètres de ce type ne seront jamais affichés en clair.
    • Text: l’intérêt de ce paramétrage est de pouvoir définir des regex pour valider la valeur du paramètre.

Un exemple présenté plus bas, permet d’illustrer l’ajout et l’utilisation d’un paramètre (cf. Ajouter un paramètre pour indiquer la version).

Agent requirements

Cet écran permet d’ajouter des conditions pour que l’exécution d’une build configuration se fasse spécifiquement sur un agent. La plupart du temps, Teamcity indique lui-même des conditions qui doivent être satisfaites pour permettre l’exécution d’une build. Par exemple, une condition pourrait être la présence de .NET Core ou de JAVA sur un serveur.

Toutes les conditions sont indiquées dans la partie “Build steps Requirements”:

Ecran “Agent requirements”

Les agents compatibles sont indiqués dans “Agents Compatibility”. L’intérêt majeur de cette partie est d’indiquer la condition non satisfaite qui empêche l’exécution d’une build sur un agent.

L’ajout d’une condition se fait en cliquant sur “Add new requirement”. On peut ensuite indiquer la condition plus spécifique:

Ajout d’une condition en cliquant sur “Add new requirement”

Perfectionner une chaine de “builds”

De façon à illustrer les éléments de configuration présentés précédemment, on va complexifier la chaine de builds (le terme utilisé dans la documentation est build chain) commencée au début de l’article.

Ajouter une “build configuration” avec une dépendance

Pour illustrer les dépendances, on va ajouter une nouvelle build configuration qui dépendra de la build configuration “Build AnyCpu” créée précédemment.

On se propose de créer une build configuration qui va générer un package NuGet avec la commande dotnet pack.

Cette build configuration utilise le résultat de la compilation de la build configuration “Build AnyCpu”.

Pour créer la nouvelle build configuration:

  1. On va donc dans les paramètres du projet “Pizza Calculator” et on clique sur “Create build configuration”.
  2. Cliquer sur “Manually” et on indique le nom “Nuget package”
  3. On ne précise rien dans l’écran suivant. On clique simplement sur “Build Step”
  4. Cliquer ensuite sur “Add build step”
  5. Sélectionner .NET CLI (dotnet)
  6. On précise les paramètres suivants après avoir cliqué sur “Show advanced options”:
    • Runner type: .NET CLI (dotnet)
    • Steps name: Nuget pack
    • Execute step: If all previous steps finished successfully
    • Command: pack
    • Projects: src/pizza-calculator.csproj
    • Command line parameters: /p:PackageVersion=1.0.0.%build.counter%. Cette valeur permettra d’indiquer un numéro de version en utilisant le paramètre build.counter (ce paramètre est auto-incrémenté par Teamcity à chaque exécution de la build configuration).
  7. Cliquer sur “Save”

On arrive ensuite à la configuration des dépendances à proprement parlé:

  1. On clique sur “Add new snapshot dependancy”. Comme indiqué plus haut, ce paramétrage permet de préciser la build configuration qui doit être exécutée avant la build configuration actuelle.
  2. On précise la valeur Pizza Calculator :: Build AnyCpu correspondant à la build configuration qui compile les sources récupérées à partir de GitHub.
  3. On coche “Do not run new build if there is a suitable one” de façon à indiquer de ne pas ré-exécuter la build configuration précédente si rien n’a changé entre 2 exécutions.
  4. On coche aussi “Only use successful builds from suitable ones” pour indiquer que seules les compilations ayant réussies seront prises en compte.
  5. On coche enfin “Run build on the same agent” pour indiquer que la build configuration précédente et la build configuration courante doivent être exécutées sur le même agent.
  6. Pour la valeur “On failed dependency”, on sélectionne la valeur “Make build failed to start”. Ce paramétrage permet d’empêcher l’exécution de la build configuration courante si la build configuration précédente a échoué.
  7. Pour la valeur “On failed to start/canceled dependancy”, on sélectionne, de même, “Make build failed to start”. De la même façon, si la build configuration précédente a été annulée, la build configuration courante ne sera pas exécutée.
  8. On clique, enfin, sur “Save”.

Sachant que la build configuration doit utiliser les résultats de la compilation de la build configuration “Build AnyCpu”, il faut ajouter des dépendances d’artifacts (le terme utilisé dans la documentation est artifact dependencies).

Dans la partie “Artifact Dependencies”:

  1. Cliquer sur “Add new artifact dependancy”.
  2. On précise la valeur "Pizza Calculator :: Build AnyCpu" correspondant à la build configuration qui compile les sources.
  3. Pour la valeur “Get artifacts from”, on sélectionne la valeur Build from the same chain pour utiliser exactement les artifacts provenant de la build configuration exécutée juste préalablement.
  4. Dans “Artifact rules”, on indique de quelle façon on récupère les artifacts de la build configuration précédente. Sachant qu’on veut récupérer le contenu du répertoire src et le placer dans le répertoire src, on l’indique avec la valeur:
    +:src=>src 
    

    Sachant que les répertoires de départ et d’arrivée ont le même nom, on peut aussi utiliser la valeur:

    +:src
    
  5. On coche ensuite “Clean destination paths before downloading artifacts” pour que le répertoire d’arrivée des artifacts soit vide avant d’effectuer la copie. Ce paramétrage permet d’éviter des comportements inattendus quand certains fichiers ont été supprimés et ne sont plus présents dans les artifacts.
  6. On termine en cliquant sur “Save”.

On peut tester l’exécution de la build chain en accédant à l’écran d’exécution des build configurations en cliquant sur “Build configuration Home” en haut à droite puis “Pizza Calculator”:

Cliquer sur “Run” au niveau de “Nuget package”

On clique sur “Run” pour lancer l’exécution de la build configuration “Nuget package”. L’exécution de la build configuration “Nuget package” va entraîner l’exécution de la build configuration “Build AnyCpu”.

En cliquant sur l’onglet “Build chains”, on peut voir un résumé de l’exécution de la chaine de build:

Affichage de la chaine de build

Ajouter un paramètre pour indiquer la version

Pour illustrer l’ajout d’un paramètre, on se propose d’ajouter un paramètre contenant un numéro de version. Cette version devra être précisée, dans un premier temps, au moment de générer le package NuGet. Dans un 2e temps, on viendra modifier la version dans les sources pour que le numéro de version soit pris en compte au moment de la compilation dans la build configuration “Build AnyCpu”.

Avant tout, on ajoute le paramètre BuildVersion:

  1. Dans les paramètres du projet “Pizza Calculator”, on clique sur “General Settings” puis sur “Nuget package” pour accéder aux paramètres de la build configuration “Nuget package”.
  2. Cliquer ensuite sur “Parameters”
  3. Ajouter un paramètre en cliquant sur “Add new parameter”
  4. On précise les paramètres suivants:
    • Name: BuildVersion
    • Kind: Configuration parameter
    • Value: on indique une valeur par défaut 0.0.0.
  5. On clique ensuite sur “Edit” et on précise les paramètres suivants:
    • Label: Numéro de version
    • Display: Prompt pour que le paramétre apparaisse sur l’écran de lancement de la build configuration.
    • Type: Text
    • Allowed Value: Regex
    • Pattern: ^(\d+\.)?(\d+\.)?(\d+)$
    • Validation Message: Le numéro de version doit être du type: x.y.z
  6. On clique sur “Save” pour le 1er panneau et “Save” de nouveau pour le 2e panneau.

Pour utiliser le paramètre:

  1. Cliquer sur “Build Step”
  2. Cliquer ensuite sur la build step “Nuget pack” pour en éditer les paramètres.
  3. On modifie la valeur correspondant au paramètre “Command line parameters” avec la valeur suivante:
    /p:PackageVersion=%BuildVersion%.%build.counter% 
    
  4. On valide en cliquant sur “Save”.

Pour tester le paramètre, on accède à l’écran d’exécution des build configurations en cliquant sur “Build configuration Home” en haut à droite puis “Pizza Calculator”. Cliquer ensuite sur “Run” au niveau de la build configuration “Nuget package”. On obtient l’écran de lancement de la build configuration avec le nouveau paramètre:

Indiquer le numéro de version au lancement de la build

On précise la valeur 1.2.3 et on clique sur “Run”.

Pour vérifier la prise en compte du paramètre, on peut aller dans les logs d’exécution de la build configuration en cliquant sur la dernière exécution:

Cliquer sur la dernière exécution

Puis sur l’onglet “Build log”, on peut voir dans les logs, une ligne du type:

[pack] Successfully created package '/usr/Teamcity/work/371ec8e2dc170c79/src/bin/Debug/pizza-calculator.1.2.3.8.nupkg'. 

Le numéro de version est donc bien utilisé.

Prendre en compte le paramètre dans un “build configuration” précédente

On souhaite utiliser le numéro de version au moment de la compilation dans la build configuration “Build AnyCpu”. Cette build configuration est exécutée avant la build configuration “Nuget package”.

La fonctionnalité qui permet d’effectuer ce paramétrage est appelée: reverse dependency parameter (cf. documentation de Teamcity).

Pour ajouter ce type de paramètre, il faut utiliser la syntaxe suivante:

reverse.dep.*.<nom du paramètre> 

On va donc modifier le paramétrage de la build configuration “Nuget package”:

  1. Dans les paramètres du projet “Pizza Calculator”, on clique sur “General Settings” puis sur “Nuget package” pour accéder aux paramètres de la build configuration “Nuget package”.
  2. Cliquer sur “Parameters”
  3. Cliquer sur le paramètre “BuildVersion” et modifier le nom de ce paramètre pour avoir:
    reverse.dep.*.BuildVersion 
    
  4. On valide en cliquant sur “Save”.

On modifie l’endroit où on utilisait le paramètre “BuildVersion” dans la build configuration “Nuget package”:

  1. Cliquer sur “Build step”
  2. Cliquer ensuite sur la build step “Nuget Pack”
  3. Modifier la valeur du paramètre “Command line parameters” pour obtenir:
    /p:PackageVersion=%reverse.dep.*.BuildVersion%.%build.counter% 
  4. On valide en cliquant sur “Save”.

Ensuite, il faut rajouter le paramètre BuildVersion au niveau de la build configuration “Build AnyCpu”:

  1. Dans les paramètres du projet “Pizza Calculator”, on clique sur “General Settings” puis sur “Build AnyCpu” pour accéder aux paramètres de la build configuration “Build AnyCpu”.
  2. Cliquer ensuite sur “Parameters”
  3. Ajouter un paramètre en cliquant sur “Add new parameter”
  4. On précise les éléments suivants:
    • Name: BuildVersion
    • Kind: Configuration parameter
    • Value: on indique une valeur par défaut 0.0.0.

Pour prendre en compte cet élément de configuration, il faut ajouter un file content replacer pour remplacer les numéros de version dans le code source.

Ajouter un “file content replacer” pour modifier la version

Cette étape permet de remplacer les numéros de version dans le code source pour qu’il soit pris en compte au moment de la compilation.

Cette configuration s’effectue en ajoutant une build feature au niveau de la build configuration “Build AnyCpu”:

  1. Dans les paramètres du projet “Pizza Calculator”, on clique sur “General Settings” puis sur “Build AnyCpu” pour accéder aux paramètres de la build configuration “Build AnyCpu”.
  2. Cliquer sur “Build features”
  3. Cliquer ensuite sur “Add build feature” pour ajouter une nouvelle build feature.
  4. On sélectionne “File Content Replacer”, ce qui permettra de remplacer le numéro de version dans le fichier pizza-calculator.csproj:
    <Project Sdk="Microsoft.NET.Sdk"> 
    	<PropertyGroup> 
    		<OutputType>Exe</OutputType> 
    		<TargetFramework>netcoreapp2.0</TargetFramework> 
    		<AssemblyVersion>1.0.0.0</AssemblyVersion> 
    		<FileVersion>1.0.0.0</FileVersion> 
    	</PropertyGroup> 
    </Project> 
    
  5. Cliquer sur “Load template” et sélectionner dans la partie .NET Core “AssemblyVersion in csproj (.NET Core)” qui permet d’affecter les valeurs:
    • Process files: **/*.csproj
    • Find what: (<(AssemblyVersion)\s*>).*(<\/\s*\2\s*>)
    • Replace with: $1\%BuildVersion%.%build.counter%$3. Cette valeur est différente de la valeur par défaut.
  6. Cliquer sur “Save”
  7. Ajouter un nouveau “File Content Replacer” pour modifier l’élément FileVersion.
  8. Cliquer sur “Load template” et sélectionner dans la partie .NET Core “FileVersion in csproj (.NET Core)” qui permet d’affecter les valeurs suivantes:
    • Process files: **/*.csproj
    • Find what: (<(FileVersion)\s*>).*(<\/\s*\2\s*>)
    • Replace with: $1\%BuildVersion%.%build.counter%$3. Cette valeur est différente de la valeur par défaut.
  9. Cliquer sur “Save”.

Pour tester le paramètre, on accède à l’écran d’exécution des build configurations en cliquant sur “Build configuration Home” en haut à droite puis “Pizza Calculator”. On clique ensuite sur “Run” au niveau de la build configuration “Nuget package”. On précise la valeur 1.2.4 et on clique sur “Run”.

Pour vérifier la prise en compte du paramètre, on peut aller dans les logs d’exécution de la build configuration “Build AnyCpu” en cliquant sur la dernière exécution, puis sur l’onglet “Parameters”, on peut voir que la valeur de BuildVersion est celle précisée au niveau de la build configuration “Nuget package”:

Valeur de la variable BuildVersion

Ajouter des “build features” pour créer un tag Git

On se propose ensuite de créer une build feature pour apposer un tag Git dans le cas où la build s’est bien passée.

Dans ce cas, on va dans les paramètres de la build configuration “Nuget package”:

  1. Dans les paramètres du projet “Pizza Calculator”, on clique sur “General Settings” puis sur “Nuget package” pour accéder aux paramètres de la build configuration “Nuget package”.
  2. Cliquer sur “Version Control Settings” pour ajouter le VCS correspondant à Git.
  3. Cliquer sur “Attach VCS root”
  4. Sélectionner Pizza-Calculator puis on valide en cliquant sur “Attach”.
  5. Cliquer ensuite sur “Build Features” pour ajouter une nouvelle build feature.
  6. Cliquer sur “Add build feature”.
  7. On sélectionne VCS labeling et on indique les paramètres suivants:
    • VCS root to label: sélectionner le VCS Pizza-calculator
    • Labeling pattern: build-%reverse.dep.*.BuildVersion%
    • On coche “Label successful builds only” pour que le tag soit apposé seulement si la build réussit.

On peut ensuite lancer une build pour tester ce paramétrage en cliquant sur “Build configuration Home” en haut à droite puis “Pizza Calculator”. On clique ensuite sur “Run” au niveau de la build configuration “Nuget package”.

A la fin de la build, si on vérifie dans GitHub, on peut se rendre compte que le tag a bien été apposé.

Rendre des “build configurations” plus génériques

Si on souhaite réutiliser des build configurations, il existe 2 méthodes pour les rendre plus génériques:

  • En créant un modèle de build (le terme utilisé dans la documentation est build template) au niveau du projet
  • En créant un meta-runner pour exploiter la build configuration en dehors du projet.

Créer un “build template”

Créer un build template est la 1ère méthode pour rendre une build configuration plus générique. Le build template va permettre de réutiliser plus facilement la build configuration sans dupliquer trop d’éléments de configuration.

On peut créer un build template de la même façon que l’on a créé précédement une build configuration:

  1. Dans les paramètres du projet “Pizza Calculator”, cliquer sur “General Settings”
  2. Cliquer ensuite sur “Create template”.
  3. Le reste du paramétrage est similaire à celui d’une build configuration.

Une autre méthode consiste à utiliser une build configuration existante pour créer un build template:

  1. Dans les paramètres du projet “Pizza Calculator”, cliquer sur “General Settings” puis sur “Build AnyCpu” pour accéder aux paramètres de la build configuration “Build AnyCpu”.
  2. On clique sur “Actions” en haut à droite puis on clique sur “Extract template”.
  3. On indique un nom, par exemple Build.

On peut créer, ensuite facilement une nouvelle build configuration en se basant sur le build template:

  1. Dans les paramètres du projet “Pizza Calculator”, cliquer sur “General Settings”.
  2. Cliquer sur “Create build configuration” pour créer une nouvelle build configuration.
  3. Cliquer sur “Manually” puis on précise quelques paramètres:
    • Name: Build x86
    • Based on template: on sélectionne Build.
  4. On valide en cliquant sur “Create”.

On va ensuite spécialiser cette build configuration pour qu’elle compile avec une configuration de runtime “x86”. 2 approches sont possibles:

  • 1ère approche: désactiver la build step valable pour le runtime “AnyCpu” et créer une build step spécialisée pour le runtime “x86”.
  • 2e approche: créer un paramètre pour la configuration correspondant au runtime et pour surcharger la valeur de ce paramètre dans les build configurations.

On va expliciter les 2 approches:
1ère approche: désactiver la build step valable pour le runtime “AnyCpu”
On va ensuite spécialiser cette build configuration pour qu’elle compile avec le runtime “x86”:

  1. Cliquer alors sur “Build steps”
  2. On ne peut modifier les paramètres des build steps héritées du build template, on va donc créer une nouvelle build step en dupliquant la build step Build.
  3. Cliquer donc sur la flèche à droite de la build step “Build” puis on clique sur “Copy build step”:
    Cliquer sur la flèche à droite de la build step “Build”
  4. On laisse le paramètre “Copy build step to:” sur la valeur Pizza Calculator :: Build x86 correspondant à la build configuration actuelle.
  5. On valide en cliquant sur “Copy”.
  6. Renommer cette build step en cliquant dessus et en modifiant le nom pour Build x86. Après avoir cliqué sur “Show advanced options”, indiquer pour le paramètre “Runtime” la valeur win-x86.
  7. On valide en cliquant sur “Save”.

On désactive la build step “Build” puisqu’elle ne sert plus à rien:

  1. Cliquer sur la flèche à droite de la build step Build
  2. Cliquer ensuite sur “Disable build step”.

La build step devient grisée:

Build step désactivée

On peut ensuite lancer l’exécution de la build configuration en cliquant sur “Build configuration Home” en haut à droite puis “Pizza Calculator”. On clique ensuite sur “Run” au niveau de la build configuration “Build x86”.

ATTENTION

Cette approche n’est pas la meilleure car si on modifie le build template, on peut changer le comportement des build configurations qui en dépendent et certains comportements peuvent être inattendus.

2e approche: créer un paramètre pour le runtime
On crée d’abord une variable pour configurer le runtime:

  1. Dans les paramètres du projet “Pizza Calculator”, on clique sur “General Settings” puis sur le build template “Build”.
  2. Cliquer ensuite sur “Parameters”.
  3. Cliquer sur “Add new parameter” avec les paramètres suivants:
    • Name: BuildRuntime
    • Kind: Configuration parameter
    • On clique sur “Edit” pour spécialiser d’autres paramètres.
    • Label: Configuration runtime dotnet
    • Display: Normal
    • Type: Text
    • Allowed value: Any
  4. On valide en cliquant sur “Save” pour valider les paramètres et cliquer de nouveau sur “Save” pour valider la création du paramètre.

On va ensuite utiliser le paramètre dans la build step qui compile:

  1. Cliquer sur “Build Steps”
  2. Cliquer sur la build step se nommant Build.
  3. Après avoir cliqué sur “Show advanced options” pour afficher toutes les options, on indique la valeur %BuildRuntime% pour l’élément de configuration “Runtime”.

On peut ensuite spécialiser une build configuration pour le runtime “x86”:

  1. Dans les paramètres du projet “Pizza Calculator”, on clique sur “General Settings”.
  2. Si on a créé une build configuration Build x86 pour la 1ère approche, il faut la supprimer en cliquant sur la flèche à droite au niveau de la build configuration:
    Supprimer la build configuration Build x86

    Cliquer ensuite sur “Delete build configuration”.

  3. Pour créer une nouvelle build configuration se basant le build template Build donc on clique sur “Create build configuration”.
  4. On clique sur “Manually” puis on précise quelques paramètres:
    • Name: Build x86
    • Based on template: on sélectionne Build.
    • Pour le paramètre BuildRuntime, on indique la valeur win-x86.
  5. On valide en cliquant sur “Create”.

On peut ensuite lancer l’exécution de la build configuration en cliquant sur “Build configuration Home” en haut à droite puis “Pizza Calculator”. On clique ensuite sur “Run” au niveau de la build configuration “Build x86”.

Privilégier la 2e approche

Cette approche est à privilégier car elle rend le paramétrage plus clair et il est plus facile de modifier le build template par la suite en maitrisant les impacts sur les build configurations qui en dépendent.

Créer un “meta-runner”

Un meta-runner est une autre méthode pour rendre une build configuration plus générique. Comme un build template, un meta-runner va permettre de réutiliser plus facilement une build configuration sans dupliquer trop d’éléments de configuration.

La différence entre un build template et un meta-runner est que le meta-runner peut se définir et se partager à n’importe quel niveau de l’arborescence alors qu’un build template est limité à un projet.

Pour créer un méta-runner, la méthode la plus simple consiste à utiliser une build configuration existante pour le générer:

  1. Dans les paramètres du projet “Pizza Calculator”, on clique sur “General Settings” puis sur “Build AnyCpu” pour accéder aux paramètres de la build configuration “Build AnyCpu”.
  2. Cliquer sur “Actions” en haut à droite puis cliquer sur “Extract template”.
  3. On précise quelques paramètres:
    • Project: <Root project> on indique un projet plus élevé pour en bénéficier en dehors du projet “Pizza calculator”
    • Name: Build MetaRunner
    • Description: Metarunner for building with .NET Core
  4. Valider en cliquant sur “Extract”.

On arrive ensuite au niveau du projet “<Root project>”:

Meta-runners de “<Root project>”

Si on clique sur le meta-runner, on voit une description en XML des différentes build steps:

<?xml version="1.0" encoding="UTF-8"?> 
<meta-runner name="Build MetaRunner"> 
  <description>Metarunner for building with .NET Core</description> 
  <settings> 
    <parameters> 
      <param name="BuildRuntime" value="" spec="text label='Configuration runtime dotne' validationMode='any' display='normal'" /> 
      <param name="BuildVersion" value="0.0.0" spec="text regexp='^(\d+\.)?(\d+\.)?(\d+)$' label='Numéro de version' validationMode='regex' display='prompt' validationMessage='Le numéro de version doit être du type: x.y.z'" /> 
    </parameters> 
    <build-runners> 
      <runner name="Restore" type="dotnet"> 
        <parameters> 
          <param name="dotNetCoverage.dotCover.home.path" value="%Teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" /> 
          <param name="dotnet-command" value="restore" /> 
          <param name="dotnet-paths" value="src/pizza-calculator.csproj" /> 
          <param name="Teamcity.step.mode" value="default" /> 
        </parameters> 
      </runner> 
      <runner name="Build" type="dotnet"> 
        <parameters> 
          <param name="dotNetCoverage.dotCover.home.path" value="%Teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" /> 
          <param name="dotnet-build-config" value="Release" /> 
          <param name="dotnet-build-runtime" value="%BuildRuntime%" /> 
          <param name="dotnet-command" value="build" /> 
          <param name="dotnet-paths" value="src/pizza-calculator.csproj" /> 
          <param name="Teamcity.step.mode" value="default" /> 
        </parameters> 
      </runner> 
      <runner name="Restore tests" type="dotnet"> 
        <parameters> 
          <param name="dotNetCoverage.dotCover.home.path" value="%Teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" /> 
          <param name="dotnet-command" value="restore" /> 
          <param name="dotnet-paths" value="tests/pizza-calculator-tests.csproj" /> 
          <param name="Teamcity.step.mode" value="default" /> 
        </parameters> 
      </runner> 
      <runner name="Test" type="dotnet"> 
        <parameters> 
          <param name="dotNetCoverage.dotCover.home.path" value="%Teamcity.tool.JetBrains.dotCover.CommandLineTools.DEFAULT%" /> 
          <param name="dotnet-command" value="test" /> 
          <param name="dotnet-paths" value="tests/pizza-calculator-tests.csproj" /> 
          <param name="Teamcity.step.mode" value="default" /> 
        </parameters> 
      </runner> 
    </build-runners> 
    <requirements /> 
  </settings> 
</meta-runner>

Le gros intérêt du meta-runner est qu’il est possible d’éditer facilement les éléments directement dans le code XML.

On peut ensuite facilement utiliser le meta-runner dans un autre projet. Par exemple, si on crée un nouveau projet:

  1. Au niveau de “<Root project>”, cliquer sur “Create subproject”
  2. Indiquer le nom SliceCalculator
  3. Valider en cliquant sur “Create”.

On peut utiliser le meta-runner de 2 façons:

  1. Dans le projet “SliceCalculator”, on clique sur “Meta-Runners” puisqu’on hérite du meta-runner se trouvant au niveau de <Root project>.
  2. Cliquer ensuite sur la flèche à droite du meta-runner puis sur “Create build configuration from meta-runner”
  3. Préciser ensuite où la build configuration doit être créée et préciser le nom de la build configuration: Build AnyCpu disconnected from MetaRunner
  4. On valide en cliquant sur “Create”.

On obtient une nouvelle build configuration avec les mêmes build steps que la build configuration “Build Any Cpu” dans le projet “PizzaCalculator”.

ATTENTION: la configuration est dupliquée

Le gros inconvénient de cette méthode est que la build configuration “Build AnyCpu disconnected from MetaRunner” dans le projet “SliceCalculator” est déconnecté du meta-runner:

  • Si on modifie le meta-runner défini au niveau de “<root project>”, les modifications ne seront pas répercutées sur la nouvelle build configuration.
  • On perd, un peu l’intérêt du meta-runner puisqu’il s’agit d’une duplication de la configuration.

Une autre méthode pour utiliser le meta-runner consiste à créer une build step qui exécute entièrement le meta-runner:

  1. Dans le projet “SliceCalculator”, on crée une nouvelle build configuration en cliquant “General Settings”.
  2. Cliquer ensuite sur “Create build configuration”.
  3. Cliquer sur “Manually” puis préciser le nom de la build configuration: Build AnyCpu connected to MetaRunner.
  4. Valider en cliquant sur “Create”.
  5. Cliquer sur “Build steps” pour créer un nouveau build step
  6. Cliquer sur “Add build step”
  7. Sélectionner le nom du meta-runner créé au niveau du projet “<Root project>” à savoir “Build AnyCpu MetaRunner”.
  8. Valider en cliquant sur “Create”.

La build step nouvellement créée permet d’exécuter en une seule étape le meta-runner se trouvant au niveau de “<Root project>”. Si on modifie le meta-runner, toutes les modifications seront répercutées dans les build steps qui l’utilisent de cette façon.

Cette méthode donne aussi la flexibilité de pouvoir surcharger la valeur de certains paramètres définis dans le meta-runner. Par exemple dans notre cas, il est possible de surcharger la valeur du paramètre “Numéro de version” au niveau de la build step:

Surcharger la valeur du paramètre “Numéro de version” au niveau de la build step
Il n’existe pas de “if” dans les meta-runners

Il n’est pas possible d’utiliser des conditions avec des directives “if” dans les meta-runners donc pour spécialiser un meta-runner dans une build configuration, il existe 2 approches:

  • 1ère approche:
    1. Créer une build configuration à partir du meta-runner en cliquant sur “Create build configuration from meta-runner” au niveau du meta-runner.
    2. Désactiver des build steps en cliquant sur “Disable build step” dans l’écran “Build steps” de la build configuration.
    3. On peut de même ajouter de nouveaux build steps en fonction des besoins.
  • 2e approche:
    1. Utiliser les paramètres en niveau du meta-runner pour spécialiser certains éléments de configuration. Par exemple dans le meta-runner définit précédemment, le paramètre “BuildRuntime” peut être spécialisé dans la build step “Build”.
    2. Si on crée une build configuration et qu’on utilise le meta-runner sous forme d’une build step (comme pour la build configuration “Build AnyCpu connected to MetaRunner” définie précédemment), on peut spécialiser la valeur du paramètre:
      Paramétrer un meta-runner dans une build step

Configurer des “feature branches” Git

Si on utilise Git en tant que VCS, il est possible de configurer Teamcity pour qu’il puisse gérer des features branches. Cette fonctionnalité est particulièrement intéressante puisqu’elle permet de lancer des builds pour une branche spécifique au lieu de la lancer systématiquement pour la branche master.

Si on va dans la configuration du VCS (i.e. Version Control System) du projet “Pizza Calculator” en cliquant sur “VCS Roots” puis sur la configuration “Pizza-calculator”, on peut voir que la valeur du paramètre “Default branch” est refs/heads/master. Ce paramètre indique que la branche par défaut qui sera systématiquement buildée est la branche master.

Pour permettre de builder d’autres branches que la branche principale, on modifie les paramètres suivants:

  1. Cliquer sur “Show advanced options”
  2. Pour le paramètre “Branch specification”, indiquer la valeur +:refs/heads/*.
    Ce paramètre signifie qu’on pourra builder toutes les branches du repository Git (dans la cas où on veut limiter à certaines branches, on peut affiner la wildcard *).
  3. Valider en cliquant sur “Save”.

A ce moment, le VCS root “Pizza-calculator” gère les feature branches.

Pour l’illustrer, on va créer une branche dans le repository Git:

  1. On clone d’abord le repository localement:
    user@debianvm:~% git clone https://github.com/teamcitytest/pizza-calculator.git
  2. Créer la branche en exécutant:
    user@debianvm:~% cd pizza-calculator
    user@debianvm:~/pizza-calculator% git checkout -b feature_branch
    user@debianvm:~/pizza-calculator% git push origin feature_branch
    

Ensuite, on vérifie dans Teamcity si on peut effectivement builder la branche feature_branch:

  1. On accède à l’écran d’exécution des build configurations en cliquant sur “Projects” en haut à gauche et en dépliant le nœud du projet “Pizza Calculator”.
    On peut voir qu’on peut sélectionner une branche particulière en dépliant la liste déroulante <Active branches>:

    Sélectionner une branche en dépliant la liste déroulante <Active branches>
  2. On lance une build sur la branche feature_branch en cliquant sur “Run” à droite de la build configuration “Build AnyCpu”.
  3. Aller dans l’onglet “Changes” et sélectionner la branche feature_branch pour l’élément de configuration “Build branch”:
    Sélectionner la branche feature_branch dans l’onglet “Changes”

A la fin de la compilation, on peut voir que les lignes de statut des builds sont différentes suivant la branche:

Le statut de plusieurs branches est affiché

Pour plus de détails sur la gestion de feature branches par Teamcity: Working with Feature Branches.

En conclusion…

Dans cet article, on a eu l’occasion d’expliquer les fonctionnalités principales de Teamcity comme:

  • Configurer une build configuration (i.e. configuration de build) avec des build steps (i.e. étapes de build),
  • Créer une autre build configuration avec des dépendances,
  • Ajouter des paramètres à une build configuration,
  • Ajouter des build features pour effectuer des modifications lors de l’exécution d’un build,
  • Créer un meta-runner.

Toutes ces explications ont pour but de rendre les premières configuration de Teamcity plus aisées de façon à mettre en place des processus de continous delivery rapidement et plus facilement.

Leave a Reply