Övning – Distribuera ett webbprogram
På ditt leksaksföretag har ditt webbplatsutvecklingsteam checkat in den senaste versionen av webbplatsen till din Git-lagringsplats. Nu är du redo att uppdatera din pipeline för att skapa webbplatsen och distribuera den till Azure App Service.
I den här processen utför du följande uppgifter:
- Lägg till en ny pipelinemall för byggjobbet.
- Uppdatera pipelinen så att den inkluderar byggjobbet.
- Lägg till ett nytt röktest.
- Uppdatera distributionssteget för att distribuera programmet.
- Kör pipelinen.
Lägga till en pipelinemall för byggjobbet
Lägg till en ny jobbdefinition som innehåller de steg som krävs för att skapa webbplatsprogrammet.
Öppna Visual Studio Code.
I mappen deploy/pipeline-templates skapar du en ny fil med namnet build.yml.
Lägg till följande innehåll i mallfilen build.yml pipeline:
jobs: - job: Build displayName: Build application and database pool: vmImage: windows-latest steps: # Build, copy, and publish the website. - task: DotNetCoreCLI@2 displayName: Build publishable website inputs: command: 'publish' publishWebProjects: true - task: CopyFiles@2 displayName: Copy publishable website inputs: sourceFolder: '$(Build.SourcesDirectory)/src/ToyCompany/ToyCompany.Website/bin' contents: '**/publish.zip' targetFolder: '$(Build.ArtifactStagingDirectory)/website' flattenFolders: true - task: PublishBuildArtifacts@1 displayName: Publish website as pipeline artifact inputs: pathToPublish: '$(Build.ArtifactStagingDirectory)/website' artifactName: 'website'
Jobbet kör ett byggsteg för att omvandla webbplatsprogrammets källkod till en kompilerad fil som är redo att köras i Azure. Jobbet kopierar sedan den kompilerade artefakten till en tillfällig mellanlagringsmapp och publicerar den som en pipelineartefakt.
Spara ändringarna i filen.
Byt namn på den första pipelinefasen och lägg till ett byggjobb
Öppna filen azure-pipelines.yml i mappen distribution.
Ändra Lint--fasen. Byt namn på den till Skapaoch lägg till ett byggjobb som använder den build.yml pipelinemall som du skapade.
trigger: batch: true branches: include: - main pool: vmImage: ubuntu-latest stages: - stage: Build jobs: # Build the Visual Studio solution. - template: pipeline-templates/build.yml # Lint the Bicep file. - template: pipeline-templates/lint.yml # Deploy to the test environment. - template: pipeline-templates/deploy.yml parameters: environmentType: Test # Deploy to the production environment. - template: pipeline-templates/deploy.yml parameters: environmentType: Production
Spara ändringarna i filen.
Uppdatera röktestfilen
Webbplatsutvecklarna lade 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 smoketest för att anropa hälsokontrollen från din distributionspipeline.
Öppna filen Website.Tests.ps1 i mappen distribuera.
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" } }
Spara ändringarna i filen.
Lägga till utdata i Bicep-filen
Du vill lägga till ett distributionssteg som publicerar din webbplats i Azure App Service, men publiceringssteget kräver namnet på App Service-appen. Här exponerar du appnamnet som utdata från din Bicep-fil.
Öppna filen main.bicep i deploy-mappen.
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
Spara ändringarna i filen.
Uppdatera distributionssteg
Öppna deploy.yml-filen i mappen deploy/pipeline-templates.
I definitionen av distributionsjobbet i Deploy-steget (nära rad 59), konfigurerar du jobbet för att använda Windows-värdbaserade agentpoolen.
- stage: Deploy_${{parameters.environmentType}} displayName: Deploy (${{parameters.environmentType}} Environment) jobs: - deployment: DeployWebsite displayName: Deploy website pool: vmImage: windows-latest variables: - group: ToyWebsite${{parameters.environmentType}} environment: ${{parameters.environmentType}} strategy:
Vissa av de pipelinesteg som du lägger till senare för att arbeta med databasen kräver att Windows-operativsystemet körs. Du kan använda olika agentpooler för olika jobb i pipelinen, så att de andra jobben fortsätter att använda Ubuntu Linux-pipelineagentpoolen.
I Deploy job's SaveDeploymentOutputs step lägger du till en ny pipelinevariabel med värdet för appnamnet från Bicep-distributionens utdata:
- bash: | echo "##vso[task.setvariable variable=appServiceAppName]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppName.value')" echo "##vso[task.setvariable variable=appServiceAppHostName;isOutput=true]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppHostName.value')" name: SaveDeploymentOutputs displayName: Save deployment outputs into variables env: DEPLOYMENT_OUTPUTS: $(deploymentOutputs)
Observera att variabeln
appServiceAppHostName
har egenskapenisOutput=true
tillämpad på den, eftersom variabeln används i rökteststeget. VariabelnappServiceAppName
anges och används i samma pipelinesteg och jobb. Därför behöver den inte inställningenisOutput=true
.I slutet av Distribuera jobbinnehåll lägger du till ett nytt steg för att distribuera appen till Azure App Service:
steps: - checkout: self - task: AzureResourceManagerTemplateDeployment@3 name: DeployBicepFile displayName: Deploy Bicep file inputs: connectedServiceName: ToyWebsite${{parameters.environmentType}} deploymentName: $(Build.BuildNumber) location: ${{parameters.deploymentDefaultLocation}} resourceGroupName: $(ResourceGroupName) csmFile: deploy/main.bicep overrideParameters: > -environmentType $(EnvironmentType) -reviewApiUrl $(ReviewApiUrl) -reviewApiKey $(ReviewApiKey) deploymentOutputs: deploymentOutputs - bash: | echo "##vso[task.setvariable variable=appServiceAppName]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppName.value')" echo "##vso[task.setvariable variable=appServiceAppHostName;isOutput=true]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppHostName.value')" name: SaveDeploymentOutputs displayName: Save deployment outputs into variables env: DEPLOYMENT_OUTPUTS: $(deploymentOutputs) - task: AzureRmWebAppDeployment@4 name: DeployWebsiteApp displayName: Deploy website inputs: appType: webApp ConnectionType: AzureRM azureSubscription: ToyWebsite${{parameters.environmentType}} ResourceGroupName: $(ResourceGroupName) WebAppName: $(appServiceAppName) Package: '$(Pipeline.Workspace)/website/publish.zip'
Notgång
Var försiktig med indragningen för YAML-filen och se till att det nya distributionssteget är indraget på samma nivå som det
DeployBicepFile
-steget. Om du inte är säker kopierar du hela deploy.yml filinnehållet från exemplet i nästa steg.Observera att du inte uttryckligen laddade ned artefakten i pipelinedefinitionen. Eftersom du använder ett distributionsjobb laddar Azure Pipelines automatiskt ned artefakten åt dig.
Verifiera innehållet i deploy.yml-filen och checka in ändringarna
Kontrollera att filen deploy.yml ser ut som i följande exempel:
parameters: - name: environmentType type: string - name: deploymentDefaultLocation type: string default: westus3 stages: - ${{ if ne(parameters.environmentType, 'Production') }}: - stage: Validate_${{parameters.environmentType}} displayName: Validate (${{parameters.environmentType}} Environment) jobs: - job: ValidateBicepCode displayName: Validate Bicep code variables: - group: ToyWebsite${{parameters.environmentType}} steps: - task: AzureResourceManagerTemplateDeployment@3 name: RunPreflightValidation displayName: Run preflight validation inputs: connectedServiceName: ToyWebsite${{parameters.environmentType}} location: ${{parameters.deploymentDefaultLocation}} deploymentMode: Validation resourceGroupName: $(ResourceGroupName) csmFile: deploy/main.bicep overrideParameters: > -environmentType $(EnvironmentType) -reviewApiUrl $(ReviewApiUrl) -reviewApiKey $(ReviewApiKey) - ${{ if eq(parameters.environmentType, 'Production') }}: - stage: Preview_${{parameters.environmentType}} displayName: Preview (${{parameters.environmentType}} Environment) jobs: - job: PreviewAzureChanges displayName: Preview Azure changes variables: - group: ToyWebsite${{parameters.environmentType}} steps: - task: AzureCLI@2 name: RunWhatIf displayName: Run what-if inputs: azureSubscription: ToyWebsite${{parameters.environmentType}} scriptType: 'bash' scriptLocation: 'inlineScript' inlineScript: | az deployment group what-if \ --resource-group $(ResourceGroupName) \ --template-file deploy/main.bicep \ --parameters environmentType=$(EnvironmentType) \ reviewApiUrl=$(ReviewApiUrl) \ reviewApiKey=$(ReviewApiKey) - stage: Deploy_${{parameters.environmentType}} displayName: Deploy (${{parameters.environmentType}} Environment) jobs: - deployment: DeployWebsite displayName: Deploy website pool: vmImage: windows-latest variables: - group: ToyWebsite${{parameters.environmentType}} environment: ${{parameters.environmentType}} strategy: runOnce: deploy: steps: - checkout: self - task: AzureResourceManagerTemplateDeployment@3 name: DeployBicepFile displayName: Deploy Bicep file inputs: connectedServiceName: ToyWebsite${{parameters.environmentType}} deploymentName: $(Build.BuildNumber) location: ${{parameters.deploymentDefaultLocation}} resourceGroupName: $(ResourceGroupName) csmFile: deploy/main.bicep overrideParameters: > -environmentType $(EnvironmentType) -reviewApiUrl $(ReviewApiUrl) -reviewApiKey $(ReviewApiKey) deploymentOutputs: deploymentOutputs - bash: | echo "##vso[task.setvariable variable=appServiceAppName]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppName.value')" echo "##vso[task.setvariable variable=appServiceAppHostName;isOutput=true]$(echo $DEPLOYMENT_OUTPUTS | jq -r '.appServiceAppHostName.value')" name: SaveDeploymentOutputs displayName: Save deployment outputs into variables env: DEPLOYMENT_OUTPUTS: $(deploymentOutputs) - task: AzureRmWebAppDeployment@4 name: DeployWebsiteApp displayName: Deploy website inputs: appType: webApp ConnectionType: AzureRM azureSubscription: ToyWebsite${{parameters.environmentType}} ResourceGroupName: $(ResourceGroupName) WebAppName: $(appServiceAppName) Package: '$(Pipeline.Workspace)/website/publish.zip' - stage: SmokeTest_${{parameters.environmentType}} displayName: Smoke Test (${{parameters.environmentType}} Environment) jobs: - job: SmokeTest displayName: Smoke test variables: appServiceAppHostName: $[ stageDependencies.Deploy_${{parameters.environmentType}}.DeployWebsite.outputs['DeployWebsite.SaveDeploymentOutputs.appServiceAppHostName'] ] steps: - task: PowerShell@2 name: RunSmokeTests displayName: Run smoke tests inputs: targetType: inline script: | $container = New-PesterContainer ` -Path 'deploy/Website.Tests.ps1' ` -Data @{ HostName = '$(appServiceAppHostName)' } Invoke-Pester ` -Container $container ` -CI - task: PublishTestResults@2 name: PublishTestResults displayName: Publish test results condition: always() inputs: testResultsFormat: NUnit testResultsFiles: 'testResults.xml'
Spara ändringarna i filen.
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
Kör pipelinen
I webbläsaren går du till Pipelines.
Välj den senaste körningen av din pipeline.
Vänta tills Build-fasen har slutförts framgångsrikt.
Pipelinen pausas innan den kör Validate (Test Environment)-fasen eftersom pipelinen behöver behörighet att använda variabelgruppen som fasen refererar till. Du måste godkänna pipelinens åtkomst till variabelgruppen eftersom du kör pipelinen i det här projektet för första gången. När du kör pipelinen igen behöver du inte godkänna åtkomst till samma variabelgrupp.
Välj Visa.
Välj Tillåt.
Välj Tillåt.
Verifiera (Testmiljö)-fasen har slutförts framgångsrikt.
Pipelinen fortsätter och fasen Deploy (Test Environment) avslutas framgångsrikt. Pipelinen kör sedan röktestet (testmiljö) fasen, men röktestfasen misslyckas.
Välj röktest (testmiljö) fas för att öppna pipelineloggen.
Välj steget Kör röktester för att visa det relaterade avsnittet i pipelinens logg.
Observera att pipelineloggen innehåller hälsokontrollsvaret. Svaret anger att det finns ett problem med programmets kommunikation med Azure SQL Database. Databasen har inte distribuerats eller konfigurerats än, vilket är anledningen till att webbplatsen inte kan komma åt den. I nästa övning åtgärdar du det här konfigurationsproblemet.