練習 - 將測試作業新增至工作流程

已完成

您的玩具公司安全性小組希望您確認網站只能透過 HTTPS 存取。 在此練習中,您將設定工作流程來執行煙霧測試,以檢查安全性小組的需求。

在此過程期間,您將執行下列工作:

  • 將測試指令碼新增至您的存放庫。
  • 更新工作流程定義以新增測試作業。
  • 執行工作流程並觀察測試失敗。
  • 修正 Bicep 檔案,並觀察工作流程順利執行。

新增測試指令碼

您將在此新增測試指令碼,以確認使用 HTTPS 時可存取網站,使用不安全的 HTTP 通訊協定時則無法存取。

  1. 在 Visual Studio Code 中的 [deploy] 資料夾內建立名為 Website.Tests.ps1 的新檔案。

    Visual Studio Code 總管的螢幕擷取畫面,其中顯示 [deploy] 資料夾和測試檔案。

  2. 將下列測試程式碼複製並貼到檔案中:

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

    這是 Pester 測試檔案的結果。 其需要名為 $HostName 的參數。 其會針對主機名稱執行兩項測試:

    • 嘗試透過 HTTPS 連線至網站。 如果伺服器回應 200 到 299 之間的 HTTP 回應狀態碼,表示連線成功,測試會通過。
    • 嘗試透過 HTTP 連線至網站。 如果伺服器回應 300 以上的 HTTP 回應狀態碼,測試會通過。

    本練習的目的並非一定要您了解測試檔案的詳細資料及其運作方式。 我們會在摘要中提供連結,如有興趣您可以自行深入了解。

將 Bicep 檔案的輸出發佈為作業輸出

您在上述步驟中建立的測試指令碼,需要主機名稱才能進行測試。 您的 Bicep 檔案已經包含輸出,但您必須先將其發佈為作業輸出,才能在煙霧測試中使用。

  1. 在 Visual Studio Code 中,開啟 [.github/workflows] 資料夾中的 workflow.yml 檔案。

  2. 部署作業中,將 id 新增至 Deploy website 步驟,以便參考該步驟。 此外,新增從部署步驟複製 appServiceAppHostName 輸出的作業輸出:

    deploy:
      runs-on: ubuntu-latest
      environment: Website
      needs: preview
      outputs:
        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 website
        with:
          failOnStdErr: false
          deploymentName: ${{ github.run_number }}
          resourceGroupName: ${{ env.AZURE_RESOURCEGROUP_NAME }}
          template: ./deploy/main.bicep
          parameters: environmentType=${{ env.ENVIRONMENT_TYPE }}
    
  3. 儲存檔案。

將煙霧測試作業新增至您的工作流程

現在,您可以新增執行測試的煙霧測試作業。

  1. 在檔案底端,為 smoke-test 作業新增下列定義:

    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
    

    此程式碼會定義作業。 作業包含檢查程式碼的步驟,以及使用 Pester 執行測試的步驟。

    作業定義會使用 needs 屬性來定義部署作業的相依性。 此相依性可確保作業在您要的序列中執行。 此外,可讓您在執行煙霧測試時使用部署作業的輸出。

    注意

    PowerShell 和 Pester 都預先安裝在 GitHub 託管的執行器上。 您不需要執行任何特殊動作,即可在指令碼步驟中使用兩者。

  2. 儲存檔案。

驗證並認可您的工作流程定義

  1. 驗證您的 workflow.yml 檔案是否如下列程式碼:

    name: deploy-toy-website-test
    concurrency: toy-company
    
    on:
      push:
        branches:
          - main
    
    permissions:
      id-token: write
      contents: read
    
    env:
      AZURE_RESOURCEGROUP_NAME: ToyWebsiteTest
      ENVIRONMENT_TYPE: Test
    
    jobs:
      lint:
        runs-on: ubuntu-latest
        steps:
        - uses: actions/checkout@v3
        - name: Run Bicep linter
          run: az bicep build --file deploy/main.bicep
    
      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 }}
        - uses: azure/arm-deploy@v1
          name: Run preflight validation
          with:
            deploymentName: ${{ github.run_number }}
            resourceGroupName: ${{ env.AZURE_RESOURCEGROUP_NAME }}
            template: ./deploy/main.bicep
            parameters: environmentType=${{ env.ENVIRONMENT_TYPE }}
            deploymentMode: Validate
    
      preview:
        runs-on: ubuntu-latest
        needs: [lint, validate]
        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
          name: Run what-if
          with:
            failOnStdErr: false
            resourceGroupName: ${{ env.AZURE_RESOURCEGROUP_NAME }}
            template: deploy/main.bicep
            parameters: >
              environmentType=${{ env.ENVIRONMENT_TYPE }}
            additionalArguments: --what-if
    
      deploy:
        runs-on: ubuntu-latest
        environment: Website
        needs: preview
        outputs:
          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 website
          with:
            failOnStdErr: false
            deploymentName: ${{ github.run_number }}
            resourceGroupName: ${{ env.AZURE_RESOURCEGROUP_NAME }}
            template: ./deploy/main.bicep
            parameters: environmentType=${{ env.ENVIRONMENT_TYPE }}
    
      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. 在 Visual Studio Code 終端機中執行下列命令,以認可所做的變更,並將其推送至您的 Git 存放庫:

    git add .
    git commit -m "Add test job"
    git push
    

