GitHub Actions

GitHub Actions es la plataforma de automatización integrada de GitHub, que te permite definir y ejecutar Workflows automatizados directamente en tu repositorio de código, sin necesidad de ninguna herramienta externa de CI/CD.

Los usos habituales incluyen: ejecutar pruebas automáticamente después de un push de código, desplegar automáticamente al servidor después de fusionar un PR, ejecutar periódicamente scripts de extracción de datos, etc.

GitHub Actions escompletamente gratuito para repositorios públicosy los repositorios privados disponen de 2000 minutos gratuitos al mes.


Conceptos clave

Antes de empezar a escribir archivos de configuración, es necesario entender los siguientes conceptos clave; su relación es la siguiente:

仓库(Repository)
└── Workflow(工作流)          ← 一个 .yml 文件 = 一个 Workflow
    ├── Event(触发事件)        ← 什么情况下启动这个 Workflow,如 push、PR
    └── Job(作业)× N          ← 一个 Workflow 可以包含多个并行或串行的 Job
        ├── Runner(运行器)     ← 执行 Job 的服务器,如 ubuntu-latest
        └── Step(步骤)× N     ← Job 内按顺序执行的一系列操作
            ├── Action          ← 可复用的封装好的操作,如 actions/checkout
            └── Run             ← 直接执行 Shell 命令
Concepto Descripción Analogía
Workflow (flujo de trabajo) Todo el flujo de automatización, definido por un.ymlarchivo, almacenado en el.github/workflows/directorio Un plan de trabajo completo
Event (evento) Condiciones que activan la ejecución de un Workflow, como push de código, creación de PR, tareas programadas, etc. Condiciones de inicio del plan
Job (trabajo) Una unidad de tarea independiente dentro de un Workflow. Cada Job se ejecuta en una máquina virtual independiente; varios Jobs se ejecutan en paralelo por defecto. Un capítulo dentro del plan
Step (paso) La unidad mínima de operación que se ejecuta secuencialmente dentro de un Job; puede ser un comando Shell o una Action. Cada paso concreto dentro de un capítulo
Action (acción) Operaciones reutilizables y empaquetadas, provenientes de GitHub oficial, de terceros o escritas por ti; medianteusesla referencia a plantillas de herramientas listas para usar
Runner (ejecutor) Servidor que ejecuta el Job. GitHub ofrece tres entornos administrados: Ubuntu, Windows y macOS. Personal que ejecuta el plan

Crear el primer Workflow

1. Estructura de directorios

Todos los archivos de Workflow deben almacenarse en el directorio raíz del repositorio, dentro de.github/workflows/la carpeta, y el nombre del archivo debe terminar en.ymlo.yamlEl nombre del archivo se puede personalizar:

your-repo/
├── .github/
│   └── workflows/
│       ├── ci.yml          ← 持续集成流程(如运行测试)
│       ├── deploy.yml      ← 部署流程
│       └── scheduled.yml   ← 定时任务
├── src/
├── package.json
└── README.md

Un repositorio puede tener varios archivos de Workflow; son independientes entre sí y cada uno se activa mediante los eventos definidos.

2. El Workflow más sencillo

A continuación se muestra un ejemplo básico: cada vez que se hace push de código al repositorio, se imprime una línea "Hello, GitHub Actions!".

Ejemplo

# .github/workflows/hello.yml

name
: Hello World                  # Nombre del Workflow; se muestra en la página de GitHub Actions

on
: push                           # Condición de disparo: se activa cuando hay un push de código en cualquier rama

jobs
:                             # Define todos los Jobs
  say-hello
:                      # ID del Job (nombre personalizado, único dentro del mismo Workflow)
    name
: Imprimir saludo# Nombre mostrado del Job (opcional; si no se indica, se muestra el ID del Job)
    runs-on
: ubuntu-latest         # Especifica el entorno de ejecución: usa la última versión de la máquina virtual Ubuntu proporcionada por GitHub

    steps
:                        # Todos los pasos de este Job se ejecutan en orden
      - name
: Imprimir mensaje# Nombre del Step (opcional; se usa para identificar este paso en los registros)
        run
: echo "Hello, GitHub Actions!"   # run: ejecuta directamente un comando Shell

