Dans quelles situations faut-il utiliser les options de Clean des pipelines d’Azure DevOps ?

Diverses tâches d’Azure Pipeline disposent d’options de Clean permettant de supprimer les fichiers inutiles (artefacts, binaires des précédentes builds, dossiers bin/obj et...). Ces options sont disponibles sur les tâches de compilations, les tâches de copies de fichiers, et dossiers.

Des développeurs un peu trop zélés auraient tendance à activer ces options à défaut. Malheureusement, celles-ci peuvent augmenter inutilement la durée d’exécution de la build. Il convient donc de prendre un peu de temps pour réfléchir à l’utilité de telles options.

Pour savoir si l’on peut avoir besoin d’utiliser des options de Clean, il convient de répondre à quelques questions simples :

  • Où s’exécutent les builds ?
  • Quel gestionnaire de code source est utilisé ?
  • Les builds utilisent elles les dossiers de binaires en plus du staging des artefacts (BinariesDirectory) ?

L’usage des options de clean est conditionné par la combinaison de vos réponses à ces trois questions.

Voulant faire simple, j’ai choisi de construire un tableau indiquant les situations pour lesquelles, un Clean est utile.

Source control BinariesDirectory
Agent de build Git TFVC Oui Non
Microsoft hosted Non Non Non Non
Self hosted
/ Azure VMs Scale Set
Non Oui Oui Non

Pour résumer simplement les raisons qui ont conduit à apporter ces réponses :

  • Les agents de builds hébergés par Microsoft sont détruits après chaque exécution. Un agent ne conserve donc aucune trace des précédentes builds, contrairement aux VM Azure, et agents que l’on héberge soit même.
  • Avant de télécharger, du code versionné via git, un pipeline lance la commande git clean -ffdx (par défaut). Celle-ci effectue un clean du repository local. Le répertoire contant le code source est donc propre, quoi qu’il arrive (par défaut).
  • Le Workspace TFVC n’est pas nettoyé entre les builds. Il en est de même pour les dossiers des binaires, et des tests uhnitaires.

Conclusion

Aucun mécanisme de Clean n’est nécessaire pour un usage 100% Cloud d’Azure DevOps, sauf si on utilise des VM Azure. Il en est de même pour un usage hybride avec Azure DevOps Server, et des agents Microsoft hosted.

Un usage 100% on-premise demandera donc un peu plus de réflexion.

Jérémy Jeanson

Pourquoi winget affiche parfois des Id étranges ?

Par le passé, j'ai eu à expliquer à des développeurs qu'il ne fallait pas utiliser un Guid pour piloter winget. Car l'Id d’une application peut parfois prendre des formes étranges.

Sachant qu'un bon exemple vaut mieux que de longues explications, voici une petite démo de winget retournant une liste contenant un id hors norme :


PS C:\Users\jeremy> winget list "app"
Nom ID Version
-----------------------------------------------------------
App {A0B1C63D-F1E2-4306-4A58-A8140C917516} 1.0.0.9
App2 a8cf55b6c07a823e 1.0.0.1


Dans le cas présent, la première application a été déployée via un msi, la seconde ClickOnce.

Voici donc la raison pour laquelle il ne faut pas penser que winget n'utilise que des Guid ;)

Jérémy Jeanson

Rendre visibles les classes, et méthodes internes, d'un assembly signé

Dans un précédent article, j'avais présenté la nouvelle manière de rendre accessibles les éléments internes d'un projet pour les tests unitaire. Aujourd'hui, je vous propose d'effectuer la même opération, avec un projet signé. L'approche est très similaire, il suffit d'ajouter l'attribut Key à InternalsVisibleTo. Seul petit problème, la documentation manque légèrement de détails sur la démarche à suivre (comment trouver la clé demandée, et comment la mettre en forme?).

Voici les étapes à suivre :

  1. Signer le projet de test

À ce niveau, la documentation est très bien faite. Si l'on suit la méthode présentée ici, Visual Studio ajoute des nœuds similaires à ceux-ci au projet de tests:


<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\strong-name-key.snk</AssemblyOriginatorKeyFile>

Note : Une bonne habitude pour se simplifier la vie consiste à réutiliser le même fichier snk pour signer l'ensemble des projets. Un seul fichier signifie qu'il n'y a qu'une seule clé à utiliser pour la totalité des projets. Ainsi, il est plus facile de s'y retrouver, et l'opération qui suit n'a besoin d'être effectuée une seule foi.

  1. Obtenir le hash de la clé publique

