Øvelse – udrul et webprogram

Fuldført

I dit legetøjsfirma har dit webstedsudviklingsteam forpligtet den nyeste version af webstedet til dit Git-lager. Nu er du klar til at opdatere din pipeline for at bygge webstedet og udrulle den i Azure App Service.

I denne proces udfører du følgende opgaver:

  • Tilføj en ny pipelineskabelon for buildjobbet.
  • Opdater pipelinen, så den indeholder buildjobbet.
  • Tilføj en ny røgtest.
  • Opdater installationsfasen for at installere programmet.
  • Kør pipelinen.

Tilføj en pipelineskabelon for buildjobbet

Tilføj en ny jobdefinition, der indeholder de trin, der kræves for at oprette webstedsprogrammet.

  1. Åbn Visual Studio Code.

  2. Opret en ny fil med navnet build.ymli mappen udrulnings-/pipelineskabeloner .

    Skærmbillede af Visual Studio Code Explorer, hvor mappen med pipelineskabeloner og filen 'build.yml' vises.

  3. Føj følgende indhold til skabelonfilen til build.yml pipeline:

    jobs:
    - job: Build
      displayName: Build application and database
      pool:
        vmImage: windows-latest
    
      steps:
    
      # Build, copy, and publish the website.
      - task: DotNetCoreCLI@2
        displayName: Build publishable website
        inputs:
          command: 'publish'
          publishWebProjects: true
    
      - task: CopyFiles@2
        displayName: Copy publishable website
        inputs:
          sourceFolder: '$(Build.SourcesDirectory)/src/ToyCompany/ToyCompany.Website/bin'
          contents: '**/publish.zip'
          targetFolder: '$(Build.ArtifactStagingDirectory)/website'
          flattenFolders: true
    
      - task: PublishBuildArtifacts@1
        displayName: Publish website as pipeline artifact
        inputs:
          pathToPublish: '$(Build.ArtifactStagingDirectory)/website'
          artifactName: 'website'
    

    Jobbet kører et buildtrin for at omdanne webstedsprogrammets kildekode til en kompileret fil, der er klar til at køre i Azure. Jobbet kopierer derefter det kompilerede artefakt til en midlertidig midlertidig mappe og udgiver det som en pipelineartefakt.

  4. Gem ændringerne i filen.

Omdøb den første pipelinefase, og tilføj et buildjob

  1. Åbn filen azure-pipelines.yml i mappen installér.

  2. Rediger fasen Lint. Omdøb den til Build, og tilføj et buildjob, der bruger den build.yml pipelineskabelon, du har oprettet.

    trigger:
      batch: true
      branches:
        include:
        - main
    
    pool:
      vmImage: ubuntu-latest
    
    stages:
    
    - stage: Build
      jobs:
      # Build the Visual Studio solution.
      - template: pipeline-templates/build.yml
    
      # Lint the Bicep file.
      - template: pipeline-templates/lint.yml
    
    # Deploy to the test environment.
    - template: pipeline-templates/deploy.yml
      parameters:
        environmentType: Test
    
    # Deploy to the production environment.
    - template: pipeline-templates/deploy.yml
      parameters:
        environmentType: Production
    
  3. Gem ændringerne i filen.

Opdater røgtestfilen

Webstedsudviklerne har føjet et tilstandsslutpunkt til webstedet. Dette slutpunkt kontrollerer, at webstedet er online, og at det kan oprette forbindelse til databasen. Her kan du tilføje en ny røgtest for at aktivere tilstandskontrollen fra din udrulningspipeline.

  1. Åbn Website.Tests.ps1-filen i mappen installér.

  2. Tilføj en ny testcase, der aktiverer tilstandskontrollen. Testcasen mislykkes, hvis svarkoden ikke er 200, hvilket angiver succes.

    param(
      [Parameter(Mandatory)]
      [ValidateNotNullOrEmpty()]
      [string] $HostName
    )
    
    Describe 'Toy Website' {
    
        It 'Serves pages over HTTPS' {
          $request = [System.Net.WebRequest]::Create("https://$HostName/")
          $request.AllowAutoRedirect = $false
          $request.GetResponse().StatusCode |
            Should -Be 200 -Because "the website requires HTTPS"
        }
    
        It 'Does not serves pages over HTTP' {
          $request = [System.Net.WebRequest]::Create("http://$HostName/")
          $request.AllowAutoRedirect = $false
          $request.GetResponse().StatusCode | 
            Should -BeGreaterOrEqual 300 -Because "HTTP is not secure"
        }
    
        It 'Returns a success code from the health check endpoint' {
          $response = Invoke-WebRequest -Uri "https://$HostName/health" -SkipHttpErrorCheck
          Write-Host $response.Content
          $response.StatusCode |
            Should -Be 200 -Because "the website and configuration should be healthy"
        }
    
    }
    
  3. Gem ændringerne i filen.

Føj output til Bicep-fil