執行工作流程並檢閱測試結果

  1. 在瀏覽器中,前往您的工作流程。

  2. 選取工作流程的最新執行。

    等候工作流程完成 lint 分析驗證預覽作業。 雖然 GitHub Actions 會以最新狀態自動更新頁面,但建議您偶爾重新整理頁面。

  3. 選取 [檢閱部署] 按鈕、選取 [網站] 環境,然後選取 [核准並部署]

    等待工作流程執行完畢。

  4. 請注意,部署作業會順利完成。 smoke-test 作業會完成,但發生錯誤。

    GitHub 介面螢幕擷取畫面,顯示工作流程執行作業。煙霧測試作業報告失敗。

  5. 選取 smoke-test 作業以查看其詳細資料。

  6. 請注意,smoke-test 輸出顯示已執行兩個測試。 一個通過,一個失敗。 失敗的測試會列為 Toy Website.Does not serve pages over HTTP

    GitHub 介面螢幕擷取畫面,顯示工作流程執行的測試結果,其中已醒目提示失敗的測試。

    此文字表示網站未正確設定以符合您的安全性小組的需求。

更新 Bicep 檔案

既然您已發現 Bicep 定義未符合您的安全性小組的需求,您可以加以修正。

  1. 在 Visual Studio Code 中,開啟 [deploy] 資料夾中的 main.bicep 檔案。

  2. 尋找 Azure App Service 應用程式的定義並予以更新,以在其 properties 區域中加入 httpsOnly 屬性:

    resource appServiceApp 'Microsoft.Web/sites@2022-03-01' = {
      name: appServiceAppName
      location: location
      properties: {
        serverFarmId: appServicePlan.id
        httpsOnly: true
        siteConfig: {
          appSettings: [
            {
              name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
              value: applicationInsights.properties.InstrumentationKey
            }
            {
              name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
              value: applicationInsights.properties.ConnectionString
            }
          ]
        }
      }
    }
    
  3. 儲存檔案。

  4. 在 Visual Studio Code 終端機中執行下列命令,以認可所做的變更,並將其推送至您的 Git 存放庫:

    git add .
    git commit -m "Configure HTTPS on website"
    git push
    

再次執行工作流程

  1. 在瀏覽器中,前往工作流程執行。

  2. 選取最近的執行。

    等候工作流程完成 lint 分析驗證預覽作業。 雖然 GitHub 會以最新狀態自動更新頁面,但建議您偶爾重新整理頁面。

  3. 選取預覽作業,然後再次檢閱假設狀況結果。

    請注意,假設狀況命令已偵測到 httpsOnly 屬性值中的變更:

    Resource and property changes are indicated with these symbols:
      - Delete
      + Create
      ~ Modify
      = Nochange
      * Ignore
    
    The deployment will update the following scope:
    
    Scope: /subscriptions/***/resourceGroups/ToyWebsiteTest
    
      ~ Microsoft.OperationalInsights/workspaces/workspace-abcdefghijklm [2022-10-01]
        - properties.retentionInDays: 30
        - properties.sku:
    
            name: "pergb2018"
    
        - properties.workspaceCapping:
    
            dailyQuotaGb: -1.0
    
      ~ Microsoft.Web/sites/toy-website-abcdefghijklm [2022-03-01]
        + properties.siteConfig.localMySqlEnabled:   false
        + properties.siteConfig.netFrameworkVersion: "v4.6"
        ~ properties.httpsOnly:                      false => true
    
      = Microsoft.Insights/components/toywebsite [2020-02-02]
      = Microsoft.Storage/storageAccounts/mystorageabcdefghijklm [2022-09-01]
      = Microsoft.Web/serverfarms/toy-website [2022-03-01]
      * microsoft.alertsmanagement/smartDetectorAlertRules/Failure Anomalies - toywebsite
    
    Resource changes: 2 to modify, 3 no change, 1 to ignore.
    
  4. 返回工作流程執行。

  5. 選取 [檢閱部署] 按鈕、選取 [網站] 環境,然後選取 [核准並部署]

    等待工作流程執行完畢。

  6. 請注意,整個工作流程會順利完成,包括 smoke-test 作業。 這表示兩個測試都通過了。

    GitHub 介面螢幕擷取畫面,顯示成功工作流程執行。

清除資源

完成本練習後,您可以移除資源以免產生費用。

在 Visual Studio Code 終端中,執行下列命令:

az group delete --resource-group ToyWebsiteTest --yes --no-wait

資源群組會在背景中刪除。

Remove-AzResourceGroup -Name ToyWebsiteTest -Force