Après compilation du projet de tests, on peut demander à Visual Studio d'afficher la totalité des fichiers. Il suffit alors de dérouler l'arborescence jusqu'aux dossiers de destination des binaires du projet de tests. Ensuite, un simple click droit sur le répertoire permet d'afficher le menu contextuel suivant. Il reste alors à choisir Open in Terminal.

clip_image002

Via le terminal intégré à Visual Studio, il ne reste plus qu'à utiliser la commande sn en lui fournissant le nom de l'assembly produit par le projet de tests unitaires.


PS C:\xxx\bin\x64\Debug\net8.0> sn -Tp .\MonProjet.Tests.dll
Microsoft (R) .NET Framework Strong Name Utility Version 4.0.30319.0
Copyright (c) Microsoft Corporation. All rights reserved.
Public key (hash algorithm: sha1):
xxx1
xxx2
xxx3
xxx4
xxx5
Public key token is yyy

La clé qui nous intéresse se trouve derrière Public key (hash algorithm: sha1).

  1. Utiliser le hash de la clé publique

La clé récupérée via la précédente étape peut alors être utilisée pour renseigner l'attribut Key de InternalVisibleTo qui se trouve dans le projet à tester. La clé doit être retranscrite sans saut de ligne.


<ItemGroup>
<InternalsVisibleTo Include="$(AssemblyName).Tests" Key="xxx1xxx2xxx3xxx4xxx5" />
</ItemGroup>

Conclusion

Simple, et efficace. Par contre, il ne s'agit pas du genre d'opération que l'on a envie de faire chaque matin. D'où mon précédent conseil d'utiliser le même fichier snk pour signer l'ensemble des projets d'une même solution.

Jérémy Jeanson

Comment remplacer simplement asp-append-version avec Blazor, et .net 8 ?

La migration vers .net 8 et Blazor Web App passe par la suppression des Tag Helpers d’ASP .net. De ce fait, le Tag asp-append-version n’est plus utilisable.

Il existe bien évidement des solutions pour réintroduire celui-ci. Mais veut-on réintroduire des méthodes qui n’ont pas vocation à fonctionner avec Blazor. Personnellement, ma réponse est non.

Le travail effectué par asp-append-version est très simple. Il consiste à ajouter à l’URL du fichier le hash de ce même fichier. De ce fait, l’URL du fichier change après chaque modification du fichier. Ceci force le navigateur à télécharger le fichier, et permet d’éviter les problèmes de mise en cache de ces fichiers.

En soi, rien de bien compliqué. On peut donc créer une méthode qui se chargera de retourner une URL incluant le hash du fichier.

Mais avec Blazor, la plupart des fichiers sont gérés automatiquement par le framework. Nous avons donc très peu de fichiers ajoutés manuellement, et devant avoir besoin de asp-append-version. Le besoin étant plus limité, il est donc possible de faire encore plus simple.

Si l’utilisateur télécharge un ou deux fichiers js / css après chaque mise à jour, ce n’est pas grave. On peut donc s’appuyer sur le hash de l’application pour générer nos URL.

Ce qui est possible avec un code aussi simple que celui-ci :


<link href="css/common.css@(AppendHashCode)" rel="stylesheet" />
<script src="js/common.js@(AppendHashCode)"></script>

@code{
    private String AppendHashCode = "?v=" + System.Reflection.Assembly.GetExecutingAssembly().GetHashCode();
}

Simple, efficace, et sans réinventer la roue.

Jérémy Jeanson

Comment utiliser Wix toolset, et les actions custom pour afficher une boite de dialogue ?

Vous venez de coder l’action cutom du siècle avec C#, et wix toolset. Seulement, vous savez qu’il y a un cas qui provoquera une erreur bloquant le déploiement. Dans une telle situation, il serait bon d’afficher une boite de dialogue dérivant le problème rencontré.

Ne cherchez pas à utiliser une méthode tirée de WinForm, WPF, ou une autre solution tirée de Win32. Cela ne fonctionnera pas comme vous le désirez.

À la place, il convient d’utiliser les méthodes fournies par l’objet Session. Celui-ci dispose d’une méthode Message qui permet d’envoyer à msiexec les informations à afficher.

Voici un petit exemple :


public static void MessageError(Session session, String message)
{
   session.Message(InstallMessage.Error, new Record { FormatString = message });
}

Simple et efficace. Malheureusement cela n’est pas bien documenté du côté de wix toolset :(

Jérémy Jeanson