練習 - 部署 Web 應用程式
在您的玩具公司,您的網站開發小組已向您的 Git 存放庫認可最新版的網站。 現在,您已準備好更新工作流程來建立網站,並部署至 Azure App Service。
在此程序中,您將會:
- 為建置作業新增新呼叫的工作流程。
- 更新工作流程以包括建置作業。
- 新增煙霧測試。
- 更新部署作業以部署應用程式。
- 執行工作流程。
為建置作業新增可重複使用的工作流程
在這裡,您會新增包含建置網站應用程式所需步驟的新作業定義。
打開 Visual Studio Code。
在 .github/workflows 資料夾中,建立名為 build.yml 的新檔案。
將下列內容新增至 build.yml 工作流程檔案:
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
此作業會安裝 .NET SDK 來建置解決方案。 然後,其會執行建置步驟,以將網站應用程式的原始程式碼轉換成可在 Azure 中執行的已編譯檔案。 接著,此作業會壓縮已編譯的成品,並將其上傳為工作流程成品。
儲存對檔案所做的變更。
將建置作業新增至工作流程
開啟 workflow.yml 檔案。
在 jobs: 行下方,在 lint 作業之前,新增名為 build 的新作業,使其能使用您剛才定義的可重複使用工作流程:
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
更新 deploy-test 作業,以相依於新的 build 作業:
# 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 }}
更新 deploy-production 作業,以同樣也相依於 built 和 lint 作業。
# 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 }}
由於生產部署會相依於測試部署,您並非一定要指定相依性。 但是明確定義是良好的做法,這是為了避免在您重新排序或移除作業或環境的情況下,導致工作流程以錯誤的方式執行。
請注意,您會以兩種不同的方式來指定
needs
清單:測試環境部署的相依性會列在單一行上,而實際執行環境的相依性則會使用多行清單。 這兩種方法都相等。儲存對檔案所做的變更。
更新煙霧測試檔案
網站開發人員已將健康情況端點新增至網站。 此端點會檢查網站是否在線上,以及是否可以連線到資料庫。 在這裡,您會新增煙霧測試,以從部署工作流程叫用健康情況檢查。
開啟 [deploy] 資料夾中的 Website.Tests.ps1 檔案。
新增測試案例來叫用健康情況檢查。 如果回應碼不是 200 (表示成功),測試案例便會失敗:
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" } }
儲存對檔案所做的變更。
將輸出新增至 Bicep 檔案
您很快就會新增部署步驟,以將網站發佈至 Azure App Service。 發佈步驟需要 App Service 應用程式的名稱。 在這裡,您會公開應用程式名稱作為 Bicep 檔案的輸出。
在 deploy 資料夾中開啟 main.bicep 檔案。
在檔案內容的結尾,新增 App Service 應用程式的名稱作為輸出:
output appServiceAppName string = appServiceApp.name output appServiceAppHostName string = appServiceApp.properties.defaultHostName
儲存對檔案所做的變更。
更新部署作業以傳播輸出
現在,您需要更新 deploy 作業,以取得 Bicep 部署的輸出值,並將其提供給工作流程的其餘部分使用。
開啟 .github/workflows 資料夾中的 deploy.yml 檔案。
在 deploy 作業的定義中,新增
appServiceAppName
的新輸出:deploy: needs: validate environment: ${{ inputs.environmentType }} runs-on: ubuntu-latest outputs: appServiceAppName: ${{ steps.deploy.outputs.appServiceAppName }} appServiceAppHostName: ${{ steps.deploy.outputs.appServiceAppHostName }} steps:
注意
當您開始在 Visual Studio Code 中使用 YAML 檔案時,您可能會看到一些紅色波浪線來指出有問題存在。 這是因為 YAML 檔案的 Visual Studio Code 延伸模組有時會猜錯檔案的結構描述。
您可以忽略延伸模組所報告的問題。 或者,如果您想要的話,也可以在檔案頂端新增下列程式碼,以隱藏擴充功能的猜測:
# yaml-language-server: $schema=./deploy.yml
新增作業以部署網站
在 deploy 作業定義下方和 smoke-test 作業定義上方,定義新的作業以將網站部署至 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
注意
請小心使用 YAML 檔案的縮排,確保新作業在與
deploy
作業相同的層級縮排。 如果您不確定,請從下一個步驟中的範例複製整個 deploy.yml 檔案內容。請注意,作業會使用
needs
關鍵字來相依於 deploy 作業。 相依性可確保在基礎結構就緒之前不會部署網站。 其也可讓作業存取 deploy 作業的appServiceAppName
輸出。此外,請注意,此作業包括下載工作流程成品和登入 Azure 的步驟。 每個作業都會在自己的執行器上執行,因此必須為獨立式。
儲存對檔案所做的變更。
確認 deploy.yml 檔案內容,並認可您的變更
確認 deploy.yml 檔案看起來像下列範例:
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
儲存對檔案所做的變更。
在 Visual Studio Code 終端機中執行下列命令,以認可您所做的變更,並將其推送至您的 Git 存放庫:
git add . git commit -m "Build and deploy website application" git push
這是您第一次推送至此存放庫,因此系統可能會提示您登入。
在 Windows 上,輸入 1 以使用網頁瀏覽器進行驗證,然後選取 Enter。
在 macOS 上,選取 [授權]。
瀏覽器視窗隨即出現。 您可能需要重新登入 GitHub。 選取授權。
執行工作流程
在瀏覽器中,前往 [Actions] \(動作\)。
您工作流程的首次執行 (標示為 [Initial commit] \(初始認可\)) 會顯示為失敗。 在您建立存放庫時,GitHub 會自動執行工作流程。 因為當時沒有準備好祕密,因此其會失敗。 您可以忽略此失敗。
選取 [deploy-toy-website-end-to-end] 工作流程。
選取工作流程的最新執行。
等候 build 作業順利完成。
等候 deploy-test / deploy 作業順利完成。
某些警告會列在 [Annotations] \(註釋\) 面板中。 所有這些警告都是因為 Bicep 將資訊訊息寫入工作流程記錄的方式所致。 您可以忽略這些警告。
然後,工作流程會執行 deploy-test / smoke-test 作業,但煙霧測試會失敗:
選取 deploy-test / smoke-test 作業以開啟工作流程記錄。
選取 [Run smoke tests] \(執行煙霧測試\) 步驟,以檢視工作流程記錄的相關聯區段:
請注意,工作流程記錄指出網站和設定狀況不良。 應用程式與 Azure SQL Database 的通訊發生問題。 您尚未部署或設定資料庫,這就是網站無法加以存取的原因。 你將能很快解決此問題。