Övning – Distribuera ett webbprogram

Slutförd

På ditt leksaksföretag har ditt webbplatsutvecklingsteam bekräftat den senaste versionen av webbplatsen till din Git-lagringsplats. Nu är du redo att uppdatera arbetsflödet för att skapa webbplatsen och distribuera den till Azure App Service.

I processen gör du följande:

  • Lägg till ett nytt arbetsflöde med namnet för byggjobbet.
  • Uppdatera arbetsflödet så att det inkluderar byggjobbet.
  • Lägg till ett nytt röktest.
  • Uppdatera distributionsjobbet för att distribuera programmet.
  • Kör arbetsflödet.

Lägga till ett återanvändbart arbetsflöde för byggjobbet

Här lägger du till en ny jobbdefinition som innehåller de steg som krävs för att skapa webbplatsprogrammet.

  1. Öppna Visual Studio Code.

  2. I mappen .github/workflows skapar du en ny fil med namnet build.yml.

    Skärmbild av Visual Studio Code Explorer, med dot github- och arbetsflödesmapparna och YML-filen för byggpunkt som visas.

  3. Lägg till följande innehåll i build.yml arbetsflödesfilen:

    name: build-website
    
    on:
      workflow_call:
    
    jobs:
      build-application:
        name: Build application
        runs-on: ubuntu-latest
        steps:
        - uses: actions/checkout@v3
    
        - name: Install .NET Core
          uses: actions/setup-dotnet@v3
          with:
            dotnet-version: 3.1
    
        - name: Build publishable website
          run: |
            dotnet publish --configuration Release
          working-directory: ./src/ToyCompany/ToyCompany.Website
    
        - name: Zip publishable website
          run: |
            zip -r publish.zip .
          working-directory: ./src/ToyCompany/ToyCompany.Website/bin/Release/netcoreapp3.1/publish
    
        - name: Upload website as workflow artifact
          uses: actions/upload-artifact@v3
          with:
            name: website
            path: ./src/ToyCompany/ToyCompany.Website/bin/Release/netcoreapp3.1/publish/publish.zip
    

    Jobbet installerar .NET SDK för att skapa lösningen. Sedan körs ett byggsteg för att omvandla webbplatsprogrammets källkod till en kompilerad fil som är redo att köras i Azure. Jobbet komprimerar sedan den kompilerade artefakten och laddar upp den som en arbetsflödesartefakt.

  4. Spara ändringarna i filen.

Lägg till byggjobbet i arbetsflödet

  1. Öppna filen workflow.yml .

  2. Under jobben : rad, före lint-jobbet , lägger du till ett nytt jobb med namnet build som använder det återanvändbara arbetsflödet som du precis definierade:

    name: deploy-toy-website-end-to-end
    concurrency: toy-company
    
    on:
      push:
        branches:
          - main
      workflow_dispatch:
    
    permissions:
      id-token: write
      contents: read
    
    jobs:
    
      # Build the application and database.
      build:
        uses: ./.github/workflows/build.yml
    
      # Lint the Bicep file.
      lint:
        uses: ./.github/workflows/lint.yml
    
  3. Uppdatera distributionstestjobbet så att det är beroende av det nya byggjobbet:

    # Deploy to the test environment.
    deploy-test:
      uses: ./.github/workflows/deploy.yml
      needs: [build, lint]
      with:
        environmentType: Test
        resourceGroupName: ToyWebsiteTest
        reviewApiUrl: https://sandbox.contoso.com/reviews
      secrets:
        AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID_TEST }}
        AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
        AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
        reviewApiKey: ${{ secrets.REVIEW_API_KEY_TEST }}
    
  4. Uppdatera distributionsproduktionsjobbet så att det även beror på bygg- och lint-jobben.

    # Deploy to the production environment.
    deploy-production:
      uses: ./.github/workflows/deploy.yml
      needs:
      - lint
      - build
      - deploy-test
      with:
        environmentType: Production
        resourceGroupName: ToyWebsiteProduction
        reviewApiUrl: https://api.contoso.com/reviews
      secrets:
        AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID_PRODUCTION }}
        AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
        AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
        reviewApiKey: ${{ secrets.REVIEW_API_KEY_PRODUCTION }}
    

    Eftersom produktionsdistributionen är beroende av testdistributionen behöver du inte ange beroenden. Men det är en bra idé att vara explicit för att undvika att arbetsflödet körs felaktigt om du ändrar ordning på eller tar bort dina jobb eller miljöer.

    Observera att needs du anger listan på två olika sätt – beroenden för din testmiljödistribution visas på en enda rad och produktionsmiljöns med hjälp av en lista med flera rader. De två metoderna är likvärdiga.

  5. Spara ändringarna i filen.

Uppdatera röktestfilen

Webbplatsutvecklarna har lagt till en hälsoslutpunkt på webbplatsen. Den här slutpunkten kontrollerar att webbplatsen är online och att den kan nå databasen. Här lägger du till ett nytt röktest för att anropa hälsokontrollen från distributionsarbetsflödet.

  1. Öppna filen Website.Tests.ps1 i mappen deploy.

  2. Lägg till ett nytt testfall som anropar hälsokontrollen. Testfallet misslyckas om svarskoden inte är 200, vilket indikerar att det lyckades:

    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. Spara ändringarna i filen.

