Exercice – Ajouter plusieurs environnements à votre pipeline

Effectué

Vous êtes maintenant prêt à mettre à jour votre pipeline pour le déployer dans vos environnements de test et de production. Dans cette unité, vous allez mettre à jour votre pipeline pour utiliser des modèles afin de pouvoir réutiliser les phases dans les environnements.

Pendant ce processus, vous allez :

  • Ajouter un modèle de pipeline pour la phase de vérification lint.
  • Ajouter un modèle de pipeline définissant les phases requises pour le déploiement dans un environnement quelconque.
  • Mettre à jour votre pipeline pour utiliser les modèles.
  • Exécuter votre pipeline et afficher les résultats.

Ajouter un modèle de pipeline pour la phase de vérification lint

La phase de vérification lint se produit une seule fois pendant l’exécution du pipeline, quel que soit le nombre d’environnements dans lesquels le pipeline effectue le déploiement. Par conséquent, vous n’avez pas vraiment besoin d’utiliser des modèles pour la phase de vérification lint. Toutefois, pour que votre fichier de définition de pipeline principal reste simple et facile à lire, vous décidez de définir la phase de vérification lint dans un modèle.

  1. Dans Visual Studio Code, créez un nouveau dossier nommé pipeline-templates dans le dossier deploy.

  2. Créez un nouveau fichier dans le dossier pipeline-templates, nommé lint.yml.

    Capture d’écran de l’Explorateur de Visual Studio Code avec le dossier pipeline-templates et le fichier lint.yml

  3. Collez la définition de modèle de pipeline suivante dans le fichier :

    jobs:
    - job: LintCode
      displayName: Lint code
      steps:
        - script: |
            az bicep build --file deploy/main.bicep
          name: LintBicepCode
          displayName: Run Bicep linter
    

    La phase de vérification lint est identique à la phase de vérification lint déjà présente dans le pipeline, mais elle se trouve maintenant dans un fichier de modèle de pipeline distinct.

  4. Enregistrer vos modifications et fermez le fichier.

Ajouter un modèle de pipeline pour le déploiement