Los archivos YAML son muy sensibles a la sangría; debes usarespaciospara la sangría; no uses la tecla Tab. Se recomienda usar VS Code e instalar el complemento YAML, que permite detectar errores de formato en tiempo real.


Eventos desencadenantes (on)

onEl campo on define qué eventos desencadenan este Workflow. Puede ser un solo evento o una combinación de varios.

1. Eventos desencadenantes comunes

Evento Momento de activación Usos habituales
push Cuando se hace push de código al repositorio Ejecutar pruebas, revisión de código
pull_request Cuando se crea o actualiza un Pull Request Revisión y pruebas automáticas antes de fusionar el PR
schedule Activación programada mediante una expresión Cron Copias de seguridad programadas, extracción de datos programada
workflow_dispatch Activación manual desde la página web de GitHub Despliegue bajo demanda, ejecución manual de scripts
release Cuando se publica una nueva versión (crear Release) Empaquetado automático, publicación en el entorno de producción
workflow_call Cuando es invocado por otro Workflow Reutilizar flujos comunes (por ejemplo, un flujo de pruebas común)

2. Filtrar por rama o ruta específica

Ejemplo

span style="color: #0053A6;">
on:
  push
:
    branches
:
     - main            # Se activa solo al hacer push a la rama main
      - develop         # O al hacer push a la rama develop
      - 'release/**'    # O al hacer push a cualquier rama que comience con release/ (** coincide con cualquier secuencia de caracteres)
    paths
:
     - 'src/**'        # Filtro adicional: solo se activa si cambian archivos en el directorio src/
      - 'package.json'  # O cuando cambia el archivo package.json
                        # La relación entre ambos es de tipo "o"; si se cumple cualquiera, se activa

  pull_request
:
    branches
:
     - main            # Se activa solo en PRs cuya rama de destino es main (es decir, PRs que se fusionarán en main)
    types
:
     - opened          # Cuando se crea el PR
      - synchronize     # Cuando se hace push de un nuevo commit al PR
      - reopened        # Cuando se reabre el PR

3. Activación programada (schedule)

Usa una expresión Cron estándar para definir el tiempo de ejecución; la zona horaria es UTC (hora de Pekín = UTC+8, requiere conversión):

Ejemplo

span style="color: #0053A6;">
on:
  schedule
:
   # Formato Cron: minuto hora día del mes mes día de la semana
    - cron
: '0 2 * * *'       # Ejecutar una vez al día a las 02:00 UTC (es decir, 10:00 hora de Pekín)
    - cron
: '0 9 * * 1'       # Ejecutar una vez cada lunes a las 09:00 UTC (es decir, 17:00 hora de Pekín)
    - cron
: '*/30 * * * *'    # Ejecutar cada 30 minutos

# Referencia rápida de expresiones Cron comunes:
# '0 0 * * *' Medianoche todos los días (UTC 00:00)
# '0 * * * *' Cada hora en punto
# '0 0 * * 0' Medianoche todos los domingos
# '0 0 1 * *' Medianoche del día 1 de cada mes

4. Activación manual (workflow_dispatch)

workflow_dispatchPermite hacer clic manualmente en un botón en la pestaña Actions de la página de GitHub para iniciar el Workflow, y también se pueden definir parámetros de entrada:

Ejemplo

span style="color: #0053A6;">
on:
  workflow_dispatch
:
    inputs
:
      environment
:             # Nombre del parámetro de entrada (se puede referenciar en los steps mediante ${{ inputs.environment }})
        description
: 'Entorno de despliegue'# Descripción del parámetro, se muestra en el formulario de activación manual
        required
: true          # Si es obligatorio o no
        default
: 'staging'      # Valor predeterminado
        type
: choice            # Tipo de parámetro: choice (menú desplegable)
        options
:
         - staging             # Valores opcionales
          - production

      run_tests
:
        description
: '¿Ejecutar pruebas?'
        required
: false
        type
: boolean           # Tipo de parámetro: boolean (casilla de verificación)
        default
: true

jobs
:
  deploy
:
    runs-on
: ubuntu-latest
    steps
:
      - name
: Mostrar parámetros de despliegue
        run
: |
echo "Entorno objetivo: ${{ inputs.environment }}"
echo "Ejecutar pruebas: ${{ inputs.run_tests }}"


Explicación detallada de Jobs y Steps

1. Estructura básica de un Job

Ejemplo

span style="color: #0053A6;">
jobs:
  build
