C'est quoi une version ?
Je vais faire quelque chose de très basique et qui ne sera probablement pas appliqué tel quel dans un cas plus professionnel. D’ailleurs, chacun ayant ses méthodes de travail, ce post reste un example de « comment on pourrait faire » pour versionner une app.
C’est quoi une version ?
La encore, je suis pas sûr que tout le monde utilise la même façon de versionner.
Par exemple les versions du navigateur Firefox utilise simplement un chiffre (https://blog.mozfr.org/pages/Calendrier-versions-Firefox). Mais si on regarde de plus prêt on a quand meme 98.0.1 et donc des points de séparations.
En fait, Pour le grand public on va utiliser « Firefox 98 ». Mais il faut savoir qu’il existe de nombreuses versions de la 98 ! Du moins en interne. Avant de livrer une version patché 98.0.1 qui va corrigé des bugs mineures.
D’après ce que j’ai pu voir, on utilise principalement ce style de nommage de version X.Y.Z
- X : Version Majeure (non rétro compatible) (nouvelles fonctionalités, gros correctif, ajout de techno, changement de look…)
- Y : Version Mineure (rétro compatible) (correctifs, patchs, en gros pas de grosse modif, mais qui répare)
- Z : Révisions. (rétro compatible) Sert plutot au dev et product owner pour savoir de quelle version on parle en pre prod pour basculer vers la prod. Quelque part, ce dernier numéro ne devrait à mon sens pas être communiqué officiellement (un peu comme Firefox qq part)
Sur la version X, on a je pense tous la même idée. On sort une version X rarement. Par contre, je suis pas certain qu’on utilise tous Y et Z de la même manière. Franchement, c’est freestyle, dans les versions mineures on peut voir de nouvelles (petites) fonctionalités. C’est vraiment selon vos préférences et ceux avec qui vous bosser.
Pour le coté retro compatible, c’est ce que j’ai lu sur le net. Intéressant mais pas du tout respecté par tous.
Autre style, voici un format intéressant ou l’on cumule en plus une date :
V 2020.10.23.1629
Je trouve ce format particulièrement intéressant car on sait tout de suite de quand date la version. Mais ca fait bcp de chiffre.
Ce format est utilisé par Larsen Lance avec un scipt powershell qui « incrémente » ce format à chaque build en automatique (http://www.lancelarsen.com/blazor-tips-n-tricks-auto-increment-your-version-tag-with-powershell/)
Pourquoi versionner ?
La version d’une app sert tout simplement de référenciel. De quoi on parle ? De la version 1.12.665 ou ya un bug qui est corrigé dans la V1.13.005. C’est quand même plus pratique.
Le product owner sera aussi attentif à ces versions concernant l’ajout de nouvelles fonctionalités et communiquer dessus.
Ca permet de prévoir une roadmap large et dire par exemple, cette fonctionalité sera attendu pour la V2.3, pas avant. En parlant de roadmap, je cite souvent Star Citizen qui est un jeux vidéo en béta depuis des années, et qui affiche ses avancés https://robertsspaceindustries.com/roadmap/release-view
Il fixe des objectifs par trimestres sous forme de version avec une majeure et une mineure. C’est clair. Mais bon il sort quand ce jeu !!!! C’est une alpha. Et certain ajoute ce terme dans la version.
Alpha, Beta, Rc (Release Candidate), Nightly Build… On peut préciser le contexte de la version.
Versionner une app .net Core avec une Pipeline automatique
Tout l’enjeu de cet article. Comment je peux modifier ma pipeline pour inclure un nouveau numéro de build par exemple à ma version et l’afficher en prod. (comme sur Firefox dans la rubrique aide ou a propos) ?
Afficher la version dans l'app
Pour que l’on voit directement la version dans mon app Blazor, je vais carrément l’afficher en haut a droite :
Une page about avec ce numéro aurait été plus propre sur une vraie App. L’idée ici c’est de l’avoir en permanence sous les yeux.
Pour cela on va modifier MainLayout.razor comme ceci
La ligne importante est celle ci :
Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
La version par défaut qui s’affiche est 1.0.0. Si vous faites (sous Visual Studio) un clic droit sur le projet client de Blazor, puis propriété et enfin dans la section Package vous verrez ce numéro. Par contre il n’est pas modifiable.
Pour le modifier, il suffit de rajouter dans le .csproj une ligne version. Easy.
Bingo
YAML comment gérer une version
Je veux une version sous cette forme yyyy.mm.dd.xx, donc date + un numéro auto incrémenté.
On commence par ajouter un compteur à une variable. Ce compteur sera automatiquement incrémenté à chaque execution de la pipeline.
revision: $[counter(format('{0:dd}', pipeline.startTime), 1)]
Pour s’en assurer, on va afficher la valeur de notre variable :
#display value
- script: echo $(revision)
displayName: 'revision display'
Executez plusieurs fois votre pipeline et aller voir ce que ça donne. Par exemple chez moi :
J’en suis à mon 24ième run.
Il me faut aussi une date du jour. pour cela on va aussi utiliser une variable dateToday ainsi qu’une derniere variable »versionString » qui va concaténer ces deux dernières. (1 h pour trouver comment faire… le ‘>’ magique). Ce qui donne :
dateToday: 'Will be set dynamically'
revision: $[counter(format('{0:dd}', pipeline.startTime), 1)]
versionString: >
$(dateToday).$(revision)
Il suffit à présent de générer dateToday. On va utiliser un script PowerShell (pompé et adapté sur ce site)
#Preparing Build Number
- task: PowerShell@2
displayName: 'Preparing Build Number'
inputs:
targetType: 'inline'
script: |
$currentDate = $(Get-Date)
$year = $currentDate.Year
$month = $currentDate.Month
$day = $currentDate.Day
Write-Host $currentDate
Write-Host $day
Write-Host $env:revision
Write-Host "##vso[task.setvariable variable=dateToday]$year.$month.$day"
On vérifie les données :
#display value
- script: echo $(revision)
displayName: 'revision display'
- script: echo $(dateToday)
displayName: 'dateToday display'
- script: echo $(versionString)
displayName: 'versionString display'
Normalement on a ce résulat :
2022.3.21.29, version numéro 29 faite le 3 mars 2022, elle est pas belle la vie ?
Publication avec la version
J’ai légérement adapté mon script de publication qui était anciennement ceci :
# Publish Blazor Demo Server
- script: dotnet publish --configuration $(buildConfiguration) src/BlazorDemo/BlazorDemo/Server/BlazorDemo.Server.csproj
displayName: 'dotnet publish $(buildConfiguration)'
Remplacé par :
# Publish Blazor Demo Server
- task: DotNetCoreCLI@2
displayName: Publish
inputs:
command: publish
publishWebProjects: false
projects: '$(projectBlazorWasmServer)'
arguments: '--configuration $(buildConfiguration) --output $(build.artifactstagingdirectory) /p:Version=$(versionString)'
zipAfterPublish: false
modifyOutputPath: false
Quelques explications :
Au lieu de passer par un script (possible aussi je pense) je passe par une task « DotNetCoreCLI@2 » qui prend en charge quelques paramètres :
- publishWebProjects: obligatoire avec la commande publish. A false car je n’ai qu’un projet.
- projects: le path de mon projet (je pouvais en mettre plusieurs)
- arguments: j’y ai ajouté un path d’Artifact et surtout la version !
- zipAfterPublish: à false, sinon le résultat final sera un zip et c’est pas ce que je veux.modifyOutputPath: à false aussi, sinon il me place le résultat dans un folder « server »
Le reste du code copie le résulat sur mon serveur en prod, via SSH. Il ne reste plus qu’à aller voir en prod :
Ma version s’affiche, c’est cool !
C’est une PWA donc ya du cache, pour le voir, faut appuyer sur le bouton « Clear site data » dans Application/Storage après un F12, et rafraichir votre page.
La prochaine fois on verra comment inclure un element du fichier de config et voir pour changer les ports des apps .net pour avoir une version dev (staging, recette, preprod) et une version prod.
Fichier YAML complet :
# ASP.NET Core
# Build and test ASP.NET Core projects targeting .NET Core.
# Add steps that run tests, create a NuGet package, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core
trigger:
- master
pool:
vmImage: ubuntu-latest
variables:
projectBlazorWasmServer: 'src/BlazorDemo/BlazorDemo/Server/BlazorDemo.Server.csproj'
buildConfiguration: 'Release'
dateToday: 'Will be set dynamically'
revision: $[counter(format('{0:dd}', pipeline.startTime), 1)]
versionString: >
$(dateToday).$(revision)
steps:
#Preparing Build Number
- task: PowerShell@2
displayName: 'Preparing Build Number'
inputs:
targetType: 'inline'
script: |
$currentDate = $(Get-Date)
$year = $currentDate.Year
$month = $currentDate.Month
$day = $currentDate.Day
Write-Host $currentDate
Write-Host $day
Write-Host $env:revision
Write-Host "##vso[task.setvariable variable=dateToday]$year.$month.$day"
#display value
- script: echo $(revision)
displayName: 'revision display'
- script: echo $(dateToday)
displayName: 'dateToday display'
- script: echo $(versionString)
displayName: 'versionString display'
# Publish Blazor Demo Server
- task: DotNetCoreCLI@2
displayName: Publish
inputs:
command: publish
publishWebProjects: false
projects: '$(projectBlazorWasmServer)'
arguments: '--configuration $(buildConfiguration) --output $(build.artifactstagingdirectory) /p:Version=$(versionString)'
zipAfterPublish: false
modifyOutputPath: false
# Copy files over SSH
- task: CopyFilesOverSSH@0
inputs:
sshEndpoint: 'SSH to Ikoula'
sourceFolder: $(build.artifactstagingdirectory)
#contents: '**'
targetFolder: '/var/www/dev.blazordemo.reactor.fr'
cleanTargetFolder: true
#overwrite: true # Optional
#failOnEmptySource: false # Optional
#flattenFolders: false # Optional