Créez un modèle de pipeline qui définit toutes les phases requises pour déployer chacun de vos environnements. Utilisez des paramètres de modèle pour spécifier les paramètres qui peuvent différer d’un environnement à l’autre.

  1. Créez un nouveau fichier dans le dossier pipeline-templates, nommé deploy.yml.

    Capture d’écran de l’Explorateur de Visual Studio Code avec le dossier pipeline-modèles et le fichier deploy.yml.

    Ce fichier représente toutes les activités de déploiement qui s’exécutent dans chacun de vos environnements.

  2. Collez les paramètres de modèle de pipeline suivants dans le fichier :

    parameters:
    - name: environmentType
      type: string
    - name: resourceGroupName
      type: string
    - name: serviceConnectionName
      type: string
    - name: deploymentDefaultLocation
      type: string
      default: westus3
    

    Notes

    Quand vous commencez à travailler avec votre fichier YAML dans Visual Studio Code, vous pouvez voir des lignes ondulées rouges indiquant un problème. Il arrive en effet que l’extension Visual Studio Code pour les fichiers YAML devine de façon incorrecte le schéma du fichier.

    Vous pouvez ignorer les problèmes signalés par l’extension. Ou, si vous préférez, vous pouvez ajouter le code suivant en haut du fichier pour supprimer la recherche de l’extension :

    # yaml-language-server: $schema=./deploy.yml
    
  3. Sous les paramètres, collez la définition de la phase de validation :

    stages:
    
    - ${{ if ne(parameters.environmentType, 'Production') }}:
      - stage: Validate_${{parameters.environmentType}}
        displayName: Validate (${{parameters.environmentType}} Environment)
        jobs:
        - job: ValidateBicepCode
          displayName: Validate Bicep code
          steps:
            - task: AzureResourceManagerTemplateDeployment@3
              name: RunPreflightValidation
              displayName: Run preflight validation
              inputs:
                connectedServiceName: ${{parameters.serviceConnectionName}}
                location: ${{parameters.deploymentDefaultLocation}}
                deploymentMode: Validation
                resourceGroupName: ${{parameters.resourceGroupName}}
                csmFile: deploy/main.bicep
                overrideParameters: >
                  -environmentType ${{parameters.environmentType}}
    

    Notez qu’une condition est appliquée à cette phase. Elle s’exécute uniquement pour les environnements hors production.

    Notez également que l’identificateur de la phase contient la valeur du paramètre environmentType. Ce paramètre garantit que chaque phase de votre pipeline possède un identificateur unique. La phase possède également une propriété displayName pour créer un nom correctement mis en forme que vous pourrez lire.

  4. Sous la phase de validation, collez la définition de la phase de préversion :

    - ${{ if eq(parameters.environmentType, 'Production') }}:
      - stage: Preview_${{parameters.environmentType}}
        displayName: Preview (${{parameters.environmentType}} Environment)
        jobs:
        - job: PreviewAzureChanges
          displayName: Preview Azure changes
          steps:
            - task: AzureCLI@2
              name: RunWhatIf
              displayName: Run what-if
              inputs:
                azureSubscription: ${{parameters.serviceConnectionName}}
                scriptType: 'bash'
                scriptLocation: 'inlineScript'
                inlineScript: |
                  az deployment group what-if \
                    --resource-group ${{parameters.resourceGroupName}} \
                    --template-file deploy/main.bicep \
                    --parameters environmentType=${{parameters.environmentType}}
    

    Notez qu’une condition est également appliquée à cette phase, mais qu’il s’agit de l’inverse de la condition de la phase de validation. La phase de préversion s’exécute uniquement pour l’environnement de production.

  5. Sous la phase de préversion, collez la définition de la phase de déploiement :

    - stage: Deploy_${{parameters.environmentType}}
      displayName: Deploy (${{parameters.environmentType}} Environment)
      jobs:
      - deployment: DeployWebsite
        displayName: Deploy website
        environment: ${{parameters.environmentType}}
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: self
    
                - task: AzureResourceManagerTemplateDeployment@3
                  name: DeployBicepFile
                  displayName: Deploy Bicep file
                  inputs:
                    connectedServiceName: ${{parameters.serviceConnectionName}}
                    deploymentName: $(Build.BuildNumber)
                    location: ${{parameters.deploymentDefaultLocation}}
                    resourceGroupName: ${{parameters.resourceGroupName}}
                    csmFile: deploy/main.bicep
                    overrideParameters: >
                      -environmentType ${{parameters.environmentType}}
                    deploymentOutputs: deploymentOutputs
    
                - bash: |
                    echo "##vso[task.setvariable variable=appServiceAppHostName;isOutput=true]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppHostName.value')"
                  name: SaveDeploymentOutputs
                  displayName: Save deployment outputs into variables
                  env:
                    DEPLOYMENT_OUTPUTS: $(deploymentOutputs)
    
  6. Sous la phase de déploiement, collez la définition de la phase de test de détection de fumée :

    - stage: SmokeTest_${{parameters.environmentType}}
      displayName: Smoke Test (${{parameters.environmentType}} Environment)
      jobs:
      - job: SmokeTest
        displayName: Smoke test
        variables:
          appServiceAppHostName: $[ stageDependencies.Deploy_${{parameters.environmentType}}.DeployWebsite.outputs['DeployWebsite.SaveDeploymentOutputs.appServiceAppHostName'] ]
        steps:
          - task: PowerShell@2
            name: RunSmokeTests
            displayName: Run smoke tests
            inputs:
              targetType: inline
              script: |
                $container = New-PesterContainer `
                  -Path 'deploy/Website.Tests.ps1' `
                  -Data @{ HostName = '$(appServiceAppHostName)' }
                Invoke-Pester `
                  -Container $container `
                  -CI
    
          - task: PublishTestResults@2
            name: PublishTestResults
            displayName: Publish test results
            condition: always()
            inputs:
              testResultsFormat: NUnit
              testResultsFiles: 'testResults.xml'
    

    Notez que la définition de la variable appServiceAppHostName incorpore le paramètre environmentType lorsqu’elle fait référence à la phase qui a publié le nom d’hôte. Ce paramètre garantit que chaque phase de test de détection de fumée s’exécute par rapport à l’environnement approprié.

  7. Vérifiez que votre fichier deploy.yml se présente maintenant comme ceci :

    parameters:
    - name: environmentType
      type: string
    - name: resourceGroupName
      type: string
    - name: serviceConnectionName
      type: string
    - name: deploymentDefaultLocation
      type: string
      default: westus3
    
    stages:
    
    - ${{ if ne(parameters.environmentType, 'Production') }}:
      - stage: Validate_${{parameters.environmentType}}
        displayName: Validate (${{parameters.environmentType}} Environment)
        jobs:
        - job: ValidateBicepCode
          displayName: Validate Bicep code
          steps:
            - task: AzureResourceManagerTemplateDeployment@3
              name: RunPreflightValidation
              displayName: Run preflight validation
              inputs:
                connectedServiceName: ${{parameters.serviceConnectionName}}
                location: ${{parameters.deploymentDefaultLocation}}
                deploymentMode: Validation
                resourceGroupName: ${{parameters.resourceGroupName}}
                csmFile: deploy/main.bicep
                overrideParameters: >
                  -environmentType ${{parameters.environmentType}}
    
    - ${{ if eq(parameters.environmentType, 'Production') }}:
      - stage: Preview_${{parameters.environmentType}}
        displayName: Preview (${{parameters.environmentType}} Environment)
        jobs:
        - job: PreviewAzureChanges
          displayName: Preview Azure changes
          steps:
            - task: AzureCLI@2
              name: RunWhatIf
              displayName: Run what-if
              inputs:
                azureSubscription: ${{parameters.serviceConnectionName}}
                scriptType: 'bash'
                scriptLocation: 'inlineScript'
                inlineScript: |
                  az deployment group what-if \
                    --resource-group ${{parameters.resourceGroupName}} \
                    --template-file deploy/main.bicep \
                    --parameters environmentType=${{parameters.environmentType}}
    
    - stage: Deploy_${{parameters.environmentType}}
      displayName: Deploy (${{parameters.environmentType}} Environment)
      jobs:
      - deployment: DeployWebsite
        displayName: Deploy website
        environment: ${{parameters.environmentType}}
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: self
    
                - task: AzureResourceManagerTemplateDeployment@3
                  name: DeployBicepFile
                  displayName: Deploy Bicep file
                  inputs:
                    connectedServiceName: ${{parameters.serviceConnectionName}}
                    deploymentName: $(Build.BuildNumber)
                    location: ${{parameters.deploymentDefaultLocation}}
                    resourceGroupName: ${{parameters.resourceGroupName}}
                    csmFile: deploy/main.bicep
                    overrideParameters: >
                      -environmentType ${{parameters.environmentType}}
                    deploymentOutputs: deploymentOutputs
    
                - bash: |
                    echo "##vso[task.setvariable variable=appServiceAppHostName;isOutput=true]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppHostName.value')"
                  name: SaveDeploymentOutputs
                  displayName: Save deployment outputs into variables
                  env:
                    DEPLOYMENT_OUTPUTS: $(deploymentOutputs)
    
    - stage: SmokeTest_${{parameters.environmentType}}
      displayName: Smoke Test (${{parameters.environmentType}} Environment)
      jobs:
      - job: SmokeTest
        displayName: Smoke test
        variables:
          appServiceAppHostName: $[ stageDependencies.Deploy_${{parameters.environmentType}}.DeployWebsite.outputs['DeployWebsite.SaveDeploymentOutputs.appServiceAppHostName'] ]
        steps:
          - task: PowerShell@2
            name: RunSmokeTests
            displayName: Run smoke tests
            inputs:
              targetType: inline
              script: |
                $container = New-PesterContainer `
                  -Path 'deploy/Website.Tests.ps1' `
                  -Data @{ HostName = '$(appServiceAppHostName)' }
                Invoke-Pester `
                  -Container $container `
                  -CI
    
          - task: PublishTestResults@2
            name: PublishTestResults
            displayName: Publish test results
            condition: always()
            inputs:
              testResultsFormat: NUnit
              testResultsFiles: 'testResults.xml'
    
  8. Enregistrez les modifications apportées au fichier.