:                         # ID del Job, debe ser único dentro del mismo Workflow
    name
: Construir proyecto# Nombre para mostrar del Job (opcional)
    runs-on
: ubuntu-latest        # Entorno de ejecución (obligatorio)

    # Opcional: definir variables de entorno para todo el Job, accesibles desde todos los Steps
    env
:
      NODE_ENV
: production
      APP_PORT
: 8080

    # Opcional: establecer tiempo de espera (minutos), si se excede el Job se cancela automáticamente para evitar bloqueos
    timeout-minutes
: 30

    steps
:
     # Forma 1 de Step: usar una Action (se referencia con uses)
      - name
: Obtener código
        uses
: actions/checkout@v4         # Referencia a la Action oficial checkout (@v4 indica usar la versión v4)

      # Forma 2 de Step: ejecutar comandos Shell (se especifica con run)
      - name
: Mostrar versión de Node
        run
: node --version

      # Forma 3 de Step: ejecutar múltiples líneas de comandos Shell (usar | para múltiples líneas)
      - name
: Instalar dependencias y construir
        run
: |
         npm install
          npm run build
echo "Compilación completada"

2. Entorno de ejecución (runs-on)

GitHub proporciona los siguientes ejecutores alojados gratuitos, se pueden elegir según sea necesario:

Etiqueta Sistema operativo Descripción
ubuntu-latest Ubuntu (última LTS) El más utilizado, rápido y con la mayor cuota gratuita; se recomienda usarlo preferentemente
ubuntu-22.04 Ubuntu 22.04 Especificar versión fija para evitar problemas de incompatibilidad por actualizaciones de latest
windows-latest Windows Server (última versión) Para pruebas o compilaciones que requieran entorno Windows
macos-latest macOS (última versión) Para compilaciones de aplicaciones iOS/macOS; consume la cuota gratuita más rápido (aproximadamente 10 veces la de Ubuntu)

3. Dependencias entre Jobs (needs)

De forma predeterminada, varios Jobs se ejecutan en paralelo. Usarneedspermite establecer el orden de ejecución de los Jobs, formando dependencias en serie:

Ejemplo

span style="color: #0053A6;">
jobs:
  test
:                          # Paso 1: ejecutar pruebas
    runs-on
: ubuntu-latest
    steps
:
      - uses
: actions/checkout@v4
      - run
: npm test

  build
:                         # Paso 2: construir proyecto
    runs-on
: ubuntu-latest
    needs
: test                   # Debe esperar a que el Job test se complete correctamente para que build comience
    steps
:
      - uses
: actions/checkout@v4
      - run
: npm run build

  deploy
:                        # Paso 3: desplegar
    runs-on
: ubuntu-latest
    needs
: [test, build]          # Debe esperar a que test y build se completen correctamente para que deploy comience
    steps
:
      - run
: echo "Iniciando despliegue..."

# Orden de ejecución: test → build → deploy (en serie)
# Si se elimina needs, los tres Jobs se ejecutarán en paralelo

4. Ejecución condicional (if)

Medianteifse puede controlar si un Job o Step se ejecuta; se usa a menudo para distinguir ramas o comprobar si el paso anterior fue exitoso:

Ejemplo

span style="color: #0053A6;">
jobs:
  deploy
:
    runs-on
: ubuntu-latest
    # if a nivel de Job: todo el Job solo se ejecuta al hacer push a la rama main
    if
: github.ref == 'refs/heads/main'
    steps
:
      - uses
: actions/checkout@v4

      - name
: Desplegar en producción
        run
: ./deploy.sh

      # if también se puede escribir a nivel de Step para controlar si un paso concreto se ejecuta
      - name
: Enviar notificación de éxito
        if
: success()             # success(): se ejecuta solo si todos los Steps anteriores tuvieron éxito
        run
: echo "Despliegue exitoso, enviar notificación"

      - name
: Enviar notificación de fallo
        if
: failure()             # failure(): se ejecuta solo si algún Step falló
        run
: echo "Despliegue fallido, enviar alerta"

      - name
: Paso de limpieza que siempre se ejecuta
        if
: always()              # always(): se ejecuta tanto si hay éxito como si hay fallo (suele usarse para limpiar archivos temporales)
        run
: rm -rf ./tmp

Variables de entorno y Secrets

