Jenkins, sers-moi donc un Chtijug !

Nicolas Géraud était venu nous parler des pipelines il y déja deux ans.Est-ce que cette présentation allait être mieux ? En tout cas, elle est bien différente.

Petit point sponsoring de l’IUT sur la taxe d’apprentissage : les entreprises peuvent déclarer des organismes de formation bénéficiaires de leur taxe d’apprentissage. Ca peut avoir une influence sur le budget de ces organismes.

Et c’est parti !

Avec d’abord un petit sondage :

  • qui connait Jenkins ? A main levée, tout le monde dans la salle.
  • qui a déja migré vers Jenkins 2 ? Encore à main levée, pas grand monde.

Jenkins 2

Donc Jenkins 2 … est totalement compatible avec Jenkins 1. Et c’est bien, parce que la montée de version va être simple. Dans l’ensemble, les plugins sont compatibles.

Avec Jenkins 2, il y a aussi de nouveaux sites

  • http://jenkins.io qui est bien plus grand public
  • le project Voltron sert de plugin store avec une chouette présentation. Limite comme le google play store, en fait.

Il y a maintenant au premier démarrage un mot de passe à aller chercher dans les logs de la machine. Ca va permettre de sécuriser le serveur Jenkins avec un admin par défaut. Evidement, on peut toujours avoir un Jenkins non sécurisé, mais il faut le vouloir. Ce qui change pas mal de Jenkins 1 qui, par défaut, n’était pas sécurisé. En bonus, une liste de plugins par défaut est disponible, pour faire une première personnalisation de Jenkins.

Et ensuite, on arrive aux fameux pipeline-as-code.

Pipeline as code

Un job est défini par un Jenkinsfile, écrit dans un DSL Groovy, qu’on peut stocker dans son SCM. L’avantage, c’est aussi de permettre d’utiliser les structures de contrôle de Groovy pour personnaliser le job.

Et ensuite

Il y a tout un tas de nouveaux trucs qui ne vont pas tarder à arriver

BlueOcean (déja disponible en pas beta, mais pas release non plus)

La fameuse nouvelle interface graphique pour Jenkins. Les captures sont très chouettes !

Franchement, l’affichage des pipelines est très chouette. Si j’avais eu ça chez Perigee, j’aurais pu montrer un vraiment très beau pipeline. Le plus incroyable, c’est quand même de pouvoir faire « pousser » un pipeline graphiquement. Il faut voir l’écran pour le croire, je trouve.

Pipeline déclaratif

En bonus, ça permet à des non-développeurs de modifier le build, ce qui n’est pas une si mauvaise idée, puisque le code exécuté est toujours en SCM. En fait, le pipeline généré n’est pas exactement identique à celui qu’un développeur écrirait : c’est un pipeline déclaratif.

D’une façon amusante, le speaker décrit la syntaxe d’un DSL Groovy comme « à mi-chemin entre YAML et Groovy ». Guillaume Laforge et tous ses amis pleurent des larmes de sang en entendant ça. Parce que quand on regarde un DSL Groovy, comme par exemple le MarkupBuilder, on est exactement dans la syntaxe visible à l’écran. Bon, je ne vais pas en vouloir au speaker : il connaît sans doute mieux Jenkins que je connais Groovy.

Back-end storage

Manifestement, l’objectif est de découpler le fonctionnement de Jenkins et le stockage des configurations d’exécution et des résultats. C’est une chouette idée, mais pas vraiment assistée par les capacités des plugins à écrire eux-mêmes des fichiers.

Donc Jenkins 2, c’est ?

Jenkins 2, c’est mieux, et orienté sur le continuous delivery. Et pas le continuous deployment. Autrement dit, l’équipe de cloudbees ne vise pas trop à utiliser Jenkins pour le déploiement en prod.

Quelques questions

Si les pipelines sont déclaratifs, comme maven ou gradle, pourquoi ne pas réutiliser leur outillage ?

Jenkins est utilisé pour faire le delivery, ce que ne font pas ces outils. En un sens, je comprend cette réponse : le scope fonctionnel est différent, et ce serait assez curieux de dire « on peut faire du gradle pour le déploiement ». Et puis, Cloudbees et Gradle inc ne vont pas fusionner demain.

Mais quand même, en transformant les jobs en bouts de code, je trouve que Cloudbees fait rentrer Jenkins dans une espace de continuum de build qui va de mon poste jusqu’aux artefacts déployables en prod.

Comment se compare l’API de pipeline-as-code et de job-dsl ?

