En esta práctica harás lo mismo que en la Práctica 2, pero usando GitHub Actions en lugar de Jenkins. El objetivo es aprender, paso a paso, cómo se define un workflow YAML, cómo se usan parámetros, variables de entorno y condiciones por rama, y cómo usar Docker como “agente” de ejecución (jobs en contenedor).
Además, al final montarás un runner self-hosted en local con Docker Compose para poder ejecutar los pipelines con conectividad a herramientas on-prem (por ejemplo un registry y Artifactory levantados en tu red).
- Tener acceso a los repositorios del curso en GitHub.
- GitHub Actions habilitado en el repositorio.
- Ramas
develop(DEV) ymaster(PRO) creadas en el repo (si tu repo usamain, adapta la práctica amain). - (Recomendado) Conocer la Práctica 2 (stages, CI/CD, cleanup).
Antes de tocar el YAML, conviene entender estas piezas:
- Workflow: fichero YAML en
.github/workflows/*.ymlque define automatizaciones. - Event triggers (
on:): cuándo se ejecuta (push, PR, manual, schedule, etc.). - Jobs: unidades de ejecución paralelizables (
jobs.<job_id>). - Steps: comandos o acciones dentro de un job.
- Runner: la “máquina” donde se ejecutan los jobs:
- GitHub-hosted (en la nube de GitHub)
- Self-hosted (en tu máquina/VM/red)
- Actions: piezas reutilizables (por ejemplo
actions/checkout@v4). - Contexts: variables internas (
github.*,env.*,secrets.*,inputs.*) que puedes usar enif:o en scripts.
Simulamos 2 entornos:
- DEV: despliegue desde
develop - PRO: despliegue desde
master
Reglas:
- CI se ejecuta en cualquier rama.
- CD solo se ejecuta si la rama es
developomastery el parámetroRUN_CDestá activo.
En cada repo de proyecto (Python/Java) tienes ficheros de referencia:
.github/workflows/workflow-dummy.yml(plantilla inicial).github/workflows/workflow-template.yml(estructura final / guía, sin “código copiable”)
Tu fichero “real” para que GitHub lo ejecute debe ser:
.github/workflows/ci.yml
Ejercicio 0 (setup):
- Crea la carpeta
.github/workflows/(si no existe). - Copia
.github/workflows/workflow-dummy.ymla.github/workflows/ci.yml. - Haz commit y push. Comprueba en GitHub:
- Actions -> workflow ejecutado
Objetivo: entender cuándo se ejecuta un workflow.
Tarea:
- Configura el workflow para ejecutarse en:
push(todas las ramas)pull_request(haciadevelopymaster)workflow_dispatch(ejecución manual) con un input booleanoRUN_CD(defaultfalse).
Referencia:
- https://docs.github.com/actions/using-workflows/events-that-trigger-workflows
- https://docs.github.com/actions/using-workflows/workflow-syntax-for-github-actions#onworkflow_dispatch
Objetivo: entender el esqueleto y validar el flujo con logs.
Tarea:
- Añade un job
cicon steps:actions/checkout@v4- Un step
Infoque imprima:github.ref_name,github.sharunner.os,runner.name
Pista:
- En GitHub Actions, la mayoría de valores se usan con la sintaxis:
${{ ... }}. - Para imprimir en logs, puedes usar
run: echo ...(bash).
Referencia:
Objetivo: definir variables y reutilizarlas sin duplicar strings.
Tarea:
- Define
enva nivel de workflow con:IMAGE_NAMEAPP_URL
- Sobrescribe una variable a nivel de job (para ver precedencia).
- Usa las variables dentro de
run:(shell) y dentro de${{ env.VAR }}.
Referencia:
Objetivo: aprender a ejecutar manualmente con parámetros, como “Build with Parameters” en Jenkins.
Tarea:
- En
workflow_dispatch, define inputs:RUN_CD(boolean, defaultfalse)DEPLOY_ENV(choice: DEV/PRO, opcional para simular)
- Imprime en un step el valor de
inputs.RUN_CDyinputs.DEPLOY_ENV.
Pista:
- Los inputs se acceden como
${{ inputs.RUN_CD }}y${{ inputs.DEPLOY_ENV }}.
Referencia:
Objetivo: aprender dónde se guardan variables y secretos, y cómo aplicarlos a nivel repo/entorno.
Qué documentar en el repo (README o en esta práctica):
- Variables:
- Settings -> Secrets and variables -> Actions -> Variables
- Secrets:
- Settings -> Secrets and variables -> Actions -> Secrets
- Niveles:
- Repository: aplica a todos los workflows del repo.
- Environment: aplica solo cuando el job usa
environment:(permite protecciones). - Organization (si aplica): centraliza para muchos repos.
Tarea:
- Crea variables (Repository variables), por ejemplo:
REGISTRY_HOST(ej.local-registry:5000oghcr.io)ARTIFACTORY_URL(ej.http://artifactory:8081/artifactory)
- Crea secrets (Repository secrets), por ejemplo:
REGISTRY_USER,REGISTRY_PASSWORDARTIFACTORY_USER,ARTIFACTORY_PASSWORD(o token)
- En el workflow, úsalo así:
- Variables:
${{ vars.REGISTRY_HOST }}/${{ vars.ARTIFACTORY_URL }} - Secrets:
${{ secrets.REGISTRY_PASSWORD }}
- Variables:
Notas importantes (seguridad):
- Los secrets se enmascaran en logs, pero no imprimas secretos deliberadamente.
- Usa Environments (DEV/PRO) si quieres separar credenciales y proteger PRO con aprobaciones.
Referencia:
- https://docs.github.com/actions/security-guides/encrypted-secrets
- https://docs.github.com/actions/deployment/targeting-different-environments/using-environments-for-deployment
Objetivo: ejecutar CI dentro de un contenedor, igual que hacíamos con agent docker en Jenkins.
Tarea:
- Python: ejecuta tests dentro de
python:3.6-slim. - Java: ejecuta
make lintymake testdentro demaven:3.8.6-openjdk-11-slim.
Pista:
- En GitHub Actions puedes usar
container:a nivel de job.
Referencia:
Objetivo: construir la imagen Docker del repo (sin despliegue aún).
Tarea:
- Construye la imagen con el mismo tag que usa tu
docker-compose.yml, para que luego CD pueda arrancar por compose.
Objetivo: simular despliegue por entornos.
Tarea:
- Crea un job
cd(o stage equivalente) que solo se ejecute si:github.ref_nameesdevelopomaster, yinputs.RUN_CD == true(workflow dispatch)
Pista:
- Usa
if:a nivel de job.
Referencia:
Objetivo: simular CD en un runner efímero:
docker compose up -d- test e2e con
curl - cleanup siempre, aunque falle
Tarea:
- Implementa el cleanup con un step
if: always().
Referencia:
- https://docs.github.com/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsif
Objetivo: publicar la imagen construida.
Notas:
- En GitHub Actions, el caso más sencillo es GHCR (
ghcr.io) usandoGITHUB_TOKEN. - Un registry “local” solo tiene sentido si usas un self-hosted runner en tu red.
Referencia:
Igual que en Práctica 2, pero ejecutándolo desde un step de GitHub Actions usando secretos.
Objetivo: ejecutar workflows de GitHub Actions desde tu máquina/red para tener conectividad con:
- Registry privado local
- Artifactory local
- Cualquier herramienta on-prem (Jenkins, SonarQube, bases de datos, etc.)
Por qué hace falta:
- Los runners GitHub-hosted NO pueden acceder a servicios de tu red local (registry/artifactory “local-registry”, IPs privadas, etc.).
- Un runner self-hosted en tu red sí puede, porque comparte conectividad (LAN/VPN) y puedes unirlo a tus redes Docker.
En GitHub:
- Settings -> Actions -> Runners -> New self-hosted runner
- Elige Linux y sigue las instrucciones.
Nota:
- Para este curso lo vamos a ejecutar dentro de un contenedor con Docker Compose.
Crea un fichero docker-compose.runner.yml (por ejemplo en el repo IaC o en tu entorno local):
version: "3.8"
services:
gha-runner:
image: myoung34/github-runner:latest
restart: unless-stopped
environment:
# TODO: configura estas variables según el asistente de GitHub
REPO_URL: "https://github.com/<org>/<repo>"
RUNNER_NAME: "local-runner-01"
RUNNER_WORKDIR: "/tmp/runner"
RUNNER_LABELS: "self-hosted,linux,docker"
# Requiere token de registro (de GitHub) o PAT según el modo
ACCESS_TOKEN: "${GITHUB_RUNNER_TOKEN}"
volumes:
# Permite ejecutar docker/docker compose desde el runner usando el Docker del host
- /var/run/docker.sock:/var/run/docker.sock
- gha-runner-work:/tmp/runner
networks:
- devops_training_net
volumes:
gha-runner-work:
networks:
# Reutiliza la red donde viven registry/artifactory en tu stack IaC (ajusta el nombre si cambia)
devops_training_net:
external: trueexport GITHUB_RUNNER_TOKEN="<token>"
docker compose -f docker-compose.runner.yml up -d
docker compose -f docker-compose.runner.yml logs -fEn tu .github/workflows/ci.yml, cambia:
runs-on: ubuntu-latestpor:runs-on: [self-hosted, linux, docker]
Así, los jobs correrán en tu runner local y tendrán conectividad con:
local-registry:5000(si está levantado en la red Docker)artifactory:8081(si está levantado en la red Docker)
- Personalización: instalas herramientas específicas (docker compose, CLIs, SDKs, etc.).
- Conectividad on-prem: acceso a servicios internos (registry, Artifactory, SonarQube, DBs, etc.).
- Seguridad: secretos y accesos permanecen en tu red (mejor control de egress/ingress).
- Rendimiento/caché: puedes persistir caches (Maven, pip, Docker layers) para builds más rápidos.
- Cumplimiento: más fácil integrar con redes segregadas, proxies, políticas internas.
Notas de seguridad:
- Montar
/var/run/docker.sockda mucho poder al runner (equivalente a root sobre Docker). En entornos reales:- aislar runners por proyecto
- usar hosts dedicados
- rotar tokens y aplicar hardening
.github/workflows/ci.ymlcreado y evolucionado en ambos repos (Python y Java).- CI funcionando en cualquier rama.
- CD condicionado por rama (
develop/master) y por parámetro (RUN_CD). - Cleanup garantizado (aunque falle el e2e).