Упражнение. Добавление нескольких сред в конвейер

Завершено

Теперь вы готовы обновить конвейер для развертывания как в тестовой, так и в рабочей среде. В этом уроке вы измените конвейер для использования шаблонов, которые позволят повторять этапы в разных средах.

В процессе вы:

  • Добавите шаблон конвейера для этапа анализа кода.
  • Добавите шаблон конвейера, в котором определены этапы, необходимые для развертывания в любой среде.
  • Измените конвейер для использования шаблонов.
  • Запустите конвейер и проверите результаты.

Добавление шаблона конвейера для этапа анализа кода

Во время выполнения конвейера этап анализа кода происходит только один раз независимо от количества сред, в которых осуществляется развертывание. Поэтому использовать шаблоны для него нет необходимости. Но чтобы упростить основной файл определения конвейера, вы решили определить этап анализа кода в шаблоне.

  1. В Visual Studio Code создайте папку pipeline-templates в папке deploy.

  2. В папке pipeline-templates создайте файл lint.yml.

    Снимок экрана обозревателя Visual Studio Code: папка pipeline-templates и файл lint.yml.

  3. Вставьте в файл следующее определение шаблона конвейера:

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

    Этап анализа кода не отличается от уже имеющегося в конвейере, но теперь он вынесен в отдельный файл шаблона конвейера.

  4. Сохраните изменения и закройте файл.

Добавление шаблона конвейера для развертывания

Создайте шаблон конвейера, в котором определяются все этапы, необходимые для развертывания в каждой из сред. Параметры шаблона используются для указания параметров, которые могут отличаться между средами.

  1. В папке pipeline-templates создайте файл deploy.yml.

    Снимок экрана: Обозреватель Visual Studio Code с папкой шаблонов конвейеров и файлом точки развертывания YML.

    Этот файл представляет все действия развертывания, выполняемые для каждой среды.

  2. Вставьте в файл следующие параметры шаблона конвейера:

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

    Примечание.

    Начиная работать с YAML-файлом в Visual Studio Code, вы можете увидеть красные волнистые линии, указывающие на наличие проблем. Причина в том, что расширение Visual Studio Code для YAML-файлов иногда неправильно распознает схему файла.

    На проблемы, о которых сообщает расширение, можно не обращать внимания. Если хотите, можете добавить следующий код в начало файла, чтобы отключить распознание схемы расширением:

    # yaml-language-server: $schema=./deploy.yml
    
  3. После параметров вставьте определение этапа проверки:

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

    Обратите внимание, что к этому этапу применяется условие. Он выполняется только для нерабочих сред.

    Также обратите внимание, что идентификатор этапа включает значение параметра environmentType. Этот параметр гарантирует, что каждый этап конвейера имеет уникальный идентификатор. У этапа также есть свойство displayName для задания понятного имени.

  4. После этапа проверки вставьте определение предварительного этапа:

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

    Обратите внимание, что к этому этапу также применяется условие, но обратное условию этапа проверки. Предварительный этап выполняется только для рабочей среды.

  5. После предварительного этапа вставьте определение этапа развертывания:

    - 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. После этапа развертывания вставьте определение этапа тестирования состояния:

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

    Обратите внимание, что определение переменной appServiceAppHostName включает в себя параметр environmentType, который указывает на этап, на котором было опубликовано имя узла. Этот параметр гарантирует, что каждый этап тестирования состояния будет выполняться для правильной среды.

  7. Убедитесь в том, что файл deploy.yml выглядит следующим образом:

    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. Сохраните внесенные в файл изменения.

Обновление определения конвейера для использования шаблонов

  1. Откройте файл azure-pipelines.yml.

  2. Измените файл для использования новых шаблонов, заменив его содержимое следующим кодом:

    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
    

    Этот конвейер однократно запускает этап анализа кода. Затем он дважды использует файл шаблона deploy.yml: по одному разу для каждой среды. Благодаря этому определение конвейера остается простым и понятным. Кроме того, происходящее поясняется комментариями.

  3. Сохранение изменений.

  4. Зафиксируйте и отправьте изменения в репозиторий Git, выполнив следующие команды в терминале Visual Studio Code:

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

Просмотр выполнения конвейера

  1. В браузере перейдите на страницу Pipelines.

  2. Выберите последнее выполнение конвейера.

    Обратите внимание, что в конвейере теперь отображаются все этапы, определенные в YAML-файле. Для просмотра их всех может потребоваться горизонтальная прокрутка.

    Снимок экрана Azure Pipelines: этапы выполнения конвейера.

  3. Дождитесь приостановки конвейера перед этапом Развертывание (рабочая среда). Для достижения этого момента может потребоваться несколько минут.

    Снимок экрана Azure Pipelines: приостановка выполнения конвейера для утверждения.

  4. Утвердите развертывание в рабочей среде, нажав кнопку Проверить.

  5. Нажмите кнопку Утвердить.

    Снимок экрана интерфейса Azure DevOps: страница утверждения конвейера с кнопкой

    Подождите, пока конвейер завершит работу.

  6. Перейдите на вкладку "Тесты", чтобы отобразить результаты теста из этого запуска конвейера.

    Обратите внимание, что результатов тестирования теперь четыре. Тест состояния проводится как в тестовой, так и в рабочей среде, поэтому результаты приводятся для обоих наборов тестов.

    Снимок экрана Azure Pipelines: страница тестов конвейера с четырьмя результатами тестирования.

  7. Выберите Pipelines>Среды.

  8. Выберите среду Рабочая.

  9. Обратите внимание, что на экране сведения о среде приводится обзор журнала развертываний в рабочей среде.

    Снимок экрана Azure Pipelines: рабочая среда с одним развертыванием в журнале развертываний.

  10. Выберите развертывание и перейдите на вкладку Изменения.

    Обратите внимание, что на вкладке Изменения приводится список фиксаций, включенных в развертывание. Эта информация поможет вам точно увидеть, что изменилось в вашей среде с течением времени.

    Снимок экрана Azure Pipelines: сведения о развертывании в рабочей среде со списком фиксаций.

  11. В браузере перейдите на портал Azure.

  12. Перейдите к группе ресурсов ToyWebsiteProduction.

  13. В списке ресурсов откройте приложение Службы приложений Azure.

    Снимок экрана портала Azure: рабочее приложение Службы приложений и сведения о номере SKU плана Службы приложений.

    Обратите внимание, что тип плана Службы приложений — S1.

  14. Перейдите к приложению Службы приложений в группе ресурсов ToyWebsiteTest.

    Обратите внимание, что тип плана Службы приложений — F1. Для двух сред используются разные параметры, определенные в файле Bicep.