L’inspiration initiale de pipeline-as-code était buildflow, mais ça a vite divergé.

Et la démo

  • Premier truc cool : les plugins installés sont toujours installés à la dernière version.
  • Deuxième truc cool : BlueOcean est déjà disponible comme plugin, et donc installable.
  • Troisième truc cool : le travail d’administrateur Jenkins s’arrête, pour les jobs, à créer les jobs et les connecter à des SCM. Tout le reste vient du Jenkinsfile.

Et donc, on passe à la création du Jenkinsfile. Et là, la structure des DSL Groovy réapparaît vraiment, et c’est bien.

  • Quatrième truc cool : les commandes checkout de SCM utilisent la révision du Jenkinsfilecomme référence. Par conséquent, l’enchaînement d’étapes se passera beaucoup mieux que dans Jenkins 1, puisqu’il n’y aura pas de révision à passer. Par contre, curieusement, le DSL ne semble pas contenir de commande maven, puisque notre speaker exécute les commandes maven via un sh "mvn clean package". Arf … apparement, le plugin exécutant maven est « mauvais ».
  • Cinquième truc cool : l’interface de Jenkins inclut un générateurs de snippets façon vieux wizards qui permet d’apprendre très rapidement le DSL des pipelines.
  • Sixième truc cool : l’affichage des pipelines en cours est vraiment très sympa, avec des logs par noeud du pipeline affichés en temps réel.
  • Septième truc cool : le DSL inclut une notion de stashes, valable uniquement pour la durée du pipeline, qui permet donc de ne pas déployer dans Nexus les artefacts temporaires.
  • Premier truc pas cool : le pipeline est toujours exécuté sur le master. Du coup, la montée en charge pourrait mal se passer.
  • Huitième truc cool : pour les pipelines déclaratifs, il est possible de demander à Jenkins d’analyser la syntaxe.
  • Deuxième truc pas cool : on peut relancer un pipeline à partir d’une étape uniquement dans la version commerciale de Jenkins. C’est moins bien … mais je comprend tout à fait.
  • Neuvième truc cool : il est possible de créer des morceaux de code partagés entre pipelines.
  • Dixième truc cool : les milestones permettent d’éviter de lancer plusieurs builds concurrents sur une ressource critique.

Et si vous voulez voir le Jenkinsfile utilisé pour ce live-coding, il est disponible sur github.

D’autres questions

Comment tester un pipeline ?

Eh bien, on ne peut pas : il faut le lancer dans une instance de Jenkins. Autrement dit, c’est le genre de truc où il faut une instance de test de Jenkins. Et mon collègue me souffle à l’oreille qu’on peut très bien utiliser l’annotation @StaticCompile de Groovy pour vérifier la syntaxe autant que possible (parce que @StaticCompile, sur un DSL, il doit bien s’amuser, tiens).

Conclusion

J’ai quand même hâte de voir les projets passer au moins aux pipelines as code, histoire d’avoir dans mon SCM, à côté de mon pom.xml, le Jenkinsfile qui va bien. Et histoire aussi d’ajouter un peu de Groovy dans tout ça !

Publicités

#devoxxfr – Infra as Code, choisissez vous la pilule rouge ou la pilule bleue ?

Après cette blockchain en délire, revenons à du concret avec l’infra as code.

Mais qu’est-ce que l’infra as code ? c’est surtout le moyen de sortir une copie complète de l’infra sans péter la prod actuelle.
En théorie, ça doit permettre d’aller plus vite. En pratique, c’est plus de code, donc il faut le maintenir sinon il ne fait pas gagner de temps.

Donc on peut très bien tenter de faire vivre l’existant avec des bouts de ficelle et des scripts bash, ou on peut tenter de prendre conscience que l’infra as code, ça reste du code, et il faut s’en occuper comme du code.

Donc pour réduire la boucle de feedback lorsqu’on monte une infra, on isole pour débugger plus vite. Avec des outils comme

  • Vagrant
  • Docker

Et on va faire du feature filpping pour éviter les besoins de prod en dév.

Evidement, avec ces outils, on essaye toujours de se contenter de déclarer l’état désiré plutôt que le mode de transition. Donc pas d’ajout manuel dans le /etc/hosts, par exemple. Et pas non plus à grands coups de grep qui ne seront jamais suffisants.

Vient ensuite la super analogie de l’ascenseur : ne déclarer que l’état désiré. C’est ce qui permet l’idempotence. Idempotence qui est vraiment bien pratique pour rendre des configurations reproductibles.