1. Variables de entorno (env)

Las variables de entorno se pueden definir en tres niveles del Workflow, con alcance decreciente:

Ejemplo

# Nivel 1: nivel de Workflow (accesible desde todos los Jobs y Steps)
env
:
  APP_NAME
: my-app
  NODE_VERSION
: '18'

jobs
:
  build
:
    runs-on
: ubuntu-latest

    # Nivel 2: nivel de Job (solo accesible desde todos los Steps del Job actual)
    env
:
      BUILD_MODE
: production

    steps
:
      - name
: Mostrar variables de entorno
        # Nivel 3: nivel de Step (solo accesible desde el Step actual)
        env
:
          STEP_VAR
: hello
        run
: |
echo "Nombre de la aplicación: $APP_NAME" # Accede a la variable a nivel de Workflow
echo "Modo de compilación: $BUILD_MODE" # Accede a la variable a nivel de Job
echo "Variable del paso: $STEP_VAR" # Accede a la variable a nivel de Step
echo "Versión de Node: $NODE_VERSION"

2. Variables integradas de GitHub (contexto github)

GitHub Actions proporciona un conjunto de variables de contexto integradas que se pueden referenciar en cualquier posición con la${{ }}sintaxis:

Ejemplo

span style="color: #0053A6;">
steps:
  - name
: Imprimir variables integradas comunes
    run
: |
echo "Nombre del repositorio: ${{ github.repository }}" # p. ej.: your-user/your-repo
echo "Evento desencadenante: ${{ github.event_name }}" # p. ej.: push, pull_request
echo "Rama actual: ${{ github.ref_name }}" # p. ej.: main, develop
echo "SHA del commit: ${{ github.sha }}" # Hash SHA completo del commit actual
echo "Autor: ${{ github.actor }}" # Nombre de usuario que activó este Workflow
echo "Directorio de trabajo: ${{ github.workspace }}" # Ruta del directorio donde se encuentra el código tras el checkout
echo "ID de ejecución: ${{ github.run_id }}" # ID único de esta ejecución del Workflow
echo "Número de ejecución: ${{ github.run_number }}" # Cuántas veces se ha ejecutado este Workflow

3. Secrets (gestión de información sensible)

Información sensible como contraseñas, claves de API o direcciones de servidorno se puede escribir directamente en el archivo yml(porque el código es público); debe almacenarse en los Secrets del repositorio de GitHub.

Pasos de configuración: entrar en la página del repositorio →Settings → Secrets and variables → Actions→ hacer clic enNew repository secret, rellenar el nombre y el valor y guardar.

Ejemplo

span style="color: #0053A6;">
steps:
 # En un Step, referenciar el Secret configurado mediante ${{ secrets.nombre_de_la_clave }}
  # El valor del Secret se oculta automáticamente con *** en los registros, no se filtrará
  - name
: Desplegar al servidor
    env
:
      SSH_KEY
: ${{ secrets.SSH_PRIVATE_KEY }}       # Clave privada SSH del servidor
      SERVER_IP
: ${{ secrets.DEPLOY_SERVER_IP }}    # Dirección IP del servidor
    run
: |
     echo "$SSH_KEY" > ~/.ssh/id_rsa
      chmod 600 ~/.ssh/id_rsa
      ssh user@$SERVER_IP "cd /app && git pull && pm2 restart all"

  # GitHub proporciona automáticamente GITHUB_TOKEN, utilizado para operar este repositorio (como subir código, crear Releases)
  # No es necesario crearlo manualmente, se puede usar directamente.
  - name
: Subir los cambios al repositorio
    run
: |
     git config user.name "github-actions[bot]"
      git config user.email "github-actions[bot]@users.noreply.github.com"
      git add .
git commit -m "actualización automática [skip ci]"
      git push

    env
:
      GITHUB_TOKEN
: ${{ secrets.GITHUB_TOKEN }}     # GitHub lo proporciona automáticamente, no es necesario crearlo manualmente.

Introducción a las Actions de uso frecuente

GitHub oficial y la comunidad proporcionan una gran cantidad de Actions listas para usar, a través deuses: action名称@版本referenciarlas, se puede evitar repetir la escritura de operaciones comunes.

1. actions/checkout (obtener el código)

Casi todos los primeros pasos de un Workflow consisten en obtener el código del repositorio, usando el oficial.actions/checkout:

Ejemplo

span style="color: #0053A6;">
steps:
 # Uso más básico: obtener el código más reciente de la rama actual al directorio de trabajo.
  - uses
: actions/checkout@v4

  # Uso avanzado: personalizar mediante el paso de parámetros con "with".
  - uses
: actions/checkout@v4
    with
:
      ref
: develop              # Obtener una rama específica (por defecto obtiene la rama donde ocurrió el evento de activación).
      fetch-depth
: 0            # Obtener el historial completo de git (por defecto solo obtiene el último commit).
                                # Si se establece en 0, se obtiene todo el historial, y comandos como git log pueden usarse correctamente.
      submodules
: true          # También inicializa y actualiza los submódulos de git (submodule).

2. actions/setup-node (configurar el entorno de Node.js)

Ejemplo

span style="color: #0053A6;">
steps:
  - uses
: actions/checkout@v4

  - name
: Configurar el entorno Node.js.
    uses
: actions/setup-node@v4
    with
:
      node-version
: '20'        # Especificar la versión de Node.js.

  # Después de la configuración, los comandos npm y node están disponibles directamente.
  - run
: node --version
  - run
: npm install
  - run
: npm test

3. actions/setup-python (configurar el entorno de Python)

Ejemplo

span style="color: #0053A6;">
steps:
  - uses
: actions/checkout@v4

  - name
: Configurar el entorno Python.
    uses
: actions/setup-python@v5
    with
:
      python-version
: '3.11'   # Especificar la versión de Python.

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

  - name
: Ejecutar pruebas.
    run
: pytest tests/

4. actions/cache (acelerar la compilación almacenando en caché las dependencias)

Cada vez que se ejecuta un Workflow, volver a descargar las dependencias es lento. Usar la Action cache permite almacenar en caché las dependencias, y en la próxima ejecución usar la caché directamente, reduciendo significativamente el tiempo de compilación:

Ejemplo

span style="color: #0053A6;">
steps:
  - uses
: actions/checkout@v4

  - uses
: actions/setup-node@v4
    with
:
      node-version
: '20'

  - name
: Cachear node_modules.
    uses
: actions/cache@v4
    with
:
      path
: ~/.npm                            # Especificar el directorio a cachear.
      key
: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
      # key: identificador único de la caché.
      # hashFiles('**/package-lock.json'): genera un hash basado en el contenido del archivo lock.
      # Si el archivo lock no cambia, la key no cambia y se acierta directamente en la caché; si el archivo lock cambia, se reinstalan las dependencias.

      restore-keys
: |
       ${{ runner.os }}-node-
      # restore-keys: estrategia de coincidencia degradada cuando la key no acierta, usa la caché válida más reciente.

  - run
: npm ci                              # npm ci es más adecuado que npm install para escenarios de CI, es más rápido y más estricto.
  - run
: npm test

5. actions/upload-artifact / download-artifact (transferir archivos entre Jobs)

Los diferentes Jobs se ejecutan en máquinas virtuales independientes, los archivos no se pueden compartir directamente. Mediante artifact (producto) se pueden transferir los archivos de salida de un Job a otro:

Ejemplo

span style="color: #0053A6;">
jobs:
  build
:
    runs-on
: ubuntu-latest
    steps
:
      - uses
: actions/checkout@v4
      - run
: npm install && npm run build     # El producto de compilación se exporta al directorio ./dist.

      - name
: Subir el producto de compilación.
        uses
: actions/upload-artifact@v4
        with
:
          name
: dist-files                   # Nombre del producto (se referencia por este nombre al descargar).
          path
: ./dist                       # Ruta del directorio o archivo a subir.
          retention-days
: 7                  # Días de retención del producto (máximo 90 días).

  deploy
:
    runs-on
: ubuntu-latest
    needs
: build                             # Esperar a que el Job build se complete antes de ejecutar.
    steps
:
      - name
: Descargar el producto de compilación.
        uses
: actions/download-artifact@v4
        with
:
          name
: dist-files                   # Debe coincidir con el nombre usado al subir.
          path
: ./dist                       # Directorio local donde se descarga.

      - name
: Desplegar archivos.
        run
: rsync -avz ./dist/ user@server:/var/www/html/

Matriz de compilación (Matrix)