Du vil tilføje et installationstrin, der publicerer dit websted i Azure App Service, men trinnet publicering kræver navnet på App Service-appen. Her får du vist appnavnet som et output fra din Bicep-fil.

  1. Åbn filen main.bicep i mappen installér.

  2. I slutningen af filindholdet skal du tilføje App Service-appens navn som output.

    output appServiceAppName string = appServiceApp.name
    output appServiceAppHostName string = appServiceApp.properties.defaultHostName
    
  3. Gem ændringerne i filen.

Opdater installationsfasen

  1. Åbn deploy.yml-filen i mappen deploy/pipeline-templates mappe.

  2. I definitionen af Installér fases installationsjob (i nærheden af Linje 59) skal du konfigurere jobbet til at bruge den Windows-hostede agentgruppe:

    - stage: Deploy_${{parameters.environmentType}}
      displayName: Deploy (${{parameters.environmentType}} Environment)
      jobs:
      - deployment: DeployWebsite
        displayName: Deploy website
        pool:
          vmImage: windows-latest
        variables:
        - group: ToyWebsite${{parameters.environmentType}}
        environment: ${{parameters.environmentType}}
        strategy:
    

    Nogle af de pipelinetrin, du tilføjer senere for at arbejde med databasen, kræver, at Windows-operativsystemet kører. Du kan bruge forskellige agentpuljer til forskellige job i din pipeline, så de andre job fortsætter med at bruge Ubuntu Linux-pipelineagentpuljen.

  3. I Installér job SaveDeploymentOutputs trin skal du tilføje en ny pipelinevariabel med værdien af appnavnet fra Bicep-installationens output:

    - bash: |
        echo "##vso[task.setvariable variable=appServiceAppName]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppName.value')"
        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)
    

    Bemærk, at variablen appServiceAppHostName har egenskaben isOutput=true anvendt på den, fordi denne variabel bruges i røgtestfasen. Variablen appServiceAppName angives og bruges i samme pipelinefase og -job. Så det behøver ikke indstillingen isOutput=true.

  4. I slutningen af Installér jobindhold skal du tilføje et nyt trin for at installere appen i Azure App Service:

    steps:
      - checkout: self
    
      - task: AzureResourceManagerTemplateDeployment@3
        name: DeployBicepFile
        displayName: Deploy Bicep file
        inputs:
          connectedServiceName: ToyWebsite${{parameters.environmentType}}
          deploymentName: $(Build.BuildNumber)
          location: ${{parameters.deploymentDefaultLocation}}
          resourceGroupName: $(ResourceGroupName)
          csmFile: deploy/main.bicep
          overrideParameters: >
            -environmentType $(EnvironmentType)
            -reviewApiUrl $(ReviewApiUrl)
            -reviewApiKey $(ReviewApiKey)
          deploymentOutputs: deploymentOutputs
    
      - bash: |
          echo "##vso[task.setvariable variable=appServiceAppName]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppName.value')"
          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)
    
      - task: AzureRmWebAppDeployment@4
        name: DeployWebsiteApp
        displayName: Deploy website
        inputs:
          appType: webApp
          ConnectionType: AzureRM
          azureSubscription: ToyWebsite${{parameters.environmentType}}
          ResourceGroupName: $(ResourceGroupName)
          WebAppName: $(appServiceAppName)
          Package: '$(Pipeline.Workspace)/website/publish.zip'
    

    Seddel

    Vær forsigtig med indrykningen af YAML-filen, og sørg for, at det nye installationstrin er indrykket på samme niveau som DeployBicepFile trin. Hvis du ikke er sikker, skal du kopiere hele deploy.yml filindholdet fra eksemplet i næste trin.

    Bemærk, at du ikke eksplicit har downloadet artefaktet i pipelinedefinitionen. Da du bruger et installationsjob, downloader Azure Pipelines automatisk artefaktet for dig.

