Hoy empiezo con GitHub Actions
Llevo varios días jugando con GitHub Actions, haciendo pruebas de diferentes escenarios que me he podido encontrar en otras herramientas de automatización, como Azure DevOps o Jenkins. En este artículo quiero contarte lo mínimo que deberías de saber para comenzar a gestionar con esta plataforma tus tareas de integración y despliegue continuos.
Nueva sección Actions en GitHub
Es posible que si ya trabajabas con GitHub te hayas dado cuenta de que, desde hace un tiempo, tienes una nueva sección llamada Actions.

En ella verás que existen diferentes plantillas para distintos lenguajes de programación llamadas workflows, las cuales te dan un punto de partida para la integración o el despliegue continuo de tus aplicaciones. Puedes explorar aquellas con las que te sientas más a gusto, en cuanto a tecnología, pero quiero enseñarte algo más elaborado en un solo vistazo
Estructura de un workflow
Si has hecho clic en alguna de las plantillas propuestas en el apartado Actions, verás que GitHub basa sus flujos en archivos en YAML. Cuando guardas cualquiera de estas plantillas estas se almacenan en .github/workflows.

Para poder explicarte mejor la estructura que debes utilizar voy a mostrártelo con este ejemplo, que compila y despliega una aplicación de ejemplo con .NET Core (y Blazor), que proviene del curso Blazor: Getting Started por Gill Cleeren, en Azure App Service:
name: Build and deploy the web app
on:
push:
branches:
- master
paths:
- 'BethanysPieShopHRM.server/**'
- '.github/workflows/build-and-deploy-web-app.yml'
env:
WEB_APP_NAME: bethanyspieshopblazor
jobs:
continuous-integration: #name of the job
runs-on: windows-latest
steps:
- uses: actions/checkout@master
- name: Set up .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.0.103'
- name: Build with dotnet
run: dotnet build --configuration Release
- name: dotnet publish
run: dotnet publish -c Release -o ${{env.DOTNET_ROOT}}/webapp
working-directory: ./BethanysPieShopHRM.server
- name: Upload artifact
uses: actions/upload-artifact@v1
with:
name: webapp-artifact
path: ${{env.DOTNET_ROOT}}/webapp
continuous-deployment:
needs: [continuous-integration]
runs-on: windows-latest
steps:
- name: Download artifact
uses: actions/download-artifact@v1
with:
name: webapp-artifact
path: ${{env.DOTNET_ROOT}}/webapp
- name: Login via Azure CLI
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS_BLAZOR_RG }}
- name: Add some settings
uses: azure/appservice-settings@v1
with:
app-name: ${{env.WEB_APP_NAME}}
app-settings-json: '${{ secrets.APP_SETTINGS_WEB_APP_WINDOWS }}'
- name: Deploy to Azure Web App
uses: azure/webapps-deploy@v1
with:
app-name: ${{env.WEB_APP_NAME}}
slot-name: 'production'
#publish-profile: ${{ secrets.WebAppPublishProfile }}
package: ${{env.DOTNET_ROOT}}/webapp
- name: Azure logout
run: |
az logout
Como puedes ver en el código anterior, un workflow tiene 4 partes fundamentales: un nombre, un evento/s que lo dispara, la declaración de variables de entorno (opcional) y los trabajos que se ejecutarán. Veamos cada apartado por separado:
name
Se trata del nombre del workflow, con el fin de poder diferenciarlo de otros flujos que tengas en el mismo repositorio.
name: Build and deploy the web app
Según la lista va creciendo es muy útil tener un nombre identificativo para cada uno.