La compilación en matriz te permite usar una configuración de Job para ejecutar en paralelo en múltiples entornos, comúnmente usada para pruebas de compatibilidad entre versiones y sistemas operativos:

Ejemplo

span style="color: #0053A6;">
jobs:
  test
:
    name
: Probar Node ${{ matrix.node-version }} on ${{ matrix.os }}
    runs-on
: ${{ matrix.os }}         # Leer el entorno de ejecución desde las variables de la matriz.

    strategy
:
      matrix
:
        os
: [ubuntu-latest, windows-latest, macos-latest]   # 3 sistemas operativos.
        node-version
: ['18', '20', '22']                    # 3 versiones de Node.
        # La combinación anterior produce 3 × 3 = 9 Jobs en paralelo.

      fail-fast
: false                # Por defecto true: si un Job falla, se cancelan todos los demás Jobs.
                                      # Si se establece en false: aunque una combinación falle, las demás continúan ejecutándose,
                                      # para ver los resultados de las pruebas en todos los entornos.

    steps
:
      - uses
: actions/checkout@v4

      - name
: Configurar Node.js ${{ matrix.node-version }}
        uses
: actions/setup-node@v4
        with
:
          node-version
: ${{ matrix.node-version }}   # Referenciar variables de la matriz.

      - run
: npm ci
      - run
: npm test

Ejemplo

# Uso avanzado: mediante exclude se excluyen combinaciones no necesarias, mediante include se agregan configuraciones especiales.
strategy
:
  matrix
:
    os
: [ubuntu-latest, windows-latest]
    node-version
: ['18', '20']
    exclude
:
      - os
: windows-latest
        node-version
: '18'    # Excluir la combinación windows + Node 18.

    include
:
      - os
: ubuntu-latest
        node-version
: '20'
        experimental
: true    # Agregar variables adicionales para combinaciones específicas (se puede referenciar con matrix.experimental en los steps).

Ejemplos prácticos

Ejemplo 1: CI para un proyecto Node.js (pruebas automáticas)

Cada vez que se sube código o se crea un PR, automáticamente se instalan las dependencias, se ejecuta la verificación de código y las pruebas:

Ejemplo

# .github/workflows/ci.yml
name
: Node.js CI

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

jobs
:
  test
:
    name
: Verificación de código y pruebas.
    runs-on
: ubuntu-latest

    steps
:
      - name
: Obtener el código.
        uses
: actions/checkout@v4

      - name
: Configurar el entorno Node.js.
        uses
: actions/setup-node@v4
        with
:
          node-version
: '20'
          cache
: 'npm'                       # setup-node incluye soporte de caché integrado, más simple que usar la Action cache por separado.

      - name
: Instalar dependencias.
        run
: npm ci                          # npm ci instala estrictamente según package-lock.json,
                                             # es más adecuado que npm install para escenarios de CI.

      - name
: Ejecutar la verificación de código (ESLint).
        run
: npm run lint

      - name
: Ejecutar pruebas unitarias.
        run
: npm test -- --coverage          # Genera también el informe de cobertura de pruebas.

      - name
: Subir el informe de cobertura.
        uses
: actions/upload-artifact@v4
        if
: always()                         # Subir el informe independientemente de si las pruebas pasan o no (para ver fácilmente la causa del fallo).
        with
:
          name
: coverage-report
          path
: ./coverage

Ejemplo 2: CI para un proyecto Python

Ejemplo

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

on
:
  push
:
    branches
: [main]
  pull_request
:

jobs
:
  test
:
    runs-on
: ubuntu-latest

    steps
:
      - uses
: actions/checkout@v4

      - name
: Configurar el entorno Python.
        uses
: actions/setup-python@v5
        with
:
          python-version
: '3.11'
          cache
: 'pip'                       # Cachear dependencias de pip.

      - name
: Instalar dependencias.
        run
: |
         python -m pip install --upgrade pip
          pip install -r requirements.txt
pip install flake8 pytest # Instalar herramientas de verificación de código y pruebas

      - name
: Ejecutar la verificación de formato de código (flake8).
        run
: |
# Verifica errores de sintaxis y variables no definidas (series E9, F63, F7, F82), si encuentra problemas, sale con error directamente.
          flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# Verifica el estilo del código (longitud máxima de línea 120), solo cuenta la cantidad de problemas, no sale con error.
          flake8 . --count --max-line-length=120 --statistics

      - name
