Il n'y a pas que les RH qui peuvent se plaindre de tâches pénibles : le métier de développeur connaît également son lot d'actions techniques rébarbatives mais nécessaires. Lucca cultivant un amour de l'automatisation et ayant prêté serment de simplifier les tâches administratives, il semblait évident que pour être en accord avec nous-mêmes, nous, devs Lucca, devions nous imposer le même standard et nous simplifier nous-même la vie.
Dans cet article, nous vous proposons de vous mettre dans la peau de Jean-Sébastien, développeur back, dont la matinée sera semée d'embûches... et de solutions techniques mises au point par Lucca et pour Lucca, afin de huiler les rouages de notre métier. L'histoire que nous allons vous raconter décrit exactement notre quotidien bien qu'habituellement nous travaillons sur des logiciels RH.
Jean-Sébastien travaille sur une application de gestion de planning de salles de musique. En ce lundi, ses notifications Slack lui remontent un problème relatif à une alerte Datadog (notre outil de monitoring), ainsi qu'un lien direct vers l'outil. En s’y connectant, il constate effectivement un nombre anormal d’erreurs 500 remontées par les serveurs de son application. "Voilà qui est baroque", se dit Jean-Seb... "Je n'ai rien déployé en production récemment".
Chez Lucca, nous centralisons tout notre workflow de travail sur Slack. Les alertes concernant notre production n’y échappent pas. Dans datadog, nous définissions des règles qui déclenchent des messages slack sur nos canaux d’alertes. Selon la gravité des alertes, nous ouvrons alors des tickets de correction de bugs ou bien un incident via l’outil incident.io. Son intégration Slack permet à la fois de créer un incident dans la foulée (
/incident
), mais également d'assigner le ticket, suivre son évolution, inviter des collaborateurs à donner un coup de main pour la résolution, partager des liens vers des PRs et lier l'état du ticket à l'état de celles-ci, sans quitter l'interface de Slack.
L’api concernée par le bug est vite isolée grâce aux outils d'analyse de datadog : il s'agit de celle des réservations de sessions de répétition. Cependant, tous les appels ne semblent pas être impactés... Jean-Sébastien bascule alors sur l’APM de Datadog, qui permet de retracer le chemin réseau complet des appels en erreur. En un coup d’oeil, il apparaît que la source du problème se matérialise non pas sur son application, mais sur un webservice dont elle dépend, qui gère la location d’instruments.
Depuis datadog, il choisit la première exception venue et clique sur le lien le menant vers le détail de l'appel en erreur dans Opserver.
Opserver est un outil développé par l’équipe de StackExchange qui permet d’effectuer du monitoring sur sa production. Chez Lucca, nous l’utilisons notamment pour stocker toutes nos exceptions. Lorsqu’une exception est loggée en production, elle apparaît immédiatement dans opserver ce qui nous permet d’avoir entre autres une stacktrace complète et des informations sur la requête initiale. Cet outil apporte un vrai gain de temps pour les équipes.
En analysant la stacktrace et les paramètres associés, il s’aperçoit que le bug réside dans la partie du code gérant les jours fériés. De plus, il remarque que seuls les clients allemands sont impactés.
Il décide alors de lancer le projet en local afin de reproduire le problème chez l'un des clients impactés : Leipzig Studios. Il a donc besoin des applications suivantes :
Seulement voilà, Jean-Seb ne développe pas les services que son soft consomme... Ils sont sous la responsabilité d'une autre équipe, et il n'a donc pas l'environnement local complet permettant de les exécuter sur sa machine de travail, ni l'envie d'avoir à le maintenir. Il doit donc se tourner vers une version containerisée.
Docker Hub, Harbor ? Que nenni, les applications sont démarrées en une commande grâce à lucca apps
.
L’utilitaire CLI
lucca
permet au développeur d’effectuer de nombreuses tâches sur son environnement de développement. La commandelucca apps
permet de simplifier le lancement des micro-services permettant de faire fonctionner Lucca en local. D’une simple commandelucca apps start [my-service]
, le service demandé est démarré sur un cluster kubernetes préconfiguré sur la machine du développeur par notre équipe IT. La solution est fonctionnelle dès le premier jour d'embauche.
Pour le webservice des jours fériés, en revanche, il va bien falloir débugger pour trouver ce qui cloche : un petit git clone / pull s’impose. En se mettant à jour sur la branche principale, il se rend compte que le serveur plante au démarrage. La dernière mise à jour a en effet introduit de nouvelles clés de config, et son fichier local appsettings.json est maintenant incomplet.
Aller chercher les clés et les valeurs manquantes, une tannée ? Pas chez Lucca. Jean-Sébastien exécute la commande lucca appsettings
, qui génère automatiquement le fichier de configuration pour son environnement de développement. Elle se nourrit d'un fichier template appsettings.json.model
commité, et communique avec un coffre-fort distant pour récupérer des valeurs renseignées par les développeurs lorsqu'ils ont créé les clés de config, pour tous les environnements : production, staging... et dev !
Le dernier élément manquant pour pouvoir tester en local est la base de données. L'approche mono-tenant de Lucca lui impose de récupérer la base de données du client concerné, Leipzig Studios. Il joue alors la commande lucca restore leipzig-studios
, et une progression de téléchargement apparaît en blanc sur noir sur son terminal.
La commande
lucca restore
du CLI lucca permet de télécharger une base anonymisée sur le poste du développeur afin qu’il puisse reproduire un bug. Elle abstrait le problème de localisation géographique de la base (cluster français ? allemands ?), vérifie les droits de l'utilisateur courant, et implémente une traçabilité forte de l'accès aux données client. Chez Lucca, les données clients sont rendues accessibles aux développeurs après une étape obligatoire d'anonymisation effectuée sur nos serveurs. Chaque soft Lucca déclare un script d'anonymisation transformant les données sensibles dont il est responsable. L'outil central qui gère les droits d'accès aux données client attend également une justification pour chaque téléchargement, pour des raisons de traçabilité.
L'application démarre. Entre les outils auxquels il est déjà bien habitué, et un fier coup de main de la fibre pour récupérer la base de données, il s'est passé 5 minutes entre la détection précise de la source du problème et le premier /ping
en local. Place à la reproduction du bug !
En testant, il s’aperçoit au passage qu'une erreur de traduction s'est glissée dans la dernière version du webservice incriminé... il n'est pas là pour ça, mais un commit supplémentaire serait la bienvenue. Il renseigne la bonne valeur dans Lokalise, puis effectue la commande lucca translate
qui intègre directement dans le projet la nouvelle valeur.
Lokalise est un service en ligne permettant de gérer ses traductions. Chaque clé peut être traduite en plusieurs langues par le développeur, PM, et même par Lokalise, qui intègre des solutions de traduction automatique ou des outil de contact avec des traducteurs professionnels. Chez Lucca, les traductions sont commitées. Nous considérons qu'elles font partie de la feature, de l'expérience utilisateur : à ce titre, elles doivent subir les mêmes étapes de validation que n'importe quelle ligne de code, au travers de PRs Slack et de recettes fonctionnelles. Pour faire redescendre les valeurs traduites les plus récentes dans son repo local, une seule commande, exécutée dans le bon répertoire :
lucca translate
.
Après quelques tentatives, le bug est découvert : un simple if
inversé... Comment s'est-il glissé là, celui-là ? La correction est simple, l'écriture d'un test rapide. Jean-Sébastien ouvre une PR... et part se faire un café, car C-3PO prend le relai.
C-3PO, c'est le nom qu'on donne en interne à un bot de vérification des PRs. Il gère entre autres : la validation de la présence de tags sur la PR, la création d'un changelog à partir de ces tags et des descriptions de PRs, la présence d'un message de PM sur la PR assurant qu'une recette fonctionnelle s'est bien passée... et bien sûr, la bonne exécution des tests.
Un coup d'oeil à la recette auto, tout est au vert, il peut transmettre sa PR à son PM, Fred.
Afin d’assurer l’absence de régressions lors des mises en production très fréquentes, Lucca a fait le pari d’une QA hautement automatisable. Les équipes sont responsables et autonomes sur la gestion de leurs tests.
Un peu plus tard, Fred, le sollicite à nouveau : il a pris le temps de recetter la correction.
Chez Lucca, les PMs peuvent créer des instances de preview de nos solutions branchées sur des données de démo, ou lorsque c'est nécessaire sur des données anonymisées d'un client arbitraire. Le PM décide de la ou des PRs dont les branches doivent être déployées, et l'outil complète en déployant le reste de l'écosystème Lucca dans la version qui est en prod.
Fred est satisfait du résultat, seul bémol, il a besoin de connaître la liste des clients impactés pour préparer une communication. Jean-Sébastien a plusieurs solutions pour lui donner cette information, parmi lesquelles s'appuyer sur les logs ; mais comme il sait que le bug se manifeste par l'écriture en base d'un objet incohérent, il préfère aller constater dans la donnée quels clients l'ont subi. Il se connecte donc à Diver.
Diver, c'est encore un outil interne, son but est de permettre l'exécution d'une requête SQL sur toutes les bases de données Lucca et l'agrégation des résultats.
Et voilà, en quelques mouvements, Jean-Sébastien a pu détecter, reproduire, corriger son bug d'une manière harmonieuse. Il ne lui reste plus qu'à reprendre sereinement l'écriture de sa symphonie.