Mettre à jour la définition du pipeline pour utiliser les modèles

  1. Ouvrez le fichier azure-pipelines.yml.

  2. Mettez à jour le fichier pour utiliser les nouveaux modèles en remplaçant le contenu par le code suivant :

    trigger:
      batch: true
      branches:
        include:
        - main
    
    pool:
      vmImage: ubuntu-latest
    
    stages:
    
    # Lint the Bicep file.
    - stage: Lint
      jobs: 
      - template: pipeline-templates/lint.yml
    
    # Deploy to the test environment.
    - template: pipeline-templates/deploy.yml
      parameters:
        environmentType: Test
        resourceGroupName: ToyWebsiteTest
        serviceConnectionName: ToyWebsiteTest
    
    # Deploy to the production environment.
    - template: pipeline-templates/deploy.yml
      parameters:
        environmentType: Production
        resourceGroupName: ToyWebsiteProduction
        serviceConnectionName: ToyWebsiteProduction
    

    Ce pipeline exécute la phase de vérification lint une fois. Ensuite, il utilise le fichier de modèle deploy.yml deux fois : une fois par environnement. Cela permet de conserver une définition de pipeline claire et facile à comprendre. En outre, les commentaires aident à expliquer ce qui se passe.

  3. Enregistrez vos modifications.

  4. Commitez et poussez (push) vos modifications à votre dépôt Git en exécutant les commandes suivantes dans le terminal Visual Studio Code :

    git add .
    git commit -m "Add pipeline templates"
    git push
    

