Entrega continua con Azure Pipelines

Use Azure Pipelines para la implementación automática en Azure Functions. Azure Pipelines permite compilar, probar e implementar con integración continua (CI) y entrega continua (CD) mediante Azure DevOps.

Las canalizaciones de YAML se definen mediante un archivo YAML en el repositorio. Un paso es el bloque de creación más pequeño de una canalización y puede ser un script o una tarea (script empaquetado previamente). Obtenga información sobre los conceptos y componentes clave que forma una canalización.

Usará la tarea AzureFunctionApp para implementar en Azure Functions. Ahora hay dos versiones de la tarea AzureFunctionApp (AzureFunctionApp@1, AzureFunctionApp@2). AzureFunctionApp@2 incluye compatibilidad mejorada con la validación que hace que las canalizaciones tengan menos probabilidades de producir errores.

Elija la versión de la tarea en la parte superior del artículo. Las canalizaciones YAML no están disponibles para Azure DevOps 2019 y versiones anteriores.

Requisitos previos

Compilación de la aplicación

  1. Inicie sesión en su organización de Azure DevOps y vaya a su proyecto.
  2. En el proyecto, vaya a la página Pipelines (Canalizaciones). Luego seleccione Nueva canalización.
  3. Seleccione una de estas opciones en ¿Dónde está su código?:
    • GitHub: es posible que se le redirija a GitHub para iniciar sesión. Si es así, escriba sus credenciales de GitHub. En su primera conexión a GitHub, el asistente también le guía por el proceso de conectar DevOps a las cuentas de GitHub.
    • Git de Azure Repos: puede elegir inmediatamente un repositorio en su proyecto de DevOps actual.
  4. Cuando aparezca la lista de repositorios, seleccione el repositorio de la aplicación de ejemplo.
  5. Azure Pipelines analiza el repositorio y, en Configure su canalización, proporciona una lista de posibles plantillas. Elija la plantilla de aplicación de funciones adecuada para su lenguaje. Si no ve la plantilla correcta, seleccione Mostrar más.
  6. Seleccione Save and run (Guardar y ejecutar) y, luego, seleccione Commit directly to the main branch (Confirmar directamente en la rama principal) y, luego, elija de nuevo Save and run (Guardar y ejecutar).
  7. Se inicia una nueva ejecución. Espere a que finalice.

Ejemplo de canalizaciones de compilación de YAML

Las siguientes canalizaciones específicas del lenguaje se pueden usar para compilar aplicaciones.

Puede utilizar el ejemplo siguiente con el fin de crear un archivo YAML para compilar la aplicación .NET.

Si ve errores al compilar la aplicación, compruebe que la versión de .NET que usa coincide con la versión de Azure Functions. Para más información, consulte Selección de un destino para versiones de runtime de Azure Functions.

pool:
  vmImage: 'windows-latest'
steps:
- script: |
    dotnet restore
    dotnet build --configuration Release
- task: DotNetCoreCLI@2
  inputs:
    command: publish
    arguments: '--configuration Release --output publish_output'
    projects: '*.csproj'
    publishWebProjects: false
    modifyOutputPath: false
    zipAfterPublish: false
- task: ArchiveFiles@2
  displayName: "Archive files"
  inputs:
    rootFolderOrFile: "$(System.DefaultWorkingDirectory)/publish_output"
    includeRootFolder: false
    archiveFile: "$(System.DefaultWorkingDirectory)/build$(Build.BuildId).zip"
- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(System.DefaultWorkingDirectory)/build$(Build.BuildId).zip'
    artifactName: 'drop'

Implementación de la aplicación

Se implementará con la tarea de implementación de Azure Function App. Esta tarea requiere una conexión de servicio de Azure como entrada. Una conexión de servicio de Azure almacena las credenciales para conectarse de Azure Pipelines a Azure.

Para implementar en Azure Functions, agregue el siguiente fragmento de código al final del archivo azure-pipelines.yml. El valor predeterminado de appType es Windows. Puede especificar Linux estableciendo el valor de appType en functionAppLinux.

trigger:
- main

variables:
  # Azure service connection established during pipeline creation
  azureSubscription: <Name of your Azure subscription>
  appName: <Name of the function app>
  # Agent VM image name
  vmImageName: 'ubuntu-latest'

- task: AzureFunctionApp@1 # Add this at the end of your file
  inputs:
    azureSubscription: <Azure service connection>
    appType: functionAppLinux # default is functionApp
    appName: $(appName)
    package: $(System.ArtifactsDirectory)/**/*.zip
    #Uncomment the next lines to deploy to a deployment slot
    #Note that deployment slots is not supported for Linux Dynamic SKU
    #deployToSlotOrASE: true
    #resourceGroupName: '<Resource Group Name>'
    #slotName: '<Slot name>'

En el fragmento de código se da por supuesto que los pasos de compilación del archivo YAML generan el archivo ZIP en la carpeta $(System.ArtifactsDirectory) del agente.

Implementación de un contenedor

Puede implementar automáticamente el código en Azure Functions como un contenedor personalizado después de cada compilación correcta. Para obtener más información sobre los contenedores, consulte Creación de una función en Linux con un contenedor personalizado.

