Übung: Bereitstellen einer Web-App in Azure
In Ihrem Spielzeugunternehmen hat Ihr Websiteentwicklungsteam die neueste Version der Website in Ihr Git-Repository committet. Nun können Sie Ihren Workflow aktualisieren, um die Website zu erstellen und in Azure App Service bereitzustellen.
Dabei gehen Sie wie folgt vor:
- Fügen Sie einen neuen Workflow für den Buildauftrag hinzu.
- Aktualisieren Sie den Workflow, um den Buildauftrag einzuschließen.
- Fügen Sie eine neue Feuerprobe hinzu.
- Aktualisieren Sie den Bereitstellungsauftrag, um die Anwendung bereitzustellen.
- Führen Sie den Workflow aus.
Hinzufügen eines wiederverwendbaren Workflows für den Buildauftrag
Hier fügen Sie eine neue Auftragsdefinition hinzu, die die erforderlichen Schritte zum Erstellen der Websiteanwendung enthält.
Öffnen Sie Visual Studio Code.
Erstellen Sie im Ordner .github/workflows eine neue Datei mit dem Namen build.yml.
Fügen Sie der Workflowdatei build.yml den folgenden Inhalt hinzu:
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
Der Auftrag installiert das .NET SDK, um die Projektmappe zu erstellen. Anschließend führt er einen Buildschritt aus, um den Quellcode der Websiteanwendung in eine kompilierte Datei umzuwandeln, die in Azure ausgeführt werden kann. Der Auftrag komprimiert dann das kompilierte Artefakt und lädt es als Workflowartefakt hoch.
Speichern Sie die geänderte Datei.
Hinzufügen des Buildauftrags zum Workflow
Öffnen Sie die Datei workflow.yml.
Fügen Sie unterhalb der Zeile jobs: vor dem Auftrag lint einen neuen Auftrag mit dem Namen build ein, der den soeben definierten wiederverwendbaren Workflow nutzt:
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
Aktualisieren Sie den Auftrag deploy-test, damit er vom Auftrag build abhängt:
# 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 }}
Aktualisieren Sie den Auftrag deploy-production, damit er auch von den Aufträgen build und lint abhängt.
# 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 }}
Da die Produktionsbereitstellung von der Testbereitstellung abhängt, müssen Sie die Abhängigkeiten nicht unbedingt angeben. Es wird aber als Best Practice empfohlen, dies explizit anzugeben. So wird vermieden, dass Ihr Workflow nicht korrekt ausgeführt wird, wenn Sie Ihre Aufträge oder Umgebungen neu anordnen oder entfernen.
Beachten Sie, dass Sie die
needs
-Liste auf zwei verschiedene Arten angeben – die Abhängigkeiten Ihrer Testumgebungsbereitstellung werden in einer einzigen Zeile aufgeführt, die Ihrer Produktionsumgebung in einer mehrzeiligen Liste. Die beiden Ansätze sind gleichwertig.Speichern Sie die geänderte Datei.
Aktualisieren der Datei für die Feuerprobe
Die Websiteentwickler haben der Website einen Integritätsendpunkt hinzugefügt. Dieser Endpunkt überprüft, ob die Website online ist und die Datenbank erreichen kann. Hier fügen Sie eine neue Feuerprobe hinzu, um die Integritätsprüfung aus Ihrem Bereitstellungsworkflow aufzurufen.
Öffnen Sie die Datei Website.Tests.ps1 im Ordner deploy.
Fügen Sie einen neuen Testfall hinzu, der die Integritätsprüfung aufruft. Der Testfall schlägt fehl, wenn nicht der Antwortcode 200 für einen erfolgreichen Test angegeben wird:
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" } }
Speichern Sie die geänderte Datei.
Hinzufügen der Ausgabe zur Bicep-Datei
In Kürze fügen Sie einen Bereitstellungsschritt hinzu, der Ihre Website in Azure App Service veröffentlicht. Für den Veröffentlichungsschritt ist der Name der App Service-App erforderlich. Hier machen Sie den App-Namen als Ausgabe aus Ihrer Bicep-Datei verfügbar.
Öffnen Sie die Datei main.bicep im Ordner deploy.
Fügen Sie am Ende des Dateiinhalts den Namen der App Service-App als Ausgabe hinzu:
output appServiceAppName string = appServiceApp.name output appServiceAppHostName string = appServiceApp.properties.defaultHostName
Speichern Sie die geänderte Datei.
Aktualisieren des Bereitstellungsauftrags zur Verteilung der Ausgabe
Nun müssen Sie Ihren Auftrag deploy aktualisieren, um den Wert der Ausgabe aus der Bicep-Bereitstellung zu übernehmen und für den Rest des Workflows verfügbar zu machen.
Öffnen Sie die Datei deploy.yml im Ordner .github/workflows.
Fügen Sie der deploy-Auftragsdefinition eine neue Ausgabe für
appServiceAppName
hinzu:deploy: needs: validate environment: ${{ inputs.environmentType }} runs-on: ubuntu-latest outputs: appServiceAppName: ${{ steps.deploy.outputs.appServiceAppName }} appServiceAppHostName: ${{ steps.deploy.outputs.appServiceAppHostName }} steps:
Hinweis
Wenn Sie beginnen, mit Ihrer YAML-Datei in Visual Studio Code zu arbeiten, werden möglicherweise einige rote Wellenlinien angezeigt, die darauf hindeuten, dass ein Problem vorliegt. Dies liegt daran, dass die Visual Studio Code-Erweiterung für YAML-Dateien manchmal fälschlicherweise das Schema der Datei errät.
Sie können die Probleme ignorieren, die die Erweiterung meldet. Wenn Sie möchten, können Sie den folgenden Code am Anfang der Datei hinzufügen, um das Raten durch die Erweiterung zu unterdrücken:
# yaml-language-server: $schema=./deploy.yml
Hinzufügen eines Auftrags zum Bereitstellen der Website
Definieren Sie unterhalb der deploy-Auftragsdefinition und oberhalb der smoke-test-Auftragsdefinition einen neuen Auftrag für die Bereitstellung der Website in 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
Hinweis
Achten Sie auf die Einzüge der YAML-Datei und stellen Sie sicher, dass der neue Bereitstellungsschritt auf der gleichen Ebene wie der Auftrag
deploy
eingerückt ist. Wenn Sie nicht sicher sind, kopieren Sie den gesamten Inhalt der Datei deploy.yml aus dem Beispiel im nächsten Schritt.Beachten Sie, dass der Auftrag durch die Verwendung des Schlüsselworts
needs
vom Auftrag deploy abhängt. Mit dieser Abhängigkeit wird sichergestellt, dass die Website erst bereitgestellt wird, wenn die Infrastruktur bereit ist. Darüber hinaus kann der Auftrag auf die AusgabeappServiceAppName
des Auftrags deploy zugreifen.Beachten Sie außerdem, dass dieser Auftrag Schritte zum Herunterladen der Workflowartefakte und zur Anmeldung bei Azure enthält. Jeder Auftrag wird in einem eigenen Runner ausgeführt und muss deshalb eigenständig sein.
Speichern Sie die geänderte Datei.
Überprüfen des Inhalts der Datei deploy.yml und Committen Ihrer Änderungen
Vergewissern Sie sich, dass die Datei deploy.yml wie im folgenden Beispiel aussieht:
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
Speichern Sie die geänderte Datei.
Committen und pushen Sie Ihre Änderungen im Visual Studio Code-Terminal in Ihr Git-Repository, indem Sie die folgenden Befehle ausführen:
git add . git commit -m "Build and deploy website application" git push
Dies ist das erste Mal, dass Sie dieses Repository verwendet haben, sodass Sie u. U. aufgefordert werden, sich anzumelden.
Geben Sie unter Windows 1 ein, um sich über einen Webbrowser zu authentifizieren, und drücken Sie die EINGABETASTE.
Wählen Sie unter macOS Authorize (Autorisieren) aus.
Ein Browserfenster wird geöffnet. Sie müssen sich möglicherweise erneut bei GitHub anmelden. Wählen Sie Autorisieren.
Ausführen des Workflows
Navigieren Sie in Ihrem Browser zu Actions.
Für die erste Ausführung Ihres Workflows mit der Bezeichnung Initial commit (Erster Commit) wird ein Fehler angezeigt. GitHub hat den Workflow automatisch ausgeführt, als Sie das Repository erstellt haben. Der Fehler ist aufgetreten, da die Geheimnisse zu diesem Zeitpunkt nicht verfügbar waren. Diesen Fehler können Sie ignorieren.
Wählen Sie den Workflow deploy-toy-website-end-to-end aus.
Wählen Sie die letzte Ausführung Ihres Workflows aus.
Warten Sie, bis der Auftrag build erfolgreich abgeschlossen wurde.
Warten Sie, bis der Auftrag deploy-test / deploy erfolgreich abgeschlossen wurde.
Im Bereich Annotations (Anmerkungen) werden einige Warnungen aufgeführt. All diese Warnungen sind darauf zurückzuführen, wie Bicep Informationsmeldungen in das Workflowprotokoll schreibt. Sie können diese Warnungen ignorieren.
Der Workflow führt dann den Auftrag deploy-test / smoke-test, aber die Feuerprobe ist nicht erfolgreich:
Wählen Sie den Auftrag deploy-test / smoke-test aus, um das Workflowprotokoll zu öffnen.
Wählen Sie den Schritt deploy-test / smoke-test aus, um den zugehörigen Abschnitt im Workflowprotokoll anzuzeigen:
Beachten Sie, dass das Workflowprotokoll anzeigt, dass die Website und die Konfiguration nicht fehlerfrei sind. Es liegt ein Problem bei der Kommunikation der Anwendung mit Azure SQL-Datenbank vor. Sie haben noch keine Datenbank bereitgestellt oder konfiguriert, weshalb die Website nicht darauf zugreifen kann. Sie beheben dieses Problem zeitnah.