Kontrollér deploy.yml filindholdet, og bekræft dine ændringer

  1. Kontrollér, at din deploy.yml-fil ligner følgende eksempel:

    parameters:
    - name: environmentType
      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
          variables:
          - group: ToyWebsite${{parameters.environmentType}}
          steps:
            - task: AzureResourceManagerTemplateDeployment@3
              name: RunPreflightValidation
              displayName: Run preflight validation
              inputs:
                connectedServiceName: ToyWebsite${{parameters.environmentType}}
                location: ${{parameters.deploymentDefaultLocation}}
                deploymentMode: Validation
                resourceGroupName: $(ResourceGroupName)
                csmFile: deploy/main.bicep
                overrideParameters: >
                  -environmentType $(EnvironmentType)
                  -reviewApiUrl $(ReviewApiUrl)
                  -reviewApiKey $(ReviewApiKey)
    
    - ${{ if eq(parameters.environmentType, 'Production') }}:
      - stage: Preview_${{parameters.environmentType}}
        displayName: Preview (${{parameters.environmentType}} Environment)
        jobs:
        - job: PreviewAzureChanges
          displayName: Preview Azure changes
          variables:
          - group: ToyWebsite${{parameters.environmentType}}
          steps:
            - task: AzureCLI@2
              name: RunWhatIf
              displayName: Run what-if
              inputs:
                azureSubscription: ToyWebsite${{parameters.environmentType}}
                scriptType: 'bash'
                scriptLocation: 'inlineScript'
                inlineScript: |
                  az deployment group what-if \
                    --resource-group $(ResourceGroupName) \
                    --template-file deploy/main.bicep \
                    --parameters environmentType=$(EnvironmentType) \
                                 reviewApiUrl=$(ReviewApiUrl) \
                                 reviewApiKey=$(ReviewApiKey)
    
    - stage: Deploy_${{parameters.environmentType}}
      displayName: Deploy (${{parameters.environmentType}} Environment)
      jobs:
      - deployment: DeployWebsite
        displayName: Deploy website
        pool:
          vmImage: windows-latest
        variables:
        - group: ToyWebsite${{parameters.environmentType}}
        environment: ${{parameters.environmentType}}
        strategy:
          runOnce:
            deploy:
              steps:
                - checkout: self
    
                - task: AzureResourceManagerTemplateDeployment@3
                  name: DeployBicepFile
                  displayName: Deploy Bicep file
                  inputs:
                    connectedServiceName: ToyWebsite${{parameters.environmentType}}
                    deploymentName: $(Build.BuildNumber)
                    location: ${{parameters.deploymentDefaultLocation}}
                    resourceGroupName: $(ResourceGroupName)
                    csmFile: deploy/main.bicep
                    overrideParameters: >
                      -environmentType $(EnvironmentType)
                      -reviewApiUrl $(ReviewApiUrl)
                      -reviewApiKey $(ReviewApiKey)
                    deploymentOutputs: deploymentOutputs
    
                - bash: |
                    echo "##vso[task.setvariable variable=appServiceAppName]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppName.value')"
                    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)
    
                - task: AzureRmWebAppDeployment@4
                  name: DeployWebsiteApp
                  displayName: Deploy website
                  inputs:
                    appType: webApp
                    ConnectionType: AzureRM
                    azureSubscription: ToyWebsite${{parameters.environmentType}}
                    ResourceGroupName: $(ResourceGroupName)
                    WebAppName: $(appServiceAppName)
                    Package: '$(Pipeline.Workspace)/website/publish.zip'
    
    - 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'
    
  2. Gem ændringerne i filen.

  3. I Visual Studio Code-terminalen skal du bekræfte og overføre dine ændringer til dit Git-lager ved at køre følgende kommandoer:

    git add .
    git commit -m "Build and deploy website application"
    git push
    

Kør pipelinen

  1. Gå til Pipelinesi din browser.

  2. Vælg den seneste kørsel af pipelinen.

    Skærmbillede af Azure DevOps, der viser listen over pipelinekørsel. Den seneste pipelinekørsel er fremhævet.

    Vent, indtil fasen build er fuldført.

    Pipelinen afbrydes midlertidigt, før den kører Validate (Test Environment) fase, fordi pipelinen skal have tilladelse til at bruge den variabelgruppe, som fasen refererer til. Du skal godkende pipelinens adgang til variabelgruppen, fordi du kører pipelinen i dette projekt for første gang. Når du kører pipelinen igen, behøver du ikke at godkende adgang til den samme variabelgruppe.

  3. Vælg Vis.

    Skærmbillede af Azure DevOps, der viser, at pipelinekørslen er midlertidigt afbrudt i valideringsfasen. Der kræves tilladelse for at fortsætte. Knappen Vis er fremhævet.

  4. Vælg Tillad.

    Skærmbillede af Azure DevOps, der viser, at pipelinen skal have tilladelse til at bruge variabelgruppen ToyWebsiteTest. Knappen Tillad er fremhævet.

  5. Vælg Tillad.

    Skærmbillede af Azure DevOps, der viser grænsefladen til bekræftelse af tilladelser. Knappen Tillad er fremhævet.

    Fasen validate (testmiljø) afsluttes.

    Pipelinen fortsætter, og Installation (testmiljø) fase afsluttes. Pipelinen kører derefter Smoke Test (Test Environment) fase, men røgtestfasen mislykkes.

  6. Vælg fasen røgtest (testmiljø) for at åbne pipelineloggen.

    Skærmbillede af Azure DevOps, der viser fasen Røgtest for pipelinekørslen for testmiljøet. Status viser, at fasen mislykkedes.

  7. Vælg Kør røgtest trin for at få vist den tilknyttede sektion i pipelineloggen.

    Skærmbillede af Azure DevOps, der viser logfilen for pipelinekørsel, hvor outputtet af røgtesten vises. Resultatet af JSON-tilstandstesten er fremhævet.

    Bemærk, at pipelineloggen indeholder svar på tilstandskontrol. Svaret angiver, at der er et problem med programmets kommunikation med Azure SQL Database. Databasen er ikke installeret eller konfigureret endnu, og derfor kan webstedet ikke få adgang til den. I den næste øvelse skal du løse dette konfigurationsproblem.