Implementación con Azure Function App para la tarea del contenedor

La manera más sencilla de implementar en un contenedor es usar la tarea de implementación de Azure Function App en el contenedor.

Para realizar la implementación, agregue el siguiente fragmento de código al final del archivo YAML:

trigger:
- main

variables:
  # Container registry service connection established during pipeline creation
  dockerRegistryServiceConnection: <Docker registry service connection>
  imageRepository: <Name of your image repository>
  containerRegistry: <Name of the Azure container registry>
  dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
  tag: '$(Build.BuildId)'

  # Agent VM image name
  vmImageName: 'ubuntu-latest'

- task: AzureFunctionAppContainer@1 # Add this at the end of your file
  inputs:
    azureSubscription: '<Azure service connection>'
    appName: '<Name of the function app>'
    imageName: $(containerRegistry)/$(imageRepository):$(tag)

El fragmento de código inserta la imagen de Docker en Azure Container Registry. La tarea de implementación de Azure Function App en el contenedor extrae la imagen de Docker adecuada correspondiente al BuildId del repositorio especificado y, a continuación, implementa la imagen.

Implementación en una ranura

Puede configurar la aplicación de funciones para que tenga varias ranuras. Las ranuras permiten implementar la aplicación de forma segura y probarla antes de ponerla a disposición de los clientes.

El siguiente fragmento de código YAML muestra cómo implementar en un espacio de ensayo y, a continuación, cambiar a un espacio de producción:

- task: AzureFunctionApp@1
  inputs:
    azureSubscription: <Azure service connection>
    appType: functionAppLinux
    appName: <Name of the Function app>
    package: $(System.ArtifactsDirectory)/**/*.zip
    deployToSlotOrASE: true
    resourceGroupName: <Name of the resource group>
    slotName: staging

- task: AzureAppServiceManage@0
  inputs:
    azureSubscription: <Azure service connection>
    WebAppName: <name of the Function app>
    ResourceGroupName: <name of resource group>
    SourceSlot: staging
    SwapWithProduction: true

Creación de una canalización con la CLI de Azure

Para crear una canalización de compilación en Azure, use el comando az functionapp devops-pipeline create. La canalización de compilación se crea para compilar y liberar los cambios de código que se realicen en el repositorio. El comando generará un nuevo archivo YAML que define la canalización de versión y compilación y lo confirma en el repositorio. Los requisitos previos para este comando dependen de la ubicación del código.

  • Si el código está en GitHub:

    • Debe contar con permisos de escritura en su suscripción.

    • Debe ser el administrador del proyecto en Azure DevOps.

    • Debe tener permisos para crear un token de acceso personal (PAT) en GitHub que tenga permisos suficientes. Para obtener más información, consulte Requisitos de permiso de token de acceso personal en GitHub.

    • Debe tener permisos para confirmar en la rama principal del repositorio de GitHub con el fin de confirmar el archivo YAML generado automáticamente.

  • Si el código está en Azure Repos:

    • Debe contar con permisos de escritura en su suscripción.

    • Debe ser el administrador del proyecto en Azure DevOps.

Compilación de la aplicación

  1. Inicie sesión en su organización de Azure DevOps y vaya a su proyecto.
  2. En el proyecto, vaya a la página Pipelines (Canalizaciones). A continuación, elija la acción para crear una canalización.
  3. Siga los pasos del asistente y seleccione primero GitHub como ubicación del código fuente.
  4. Puede que se le redirija a GitHub para iniciar sesión. Si es así, escriba sus credenciales de GitHub.
  5. Cuando aparezca la lista de repositorios, seleccione el repositorio de la aplicación de ejemplo.
  6. Azure Pipelines analizará el repositorio y recomendará una plantilla. Seleccione Save and run (Guardar y ejecutar) y, luego, seleccione Commit directly to the main branch (Confirmar directamente en la rama principal) y, luego, elija de nuevo Save and run (Guardar y ejecutar).
  7. Se inicia una nueva ejecución. Espere a que finalice.

Ejemplo de canalizaciones de compilación de YAML

Las siguientes canalizaciones específicas del lenguaje se pueden usar para compilar aplicaciones.

Puede utilizar el ejemplo siguiente con el fin de crear el archivo YAML para compilar la aplicación de .NET:

pool:
  vmImage: 'windows-latest'
steps:
- script: |
    dotnet restore
    dotnet build --configuration Release
- task: DotNetCoreCLI@2
  inputs:
    command: publish
    arguments: '--configuration Release --output publish_output'
    projects: '*.csproj'
    publishWebProjects: false
    modifyOutputPath: false
    zipAfterPublish: false
- task: ArchiveFiles@2
  displayName: "Archive files"
  inputs:
    rootFolderOrFile: "$(System.DefaultWorkingDirectory)/publish_output"
    includeRootFolder: false
    archiveFile: "$(System.DefaultWorkingDirectory)/build$(Build.BuildId).zip"
- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(System.DefaultWorkingDirectory)/build$(Build.BuildId).zip'
    artifactName: 'drop'

Implementación de la aplicación

