Oefening: een webtoepassing implementeren

Voltooid

Bij uw speelgoedbedrijf heeft uw team voor websiteontwikkeling de nieuwste versie van de website doorgevoerd in uw Git-opslagplaats. U bent nu klaar om uw pijplijn bij te werken om de website te bouwen en deze te implementeren in Azure-app Service.

In dit proces voert u de volgende taken uit:

  • Voeg een nieuwe pijplijnsjabloon toe voor de buildtaak.
  • Werk de pijplijn bij om de buildtaak op te nemen.
  • Voeg een nieuwe betrouwbaarheidstest toe.
  • Werk de implementatiefase bij om de toepassing te implementeren.
  • Voer de pijplijn uit.

Een pijplijnsjabloon voor de buildtaak toevoegen

Voeg een nieuwe taakdefinitie toe die de stappen bevat die nodig zijn om de websitetoepassing te bouwen.

  1. Open Visual Studio Code.

  2. Maak in de map deploy/pipeline-templates een nieuw bestand met de naam build.yml.

    Screenshot of Visual Studio Code Explorer, with the pipeline-templates folder and the 'build.yml' file shown.

  3. Voeg de volgende inhoud toe aan het build.yml pijplijnsjabloonbestand:

    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'
    

    De taak voert een buildstap uit om de broncode van de websitetoepassing om te zetten in een gecompileerd bestand dat klaar is om te worden uitgevoerd in Azure. De taak kopieert vervolgens het gecompileerde artefact naar een tijdelijke faseringsmap en publiceert het als een pijplijnartefact.

  4. Sla de wijzigingen in het bestand op.

Wijzig de naam van de eerste pijplijnfase en voeg een buildtaak toe

  1. Open het azure-pipelines.yml bestand in de map Deploy .

  2. Wijzig de lintfase . Wijzig de naam in Build en voeg een buildtaak toe die gebruikmaakt van de build.yml pijplijnsjabloon die u hebt gemaakt.

    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. Sla de wijzigingen in het bestand op.

Het betrouwbaarheidstestbestand bijwerken

De websiteontwikkelaars hebben een statuseindpunt toegevoegd aan de website. Dit eindpunt controleert of de website online is en of deze de database kan bereiken. Hier voegt u een nieuwe betrouwbaarheidstest toe om de statuscontrole aan te roepen vanuit uw implementatiepijplijn.

  1. Open het bestand Website.Tests.ps1 in de map Deploy .

  2. Voeg een nieuwe testcase toe waarmee de statuscontrole wordt aangeroepen. De testcase mislukt als de antwoordcode niet 200 is, wat aangeeft dat de test is geslaagd.

    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. Sla de wijzigingen in het bestand op.

Uitvoer toevoegen aan Bicep-bestand

U wilt een implementatiestap toevoegen waarmee uw website naar Azure-app Service wordt gepubliceerd, maar voor de publicatiestap is de naam van de App Service-app vereist. Hier maakt u de naam van de app beschikbaar als uitvoer van uw Bicep-bestand.

  1. Open het bestand main.bicep in de implementatiemap .

  2. Voeg aan het einde van de bestandsinhoud de naam van de App Service-app toe als uitvoer.

    output appServiceAppName string = appServiceApp.name
    output appServiceAppHostName string = appServiceApp.properties.defaultHostName
    
  3. Sla de wijzigingen in het bestand op.

