Exercício - Adicione vários ambientes ao seu pipeline

Concluído

Agora você está pronto para atualizar seu pipeline para implantar em seus ambientes de teste e produção. Nesta unidade, você atualizará seu pipeline para usar modelos para que possa reutilizar os estágios em todos os ambientes.

Durante o processo, você:

  • Adicione um modelo de pipeline para o estágio de fiapos.
  • Adicione um modelo de pipeline que defina os estágios necessários para implantar em qualquer ambiente.
  • Atualize seu pipeline para usar os modelos.
  • Execute seu pipeline e visualize os resultados.

Adicionar um modelo de pipeline para o estágio lint

O estágio lint acontece apenas uma vez durante a execução do pipeline, independentemente de quantos ambientes o pipeline implanta. Então, você realmente não precisa usar modelos para o estágio de fiapos. Mas para manter seu arquivo de definição de pipeline principal simples e fácil de ler, você decide definir o estágio de fiapos em um modelo.

  1. No Visual Studio Code, crie uma nova pasta chamada pipeline-templates dentro da pasta deploy .

  2. Crie um novo arquivo na pasta pipeline-templates chamada lint.yml.

    Captura de tela do Visual Studio Code Explorer, com a pasta pipeline-templates e o arquivo lint dot Y M L.

  3. Cole a seguinte definição de modelo de pipeline no arquivo:

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

    O estágio de fiapos é o mesmo que o estágio de fiapos já no pipeline, mas agora está em um arquivo de modelo de pipeline separado.

  4. Salve as alterações e feche o arquivo.

Adicionar um modelo de pipeline para implantação

Crie um modelo de pipeline que defina todos os estágios necessários para implantar cada um dos seus ambientes. Você usa parâmetros de modelo para especificar as configurações que podem diferir entre ambientes.

  1. Crie um novo arquivo na pasta pipeline-templates chamada deploy.yml.

    Captura de tela do Visual Studio Code Explorer, com a pasta pipeline-templates e o arquivo deploy dot YML.

    Esse arquivo representa todas as atividades de implantação executadas para cada um dos seus ambientes.

  2. Cole os seguintes parâmetros de modelo de pipeline no arquivo:

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

    Nota

    Quando você começa a trabalhar com seu arquivo YAML no Visual Studio Code, você pode ver algumas linhas onduladas vermelhas dizendo que há um problema. Isso ocorre porque a extensão de código do Visual Studio para arquivos YAML às vezes adivinha incorretamente o esquema do arquivo.

    Você pode ignorar os problemas que a extensão relata. Ou, se preferir, você pode adicionar o seguinte código à parte superior do arquivo para suprimir a adivinhação da extensão:

    # yaml-language-server: $schema=./deploy.yml
    
  3. Abaixo dos parâmetros, cole a definição da etapa de validação:

    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}}
    

    Observe que uma condição é aplicada a esta etapa. Ele é executado apenas para ambientes que não são de produção.

    Observe também que o identificador de estágio inclui o valor do environmentType parâmetro. Esse parâmetro garante que cada estágio do seu pipeline tenha um identificador exclusivo. O palco também tem uma displayName propriedade para criar um nome bem formatado para você ler.

  4. Abaixo da etapa de validação, cole a definição da etapa de visualização:

    - ${{ 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}}
    

    Observe que esta etapa também tem uma condição aplicada, mas é o oposto da condição da etapa de validação. O estágio de visualização é executado apenas para o ambiente de produção.

  5. Abaixo do estágio de visualização, cole a definição do estágio de implantação:

    - 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. Abaixo do estágio de implantação, cole a definição do estágio de teste de fumaça:

    - 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'
    

    Observe que a definição da appServiceAppHostName variável incorpora o environmentType parâmetro quando se refere ao estágio que publicou o nome do host. Este parâmetro garante que cada etapa de teste de fumaça seja executada contra o ambiente correto.

  7. Verifique se o arquivo deploy.yml agora se parece com o exemplo a seguir:

    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. Guarde as alterações ao ficheiro.

Atualizar a definição de pipeline para usar os modelos

  1. Abra o ficheiro azure-pipelines.yml.

  2. Atualize o arquivo para usar os novos modelos substituindo o conteúdo pelo seguinte código:

    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
    

    Este pipeline executa o estágio de fiapos uma vez. Em seguida, ele usa o arquivo de modelo deploy.yml duas vezes: uma vez por ambiente. Isso mantém a definição do pipeline clara e fácil de entender. Além disso, os comentários ajudam a explicar o que está acontecendo.

  3. Guardar as suas alterações.

  4. Confirme e envie suas alterações para o repositório Git executando os seguintes comandos no terminal do Visual Studio Code:

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

Exibir a execução do pipeline

  1. No seu navegador, vá para Pipelines.

  2. Selecione a execução mais recente do seu pipeline.

    Observe que a execução do pipeline agora mostra todos os estágios que você definiu no arquivo YAML. Talvez seja necessário rolar horizontalmente para vê-los todos.

    Captura de tela do Azure Pipelines que mostra os estágios de execução do pipeline.

  3. Aguarde a pausa do pipeline antes do estágio Implantar (Ambiente de Produção ). Pode levar alguns minutos para que o gasoduto chegue a este ponto.

    Captura de tela do Azure Pipelines que mostra a execução do pipeline pausada para aprovação.

  4. Aprove a implantação no ambiente de produção selecionando o botão Revisão .

  5. Selecione o botão Aprovar .

    Captura de tela da interface do Azure DevOps que mostra a página de aprovação de pipeline e o botão Aprovar.

    Aguarde até que o pipeline termine a execução.

  6. Selecione a guia Testes para mostrar os resultados do teste dessa execução de pipeline.

    Repare que agora há quatro resultados de testes. O teste de fumaça é executado nos ambientes de teste e produção, para que você veja os resultados de ambos os conjuntos de testes.

    Captura de tela do Azure Pipelines que mostra a página para testes de execução de pipeline, com quatro resultados de teste.

  7. Selecione Ambientes de pipelines>.

  8. Selecione o Ambiente de produção .

  9. Observe que, na tela de detalhes do ambiente, você verá uma visão geral do histórico de implantação do ambiente de produção.

    Captura de tela do Azure Pipelines que mostra o ambiente de produção, com o histórico de implantação mostrando uma única implantação.

  10. Selecione a implantação e selecione a guia Alterações .

    Observe que a guia Alterações mostra a lista de confirmações incluídas na implantação. Essas informações ajudam você a ver exatamente o que mudou em seu ambiente ao longo do tempo.

    Captura de tela do Azure Pipelines que mostra os detalhes de implantação do ambiente de produção, com uma lista de confirmações.

  11. No browser, aceda ao Portal do Azure.

  12. Vá para o grupo de recursos ToyWebsiteProduction .

  13. Na lista de recursos, abra o aplicativo Serviço de Aplicativo do Azure.

    Captura de tela do portal do Azure que mostra o aplicativo Serviço de Aplicativo de produção e os detalhes da SKU do plano do Serviço de Aplicativo.

    Observe que o tipo de plano do Serviço de Aplicativo é S1.

  14. Vá para o aplicativo Serviço de Aplicativo no grupo de recursos ToyWebsiteTest .

    Observe que o tipo de plano do Serviço de Aplicativo é F1. Os dois ambientes usam configurações diferentes, conforme você definiu no arquivo Bicep.