Exercice – Déployer une application web
Dans votre entreprise de jouets, votre équipe de développement de site web a validé la dernière version du site web dans votre référentiel Git. Vous êtes maintenant prêt à mettre à jour votre pipeline pour générer le site web et le déployer sur Azure App Service.
Au cours de ce processus, vous effectuez les tâches suivantes :
- Ajouter un nouveau modèle de pipeline pour la tâche de build.
- Mettre à jour le pipeline pour inclure la tâche de build.
- Ajouter un nouveau test de détection de fumée.
- Mettre à jour la phase de déploiement pour déployer l’application.
- Exécuter le pipeline.
Ajouter un modèle de pipeline pour la tâche de build
Ajoutez une nouvelle définition de travail qui contient les étapes nécessaires à la génération de l’application de site web.
Ouvrez Visual Studio Code.
Dans le dossier deploy/pipeline-templates, créez un fichier nommé build.yml.
Ajoutez le contenu suivant dans le fichier de modèle de pipeline build.yml :
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'
Le travail exécute une étape de génération pour transformer le code source de l’application de site web en un fichier compilé prêt à être exécuté dans Azure. Le travail copie ensuite l’artefact compilé dans un dossier intermédiaire temporaire et le publie en tant qu’artefact de pipeline.
Enregistrez les modifications apportées au fichier.
Renommer la première phase du pipeline et ajouter une tâche de build
Ouvrez le fichier azure-pipelines.yml dans le dossier deploy.
Modifiez la phase Lint. Renommez-la Build et ajoutez une tâche de build qui utilise le modèle de pipeline build.yml que vous avez créé.
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
Enregistrez les modifications apportées au fichier.
Mettre à jour le fichier de test de détection de fumée
Les développeurs du site web ont ajouté un point de terminaison d’intégrité au site web. Ce point de terminaison vérifie que le site web est en ligne et qu’il peut accéder à la base de données. Ici, vous ajoutez un nouveau test de détection de fumée pour appeler le contrôle d’intégrité à partir de votre pipeline de déploiement.
Ouvrez le fichier Website.Tests.ps1 dans le dossier deploy.
Ajoutez un nouveau cas de test qui appelle le contrôle d’intégrité. Le cas de test échoue si le code de réponse n’est pas 200, valeur qui indique une réussite.
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" } }
Enregistrez les modifications apportées au fichier.
Ajouter la sortie au fichier Bicep
Vous souhaitez ajouter une étape de déploiement qui publie votre site web sur Azure App Service, mais l’étape de publication nécessite le nom de l’application App Service. Ici, vous exposez le nom de l’application en tant que sortie de votre fichier Bicep.
Ouvrez le fichier main.bicep dans le dossier deploy.
À la fin du contenu du fichier, ajoutez le nom de l’application App Service comme sortie.
output appServiceAppName string = appServiceApp.name output appServiceAppHostName string = appServiceApp.properties.defaultHostName
Enregistrez les modifications apportées au fichier.
Mettre à jour la phase de déploiement
Ouvrez le fichier deploy.yml dans le dossier deploy/pipeline-templates.
Dans la définition du travail de déploiement de la phase Déployer (près de la ligne 59), configurez le travail pour utiliser le pool d’agents hébergés Windows :
- 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:
Certaines étapes du pipeline que vous ajoutez ultérieurement pour travailler avec votre base de données nécessitent le système d’exploitation Windows pour s’exécuter. Vous pouvez utiliser différents pools d’agents pour différents travaux dans votre pipeline, de sorte que les autres travaux continuent à utiliser le pool d’agents de pipeline Ubuntu Linux.
Dans l’étape Déployer SaveDeploymentOutputs du travail, ajoutez une nouvelle variable de pipeline avec la valeur du nom de l’application à partir de la sortie du déploiement Bicep :
- 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)
Notez que la propriété
isOutput=true
est appliquée à la variableappServiceAppHostName
, car cette variable est utilisée dans la phase de test de détection de fumée. La variableappServiceAppName
est définie et utilisée dans la même phase de pipeline et le même travail. Il n’a donc pas besoin du paramètreisOutput=true
.À la fin du contenu du travail Deploy, ajoutez une nouvelle étape pour déployer l’application sur 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'
Notes
Soyez vigilant avec la mise en retrait du fichier YAML et veillez à ce que la nouvelle étape de déploiement soit mise en retrait au même niveau que l’étape
DeployBicepFile
. Si vous n’êtes pas sûr, copiez l’intégralité du contenu du fichier deploy.yml à partir de l’exemple figurant à l’étape suivante.Notez que vous n’avez pas téléchargé de manière explicite l’artefact dans la définition du pipeline. Comme vous utilisez un travail de déploiement, Azure Pipelines télécharge automatiquement l’artefact pour vous.
Vérifier le contenu du fichier deploy.yml et valider vos modifications
Vérifiez que votre fichier deploy.yml ressemble à l’exemple suivant :
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'
Enregistrez les modifications apportées au fichier.
Dans le terminal Visual Studio Code, validez et envoyez (push) vos modifications dans votre dépôt Git en exécutant les commandes suivantes :
git add . git commit -m "Build and deploy website application" git push
Exécuter le pipeline
Dans votre navigateur, accédez à Pipelines.
Sélectionnez l’exécution la plus récente de votre pipeline.
Attendez que la phase Générer se termine avec succès.
Le pipeline s’interrompt avant d’exécuter la phase Valider (environnement de test), car le pipeline a besoin d’une autorisation pour utiliser le groupe de variables auquel la phase fait référence. Vous devez approuver l’accès du pipeline au groupe de variables, car c’est la première fois que vous exécutez le pipeline dans ce projet. Quand vous réexécuterez ce pipeline, vous n’avez pas besoin d’approuver l’accès au même groupe de variables.
Sélectionnez Affichage.
Sélectionnez Autoriser.
Sélectionnez Autoriser.
La phase Valider (environnement de test) se termine avec succès.
Le pipeline continue et la phase Déployer (environnement de test) se termine correctement. Le pipeline exécute alors la phase Test de détection de fumée (environnement de test), mais la phase de test de détection de fumée échoue.
Sélectionnez la phase Test de détection de fumée (environnement de test) pour ouvrir le journal de pipeline.
Sélectionnez l’étape Effectuer des tests de détection de fumée pour consulter la section associée du journal de pipeline.
Notez que le journal de pipeline comprend la réponse du contrôle d’intégrité. Cette réponse indique qu’il y a un problème avec la communication de l’application avec Azure SQL Database. La base de données n’est pas encore déployée ou configurée, c’est pourquoi le site web ne peut pas y accéder. Dans l’exercice suivant, vous corrigez ce problème de configuration.