on
Esta propiedad es fundamental, ya que se utilizará para indicar en base a qué se lanzará este flujo.
on:
push:
branches:
- master
paths:
- 'BethanysPieShopHRM.server/**'
- '.github/workflows/build-and-deploy-web-app.yml'
Como ves, el mismo puede ejecutarse gracias al evento push, entre muchos otros que ya te contaré, sobre ramas específicas (branches), e incluso puede depender también de los cambios que se hayan producido en las rutas especificadas a través de paths. En este ejemplo, el flujo sólo se lanzará para la rama master, pero solo cuando haya ocurrido algún cambio o bien en el propio archivo del workflow o bien en alguno de los archivos dentro del directorio BethanysPieShopHRM.server.
env
Esta sección no es obligatoria pero es muy útil para declarar variables de entorno, que estarán disponibles a nivel global mientras dure el flujo, incluso entre diferentes agentes.
env:
WEB_APP_NAME: bethanyspieshopblazor
jobs
Como su propio nombre indica, en este apartado se definirán los diferentes trabajos que componen el flujo. Cada uno de ellos tendrá un nombre, runs-on identifica el tipo de runner (agente) que necesita para ejecutar las tareas y una serie de pasos (steps) que se van a llevar a cabo como parte del trabajo.
jobs:
continuous-integration: #name of the job
runs-on: windows-latest
steps:
- uses: actions/checkout@master
- name: Set up .NET Core
uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.0.103'
- name: Build with dotnet
run: dotnet build --configuration Release
- name: dotnet publish
run: dotnet publish -c Release -o ${{env.DOTNET_ROOT}}/webapp
working-directory: ./BethanysPieShopHRM.server
- name: Upload artifact
uses: actions/upload-artifact@v1
with:
name: webapp-artifact
path: ${{env.DOTNET_ROOT}}/webapp
Dentro de cada uno de los pasos se pueden ver diferentes acciones: aquellas ejecutadas a través de run, las cuales son comandos sin más, o aquellas que utilizan acciones ya predefinidas, a través de uses. En este fragmento se utilizan varias:
- actions/checkout@master: permite obtener una copia del código fuente del repositorio sobre la que trabajar.
- actions/upload-artifact@v1: se utiliza para crear artefactos en base a archivos o directorios que se especifiquen en dicha acción. Normalmente se utilizan para que otro job pueda descargarlo y hacer uso de él. En este ejemplo se genera un artefacto con el resultado de la compilación del proyecto.
Por último, fíjate en el segundo job:
continuous-deployment:
needs: [continuous-integration]
runs-on: windows-latest
steps:
- name: Download artifact
uses: actions/download-artifact@v1
with:
name: webapp-artifact
path: ${{env.DOTNET_ROOT}}/webapp
- name: Login via Azure CLI
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS_BLAZOR_RG }}
- name: Add some settings
uses: azure/appservice-settings@v1
with:
app-name: ${{env.WEB_APP_NAME}}
app-settings-json: '${{ secrets.APP_SETTINGS_WEB_APP_WINDOWS }}'
- name: Deploy to Azure Web App
uses: azure/webapps-deploy@v1
with:
app-name: ${{env.WEB_APP_NAME}}
slot-name: 'production'
#publish-profile: ${{ secrets.WebAppPublishProfile }}
package: ${{env.DOTNET_ROOT}}/webapp
- name: Azure logout
run: |
az logout
Este se va a encargar del despliegue. Para que esto sea posible va a depender del job anterior, el cual genera el paquete a desplegar. Las dependencias de otros jobs se establecen con la propiedad needs, donde puedes especificar uno o varios jobs por los cuales este debe esperar para poder ejecutarse. De no indicar nada ambos jobs se ejecutarían en paralelo, por lo que este último fallaría al no estar el artefacto listo.
Aquí se utilizan otras acciones diferentes al anterior:
- actions/download-artifact@v1: te permite descargar el artefacto generado en el job anterior.
- azure/login@v1: inicia sesión a través de Azure CLI en tu suscripción de Microsoft Azure, ya que en este ejemplo el despliegue se hará en un App Service.
- azure/appservice-settings@v1: añade valores en la configuración de este servicio de Azure (depende de la acción anterior, ya que necesitas iniciar sesión antes).
- azure/webapps-deploy@v1: hace propiamente el despliegue. En este ejemplo he dejado comentada la posibilidad de realizar el mismo utilizando la opción publish-profile. Si no necesitaras la tarea anterior, que añade configuración en el servicio, se puede utilizar el perfil de publicación en lugar de Azure CLI.
Estas dos últimas acciones, además de utilizar variables de entorno, también están haciendo uso de secretos: secrets.AZURE_CREDENTIALS_BLAZOR_RG y secrets.APP_SETTINGS_WEB_APP_WINDOWS. Estos se configuran en el apartado Settings del repositorio, en la sección Secrets:

Una vez guardados en esta sección no será posible volver a visualizar su contenido.
Acciones predefinidas para tus workflows
Como has podido ver en el ejemplo, los workflows (flujos) están compuestos de jobs (trabajos) y estos están compuestos de steps (pasos). Si bien podrías definir todos los pasos utilizando scripting, existe un marketplace con más de 32.000 acciones que puedes utilizar para tus flujos.

¡Saludos!