Ejercicio: Incorporación de varios entornos a la canalización
Ahora está listo para actualizar la canalización a fin de implementarla en los entornos de prueba y producción. En esta unidad va a actualizar la canalización para usar plantillas de modo que se puedan reutilizar las fases en los entornos.
Durante el proceso, hará lo siguiente:
- Agregar una plantilla de canalización para la fase de lint.
- Agregar una plantilla de canalización que defina las fases necesarias para realizar la implementación en cualquier entorno.
- Actualizar la canalización para usar las plantillas.
- Ejecutar la canalización y ver los resultados.
Incorporación de una plantilla de canalización para la fase de lint
La fase de lint solo se produce una vez durante la ejecución de canalización, independientemente del número de entornos en los que se implemente la canalización. Por lo tanto, no es realmente necesario usar plantillas para la fase de lint. Pero para que el archivo de definición de canalización principal sea sencillo y fácil de leer, decide definir la fase de lint en una plantilla.
En Visual Studio Code, cree una nueva carpeta de nombre pipeline-templates dentro de la carpeta deploy.
Cree un nuevo archivo en la carpeta pipeline-templates con el nombre lint.yml.
Pegue la siguiente definición de plantilla de canalización en el archivo:
jobs: - job: LintCode displayName: Lint code steps: - script: | az bicep build --file deploy/main.bicep name: LintBicepCode displayName: Run Bicep linter
La fase de lint es la misma que la fase de lint que ya está en la canalización, solo que ahora está en un archivo de plantilla de canalización independiente.
Guarde los cambios y cierre el archivo.
Incorporación de una plantilla de canalización para la implementación
Cree una plantilla de canalización que defina todas las fases necesarias para implementar cada uno de los entornos. Use los parámetros de la plantilla para especificar la configuración que puede diferir entre los entornos.
Cree un nuevo archivo en la carpeta pipeline-templates con el nombre deploy.yml.
Este archivo representa todas las actividades de implementación que se ejecutan para cada uno de los entornos.
Pegue los siguientes parámetros de plantilla de canalización en el archivo:
parameters: - name: environmentType type: string - name: resourceGroupName type: string - name: serviceConnectionName type: string - name: deploymentDefaultLocation type: string default: westus3
Nota:
Cuando empiece a trabajar con el archivo YAML en Visual Studio Code, es posible que vea algunas líneas onduladas de color rojo que indican que hay un problema. Esto se debe a que la extensión de Visual Studio Code para los archivos YAML a veces no adivina correctamente el esquema del archivo.
Puede pasar por alto los problemas que notifica la extensión. O bien, si lo prefiere, puede agregar el código siguiente a la parte superior del archivo para suprimir la adivinación de la extensión:
# yaml-language-server: $schema=./deploy.yml
Debajo de los parámetros, pegue la definición de la fase de validación:
stages: - ${{ if ne(parameters.environmentType, 'Production') }}: - stage: Validate_${{parameters.environmentType}} displayName: Validate (${{parameters.environmentType}} Environment) jobs: - job: ValidateBicepCode displayName: Validate Bicep code steps: - task: AzureResourceManagerTemplateDeployment@3 name: RunPreflightValidation displayName: Run preflight validation inputs: connectedServiceName: ${{parameters.serviceConnectionName}} location: ${{parameters.deploymentDefaultLocation}} deploymentMode: Validation resourceGroupName: ${{parameters.resourceGroupName}} csmFile: deploy/main.bicep overrideParameters: > -environmentType ${{parameters.environmentType}}
Observe que se aplica una condición a esta fase. Solo se ejecuta en entornos que no son de producción.
Observe también que el identificador de fase incluye el valor del parámetro
environmentType
. Este parámetro garantiza que todas las fases de la canalización tengan un identificador único. La fase también tiene una propiedaddisplayName
para crear un nombre con el formato correcto que pueda ser leído.Debajo de la fase de validación, pegue la definición de la fase de versión preliminar:
- ${{ if eq(parameters.environmentType, 'Production') }}: - stage: Preview_${{parameters.environmentType}} displayName: Preview (${{parameters.environmentType}} Environment) jobs: - job: PreviewAzureChanges displayName: Preview Azure changes steps: - task: AzureCLI@2 name: RunWhatIf displayName: Run what-if inputs: azureSubscription: ${{parameters.serviceConnectionName}} scriptType: 'bash' scriptLocation: 'inlineScript' inlineScript: | az deployment group what-if \ --resource-group ${{parameters.resourceGroupName}} \ --template-file deploy/main.bicep \ --parameters environmentType=${{parameters.environmentType}}
Observe que esta fase también tiene aplicada una condición, aunque opuesta a la condición de la fase de validación. La fase de versión preliminar solo se ejecuta en el entorno de producción.
Debajo de la fase de versión preliminar, pegue la definición de la fase de implementación:
- stage: Deploy_${{parameters.environmentType}} displayName: Deploy (${{parameters.environmentType}} Environment) jobs: - deployment: DeployWebsite displayName: Deploy website environment: ${{parameters.environmentType}} strategy: runOnce: deploy: steps: - checkout: self - task: AzureResourceManagerTemplateDeployment@3 name: DeployBicepFile displayName: Deploy Bicep file inputs: connectedServiceName: ${{parameters.serviceConnectionName}} deploymentName: $(Build.BuildNumber) location: ${{parameters.deploymentDefaultLocation}} resourceGroupName: ${{parameters.resourceGroupName}} csmFile: deploy/main.bicep overrideParameters: > -environmentType ${{parameters.environmentType}} deploymentOutputs: deploymentOutputs - bash: | 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)
Debajo de la fase de implementación, pegue la definición de la fase de prueba de aceptación de la compilación:
- 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'
Observe que la definición de la variable
appServiceAppHostName
incorpora el parámetroenvironmentType
cuando hace referencia a la fase que ha publicado el nombre de host. Este parámetro garantiza que cada fase de prueba de aceptación de la compilación se ejecute en el entorno correcto.Compruebe que el archivo deploy.yml es similar al ejemplo siguiente:
parameters: - name: environmentType type: string - name: resourceGroupName type: string - name: serviceConnectionName 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 steps: - task: AzureResourceManagerTemplateDeployment@3 name: RunPreflightValidation displayName: Run preflight validation inputs: connectedServiceName: ${{parameters.serviceConnectionName}} location: ${{parameters.deploymentDefaultLocation}} deploymentMode: Validation resourceGroupName: ${{parameters.resourceGroupName}} csmFile: deploy/main.bicep overrideParameters: > -environmentType ${{parameters.environmentType}} - ${{ if eq(parameters.environmentType, 'Production') }}: - stage: Preview_${{parameters.environmentType}} displayName: Preview (${{parameters.environmentType}} Environment) jobs: - job: PreviewAzureChanges displayName: Preview Azure changes steps: - task: AzureCLI@2 name: RunWhatIf displayName: Run what-if inputs: azureSubscription: ${{parameters.serviceConnectionName}} scriptType: 'bash' scriptLocation: 'inlineScript' inlineScript: | az deployment group what-if \ --resource-group ${{parameters.resourceGroupName}} \ --template-file deploy/main.bicep \ --parameters environmentType=${{parameters.environmentType}} - stage: Deploy_${{parameters.environmentType}} displayName: Deploy (${{parameters.environmentType}} Environment) jobs: - deployment: DeployWebsite displayName: Deploy website environment: ${{parameters.environmentType}} strategy: runOnce: deploy: steps: - checkout: self - task: AzureResourceManagerTemplateDeployment@3 name: DeployBicepFile displayName: Deploy Bicep file inputs: connectedServiceName: ${{parameters.serviceConnectionName}} deploymentName: $(Build.BuildNumber) location: ${{parameters.deploymentDefaultLocation}} resourceGroupName: ${{parameters.resourceGroupName}} csmFile: deploy/main.bicep overrideParameters: > -environmentType ${{parameters.environmentType}} deploymentOutputs: deploymentOutputs - bash: | 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) - 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'
Guarde los cambios en el archivo.
Actualización de la definición de canalización para usar las plantillas
Abra el archivo azure-pipelines.yml.
Actualice el archivo para usar las nuevas plantillas al reemplazar el contenido por el código siguiente:
trigger: batch: true branches: include: - main pool: vmImage: ubuntu-latest stages: # Lint the Bicep file. - stage: Lint jobs: - template: pipeline-templates/lint.yml # Deploy to the test environment. - template: pipeline-templates/deploy.yml parameters: environmentType: Test resourceGroupName: ToyWebsiteTest serviceConnectionName: ToyWebsiteTest # Deploy to the production environment. - template: pipeline-templates/deploy.yml parameters: environmentType: Production resourceGroupName: ToyWebsiteProduction serviceConnectionName: ToyWebsiteProduction
Esta canalización ejecuta la fase de lint una vez. Luego usa el archivo de plantilla deploy.yml dos veces: una por entorno. Esto mantiene la definición de canalización clara y fácil de entender. Además, los comentarios ayudan a explicar lo que sucede.
Guarde los cambios.
Confirme e inserte los cambios en el repositorio de Git mediante la ejecución de los comandos siguientes en el terminal de Visual Studio Code:
git add . git commit -m "Add pipeline templates" git push
Visualización de la ejecución de canalización
En el explorador, vaya a Canalizaciones.
Seleccione la ejecución más reciente de la canalización.
Observe que ahora la ejecución de canalización muestra todas las fases que ha definido en el archivo YAML. Es posible que tenga que desplazarse horizontalmente para verlas todas.
Espere a que la canalización se ponga en pausar antes de la fase Implementación (entorno de producción). La canalización puede tardar unos minutos en llegar a este punto.
Apruebe la implementación en el entorno de producción mediante la selección del botón Revisar.
Seleccione el botón Aprobar.
Espere a que finalice la ejecución de la canalización.
Seleccione la pestaña Pruebas para mostrar los resultados de las pruebas de esta ejecución de la canalización.
Observe que ahora hay resultados de cuatro pruebas. La prueba de aceptación de la compilación se ejecuta en los entornos de prueba y producción, por lo que se ven los resultados de ambos conjuntos de pruebas.
Seleccione Canalizaciones>Entornos.
Seleccione el entorno Producción.
Observe que, en la pantalla de detalles del entorno, se ve información general del historial de implementaciones del entorno de producción.
Seleccione la implementación y luego la pestaña Cambios.
Observe que la pestaña Cambios muestra la lista de confirmaciones incluidas en la implementación. Esta información ayuda a ver exactamente lo que ha cambiado en el entorno a lo largo del tiempo.
En el explorador, vaya a Azure Portal.
Vaya al grupo de recursos ToyWebsiteProduction.
En la lista de recursos, abra la aplicación Azure App Service.
Observe que el tipo de plan de App Service es S1.
Vaya a la aplicación App Service del grupo de recursos ToyWebsiteTest.
Observe que el tipo de plan de App Service es F1. Los dos entornos usan configuraciones diferentes, como se ha definido en el archivo de Bicep.