Pour chaque profil de dév, il y a des outils qui vont permettre de les faire bosser mieux et plus vite. Je vous laisse regarder les détails et la vidéo, mais ça met bien face à chaque profil l’outil approprié.

L’un des meilleurs outils pour la prod est Gitlab/Github, parce que si on y met l’infra as code, ça permet aux développeurs de le lire et de comprendre comment marche la prod.

La dette technique peut également apparaître dans l’infra as code comme dans le code, et doit être gérée comme dans le code, c’est-à-dire comme à Tetris : si on ne veut pas s’y noyer, il faut éliminer les blocs dès qu’on peut.

Et l’un des endroits clé, c’est le bash, pour lequel il y a aussi des bonnes pratiques : interdire les unset, arrêter le script quand une commande échoue. Et comme dans le code, les caractères sont gratuits, donc priviliégiez les flags avec des noms longs.

Pour aller en prod sereinement

D’abord il faut savoir ce qu’il y a en prod … en loggant les résultats de chaque install en prod. Parce que la prod est faite du code de déploiement ET de l’état actuel de la prod … qui ne sera visible que dans les logs.

Ensuite, pour garantir la prédictibilité du déploiement, il vaut mieux enlever tous les sleeps du script de déploiement et les remplacer (quelque soit l’outil) par des tests de démarrage des services.

Et puis ne mettez pas tous vos scripts directement dans Jenkins, testez-les d’abord en ligne de commande avant de les mettre dans Jenkins, pour pouvoir versionner ce script d’une part, et pouvoir l’utiliser même quand jenkins est down ensuite.

Pour tester son environnement, on utilise les mêmes méthodes que les dévs (oui oui, on parle bien de pyramide des tests et de TDD). Malheureusement, il n’y a de l’outillage de test unitaire que dans chef et puppet. Là, il s’agira vraiment de tester le script chef/puppet et pas le code applicatif. Pour le test d’intégration, on peut très bien tout piloter dans Jenkins en quatre étapes d’un build.

Cinq ans d’ALM, putain !

Encore une suite à cinq ans, putain !

Oui, je mets le terme ALM à toutes les sauces, parce que c’est mon bon plaisir.

Donc, sur ce gros projet, j’ai fait ce qu’on pourrait de l’ALM. Qu’est-ce que je mets sous ce terme ?

L’ensemble des tâches qui permettent de passer du code au produit.

Ca inclut, de façon non exhaustive

  • Les outils de build
  • Les outils d’intégration continue
  • L’intégration entre ces outils et les outils de suivi de bugs.

Et évidement, je vais vous (re)parler de Tuleap.

Mais avant, je vais reprendre les étages un par un

Compiling !

Aimablement fourni par http://xkcd.com/303/ mais vous vous en doutiez, non ?

Quand on a commencé notre projet, j’avais déja touché du build maven multi-module. Maias je n’imaginais pas que j’en ferais autant, puisque notre build intègre maintenant

  • De la compilation flex avec flexmojos (raisonnablement facile)
  • De la compilation C++ … et selon la plateforme, cette compilation utilise soit Visual Studio, soit XCode … alors ne me parlez pas de maven-nar-plugin, parce qu’il est notoirement insuffisant pour nos besoins.
  • Du packaging sous d’innombrables formes (war, ear, zxp, …)

Qu’est-ce que ça m’a appris ?

It’s alive

Que la vraie force de maven n’est pas la création d’un format de dépendance universellement utilisé.

Je veux dire, c’est vrai que c’est pratique, ces dépendances, mais quand on arrive à du build « d’entreprise », c’est-à-dire moche et farci de profils, la vraie force de maven, ça n’est pas ça. Non.

La vraie force de maven, c’est de définir un cycle de vie universel. Parce que ce cycle de vie permet, quelquesoit le type de projet, le langage utilisé, ou quelque concept que ce soit, de positionner les différentes opérations dans un tout cohérent. Ca n’a l’air de rien, comme ça, mais c’est réellement indispensable pour les gens qui s’occupent de faire un packaging réaliste. Parce que je sais, quand j’en arrive à la phase « packaging », que tout mon code est compilé, testé, que les ressources ont été traité.

Franchement, quand je regarde les alternatives à maven, je me dis qu’ils n’ont rien compris : ne pas reprendre ce cycle de vie, c’est juste irresponsable maintenant.

Groovy, baby

Alors évidement, vous me direz qu’écrire un plugin maven pour les cas non standard, c’est l’enfer. Et c’est vrai.

