GitHub Actions es la plataforma de CI/CD integrada en GitHub que permite automatizar pruebas, builds y despliegues directamente desde tu repositorio sin herramientas externas. Es gratuita para repositorios públicos y tiene una capa gratuita generosa para proyectos privados. En este tutorial aprenderás a crear tus primeros workflows de CI/CD con GitHub Actions con ejemplos reales para PHP, Python y Node.js.

¿Qué es CI/CD?

  • CI (Integración Continua): ejecutar pruebas automáticamente en cada push o pull request para detectar errores antes de que lleguen al código principal
  • CD (Entrega/Despliegue Continuo): desplegar automáticamente cuando el código pasa todas las verificaciones

GitHub Actions es gratuito para repositorios públicos y ofrece 2000 minutos/mes en la capa gratuita para repositorios privados.

Conceptos clave de GitHub Actions

  • Workflow: archivo YAML en .github/workflows/ que define la automatización
  • Event (trigger): qué evento dispara el workflow (push, pull_request, schedule...)
  • Job: conjunto de steps que se ejecutan en el mismo runner
  • Step: comando individual o action reutilizable de GitHub Marketplace
  • Runner: máquina virtual donde se ejecuta el job (ubuntu-latest, windows-latest, macos-latest)

Tu primer workflow

# .github/workflows/hola.yml
name: Mi primer workflow

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  saludo:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout del codigo
        uses: actions/checkout@v4

      - name: Saludar
        run: echo "Hola desde GitHub Actions!"

      - name: Informacion del runner
        run: |
          echo "Sistema: ${{ runner.os }}"
          echo "Rama: ${{ github.ref_name }}"
          echo "Actor: ${{ github.actor }}"

Workflow de CI para PHP/Symfony

# .github/workflows/ci-php.yml
name: CI -- PHP/Symfony

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    services:
      mysql:
        image: mysql:8.0
        env:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: test_db
        ports: ["3306:3306"]
        options: --health-cmd="mysqladmin ping" --health-interval=10s

    steps:
      - uses: actions/checkout@v4

      - name: Setup PHP 8.4
        uses: shivammathur/setup-php@v2
        with:
          php-version: "8.4"
          extensions: mbstring, pdo, pdo_mysql
          coverage: xdebug

      - name: Instalar dependencias
        run: composer install --no-interaction --prefer-dist

      - name: Ejecutar migraciones
        run: php bin/console doctrine:migrations:migrate --no-interaction
        env:
          DATABASE_URL: mysql://root:root@127.0.0.1:3306/test_db

      - name: Ejecutar tests
        run: php bin/phpunit --coverage-text

Workflow de CI para Python

# .github/workflows/ci-python.yml
name: CI -- Python

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.11", "3.12"]

    steps:
      - uses: actions/checkout@v4

      - name: Setup Python ${{ matrix.python-version }}
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}

      - name: Instalar dependencias
        run: |
          pip install -r requirements.txt
          pip install pytest pytest-cov

      - name: Linting con Ruff
        run: pip install ruff && ruff check .

      - name: Ejecutar tests con cobertura
        run: pytest --cov=. --cov-report=xml

      - name: Subir cobertura a Codecov
        uses: codecov/codecov-action@v4

Deploy automático a producción

# .github/workflows/deploy.yml
name: Deploy a Produccion

on:
  push:
    tags: ["v*.*.*"]  # Solo en tags de version (ej: v1.1.0)

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: produccion

    steps:
      - uses: actions/checkout@v4

      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SSH_HOST }}
          username: ${{ secrets.SSH_USER }}
          password: ${{ secrets.SSH_PASSWORD }}
          script: |
            cd ~/mi-proyecto
            git pull origin main
            composer install --no-dev --optimize-autoloader
            php bin/console cache:clear --env=prod

Secretos y variables de entorno

Nunca escribas credenciales directamente en los archivos YAML. Usa GitHub Secrets:

  1. Ve a tu repo: Settings > Secrets and variables > Actions
  2. Añade secretos como SSH_PASSWORD, DATABASE_URL
  3. Referéncialos en el workflow: ${{ secrets.NOMBRE_SECRETO }}

Preguntas frecuentes sobre GitHub Actions

¿GitHub Actions es gratuito?

GitHub Actions es completamente gratuito para repositorios públicos sin límite de minutos. Para repositorios privados, el plan gratuito incluye 2000 minutos al mes en runners Linux. Los runners de Windows consumen 2x minutos y los de macOS 10x. Puedes añadir self-hosted runners propios para eliminar ese límite y tener mayor control del entorno.

¿Cuál es la diferencia entre CI y CD en GitHub Actions?

CI (Continuous Integration) ejecuta automáticamente pruebas y validaciones en cada push o pull request, detectando errores antes de que lleguen al código principal. CD (Continuous Delivery/Deployment) automatiza el despliegue a staging o producción cuando el código supera todas las verificaciones. Puedes hacer ambas cosas en el mismo workflow o separarlas en archivos distintos.

¿Cómo se almacenan las credenciales de forma segura?

Nunca escribas contraseñas o tokens en los archivos YAML. Usa GitHub Secrets: en tu repositorio ve a Settings > Secrets and variables > Actions > New repository secret. Referéncialos con ${{ secrets.NOMBRE_SECRETO }}. Los secretos nunca aparecen en los logs de ejecución y no se transmiten a forks de repositorios públicos.

¿Qué son los environments y para qué sirven?

Los environments son entornos de despliegue configurables (staging, produccion) con reglas de protección propias. Puedes requerir aprobación manual antes de desplegar a producción, restringir qué ramas pueden hacer el deploy y tener secretos específicos por entorno. Se configuran en Settings > Environments y se referencian en el workflow con environment: nombre-entorno.

Conclusión

GitHub Actions transforma tu flujo de trabajo: cada push puede ejecutar tests, verificar la calidad del código y desplegar automáticamente. Combínalo con nuestro tutorial de Docker para tener un entorno de desarrollo y producción completamente automatizado.