Übung: Seeding eines Speicherkontos und einer Datenbank
Sie haben Ihren Workflow aktualisiert, um die Anwendung Ihrer Website in der Azure App Service-App zu erstellen und bereitzustellen, die in Ihrer Bicep-Datei definiert ist, aber der Feuerprobenauftrag ist fehlgeschlagen, da die Datenbank noch nicht funktioniert. In dieser Lerneinheit stellen Sie einen neuen logischen Azure SQL-Server und eine Datenbank bereit und konfigurieren Ihren Workflow für die Erstellung und Bereitstellung des Datenbankschemas. Außerdem aktualisieren Sie Ihren Workflow, um einige Beispielproduktdaten für Ihre Testumgebung hinzuzufügen, damit Ihr Team die Website ausprobieren kann.
Dabei gehen Sie wie folgt vor:
- Fügen Sie dem Azure-Speicherkonto einen Blobcontainer hinzu.
- Fügen Sie einen logischen Azure SQL-Server und eine Datenbank hinzu.
- Aktualisieren des Buildauftrags, um das Datenbankprojekt in eine DACPAC-Datei zu kompilieren
- Hinzufügen neuer Variablen und Geheimnisse für den logischen Azure SQL-Server und die Datenbank
- Aktualisieren Ihres Workflows, um die neuen Variablen und Geheimnisse zu verwenden
- Hinzufügen neuer Workflowschritte, um Ihre DACPAC-Datei bereitzustellen
- Ausführen des Workflows und Anzeigen der Website
Erstellen eines Speichercontainers
Ihre Bicep-Datei definiert bereits ein Speicherkonto, aber keinen Blobcontainer. Hier fügen Sie Ihrer Bicep-Datei einen Blobcontainer hinzu. Sie geben auch den Namen des Speicherkontos und Blobcontainers mithilfe der Konfigurationseinstellungen für die Anwendung an. Auf diese Weise weiß die App, auf welches Speicherkonto sie zugreifen soll.
Öffnen Sie in Visual Studio Code die Datei main.bicep im Ordner Bereitstellen.
Fügen Sie unter den Variablen, die Ressourcennamen definieren (in der Nähe von Zeile 27), eine neue Variablendefinition für den Namen des Blobspeichercontainers hinzu:
var storageAccountImagesBlobContainerName = 'toyimages'
Aktualisieren Sie die
storageAccount
-Ressource, um den Blobcontainer zu definieren:resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = { name: storageAccountName location: location kind: 'StorageV2' sku: environmentConfigurationMap[environmentType].storageAccount.sku resource blobService 'blobServices' = { name: 'default' resource storageAccountImagesBlobContainer 'containers' = { name: storageAccountImagesBlobContainerName properties: { publicAccess: 'Blob' } } } }
Aktualisieren Sie die
appSettings
-Eigenschaft der App, um zwei neue Anwendungseinstellungen hinzuzufügen: eine für den Speicherkontonamen und eine für den Blobcontainernamen: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 } { name: 'ReviewApiUrl' value: reviewApiUrl } { name: 'ReviewApiKey' value: reviewApiKey } { name: 'StorageAccountName' value: storageAccount.name } { name: 'StorageAccountBlobEndpoint' value: storageAccount.properties.primaryEndpoints.blob } { name: 'StorageAccountImagesContainerName' value: storageAccount::blobService::storageAccountImagesBlobContainer.name } ] } } }
Fügen Sie am Ende des Dateiinhalts neue Ausgaben hinzu, um die Namen des Speicherkontos und des Blobcontainers verfügbar zu machen:
output storageAccountName string = storageAccount.name output storageAccountImagesBlobContainerName string = storageAccount::blobService::storageAccountImagesBlobContainer.name
Speichern Sie die geänderte Datei.
Committen Sie Ihre Änderungen in Ihr Git-Repository, aber pushen Sie sie noch nicht. Führen Sie im Visual Studio Code-Terminal die folgenden Befehle aus:
git add . git commit -m "Add storage container"
Hinzufügen eines logischen Azure SQL-Servers und einer Datenbank
Ihre Bicep-Datei stellt derzeit keinen logischen Azure SQL-Server oder eine Datenbank bereit. In diesem Abschnitt fügen Sie diese Ressourcen Ihrer Bicep-Datei hinzu.
Fügen Sie am Anfang der Datei main.bicep unter dem Parameter
reviewApiKey
zwei neue Parameter hinzu:@description('The administrator login username for the SQL server.') param sqlServerAdministratorLogin string @secure() @description('The administrator login password for the SQL server.') param sqlServerAdministratorLoginPassword string
Fügen Sie unterhalb der Variablen, die Ressourcennamen definieren, neue Variablen hinzu, um die Namen Ihres logischen Azure SQL-Servers und der Datenbank zu definieren:
var sqlServerName = 'toy-website-${resourceNameSuffix}' var sqlDatabaseName = 'Toys'
Definieren Sie unter den soeben hinzugefügten Variablen eine neue Variable, die eine Verbindungszeichenfolge für die Anwendung für den Zugriff auf die Datenbank erstellt:
// Define the connection string to access Azure SQL. var sqlDatabaseConnectionString = 'Server=tcp:${sqlServer.properties.fullyQualifiedDomainName},1433;Initial Catalog=${sqlDatabase.name};Persist Security Info=False;User ID=${sqlServerAdministratorLogin};Password=${sqlServerAdministratorLoginPassword};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;'
Hinweis
Der Einfachheit halber verwendet die Anwendung die Administratoranmeldung und das Kennwort für den Zugriff auf die Datenbank. Dies ist jedoch keine bewährte Methode für eine Produktionslösung. Es ist besser, eine von App Service verwaltete Identität für den Zugriff auf die Datenbank zu verwenden und der verwalteten Identität die für die Anwendung erforderlichen Mindestberechtigungen zu gewähren. Weitere Informationen finden Sie auf der Zusammenfassungsseite dieses Moduls.
Fügen Sie am Ende des Dateiinhalts oberhalb der Ausgaben den logischen Azure SQL-Server und die Datenbank als Ressourcen hinzu:
resource sqlServer 'Microsoft.Sql/servers@2022-05-01-preview' = { name: sqlServerName location: location properties: { administratorLogin: sqlServerAdministratorLogin administratorLoginPassword: sqlServerAdministratorLoginPassword } } resource sqlServerFirewallRule 'Microsoft.Sql/servers/firewallRules@2022-05-01-preview' = { parent: sqlServer name: 'AllowAllWindowsAzureIps' properties: { endIpAddress: '0.0.0.0' startIpAddress: '0.0.0.0' } } resource sqlDatabase 'Microsoft.Sql/servers/databases@2022-05-01-preview' = { parent: sqlServer name: sqlDatabaseName location: location sku: environmentConfigurationMap[environmentType].sqlDatabase.sku }
Aktualisieren Sie die Variable
environmentConfigurationMap
, um die SKUs zu definieren, die für Ihre Datenbank für jede Umgebung verwendet werden:var environmentConfigurationMap = { Production: { appServicePlan: { sku: { name: 'S1' capacity: 1 } } storageAccount: { sku: { name: 'Standard_LRS' } } sqlDatabase: { sku: { name: 'Standard' tier: 'Standard' } } } Test: { appServicePlan: { sku: { name: 'F1' } } storageAccount: { sku: { name: 'Standard_GRS' } } sqlDatabase: { sku: { name: 'Standard' tier: 'Standard' } } } }
Fügen Sie Ihrer App Service-App eine weitere App-Einstellung für die Datenbankverbindungszeichenfolge hinzu:
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 } { name: 'ReviewApiUrl' value: reviewApiUrl } { name: 'ReviewApiKey' value: reviewApiKey } { name: 'StorageAccountName' value: storageAccount.name } { name: 'StorageAccountBlobEndpoint' value: storageAccount.properties.primaryEndpoints.blob } { name: 'StorageAccountImagesContainerName' value: storageAccount::blobService::storageAccountImagesBlobContainer.name } { name: 'SqlDatabaseConnectionString' value: sqlDatabaseConnectionString } ] } } }
Fügen Sie am Ende der Datei Ausgaben hinzu, um den Hostnamen des logischen Azure SQL-Servers und den Namen der Datenbank verfügbar zu machen:
output appServiceAppName string = appServiceApp.name output appServiceAppHostName string = appServiceApp.properties.defaultHostName output storageAccountName string = storageAccount.name output storageAccountImagesBlobContainerName string = storageAccount::blobService::storageAccountImagesBlobContainer.name output sqlServerFullyQualifiedDomainName string = sqlServer.properties.fullyQualifiedDomainName output sqlDatabaseName string = sqlDatabase.name
Speichern Sie die geänderte Datei.
Hinzufügen neuer Buildschritte für das Datenbankprojekt
Ihre Websiteentwickler haben ein Visual Studio-Datenbankprojekt vorbereitet, das Ihre Websitedatenbanktabelle bereitstellt und konfiguriert. Hier aktualisieren Sie Ihren Workflow build, um das Datenbankprojekt in eine DACPAC-Datei zu kompilieren und diese als Workflowartefakt hochzuladen.
Öffnen Sie die Datei build.yml im Ordner .github/workflows.
Um das Visual Studio-Datenbankprojekt zu kompilieren und die generierte DACPAC-Datei als Workflowartefakt hochzuladen, fügen Sie den Auftrag build-database 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 build-database: name: Build database runs-on: windows-latest steps: - uses: actions/checkout@v3 - name: Prepare MSBuild uses: microsoft/setup-msbuild@v1.1 - name: Build database project working-directory: ./src/ToyCompany/ToyCompany.Database run: MSBuild.exe ToyCompany.Database.sqlproj -property:Configuration=Release - name: Upload website as workflow artifact uses: actions/upload-artifact@v3 with: name: database path: ./src/ToyCompany/ToyCompany.Database/bin/Release/ToyCompany.Database.dacpac
Der Auftrag build-database verwendet einen Windows-Runner. Derzeit müssen Visual Studio-Datenbankprojekte auf dem Windows-Betriebssystem entwickelt werden.
Speichern Sie die geänderte Datei.
Definieren der Geheimnisse
Sie müssen das Administratorkennwort Ihres logischen Azure SQL-Servers für jede Umgebung sicher speichern. Sie entscheiden sich für die Verwendung von GitHub-Geheimnissen, um die Informationen zu schützen.
Wechseln Sie in Ihrem Browser zu Einstellungen>Geheimnisse und Variablen>Aktionen.
Wählen Sie die Schaltfläche New repository secret (Neues Repositorygeheimnis) aus.
Geben Sie SQL_SERVER_ADMINISTRATOR_LOGIN_PASSWORD_TEST als den geheimen Namen und SecurePassword!111 als Wert für den Wert ein.
Klicken Sie auf Add secret (Geheimnis hinzufügen).
Wiederholen Sie den Vorgang, um ein weiteres Geheimnis namens SQL_SERVER_ADMINISTRATOR_LOGIN_PASSWORD_PRODUCTION mit dem Wert SecurePassword!999 hinzuzufügen. Klicken Sie auf Add secret (Geheimnis hinzufügen).
Hinzufügen der Geheimnisse und Eingaben in Ihrem Workflow
Öffnen Sie in Visual Studio Code die Datei deploy.yml im Ordner .github/workflows.
Definieren Sie am Anfang der Datei eine neue Eingabe mit dem Namen
sqlServerAdministratorLogin
und ein neues Geheimnis mit dem NamensqlServerAdministratorLoginPassword
:name: deploy on: workflow_call: inputs: environmentType: required: true type: string resourceGroupName: required: true type: string reviewApiUrl: required: true type: string sqlServerAdministratorLogin: required: true type: string secrets: AZURE_CLIENT_ID: required: true AZURE_TENANT_ID: required: true AZURE_SUBSCRIPTION_ID: required: true reviewApiKey: required: true sqlServerAdministratorLoginPassword: required: true
Speichern Sie die geänderte Datei.
Öffnen Sie die Datei workflow.yml.
Definieren Sie in der Definition von deploy-test einen Wert für die
sqlServerAdministratorLogin
Eingabe und geben Sie den Wert für dassqlServerAdministratorLoginPassword
-Geheimnis weiter:# 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 sqlServerAdministratorLogin: TestToyCompanyAdmin 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 }} sqlServerAdministratorLoginPassword: ${{ secrets.SQL_SERVER_ADMINISTRATOR_LOGIN_PASSWORD_TEST }}
Wiederholen Sie Vorgang in der Definition deploy-production mit den Werten für die Produktionsumgebung:
# 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 sqlServerAdministratorLogin: ToyCompanyAdmin 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 }} sqlServerAdministratorLoginPassword: ${{ secrets.SQL_SERVER_ADMINISTRATOR_LOGIN_PASSWORD_PRODUCTION }}
Speichern Sie die geänderte Datei.
Hinzufügen von Parameterwerten und Ausgaben
Die Bicep-Datei verfügt jetzt über zwei neue obligatorische Parameter: sqlServerAdministratorLogin
und sqlServerAdministratorLoginPassword
. Hier geben Sie diese Parameterwerte aus Ihren Workfloweingaben und -geheimnissen für die Aufträge validate und deploy weiter. Sie geben außerdem die Ausgaben der Bicep-Bereitstellungen an die Ausgaben des Auftrags weiter.
Öffnen Sie die Datei deploy.yml.
Aktualisieren Sie den Schritt Run preflight validation (Preflightvalidierung ausführen) des Auftrags validate, um die neuen Parameter hinzuzufügen:
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 }} sqlServerAdministratorLogin=${{ inputs.sqlServerAdministratorLogin }} sqlServerAdministratorLoginPassword=${{ secrets.sqlServerAdministratorLoginPassword }} deploymentMode: Validate
Aktualisieren Sie den Schritt Run what-if (Was-wäre-wenn-Ausführung), um die neuen Parameter hinzuzufügen:
- 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 }} sqlServerAdministratorLogin=${{ inputs.sqlServerAdministratorLogin }} sqlServerAdministratorLoginPassword=${{ secrets.sqlServerAdministratorLoginPassword }} additionalArguments: --what-if
Aktualisieren Sie den Schritt Deploy Bicep file (Bicep-Datei bereitstellen) des Auftrags deploy, um die neuen Parameter hinzuzufügen:
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 }} sqlServerAdministratorLogin=${{ inputs.sqlServerAdministratorLogin }} sqlServerAdministratorLoginPassword=${{ secrets.sqlServerAdministratorLoginPassword }}
Fügen Sie der deploy-Auftragsdefinition neue Ausgaben für die Bicep-Datei hinzu:
deploy: needs: validate environment: ${{ inputs.environmentType }} runs-on: ubuntu-latest outputs: appServiceAppName: ${{ steps.deploy.outputs.appServiceAppName }} appServiceAppHostName: ${{ steps.deploy.outputs.appServiceAppHostName }} storageAccountName: ${{ steps.deploy.outputs.storageAccountName }} storageAccountImagesBlobContainerName: ${{ steps.deploy.outputs.storageAccountImagesBlobContainerName }} sqlServerFullyQualifiedDomainName: ${{ steps.deploy.outputs.sqlServerFullyQualifiedDomainName }} sqlDatabaseName: ${{ steps.deploy.outputs.sqlDatabaseName }}
Hinzufügen von Aufträgen für Datenbank und Datenseeding
In diesem Abschnitt definieren Sie die Schritte, die zum Bereitstellen der Datenbankkomponenten Ihrer Website erforderlich sind. Zunächst fügen Sie einen Schritt zum Bereitstellen der DACPAC-Datei hinzu, die der Workflow zuvor erstellt hat. Anschließend fügen Sie der Datenbank und dem Speicherkonto Beispieldaten hinzu, jedoch nur für Nicht-Produktionsumgebungen.
Fügen Sie unter dem Auftrag deploy-website einen neuen Auftrag zum Bereitstellen der DACPAC-Datei hinzu:
deploy-database: 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/sql-action@v1.2 name: Deploy DACPAC to database with: server-name: ${{ needs.deploy.outputs.sqlServerFullyQualifiedDomainName }} connection-string: ${{ format('Server={0};Initial Catalog={1};User Id={2};Password={3};', needs.deploy.outputs.sqlServerFullyQualifiedDomainName, needs.deploy.outputs.sqlDatabaseName, inputs.sqlServerAdministratorLogin, secrets.sqlServerAdministratorLoginPassword) }} dacpac-package: database/ToyCompany.Database.dacpac
Definieren Sie unterhalb des soeben hinzugefügten Auftrags und oberhalb des Auftrags smoke-test einen neuen Auftrag für das Seeding der Datenbank mit Beispieldaten.
seed-database: needs: - deploy - deploy-database environment: ${{ inputs.environmentType }} 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/sql-action@v1.2 name: Add test data to database with: server-name: ${{ needs.deploy.outputs.sqlServerFullyQualifiedDomainName }} connection-string: ${{ format('Server={0};Initial Catalog={1};User Id={2};Password={3};', needs.deploy.outputs.sqlServerFullyQualifiedDomainName, needs.deploy.outputs.sqlDatabaseName, inputs.sqlServerAdministratorLogin, secrets.sqlServerAdministratorLoginPassword) }} sql-file: 'deploy/sample-data/Toys.sql'
Beachten Sie, dass auf den Schritt Add test data to database (Testdaten zur Datenbank hinzufügen) eine Bedingung angewendet wurde. Sie wird nur für Nicht-Produktionsumgebungen ausgeführt. Die Bedingung gilt für den Schritt, nicht für den gesamten Auftrag, sodass spätere Aufträge unabhängig vom Umgebungstyp von diesem Auftrag abhängen können.
Definieren Sie unterhalb des soeben hinzugefügten Auftrags und oberhalb des Auftrags smoke-test einen weiteren Auftrag, um mithilfe der Azure CLI einige Beispielbilder von Spielzeug in den Blobcontainer hochzuladen:
seed-storage-account: needs: deploy environment: ${{ inputs.environmentType }} 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/CLI@v1 name: Upload sample images with: inlineScript: | az storage blob upload-batch \ --account-name ${{ needs.deploy.outputs.storageAccountName }} \ --destination ${{ needs.deploy.outputs.storageAccountImagesBlobContainerName }} \ --source 'deploy/sample-data/toyimages'
Beachten Sie, dass dieser Auftrag einen Ubuntu-Läufer verwendet, da für die
azure/cli
Aktion Linux ausgeführt werden muss, aber der von Ihnen definiertebuild-database
Auftrag verwendet einen Windows-Runner zum Erstellen des Datenbankprojekts. Dieser Workflow ist ein gutes Beispiel für das Verwenden verschiedener Betriebssysteme, um Ihre Anforderungen zu erfüllen.
Aktualisieren der Abhängigkeiten für den Auftrag „smoke-test“
Aktualisieren Sie die Abhängigkeiten des Auftrags smoke-test, um sicherzustellen, dass er nach Abschluss aller Bereitstellungsschritte ausgeführt wird:
smoke-test: runs-on: ubuntu-latest needs: - deploy - deploy-website - deploy-database - seed-database - seed-storage-account 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.
Überprüfen von Dateien und Commit ihrer Änderungen
Überprüfen Sie, ob die Datei main.bicep wie folgt aussieht:
@description('The location into which your Azure resources should be deployed.') param location string = resourceGroup().location @description('Select the type of environment you want to provision. Allowed values are Production and Test.') @allowed([ 'Production' 'Test' ]) param environmentType string @description('A unique suffix to add to resource names that need to be globally unique.') @maxLength(13) param resourceNameSuffix string = uniqueString(resourceGroup().id) @description('The URL to the product review API.') param reviewApiUrl string @secure() @description('The API key to use when accessing the product review API.') param reviewApiKey string @description('The administrator login username for the SQL server.') param sqlServerAdministratorLogin string @secure() @description('The administrator login password for the SQL server.') param sqlServerAdministratorLoginPassword string // Define the names for resources. var appServiceAppName = 'toy-website-${resourceNameSuffix}' var appServicePlanName = 'toy-website' var logAnalyticsWorkspaceName = 'workspace-${resourceNameSuffix}' var applicationInsightsName = 'toywebsite' var storageAccountName = 'mystorage${resourceNameSuffix}' var storageAccountImagesBlobContainerName = 'toyimages' var sqlServerName = 'toy-website-${resourceNameSuffix}' var sqlDatabaseName = 'Toys' // Define the connection string to access Azure SQL. var sqlDatabaseConnectionString = 'Server=tcp:${sqlServer.properties.fullyQualifiedDomainName},1433;Initial Catalog=${sqlDatabase.name};Persist Security Info=False;User ID=${sqlServerAdministratorLogin};Password=${sqlServerAdministratorLoginPassword};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;' // Define the SKUs for each component based on the environment type. var environmentConfigurationMap = { Production: { appServicePlan: { sku: { name: 'S1' capacity: 1 } } storageAccount: { sku: { name: 'Standard_LRS' } } sqlDatabase: { sku: { name: 'Standard' tier: 'Standard' } } } Test: { appServicePlan: { sku: { name: 'F1' } } storageAccount: { sku: { name: 'Standard_GRS' } } sqlDatabase: { sku: { name: 'Standard' tier: 'Standard' } } } } resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = { name: appServicePlanName location: location sku: environmentConfigurationMap[environmentType].appServicePlan.sku } 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 } { name: 'ReviewApiUrl' value: reviewApiUrl } { name: 'ReviewApiKey' value: reviewApiKey } { name: 'StorageAccountName' value: storageAccount.name } { name: 'StorageAccountBlobEndpoint' value: storageAccount.properties.primaryEndpoints.blob } { name: 'StorageAccountImagesContainerName' value: storageAccount::blobService::storageAccountImagesBlobContainer.name } { name: 'SqlDatabaseConnectionString' value: sqlDatabaseConnectionString } ] } } } resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2022-10-01' = { name: logAnalyticsWorkspaceName location: location } resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = { name: applicationInsightsName location: location kind: 'web' properties: { Application_Type: 'web' Request_Source: 'rest' Flow_Type: 'Bluefield' WorkspaceResourceId: logAnalyticsWorkspace.id } } resource storageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = { name: storageAccountName location: location kind: 'StorageV2' sku: environmentConfigurationMap[environmentType].storageAccount.sku resource blobService 'blobServices' = { name: 'default' resource storageAccountImagesBlobContainer 'containers' = { name: storageAccountImagesBlobContainerName properties: { publicAccess: 'Blob' } } } } resource sqlServer 'Microsoft.Sql/servers@2022-05-01-preview' = { name: sqlServerName location: location properties: { administratorLogin: sqlServerAdministratorLogin administratorLoginPassword: sqlServerAdministratorLoginPassword } } resource sqlServerFirewallRule 'Microsoft.Sql/servers/firewallRules@2022-05-01-preview' = { parent: sqlServer name: 'AllowAllWindowsAzureIps' properties: { endIpAddress: '0.0.0.0' startIpAddress: '0.0.0.0' } } resource sqlDatabase 'Microsoft.Sql/servers/databases@2022-05-01-preview' = { parent: sqlServer name: sqlDatabaseName location: location sku: environmentConfigurationMap[environmentType].sqlDatabase.sku } output appServiceAppName string = appServiceApp.name output appServiceAppHostName string = appServiceApp.properties.defaultHostName output storageAccountName string = storageAccount.name output storageAccountImagesBlobContainerName string = storageAccount::blobService::storageAccountImagesBlobContainer.name output sqlServerFullyQualifiedDomainName string = sqlServer.properties.fullyQualifiedDomainName output sqlDatabaseName string = sqlDatabase.name
Falls nicht, aktualisieren Sie sie so, dass sie mit dem Dateiinhalt übereinstimmt.
Überprüfen Sie, ob die Datei deploy.yml wie folgt aussieht:
name: deploy on: workflow_call: inputs: environmentType: required: true type: string resourceGroupName: required: true type: string reviewApiUrl: required: true type: string sqlServerAdministratorLogin: required: true type: string secrets: AZURE_CLIENT_ID: required: true AZURE_TENANT_ID: required: true AZURE_SUBSCRIPTION_ID: required: true reviewApiKey: required: true sqlServerAdministratorLoginPassword: 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 }} sqlServerAdministratorLogin=${{ inputs.sqlServerAdministratorLogin }} sqlServerAdministratorLoginPassword=${{ secrets.sqlServerAdministratorLoginPassword }} 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 }} sqlServerAdministratorLogin=${{ inputs.sqlServerAdministratorLogin }} sqlServerAdministratorLoginPassword=${{ secrets.sqlServerAdministratorLoginPassword }} additionalArguments: --what-if deploy: needs: validate environment: ${{ inputs.environmentType }} runs-on: ubuntu-latest outputs: appServiceAppName: ${{ steps.deploy.outputs.appServiceAppName }} appServiceAppHostName: ${{ steps.deploy.outputs.appServiceAppHostName }} storageAccountName: ${{ steps.deploy.outputs.storageAccountName }} storageAccountImagesBlobContainerName: ${{ steps.deploy.outputs.storageAccountImagesBlobContainerName }} sqlServerFullyQualifiedDomainName: ${{ steps.deploy.outputs.sqlServerFullyQualifiedDomainName }} sqlDatabaseName: ${{ steps.deploy.outputs.sqlDatabaseName }} 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 }} sqlServerAdministratorLogin=${{ inputs.sqlServerAdministratorLogin }} sqlServerAdministratorLoginPassword=${{ secrets.sqlServerAdministratorLoginPassword }} 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 deploy-database: 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/sql-action@v1.2 name: Deploy DACPAC to database with: server-name: ${{ needs.deploy.outputs.sqlServerFullyQualifiedDomainName }} connection-string: ${{ format('Server={0};Initial Catalog={1};User Id={2};Password={3};', needs.deploy.outputs.sqlServerFullyQualifiedDomainName, needs.deploy.outputs.sqlDatabaseName, inputs.sqlServerAdministratorLogin, secrets.sqlServerAdministratorLoginPassword) }} dacpac-package: database/ToyCompany.Database.dacpac seed-database: needs: - deploy - deploy-database environment: ${{ inputs.environmentType }} 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/sql-action@v1.2 name: Add test data to database with: server-name: ${{ needs.deploy.outputs.sqlServerFullyQualifiedDomainName }} connection-string: ${{ format('Server={0};Initial Catalog={1};User Id={2};Password={3};', needs.deploy.outputs.sqlServerFullyQualifiedDomainName, needs.deploy.outputs.sqlDatabaseName, inputs.sqlServerAdministratorLogin, secrets.sqlServerAdministratorLoginPassword) }} sql-file: 'deploy/sample-data/Toys.sql' seed-storage-account: needs: deploy environment: ${{ inputs.environmentType }} 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/CLI@v1 name: Upload sample images with: inlineScript: | az storage blob upload-batch \ --account-name ${{ needs.deploy.outputs.storageAccountName }} \ --destination ${{ needs.deploy.outputs.storageAccountImagesBlobContainerName }} \ --source 'deploy/sample-data/toyimages' smoke-test: runs-on: ubuntu-latest needs: - deploy - deploy-website - deploy-database - seed-database - seed-storage-account 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
Falls nicht, aktualisieren Sie sie so, dass sie mit dem Dateiinhalt übereinstimmt.
Speichern Sie die geänderte Datei.
Committen und pushen Sie Ihre Änderungen in Ihr Git-Repository. Führen Sie im Visual Studio Code-Terminal die folgenden Befehle aus:
git add . git commit -m "Add SQL database" git push
Ausführen des Workflows
Navigieren Sie in Ihrem Browser zu Ihren Workflowausführungen.
Wählen Sie die letzte Ausführung aus.
Warten Sie, bis alle Aufträge für die Testumgebung erfolgreich abgeschlossen wurden. Beachten Sie, dass die Feuerprobe jetzt auch erfolgreich ist.
Warten Sie, bis der Workflow einschließlich der Produktionsbereitstellung erfolgreich abgeschlossen wurde.
Anzeigen der Website
Wählen Sie den Auftrag deploy-test / deploy-website aus, um das Workflowprotokoll zu öffnen.
Wählen Sie den Schritt Website bereitstellen aus.
Halten Sie die STRG-TASTE gedrückt (⌘ unter macOS), und wählen Sie die URL der App Service-App aus, um sie auf einer neuen Browserregisterkarte zu öffnen.
Wählen Sie Toys aus.
Beachten Sie, dass Beispieldaten in der Testumgebung angezeigt werden.
Wiederholen Sie den vorangegangenen Vorgang für die App des Auftrags deploy-production / deploy-website.
Beachten Sie, dass in der Produktionsumgebung keine Beispieldaten angezeigt werden.
Bereinigen von Ressourcen
Nachdem Sie die Übung abgeschlossen haben, sollten Sie die Azure-Ressourcen entfernen, damit Ihnen dafür keine Gebühren berechnet werden.
Führen Sie im Visual Studio Code-Terminal die folgenden Befehle aus:
az group delete --resource-group ToyWebsiteTest --yes --no-wait
az group delete --resource-group ToyWebsiteProduction --yes --no-wait
Die Ressourcengruppe wird im Hintergrund gelöscht.
Remove-AzResourceGroup -Name ToyWebsiteTest -Force
Remove-AzResourceGroup -Name ToyWebsiteProduction -Force