Ejercicio: Implementación de una aplicación web
En su empresa de juguetes, el equipo de desarrollo de sitios web ha confirmado la versión más reciente del sitio web en el repositorio de Git. Ahora, está listo para actualizar el flujo de trabajo a fin de compilar el sitio web e implementarlo en Azure App Service.
En el proceso, hará lo siguiente:
- Agregar un nuevo flujo de trabajo al que se llamará para el trabajo de compilación.
- Actualizar el flujo de trabajo para incluir el trabajo de compilación.
- Agregar una nueva prueba de comprobación de la compilación.
- Actualizar el trabajo de implementación para implementar la aplicación.
- Ejecute el flujo de trabajo.
Adición de un flujo de trabajo reutilizable para el trabajo de compilación
Aquí, agregará una definición de trabajo nueva que incluye los pasos necesarios para compilar la aplicación de sitio web.
Abra Visual Studio Code.
En la carpeta .github/workflows, cree un nuevo archivo denominado deploy.yml.
Agregue el contenido siguiente al archivo de flujo de trabajo build.yml:
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
El trabajo instala el SDK de .NET para compilar la solución. A continuación, ejecuta un paso de compilación para convertir el código fuente de la aplicación de sitio web en un archivo compilado que está listo para ejecutarse en Azure. El trabajo comprime entonces el artefacto compilado y lo carga como un artefacto de flujo de trabajo.
Guarde los cambios en el archivo.
Adición del trabajo de compilación al flujo de trabajo
Abra el archivo workflow.yml.
Debajo de la línea jobs:, antes del trabajo lint, agregue un nuevo trabajo llamado build que utilice el flujo de trabajo reutilizable que acaba de definir:
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
Actualice el trabajo deploy-test para que dependa del nuevo trabajo build:
# 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 }}
Actualice el trabajo deploy-production para que también dependa de los trabajos build y lint.
# 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 }}
Dado que la implementación de producción depende de la implementación de prueba, no es estrictamente necesario especificar las dependencias. Sin embargo, es recomendable ser explícito, para evitar que su flujo de trabajo se ejecute incorrectamente si reordena o elimina sus trabajos o entornos.
Observe que especifica la lista
needs
de dos maneras diferentes: las dependencias de la implementación de su entorno de prueba se enumeran en una sola línea, y las de su entorno de producción mediante una lista de varias líneas. Los dos enfoques son equivalentes.Guarde los cambios en el archivo.
Actualización del archivo de prueba de comprobación de la compilación
Los desarrolladores del sitio web han agregado un punto de conexión de estado al sitio web. Este punto de conexión comprueba que el sitio web está en línea y que puede conectarse a la base de datos. Aquí, agregará una nueva prueba de comprobación de la compilación para invocar la comprobación de estado desde el flujo de trabajo de implementación.
Abra el archivo Website.Tests.ps1 en la carpeta deploy.
Agregue un caso de prueba nuevo que invoque la comprobación de estado. Se produce un error en el caso de prueba si el código de respuesta no es 200, lo que indica que se ha hecho correctamente:
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" } }
Guarde los cambios en el archivo.
Incorporación de una salida al archivo de Bicep
Pronto agregará un paso de implementación que publica el sitio web en Azure App Service. El paso de publicación requiere el nombre de la aplicación de App Service. Aquí, expondrá el nombre de la aplicación como salida del archivo de Bicep.
Abra el archivo main.bicep en la carpeta deploy.
Al final del contenido del archivo, agregue el nombre de la aplicación de App Service como salida:
output appServiceAppName string = appServiceApp.name output appServiceAppHostName string = appServiceApp.properties.defaultHostName
Guarde los cambios en el archivo.
Actualización del trabajo de implementación para propagar la salida
Ahora, debe actualizar el trabajo deploy para tomar el valor de la salida de la implementación de Bicep y hacer que esté disponible para el resto del flujo de trabajo.
Abra el archivo deploy.yml en la carpeta .github/workflows.
En la definición del trabajo deploy, agregue una nueva salida para
appServiceAppName
:deploy: needs: validate environment: ${{ inputs.environmentType }} runs-on: ubuntu-latest outputs: appServiceAppName: ${{ steps.deploy.outputs.appServiceAppName }} appServiceAppHostName: ${{ steps.deploy.outputs.appServiceAppHostName }} steps:
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
Adición de un trabajo para implementar el sitio web
Debajo de la definición del trabajo deploy, y encima de la definición del trabajo smoke-test, defina un nuevo trabajo para implementar el sitio web en 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
Nota:
Tenga cuidado con la sangría del archivo YAML, asegurándose de que el nuevo trabajo tiene sangría en el mismo nivel que el trabajo
deploy
. Si no está seguro, copie todo el contenido del archivo deploy.yml del ejemplo del paso siguiente.Observe que el trabajo depende del trabajo deploy mediante la palabra clave
needs
. Esta dependencia garantiza que el sitio web no se implemente hasta que la infraestructura esté lista. También permite que el trabajo acceda a la salidaappServiceAppName
del trabajo deploy.Además, tenga en cuenta que este trabajo incluye pasos para descargar los artefactos de flujo de trabajo e iniciar sesión en Azure. Cada trabajo se ejecuta en su propio ejecutor, por lo que debe ser independiente.
Guarde los cambios en el archivo.
Comprobación del contenido del archivo deploy.yml y confirmación de los cambios
Compruebe que el archivo deploy.yml es similar al ejemplo siguiente:
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
Guarde los cambios en el archivo.
En el terminal de Visual Studio Code, confirme e inserte los cambios en el repositorio de Git ejecutando los comandos siguientes:
git add . git commit -m "Build and deploy website application" git push
Esta es la primera vez que inserta contenido este repositorio, por lo que es posible que se le pida que inicie sesión.
En Windows, escriba 1 para autenticarse mediante un explorador web y presione Entrar.
En macOS, seleccione Autorizar.
Aparece una ventana del explorador. Puede que tenga que volver a iniciar sesión en GitHub. Seleccione Autorizar.
Ejecución del flujo de trabajo
En el explorador, vaya Acciones.
La primera ejecución del flujo de trabajo, con la etiqueta Initial commit (Confirmación inicial), se muestra como un error. GitHub ejecutó automáticamente el flujo de trabajo al crear el repositorio. Se produjo un error porque los secretos no estaban listos en ese momento. Puede omitir este error.
Seleccione el flujo de trabajo deploy-toy-website-end-to-end.
Seleccione la ejecución más reciente del flujo de trabajo.
Espere hasta que el trabajo build finalice correctamente.
Espere a que el trabajo deploy-test / deploy finalice correctamente.
Algunas advertencias se muestran en el panel Annotations (Anotaciones). Todas estas advertencias se deben a la forma en que Bicep escribe mensajes informativos en el registro del flujo de trabajo. Puede omitir estas advertencias.
El flujo de trabajo ejecuta entonces el trabajo deploy-test / smoke-test, pero la prueba de aceptación de la compilación da error:
Seleccione el trabajo deploy-test / smoke-test para abrir el registro de flujo de trabajo.
Seleccione el paso de ejecución de las prueba de aceptación de la compilación para ver la sección asociada del registro del flujo de trabajo:
Observe que el registro de flujo de trabajo indica que el sitio web y la configuración no son correctos. Hay un problema con la comunicación de la aplicación con Azure SQL Database. Aún no ha implementado ni configurado una base de datos, por lo que el sitio web no puede acceder a ella. Pronto corregirá este problema.