Se implementará con la tarea de Implementación de Azure Function App v2. Esta tarea requiere una conexión de servicio de Azure como entrada. Una conexión de servicio de Azure almacena las credenciales para conectarse de Azure Pipelines a Azure.

La versión v2 de la tarea incluye compatibilidad con pilas de aplicaciones más recientes para .NET, Python y Node. La tarea incluye comprobaciones previas a la implementación de redes. Cuando hay problemas de implementación previa, la implementación se detiene.

Para implementar en Azure Functions, agregue el siguiente fragmento de código al final del archivo azure-pipelines.yml. El valor predeterminado de appType es Windows. Puede especificar Linux estableciendo el valor de appType en functionAppLinux.

trigger:
- main

variables:
  # Azure service connection established during pipeline creation
  azureSubscription: <Name of your Azure subscription>
  appName: <Name of the function app>
  # Agent VM image name
  vmImageName: 'ubuntu-latest'

- task: AzureFunctionApp@2 # Add this at the end of your file
  inputs:
    azureSubscription: <Azure service connection>
    appType: functionAppLinux # default is functionApp
    appName: $(appName)
    package: $(System.ArtifactsDirectory)/**/*.zip
    deploymentMethod: 'auto' # 'auto' | 'zipDeploy' | 'runFromPackage'. Required. Deployment method. Default: auto.
    #Uncomment the next lines to deploy to a deployment slot
    #Note that deployment slots is not supported for Linux Dynamic SKU
    #deployToSlotOrASE: true
    #resourceGroupName: '<Resource Group Name>'
    #slotName: '<Slot name>'

En el fragmento de código se da por supuesto que los pasos de compilación del archivo YAML generan el archivo ZIP en la carpeta $(System.ArtifactsDirectory) del agente.

Implementación de un contenedor

Puede implementar automáticamente el código en Azure Functions como un contenedor personalizado después de cada compilación correcta. Para más información sobre los contenedores, consulte Trabajar con contenedores y Azure Functions.

Implementación con Azure Function App para la tarea del contenedor

La manera más sencilla de implementar en un contenedor es usar la tarea de implementación de Azure Function App en el contenedor.

Para realizar la implementación, agregue el siguiente fragmento de código al final del archivo YAML:

trigger:
- main

variables:
  # Container registry service connection established during pipeline creation
  dockerRegistryServiceConnection: <Docker registry service connection>
  imageRepository: <Name of your image repository>
  containerRegistry: <Name of the Azure container registry>
  dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
  tag: '$(Build.BuildId)'

  # Agent VM image name
  vmImageName: 'ubuntu-latest'

- task: AzureFunctionAppContainer@1 # Add this at the end of your file
  inputs:
    azureSubscription: '<Azure service connection>'
    appName: '<Name of the function app>'
    imageName: $(containerRegistry)/$(imageRepository):$(tag)

El fragmento de código inserta la imagen de Docker en Azure Container Registry. La tarea de implementación de Azure Function App en el contenedor extrae la imagen de Docker adecuada correspondiente al BuildId del repositorio especificado y, a continuación, implementa la imagen.

Implementación en una ranura

Puede configurar la aplicación de funciones para que tenga varias ranuras. Las ranuras permiten implementar la aplicación de forma segura y probarla antes de ponerla a disposición de los clientes.

El siguiente fragmento de código YAML muestra cómo implementar en un espacio de ensayo y, a continuación, cambiar a un espacio de producción:

- task: AzureFunctionApp@2
  inputs:
    azureSubscription: <Azure service connection>
    appType: functionAppLinux
    appName: <Name of the Function app>
    package: $(System.ArtifactsDirectory)/**/*.zip
    deploymentMethod: 'auto'
    deployToSlotOrASE: true
    resourceGroupName: <Name of the resource group>
    slotName: staging

- task: AzureAppServiceManage@0
  inputs:
    azureSubscription: <Azure service connection>
    WebAppName: <name of the Function app>
    ResourceGroupName: <name of resource group>
    SourceSlot: staging
    SwapWithProduction: true

Creación de una canalización con la CLI de Azure

Para crear una canalización de compilación en Azure, use el comando az functionapp devops-pipeline create. La canalización de compilación se crea para compilar y liberar los cambios de código que se realicen en el repositorio. El comando generará un nuevo archivo YAML que define la canalización de versión y compilación y lo confirma en el repositorio. Los requisitos previos para este comando dependen de la ubicación del código.

  • Si el código está en GitHub:

    • Debe contar con permisos de escritura en su suscripción.

    • Debe ser el administrador del proyecto en Azure DevOps.

    • Debe tener permisos para crear un token de acceso personal (PAT) en GitHub que tenga permisos suficientes. Para obtener más información, consulte Requisitos de permiso de token de acceso personal en GitHub.

    • Debe tener permisos para confirmar en la rama principal del repositorio de GitHub con el fin de confirmar el archivo YAML generado automáticamente.

  • Si el código está en Azure Repos:

    • Debe contar con permisos de escritura en su suscripción.

    • Debe ser el administrador del proyecto en Azure DevOps.

Pasos siguientes