Azure Dev Ops Pipelines: différencier vos builds

Azure Dev Ops Pipelines: différencier vos builds

Il est très courant d’utiliser le même script de build pour les builds lancée automatiquement par les Pull Request (PR) et les builds lancé par l’intégration continue (aussi appelé Continuous Intregration : CI).

Cependant même si ces deux builds sont très proche, leurs besoins ne sont pas exactement les mêmes.

Dans cet article nous verrons :

  • quelles sont les différences entre ces deux builds
  • comment utiliser le même script YAML pour ces deux builds et désactiver les « steps » non nécessaire à nos builds.

La problématique

Les étapes d’une Build de PR

Quelles sont les étapes usuelle d’une build lancée sur chaque Pull Requests :

  • Choix du SDK .NET Core : c’est une bonne pratique de spécifier au compilateur quel version du SDK utiliser pour avoir exactement le même comportement que votre machine global.json
  • dotnet restore : avant de compiler notre application il faut restaurer les packages nuget
  • dotnet build : l’étape la plus importante la build de votre application elle même
  • dotnet test: cette étape lance les tests de votre application. Généralement dans mes programmes je sépare le sépare en 2 étapes tests unitaires des tests d’intégration. Valider les tests sur sur chaque PR permet de détecter au plus tôt quand l’évolution de votre code base casse un fonctionnement attendu.

Les étapes d’une build de CI

  • Choix du SDK .NET Core
  • dotnet restore
  • dotnet build
  • dotnet publish : crée les binaires dans une dossier spécifique
  • publish artefact : publie les artefacts (les binaires) pour qu’ils puissent être utilisé par une tache de release

La Build PR a donc une étape supplémentaire à la build de CI l’étape de l’exécution des tests.
Cette étape n’est pas nécessaire lors de la CI car elle a déjà été faite par la PullRequest rejouer les tests n’a pas de grand intérêt.

Pourquoi des étapes différentes ?

La Build de CI quant à elle a 2 étapes supplémentaire à la build de PR, lié à la publication d’artefacts. La build de PR n’a pas besoin de créer d’artefact ni de les publier pour une release.

Pourquoi garder un temps de build bas ?

Il est très important de garder un temps de build et release bas, et cela pour plusieurs raisons :

  • car ceux ci impacte notre capacité a publier rapidement
  • plus votre temps de build est long moins votre équipe aura de feedback rapide si leurs PR sont mergeable ou non ce qui peut ralentir considérablement votre capacité de delivery
  • vous avez un temps d’occupation limité de vos agents de builds autant les faire travailler uniquement pour des taches dont vous avez vraiment besoin 🙂

Ma solution

Une solution simple est tout simplement d’activer ou désactiver certaines étapes de votre “build” en fonction de son origine via les conditions.

Pour activer une étape lors des builds PR je vais ajouter sur chaque étape (step) le code suivant :

condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest'))

Pour activer une étape lors des builds de CI je vais ajouter sur chaque étape le code suivant :

 condition: and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'))

Exemple de script complet :

#Lance la build CI lors d'un merge sur develop staging et master
trigger:
- develop
- staging
- master
# Lance la build pr sur les branches suivantes
pr:
  branches:
    include: 
    - develop
    - staging
    - master

# Image de la VM utilisée
pool:
  vmImage: 'ubuntu-latest'

variables:
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'

steps:

- task: UseDotNet@2
  displayName: use dotnet SDK
  inputs:
    packageType: 'sdk'
    useGlobalJson: true

- task: DotNetCoreCLI@2
  displayName: dotnet restore
  inputs:
    command: 'restore'


- task: DotNetCoreCLI@2
  displayName: dotnet build
  inputs:
    command: 'build'
    projects: '**/*.csproj'
    arguments: '--configuration $(BuildConfiguration)'

- task: DotNetCoreCLI@2
  displayName: dotnet test
  condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest'))
  inputs:
    command: 'test'
    projects: '**/*Test.csproj'

- task: DotNetCoreCLI@2
  displayName: dotnet publish
  condition: and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'))
  inputs:
    command: 'publish'
    publishWebProjects: true
    arguments: '--output $(build.artifactstagingdirectory) --no-build --configuration $(BuildConfiguration)'

- task: PublishBuildArtifacts@1
  displayName: publish artefacts
  condition: and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI'))
  inputs:
    PathtoPublish: '$(Build.ArtifactStagingDirectory)'
    ArtifactName: 'drop'
    publishLocation: 'Container'

Happy building 🙂

Pour aller plus loin :

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Pin It on Pinterest