Lägga till utdata i Bicep-filen

Du kommer snart att lägga till ett distributionssteg som publicerar din webbplats till Azure App Service. Publiceringssteget kräver namnet på App Service-appen. Här exponerar du appnamnet som utdata från din Bicep-fil.

  1. Öppna filen main.bicep i distributionsmappen.

  2. I slutet av filinnehållet lägger du till App Service-appens namn som utdata:

    output appServiceAppName string = appServiceApp.name
    output appServiceAppHostName string = appServiceApp.properties.defaultHostName
    
  3. Spara ändringarna i filen.

Uppdatera distributionsjobbet för att sprida utdata

Nu måste du uppdatera distributionsjobbet för att ta värdet för utdata från Bicep-distributionen och göra det tillgängligt för resten av arbetsflödet.

  1. Öppna filen deploy.yml i mappen .github/workflows .

  2. I distributionsjobbets definition lägger du till ett nytt utdata för appServiceAppName:

    deploy:
      needs: validate
      environment: ${{ inputs.environmentType }}
      runs-on: ubuntu-latest
      outputs:
        appServiceAppName: ${{ steps.deploy.outputs.appServiceAppName }}
        appServiceAppHostName: ${{ steps.deploy.outputs.appServiceAppHostName }}
      steps:
    

    Kommentar

    När du börjar arbeta med YAML-filen i Visual Studio Code kan du se några röda vågiga rader som säger att det finns ett problem. Det beror på att Visual Studio Code-tillägget för YAML-filer ibland felaktigt gissar filens schema.

    Du kan ignorera de problem som tillägget rapporterar. Eller om du vill kan du lägga till följande kod överst i filen för att utelämna tilläggets gissning:

    # yaml-language-server: $schema=./deploy.yml
    

Lägga till ett jobb för att distribuera webbplatsen

  1. Under definitionen för distributionsjobbet och ovanför definitionen för röktestjobb definierar du ett nytt jobb för att distribuera webbplatsen till App Service:

    deploy-website:
      needs: deploy
      environment: ${{ inputs.environmentType }}
      runs-on: ubuntu-latest
      steps:
      - uses: actions/download-artifact@v3
      - uses: azure/login@v1
        name: Sign in to Azure
        with:
          client-id: ${{ secrets.AZURE_CLIENT_ID }}
          tenant-id: ${{ secrets.AZURE_TENANT_ID }}
          subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
      - uses: azure/webapps-deploy@v2
        name: Deploy website
        with:
          app-name: ${{ needs.deploy.outputs.appServiceAppName }}
          package: website/publish.zip
    

    Kommentar

    Var försiktig med indraget för YAML-filen och se till att det nya jobbet är indraget på samma nivå som deploy jobbet. Om du inte är säker kopierar du hela deploy.yml filinnehållet från exemplet i nästa steg.

    Observera att jobbet är beroende av distributionsjobbet med hjälp av nyckelordet needs . Det här beroendet säkerställer att webbplatsen inte distribueras förrän infrastrukturen är klar. Det gör också att jobbet kan komma åt appServiceAppName utdata från distributionsjobbet.

    Observera också att det här jobbet innehåller steg för att ladda ned arbetsflödesartefakter och logga in på Azure. Varje jobb körs på sin egen löpare, så det måste vara självständigt.

  2. Spara ändringarna i filen.