Visualiser l’exécution du pipeline

  1. Dans votre navigateur, accédez à Pipelines.

  2. Sélectionnez l’exécution la plus récente de votre pipeline.

    Notez que l’exécution du pipeline montre maintenant les trois phases que vous avez définies dans le fichier YAML. Vous devrez peut-être faire défiler horizontalement l’affichage pour les afficher toutes.

    Capture d’écran d’Azure Pipelines montrant les phases de l’exécution du pipeline

  3. Attendez que le pipeline s’interrompe avant la phase Déployer (environnement de production). Le pipeline peut mettre quelques minutes pour atteindre ce point.

    Capture d’écran d’Azure Pipelines montrant l’exécution du pipeline suspendue pour approbation

  4. Approuvez le déploiement dans l’environnement de production en sélectionnant le bouton Réviser.

  5. Sélectionnez le bouton Approuver.

    Capture d’écran de l’interface Azure DevOps montrant la page d’approbation du pipeline et le bouton Approuver

    Attendez la fin de l’exécution du pipeline.

  6. Sélectionnez l’onglet Tests pour consulter les résultats des tests à partir de cette exécution du pipeline.

    Notez qu’il y a maintenant quatre résultats de test. Le test de détection de fumée s’exécute sur les deux environnements de test et de production, et vous voyez donc les résultats de ces deux ensembles de tests.

    Capture d’écran d’Azure Pipelines montrant la page pour les tests d’exécution de pipeline, avec quatre résultats de test

  7. Sélectionnez Pipelines>Environnements.

  8. Sélectionnez l’environnement Production.

  9. Notez que, dans l’écran de détails de l’environnement, vous voyez une vue d’ensemble de l’historique de déploiement de l’environnement de production.

    Capture d’écran d’Azure Pipelines montrant l’environnement de production, avec l’historique de déploiement montrant un seul déploiement

  10. Sélectionnez le déploiement et sélectionnez l’onglet Modifications.

    Notez que l’onglet Modifications affiche la liste des validations incluses dans le déploiement. Ces informations vous permettent de voir exactement ce qui a changé dans votre environnement au fil du temps.

    Capture d’écran d’Azure Pipelines montrant les détails du déploiement de l’environnement de production, avec la liste des validations

  11. Dans votre navigateur, accédez au Portail Azure.

  12. Accédez au groupe de ressources ToyWebsiteProduction.

  13. Dans la liste des ressources, ouvrez l’application Azure App Service.

    Capture d’écran du portail Azure montrant l’application App Service de production et les détails de la référence SKU du plan App Service.

    Notez que le type de plan App Service est S1.

  14. Accédez à l’application App Service dans le groupe de ressources ToyWebsiteTest.

    Notez que le type de plan App Service est F1. Les deux environnements utilisent des paramètres différents, tels que vous les avez définis dans votre fichier Bicep.