: Ejecutar pruebas.
        run
: pytest tests/ -v                # -v muestra resultados detallados de las pruebas.

Ejemplo 3: Construir y hacer push de una imagen Docker

Ejemplo

# .github/workflows/docker.yml
name
: Construir y subir la imagen Docker.

on
:
  push
:
    branches
: [main]
    tags
:
     - 'v*'                               # Se activa al subir un tag que comienza con v, como v1.0.0.

jobs
:
  docker
:
    runs-on
: ubuntu-latest
    steps
:
      - uses
: actions/checkout@v4

      # Usa la Action oficial Docker metadata para generar automáticamente etiquetas de imagen.
      # Por ejemplo, al subir el tag v1.2.3, genera automáticamente varias etiquetas como 1.2.3, 1.2, 1, latest, etc.
      - name
: Extraer metadatos de Docker (etiquetas de imagen, etc.).
        id
: meta                           # Establecer un ID para este Step, para que los Steps posteriores referencien su salida.
        uses
: docker/metadata-action@v5
        with
:
          images
: your-dockerhub-username/your-image-name

      - name
: Iniciar sesión en Docker Hub.
        uses
: docker/login-action@v3
        with
:
          username
: ${{ secrets.DOCKERHUB_USERNAME }}
          password
: ${{ secrets.DOCKERHUB_TOKEN }}   # Usar Access Token en lugar de contraseña es más seguro.

      - name
: Construir y subir la imagen.
        uses
: docker/build-push-action@v5
        with
:
          context
: .                       # Directorio donde se encuentra el Dockerfile (directorio actual).
          push
: true                       # true: enviar al Registry después de completar la compilación.
          tags
: ${{ steps.meta.outputs.tags }}       # Referenciar la lista de etiquetas generada por el Step meta.
          labels
: ${{ steps.meta.outputs.labels }}   # Referenciar la información de etiquetas generada por el Step meta.

Ejemplo 4: Despliegue automático al servidor después de la compilación

Ejemplo

# .github/workflows/deploy.yml
name
: Construir y desplegar.

on
:
  push
:
    branches
: [main]                       # Solo se activa el despliegue cuando se sube a la rama main.

jobs
:
  build-and-deploy
:
    runs-on
: ubuntu-latest

    steps
:
      - uses
: actions/checkout@v4

      - uses
: actions/setup-node@v4
        with
:
          node-version
: '20'
          cache
: 'npm'

      - name
: Instalar dependencias y compilar.
        run
: |
         npm ci
npm run build # El producto de compilación se exporta al directorio ./dist

      - name
: Desplegar al servidor vía SSH.
        uses
: appleboy/[email protected]   # Action SSH de terceros, no es necesario configurar SSH manualmente.
        with
:
          host
: ${{ secrets.SERVER_HOST }}       # IP o dominio del servidor.
          username
: ${{ secrets.SERVER_USER }}   # Nombre de usuario de inicio de sesión SSH.
          key
: ${{ secrets.SSH_PRIVATE_KEY }}    # Contenido de la clave privada SSH (correspondiente a la clave pública del servidor).
          port
: 22                               # Puerto SSH, por defecto 22.
          script
: |
# Los siguientes comandos se ejecutan en el servidor remoto.
            cd /var/www/my-app
            git pull origin main
            npm ci --production
pm2 restart my-app # Reiniciar la aplicación Node.js con pm2
echo "despliegue completado: $(date)"

Ejemplo 5: Tarea programada (copia de seguridad automática de la base de datos)

Ejemplo

# .github/workflows/backup.yml
name
: Copia de seguridad programada de la base de datos.

on
:
  schedule
:
    - cron
: '0 2 * * *'                    # Ejecutar diariamente a las 02:00 UTC (10:00 hora de Pekín)
  workflow_dispatch
:                       # También admite activación manual, conveniente para copias de seguridad temporales

jobs
:
  backup
:
    runs-on
: ubuntu-latest

    steps
:
      - name
: Ejecutar el script de respaldo a través de SSH
        uses
: appleboy/[email protected]
        with
:
          host
: ${{ secrets.SERVER_HOST }}
          username
: ${{ secrets.SERVER_USER }}
          key
: ${{ secrets.SSH_PRIVATE_KEY }}
          script