Heureusement, j’ai également découvert une gradation dans la personnalisation que j’applique de façon systématique (vous savez, pour tous ces trucs foireux – comme par exemple construire un fiochier de config requirejs à partir de dépendances Javascript) :

  1. Je trouve un plugin maven qui convient ? C’est la fête
  2. Je trouve un ensemble de tâche ANT qui colle ? Cool
  3. Je peux écrire un script groovy avec gmaven ? Bien (dans ce cas-là, n’écrivez pas le script dans le build, mais mettez-le dans un dossier clairement séparé, par exemple src/build/gmaven)
  4. Aucun des trois n’est suffisant ? Alors il est temps d’écrire un plugin maven.

Avec ça, rien n’est impossible dans un build.

Et notez que je ne suis passé du point 3 au point 4 que dans deux cas. Et dans les deux cas, c’est parce que je devais en fait écrire un plugin avec cycle de vie complet. Dans tous les autres cas, groovy a été suffisant, et je dirais même fun.

Non mais tout ce XML, quand même …

Tout ce XML de maven ? A priori, on le regardait sous tes les angles dans m2e quand on ajoutait un nouveau type de build, et après, il n’y avait plus vraiment besoin d’intervenir dessus. Alors dire que c’est pénible, faut pas déconner. Le pire, en fait,a vec maven, c’est qu’Eclipse ne différencie pas les scopes des dépendances. Heureusement pour nous, Jenkins compilait en-dehors de tout IDE.

Make me a sandwich

Et encore, on n’a pas besoin de sudoer Jenkins

Ben oui, Jenkins, le gagnant de la grande guerre du fork.

Lui aussi, on l’a bien tanné.

Justement à cause de notre build natif multi-plateforme. Parce que si on compile une partie de notre application selon la plateforme, on fait comment pour avoir les artefacts dans un build commun ?

Eh bien on se fait un profil spécial Jenkins, dans lequel le build maven est découpé en parties multi-plateformes et dépendant de la palteforme, et on joue du build matrix plugin pour que tout compile et se package sans problème.

Et ça marche, mpême si c’est pas très facile.

Ca chauffe !

A vrai dire, le plus grand échec a été l’implication de l’équipe : même avec un bon radiateur, personne (sauf la testeuse en chef – que toujours elle marche sur un chemin de roses fraîchement coupées) ne s’y est jamais vraiment intéressé. Et ça, c’est triste.

Parce que ça veut dire que cette histoire d’intégration continue n’a été qu’une lubie de ma part, et que je n’ai pas réussi à en communiquer la valeur pour l’équipe, le projet, le produit.

Là-dessus, je peux dire que je retiens la leçon, et que je ferais en sorte que les builds en échec ne puissent plus être ignorés.

Tester c’est douter

Cela dit, tout n’est pas si sombre, puisque le projet a quand même une bonne partie de son code testé, et que TDD a été utilisé dans la plupart des acceptations du terme. La meilleure, et la plus efficace étant qu’aucun bug ne devait être marqué corrigé sans qu’un test ait été ajouté spécifiquement. Parce que

ce qui a foiré foirera

Ca a l’air con dit comme ça, mais ça c’est vérifié à chaque fois : les parties de code ayant connu un bug en ont toujours connu plus, et plus encore.

Heureusement qu’il n’y avait pas d’exploitation statistique des liens entre code et bugs pour vérifier ça, sinon c’aurait été l’enfer.

Et mylyn ? Et Tuleap ?

Là, par contre, l’échec est patent.

Plus encore quand je regarde ce que j’ai pu faire avec gaedo où, là, chaque bug est corrigé à travers un commentaire de commit.

Imaginez que le seul lien dont on ait pu dispoiser était, éventuellement, un lien HTTP dans un commentaire de commit référençant un bug. Comme ça, par exemple :

http://mantis/bugs/view.php?id=7137
the error was stupid : I did not add children to parents when they were needed

ca, c’est moi qui l’ait écrit aujourd’hui.

Ce qui est bizarre, c’est que j’avais parlé de mylyn, de Tuleap, et qu’un autre collègue avait parlé de svn commit hooks … mais aucune de ces tentatives n’a pris. Et pour des raisons diverses … La pire étant celle qui nous a empêché d’utiliser Tuleap : « j’ai pas vraiment eu le temps de regarder ». je dois dire que ça, ça m’a tué.

Alors, content ?

En fait, la plupart des choses installées vont continuer à fonctionner … jusqu’à ce qu’on les arrête.

En revanche, je reste convaincu de l’intérêt de ces outils, et je n’hésiterai pas à pousser leur adoption la prochaine fois.