Verifiera innehållet i deploy.yml-filen och checka in ändringarna

  1. Kontrollera att filen deploy.yml ser ut som i följande exempel:

    name: deploy
    
    on:
      workflow_call:
        inputs:
          environmentType:
            required: true
            type: string
          resourceGroupName:
            required: true
            type: string
          reviewApiUrl:
            required: true
            type: string
        secrets:
          AZURE_CLIENT_ID:
            required: true
          AZURE_TENANT_ID:
            required: true
          AZURE_SUBSCRIPTION_ID:
            required: true
          reviewApiKey:
            required: true
    
    jobs:
      validate:
         runs-on: ubuntu-latest
         steps:
         - uses: actions/checkout@v3
         - uses: azure/login@v1
           name: Sign in to Azure
           with:
             client-id: ${{ secrets.AZURE_CLIENT_ID }}
             tenant-id: ${{ secrets.AZURE_TENANT_ID }}
             subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
         - if: inputs.environmentType != 'Production'
           uses: azure/arm-deploy@v1
           name: Run preflight validation
           with:
             deploymentName: ${{ github.run_number }}
             resourceGroupName: ${{ inputs.resourceGroupName }}
             template: ./deploy/main.bicep
             parameters: >
               environmentType=${{ inputs.environmentType }}
               reviewApiUrl=${{ inputs.reviewApiUrl }}
               reviewApiKey=${{ secrets.reviewApiKey }}
             deploymentMode: Validate
         - if: inputs.environmentType == 'Production'
           uses: azure/arm-deploy@v1
           name: Run what-if
           with:
             failOnStdErr: false
             resourceGroupName: ${{ inputs.resourceGroupName }}
             template: ./deploy/main.bicep
             parameters: >
               environmentType=${{ inputs.environmentType }}
               reviewApiUrl=${{ inputs.reviewApiUrl }}
               reviewApiKey=${{ secrets.reviewApiKey }}
             additionalArguments: --what-if
    
      deploy:
        needs: validate
        environment: ${{ inputs.environmentType }}
        runs-on: ubuntu-latest
        outputs:
          appServiceAppName: ${{ steps.deploy.outputs.appServiceAppName }}
          appServiceAppHostName: ${{ steps.deploy.outputs.appServiceAppHostName }}
        steps:
        - uses: actions/checkout@v3
        - uses: azure/login@v1
          name: Sign in to Azure
          with:
            client-id: ${{ secrets.AZURE_CLIENT_ID }}
            tenant-id: ${{ secrets.AZURE_TENANT_ID }}
            subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
        - uses: azure/arm-deploy@v1
          id: deploy
          name: Deploy Bicep file
          with:
            failOnStdErr: false
            deploymentName: ${{ github.run_number }}
            resourceGroupName: ${{ inputs.resourceGroupName }}
            template: ./deploy/main.bicep
            parameters: >
               environmentType=${{ inputs.environmentType }}
               reviewApiUrl=${{ inputs.reviewApiUrl }}
               reviewApiKey=${{ secrets.reviewApiKey }}
    
      deploy-website:
        needs: deploy
        environment: ${{ inputs.environmentType }}
        runs-on: ubuntu-latest
        steps:
        - uses: actions/download-artifact@v3
        - uses: azure/login@v1
          name: Sign in to Azure
          with:
            client-id: ${{ secrets.AZURE_CLIENT_ID }}
            tenant-id: ${{ secrets.AZURE_TENANT_ID }}
            subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
        - uses: azure/webapps-deploy@v2
          name: Deploy website
          with:
            app-name: ${{ needs.deploy.outputs.appServiceAppName }}
            package: website/publish.zip
    
      smoke-test:
        runs-on: ubuntu-latest
        needs: deploy
        steps:
        - uses: actions/checkout@v3
        - run: |
            $container = New-PesterContainer `
              -Path 'deploy/Website.Tests.ps1' `
              -Data @{ HostName = '${{needs.deploy.outputs.appServiceAppHostName}}' }
            Invoke-Pester `
              -Container $container `
              -CI
          name: Run smoke tests
          shell: pwsh
    
  2. Spara ändringarna i filen.

  3. I Visual Studio Code-terminalen checkar du in och push-överför dina ändringar till Git-lagringsplatsen genom att köra följande kommandon:

    git add .
    git commit -m "Build and deploy website application"
    git push
    
  4. Det här är första gången du skickar till den här lagringsplatsen, så du kan uppmanas att logga in.

    I Windows skriver du 1 för att autentisera med hjälp av en webbläsare och väljer Retur.

    På macOS väljer du Auktorisera.

  5. Ett webbläsarfönster öppnas. Du kan behöva logga in på GitHub igen. Välj Auktorisera.

Kör arbetsflödet

  1. Gå till Åtgärder i webbläsaren.

    Den första körningen av arbetsflödet, märkt Initial commit, visas som ett fel. GitHub körde automatiskt arbetsflödet när du skapade lagringsplatsen. Det misslyckades eftersom hemligheterna inte var redo vid den tidpunkten. Du kan ignorera det här felet.

  2. Välj arbetsflödet deploy-toy-website-end-to-end.

  3. Välj den senaste körningen av arbetsflödet.

  4. Vänta tills byggjobbet har slutförts.

    Skärmbild av GitHub som visar arbetsflödets körningsjobb.

  5. Vänta tills distributionstest -/distributionsjobbet har slutförts.

    Vissa varningar visas i panelen Anteckningar . Alla dessa varningar beror på hur Bicep skriver informationsmeddelanden till arbetsflödesloggen. Du kan ignorera dessa varningar.

  6. Arbetsflödet kör sedan jobbet deploy-test/smoke-test , men röktestet misslyckas:

    Skärmbild av GitHub som visar arbetsflödeskörningens röktestjobb för testmiljön. Statusen visar att jobbet har misslyckats.

  7. Välj jobbet deploy-test/smoke-test för att öppna arbetsflödesloggen.

  8. Välj steget Kör röktester för att visa det associerade avsnittet i arbetsflödesloggen:

    Skärmbild av GitHub som visar arbetsflödets körningslogg med utdata från röktestet. JSON-hälsotestresultatet är markerat.

    Observera att arbetsflödesloggen anger att webbplatsen och konfigurationen inte är felfri. Det är problem med programmets kommunikation med Azure SQL Database. Du har ännu inte distribuerat eller konfigurerat en databas, vilket är anledningen till att webbplatsen inte kan komma åt den. Du löser det här problemet snart.