: |
           TIMESTAMP=$(date +%Y%m%d_%H%M%S)
            BACKUP_FILE="/backup/db_$TIMESTAMP.sql"

# Realizar copia de seguridad de la base de datos
            mysqldump -u root -p${{ secrets.DB_PASSWORD }} my_database > $BACKUP_FILE

# Comprimir el archivo de respaldo
            gzip $BACKUP_FILE

# Eliminar archivos de respaldo de hace más de 30 días para evitar que el disco se llene
            find /backup -name "*.sql.gz" -mtime +30 -delete

echo "Copia de seguridad completada: ${BACKUP_FILE}.gz"


Consejos de depuración

1. Activar los registros de Debug

Cuando un Workflow falla pero la información del registro no es suficiente, se puede activar el modo de depuración detallado. Método: entrar al repositorioSettings → Secrets and variables → Actions, agregar los siguientes dos Secret (ambos valores establecidos entrue):

  • ACTIONS_RUNNER_DEBUG: Habilitar registro detallado del runner
  • ACTIONS_STEP_DEBUG: Habilitar el registro de depuración detallado de cada Step

2. Imprimir información de contexto para ayudar a diagnosticar problemas

Ejemplo

span style="color: #0053A6;">
steps:
  - name
: Imprimir toda la información de contexto (para depuración, añadir al resolver problemas, eliminar después de resolverlos)
    run
: |
echo "=== contexto de github ==="
echo '${{ toJson(github) }}' # toJson() formatea el objeto como una cadena JSON de salida
echo "=== contexto de env ==="
      echo '${{ toJson(env) }}'
echo "=== contexto de job ==="
      echo '${{ toJson(job) }}'

3. Probar el Workflow localmente (usando act)

Es muy ineficiente tener que hacer push del código cada vez para probar el Workflow.actes una herramienta de código abierto que puede simular la ejecución de GitHub Actions localmente, aumentando en gran medida la eficiencia de depuración:

# 安装 act(需要本地已安装 Docker)
# macOS
brew install act

# Linux
curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash

# 在仓库根目录运行所有 Workflow
act

# 只运行指定事件触发的 Workflow
act push

# 只运行指定的 Job
act -j build

Al realizar pruebas locales,actse utilizan contenedores Docker para simular el entorno de ejecución de GitHub, pero algunas Actions (comoactions/cache) en la simulación local pueden diferir del entorno real; el resultado final se basará en la ejecución real en GitHub.


Preguntas frecuentes y consideraciones

1. Problema de permisos (Permission denied)

Si el Workflow necesita enviar código al repositorio o gestionar Issues, debe declarar explícitamente los permisos en el archivo de configuración:

Ejemplo

# Establecer permisos en el nivel superior del Workflow o a nivel de Job
permissions
:
  contents
: write       # Permitir lectura y escritura del contenido del repositorio (código, archivos)
  issues
: write         # Permitir crear y modificar Issues
  pull-requests
: write  # Permitir operar en Pull Requests

# Principio de mínimos privilegios: solo otorgar los permisos realmente necesarios, el resto por defecto como read o none

2. Evitar la activación en bucle del Workflow

Si el Workflow envía código automáticamente al repositorio, puede provocar un nuevo evento push y causar un bucle infinito. Solución: agregar[skip ci]la palabra clave, y GitHub omitirá la activación del Workflow para esa confirmación:

git commit -m "自动格式化代码 [skip ci]"

3. Escape de caracteres especiales en YAML

EnrunEn el comando Shell del campo, al usar${{ }}expresiones, si la expresión contiene dos puntos (:) y otros caracteres especiales de YAML, es necesario encerrar todo el valor entre comillas, o bien asignarlo primero a una variable de entorno y luego usarla:

Ejemplo

span style="color: #0053A6;">
steps:
 # No recomendado: insertar la expresión ${{ }} directamente en comandos complejos puede causar errores de análisis de YAML
  - run
: echo ${{ github.event.pull_request.title }}

  # Recomendado: asignar primero el valor a una variable de entorno y luego usar la variable de entorno en Shell
  - name
: Imprimir el título del PR
    env
:
      PR_TITLE
: ${{ github.event.pull_request.title }}
    run
: echo "Título del PR: $PR_TITLE"

Para más documentación completa, consulte la documentación oficial:https://docs.github.com/zh/actions

Otras extensiones