novembre 4, 2020
Stéphane Restani

Traçabilité et gestion de version : à faire au plus tôt !

Nous avons couvert dans un précédent article notre pipeline pour compiler et déployer une application mobile avec le moins d’efforts possible. Dans cet article, nous parlerons d’un autre sujet important dans un environnement d’intégration continue : la traçabilité.

La traçabilité, identifier les versions

Puisque nous distribuons des versions du jeu à de multiples personnes, que le jeu est en développement actif et que les choses bougent rapidement, il nous faut être capables d’identifier de quelle version du jeu un joueur parle lorsqu’il nous fait des retours. Deux problèmes sont à résoudre : quelles informations utiliser pour identifier une version, et comment faire pour la récupérer.

L’identification d’une version paraît simple au premier abord : mettons simplement la date à laquelle la build a été faite. Le problème de la date, c’est qu’étant donné le nombre de builds par jour (plusieurs dizaines), il lui faut aussi contenir les heures et minutes, voire même des secondes. Avec ces informations, nous pourrions certes retracer la version du code utilisée pour compiler, en fouillant dans l’historique des builds de notre serveur, mais cela serait long et sujet à l’erreur.

À l’inverse, le `commit hash`, identifiant unique correspondant à une version précise du code, est sans failles. Cette information nous permet de retrouver exactement ce qui est “dans la boîte”. Il souffre toutefois du même problème que la date : pour retrouver la version correspondante, nous devons fouiller notre historique pour retrouver ce commit, et la build associée.

Ce que nous utilisons

Le système de versioning que nous utilisons s’appelle git. Un des points forts du git est sa capacité à créer des branches : des versions du code peuvent exister en parallèle, et chacun peut travailler sur une partie du projet sans gêner les autres. Après quoi le travail de tout le monde est réintégré dans une seule branche commune : `master`. Puisque nous pouvons distribuer des versions spéciales, il est important pour nous de pouvoir savoir de quelle branche provient une build. Vient-elle de master (sur laquelle nous n’attendons aucun bug, qui doit être “parfaite”), ou alors d’une branche de travail sur laquelle certaines choses peuvent être cassées ? L’information de branche nous est, elle aussi, utile. Bien que contenue implicitement dans le `commit hash` (qui est lié à une branche), avoir le nom de la branche dans les informations de version nous permet de rapidement mettre en contexte la build en question.

Pour tout arranger, nous faisons des exécutables pour Windows, MacOS et Nintendo Switch. Nous avons donc besoin de pouvoir retrouver la bonne build parmi tous ces environnements.

La dernière information souhaitée est un contexte général : est-ce un prototype, une vertical slice, une version plus avancée, déjà sortie ? Nous utilisons pour cela un numéro de version écrit de la sorte : “a.b”, où “a” correspond à la version “majeure” du jeu. Une valeur de « 0 » indique que le jeu n’est pas encore disponible publiquement. À l’inverse, “1” indique qu’il l’est. Plus tard, un “2” pourra apparaître si le jeu change drastiquement. Nous utilisons “b” pour dénoter des milestones. Durant le développement, nous avons plusieurs milestones (nous en sommes actuellement au 2). Une fois le jeu sorti, “b” sera incrémenté pour chaque mise à jour de contenu.

En résumé, nous voulons :

  • Savoir si l’on doit s’attendre à des bugs/déséquilibres, ou bien si tout est censé marcher “top notch”. L’information de branche git nous renseigne là-dessus.
  • Rapidement retrouver une version dans notre historique sur notre serveur de build. Nous utilisons pour cela un compteur incrémental de build par environnement (Windows, Mac, Switch).
  • Savoir quelle version du code est utilisée : le `commit hash` nous renseigne là-dessus.
  • Connaître le contexte global de la build : le numéro de version nous sert à cela.

En tout et pour tout, notre indication de version est formatée ainsi :

a.bbranchennn.ggggggg-build.bbb

Où :

  • a.b est notre numéro de version
  • branche est le nom de la branche git
  • nnn est le nombre de commits dans la branche depuis le début du projet
  • ggggggg est une version raccourcie du `commit hash`
  • bbb est le numéro de la build dans notre serveur, pour l’OS donné.

Pour les curieux, “branche-nnn.ggggggg” est la sortie de cette commande :

$(git rev-parse –abbrev-ref HEAD).$(git rev-list –count HEAD).$(git rev-parse –short HEAD)

Au total, notre numéro de version peut ressembler à ça :

0.2-master.922.abcdef1-build.754

Comment l’afficher ?

La deuxième partie du problème à résoudre est “comment récupérer ce numéro de version”. Nous ne voulons pas avoir à déranger nos joueurs/testeurs en leur demandant de fouiller des logs, donc nous optons pour une solution simple : le numéro de version est affiché en permanence à l’écran.

Nous utilisons pour cela un petit script très simple :

 

Attaché à un `GameObject` présent dans notre scène de chargement initial, ce `GameObject` restera dans le jeu en permanence et nous permettra constamment de connaître la version derrière un screenshot ou une vidéo.

Petit détail d’implémentation : ce script lit le contenu d’un fichier `Resources/VersionInfo.txt`, et le joint au numéro de version donné dans les `PlayerSettings` d’Unity. Notre numéro de version complet provient donc de la concaténation de deux sources : les `PlayerSettings` et le fichier `VersionInfo`. Nous mettons à jour manuellement les `PlayerSettings` à chaque nouveau milestone. Quant au fichier `VersionInfo`, notre serveur de build se charge de le mettre à jour avec chaque build.

 

Conclusion

La gestion des versions d’un jeu et leur traçabilité tombent dans cette famille de problèmes qui paraissent peu importants, jusqu’à ce qu’on en ait besoin (un peu comme un extincteur par exemple…). Grâce à cet article, vous connaissez maintenant tous les détails derrière les numéros de version que vous pourrez voir en bas à gauche de certains de nos jeux.