Accueil Nos publications Blog Stratégie de déploiement continu des packages avec Azure Artifacts

Stratégie de déploiement continu des packages avec Azure Artifacts

Avec entre autres l’essor de la pratique DevOps et de l’approche micro-services, il est devenu courant d’avoir recours aux packages pour partager des bibliothèques de classes entre plusieurs applications.

Dans le monde des technologies Microsoft, si il est maintenant assez simple de mettre en place un package et de le déployer grâce à Azure DevOps, mettre en place une stratégie de développement et de déploiement continue efficace et pérenne demande un peu plus de réflexion.

Je vous propose dans cet article d’implémenter une stratégie de déploiement continue des packages, en utilisant un modèle de branching et de versioning avec la CI/CD Azure DevOps.

Qu’est-ce qu’Azure Artifacts ?

Azure Artifacts est un service Azure, organisé en “Feeds” qui contient des packages. Un feed peut être public ou privé avec authentification, il peut contenir tout type de package : NuGet, npm, Maven, PyPi mais aussi des “Universal Packages” (un ensemble de fichiers labellisé avec un numéro de version).

Il permet aussi de créer des “Views”, qui sont des sous ensemble d’un feed sur lequel on peut appliquer des droits d’accès spécifiques. Par défaut, les vues “Local”, “Prerelease” et “Release” sont créées.
[…]

Dans cet article, je vais prendre pour exemple les packages NuGet avec .NET Core 3.0.

Porter un message à travers la CI/CD

En tant qu’éditeur de package, nous avons des devoirs envers nos consommateurs :

  • communiquer la nature du changement
  • communiquer la qualité du changement
  • garantir un package valide en version finale

Pour ça, nous pouvons nous appuyer sur des outils : le versioning des packages, la validation du code via les pull requests, et l’utilisation des View d’Azure Artifcats.

Versioning des packages

Utiliser une bonne nomenclature de numéro de version lors qu’on publie des package est important puisqu’il est exposé et visible. Il peut être à lui tout seul une source d’information sur la maturité du package par exemple, ou encore la nature des changements apportés par la version.

Microsoft tout comme NPM suggère de se conformer à la spécification Semantic Versioning (SemVer)
Cette spécification propose d’utiliser le format : MAJOR.MINOR.PATCH, avec possibilité d’ajouter des informations en extension (numéro de build, suffixe de pré-release, méta-données, etc.).

Major.Minor.Patch représente la nature du changement :

  • Major représente un “breaking change” par rapport à la version précédente
  • Minor représente un changement rétro-compatible
  • Patch représente une résolution de bug rétro-compatible

L’extension peut véhiculer la qualité du changement via un tag de pré-release par exemple : 

Suivre cette spécification pose la question de savoir quand et comment ce numéro sera appliqué.
La problématique à mon sens est que le risque du changement est connu par la·le développeur·euse, alors que les métadonnées et l’application du numéro de version se fait au moment de la conception du package par la CI.
Une autre problématique à prendre en compte, est l’immutabilité des packages NuGet : un numéro de version attribué une fois est réservé de manière permanente.

Stratégie de gestion des branches

Plusieurs stratégies de gestion des branches avec Git existent, vous devez avoir sûrement entendu parler de GitFlow, GitHubFlow, les avoir déjà utilisées ou avoir utilisé une adaptation de ces stratégies.

Dans cet article, je vais démontrer le principe sur une version de GitHubFlow simple : on utilise une branche master qui est à l’image de la production et des branches de feature.
Pour développer une fonctionnalité, on tire une branche de feature, une fois la feature terminée, on créé une pull request pour l’intégrer à master.

Donner à Git la responsabilité du versioning

Je propose d’utiliser SemVer, avec un tag de pré-release qui renseignerait sur la qualité du package, ex : 1.5.2-alpha.4 pour une version non mature, et 1.5.2 pour la version finale.
Avant la version finale, on utilise un suffixe unique, dans le but de pouvoir publier plusieurs fois le package en respectant la notion d’immutabilité.

Dans l’idée, on gèrerait :

  • Les modifications du numéro de version via les commits effectués
  • La tag directement avec la CI : au moment de la Pull Request

Ces fonctionnalités n’étant pas supportées de base par Azure DevOps, nous allons utiliser GitVersion.
Cet outil permet de mettre en place SemVer en se basant sur l’historique Git.

Mise en place

Installation des extensions

Premièrement, nous allons commencer par installer nos prérequis : “GitVersion” et “Promote package to view” dont on parlera plus tard.
Ils sont disponibles tous les deux en tant qu’extensions de Azure DevOps sur la marketplace : c’est selon moi le moyen le plus simple de les rendre disponibles pour l’utilisation dans la CI/CD Azure.

GitVersion extension marketplace

Configuration de GitVersion

  • Configuration du fichier GitVersion.yml

Construction du pipeline

  • Mise en place des triggers PR et CI
  • Tâche GitVersion
  • Donet restore et build
  • Création du package NuGet
  • Publication des artéfacts

Modification du repository

  • Protection de la branche master avec ajout du build à la PR

Création de la release

  • Ajout des 3 stages : local, pre-release et release
  • Configuration nuget push en local
  • Configuration promote package to view pour pre-release et release

Utilisation

  • Création de la Pull Request
  • Téléchargement du package -alpha
  • Intégration à master
  • Téléchargement du package final