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.

    Screenshot of Visual Studio Code Explorer, with the pipeline-templates folder and the lint dot Y M L file.

  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.

    Screenshot of Visual Studio Code Explorer, with the pipeline-templates folder and the deploy dot YML file.

    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.

    Screenshot of Azure Pipelines that shows the pipeline run stages.

  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.

    Screenshot of Azure Pipelines that shows the pipeline run paused for approval.

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

  5. Sélectionnez le bouton Approuver.

    Screenshot of the Azure DevOps interface that shows the pipeline approval page and the Approve button.

    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.

    Screenshot of Azure Pipelines that shows the page for pipeline run tests, with four test results.

  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.

    Screenshot of Azure Pipelines that shows the production environment, with the deployment history showing a single deployment.

  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.

    Screenshot of Azure Pipelines that shows the production environment's deployment details, with a list of commits.

  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.

    Screenshot of the Azure portal that shows the production App Service app and the App Service plan SKU details.

    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.