Implementatiefase bijwerken

  1. Open het bestand deploy.yml in de map deploy/pipeline-templates .

  2. Configureer in de definitie van de implementatietaak van de implementatiefase (in de buurt van regel 59) de taak voor het gebruik van de door Windows gehoste agentgroep:

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

    Voor sommige van de pijplijnstappen die u later toevoegt om met uw database te kunnen werken, moet het Windows-besturingssysteem worden uitgevoerd. U kunt verschillende agentpools gebruiken voor verschillende taken in uw pijplijn, zodat de andere taken de Ubuntu Linux-pijplijnagentgroep blijven gebruiken.

  3. Voeg in de stap SaveDeploymentOutputs van de deploy-taakeen nieuwe pijplijnvariabele toe met de waarde van de app-naam uit de uitvoer van de Bicep-implementatie:

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

    U ziet dat de appServiceAppHostName variabele de isOutput=true eigenschap erop heeft toegepast, omdat die variabele wordt gebruikt in de betrouwbaarheidstestfase. De appServiceAppName variabele wordt ingesteld en gebruikt in dezelfde pijplijnfase en -taak. De instelling is dus niet nodig isOutput=true .

  4. Voeg aan het einde van de inhoud van de taak Implementeren een nieuwe stap toe om de app te implementeren in 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'
    

    Notitie

    Wees voorzichtig met de inspringing van het YAML-bestand, zodat de nieuwe implementatiestap op hetzelfde niveau als de DeployBicepFile stap wordt ingesprongen. Als u het niet zeker weet, kopieert u de hele deploy.yml bestandsinhoud uit het voorbeeld in de volgende stap.

    U ziet dat u het artefact niet expliciet hebt gedownload in de pijplijndefinitie. Omdat u een implementatietaak gebruikt, downloadt Azure Pipelines het artefact automatisch voor u.

Controleer de inhoud van het deploy.yml bestand en voer uw wijzigingen door

  1. Controleer of uw deploy.yml bestand eruitziet als in het volgende voorbeeld:

    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. Sla de wijzigingen in het bestand op.

  3. Voer in de Visual Studio Code-terminal uw wijzigingen door en push deze naar uw Git-opslagplaats door de volgende opdrachten uit te voeren:

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

De pijplijn uitvoeren

  1. Ga in uw browser naar Pijplijnen.

  2. Selecteer de meest recente uitvoering van uw pijplijn.

    Screenshot of Azure DevOps showing the pipeline run list. The latest pipeline run is highlighted.

    Wacht totdat de buildfase is voltooid.

    De pijplijn wordt onderbroken voordat de fase Validate (Test Environment) wordt uitgevoerd, omdat de pijplijn toestemming nodig heeft om de variabelegroep te gebruiken waarnaar de fase verwijst. U moet de toegang van de pijplijn tot de variabelegroep goedkeuren, omdat u de pijplijn voor het eerst in dit project uitvoert. Wanneer u de pijplijn opnieuw uitvoert, hoeft u de toegang tot dezelfde variabelegroep niet goed te keuren.

  3. Selecteer Weergeven.

    Screenshot of Azure DevOps showing the pipeline run paused at the Validate stage. Permission is required to continue. The View button is highlighted.

  4. Selecteer Toestaan.

    Screenshot of Azure DevOps showing that the pipeline needs permission to use the ToyWebsiteTest variable group. The Permit button is highlighted.

  5. Selecteer Toestaan.

    Screenshot of Azure DevOps showing the permission confirmation interface. The Permit button is highlighted.

    De fase Valideren (testomgeving) is voltooid.

    De pijplijn wordt voortgezet en de fase Deploy (Test Environment) is voltooid. De pijplijn voert vervolgens de fase Betrouwbaarheidstest (Testomgeving) uit, maar de betrouwbaarheidstestfase mislukt.

  6. Selecteer de fase Betrouwbaarheidstest (testomgeving) om het pijplijnlogboek te openen.

    Screenshot of Azure DevOps showing the pipeline run's Smoke Test stage for the test environment. The status shows that the stage failed.

  7. Selecteer de stap Betrouwbaarheidstests uitvoeren om de bijbehorende sectie van het pijplijnlogboek weer te geven.

    Screenshot of Azure DevOps showing the pipeline run log, with the output of the smoke test displayed. The JSON health test result is highlighted.

    U ziet dat het pijplijnlogboek het antwoord van de statuscontrole bevat. Het antwoord geeft aan dat er een probleem is met de communicatie van de toepassing met Azure SQL Database. De database is nog niet geïmplementeerd of geconfigureerd. Daarom heeft de website er geen toegang toe. In de volgende oefening lost u dit configuratieprobleem op.