Escribir Workflows en Forgejo Actions

Por: Artiko
forgejoactionsworkflowsyamlci-cdnodejs

Capitulo 16: Escribir Workflows

Un workflow es un archivo YAML que define que hacer y cuando hacerlo. Forgejo los lee automaticamente desde el directorio .forgejo/workflows/ de tu repositorio.

Estructura del archivo YAML

Crea el directorio y el primer workflow:

mkdir -p .forgejo/workflows
touch .forgejo/workflows/ci.yaml

La estructura basica de un workflow es:

name: CI

on:
  push:
    branches: [main]

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

      - name: Ejecutar pruebas
        run: npm test

Las cuatro secciones principales son:

Triggers (on)

El campo on define cuando se ejecuta el workflow.

Push a ramas especificas:

on:
  push:
    branches:
      - main
      - develop

Pull requests:

on:
  pull_request:
    branches: [main]
    types: [opened, synchronize, reopened]

Tags:

on:
  push:
    tags:
      - "v*"

Ejecucion manual (workflow_dispatch):

on:
  workflow_dispatch:
    inputs:
      ambiente:
        description: "Ambiente de deploy"
        required: true
        default: "staging"
        type: choice
        options: [staging, production]

Horario (cron):

on:
  schedule:
    - cron: "0 6 * * 1-5"  # Lunes a viernes a las 6am UTC

Multiples triggers combinados:

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  workflow_dispatch:

Jobs y runs-on

Cada job es una unidad de trabajo independiente. El campo runs-on debe coincidir con una label del runner registrado:

jobs:
  test:
    runs-on: ubuntu-latest    # Label del runner
    steps:
      - run: echo "corriendo tests"

  lint:
    runs-on: ubuntu-latest
    steps:
      - run: echo "corriendo lint"

Por defecto, los jobs corren en paralelo. Para ejecutarlos en secuencia usa needs (ver capitulo siguiente).

Steps: uses y run

Cada step dentro de un job puede ser de dos tipos:

uses: ejecuta una action reutilizable

steps:
  - name: Checkout
    uses: actions/checkout@v4

  - name: Configurar Node.js
    uses: actions/setup-node@v4
    with:
      node-version: "20"
      cache: "npm"

run: ejecuta comandos de shell directamente

steps:
  - name: Instalar dependencias
    run: npm ci

  - name: Comandos multiples
    run: |
      echo "Paso 1"
      npm run lint
      npm run build

Variables de entorno

Las variables se pueden definir en tres niveles:

A nivel de workflow (disponibles en todos los jobs):

env:
  NODE_ENV: production
  API_URL: https://api.ejemplo.com

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo $NODE_ENV

A nivel de job (disponibles en todos los steps del job):

jobs:
  test:
    runs-on: ubuntu-latest
    env:
      DATABASE_URL: postgres://localhost/test
    steps:
      - run: npm test

A nivel de step (solo en ese step):

steps:
  - name: Deploy
    run: ./deploy.sh
    env:
      DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
      TARGET_ENV: staging

Secrets del repositorio

Los secrets son valores sensibles (tokens, contrasenas, claves API) que se almacenan cifrados en Forgejo y se inyectan como variables de entorno en los workflows.

Crear un secret:

Navega a tu repositorio y ve a:

Settings > Secrets and Variables > Actions > New Repository Secret

Ingresa el nombre (por convencion en MAYUSCULAS) y el valor.

Usar un secret en el workflow:

steps:
  - name: Login a registry
    run: |
      echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login \
        -u ${{ secrets.REGISTRY_USER }} \
        --password-stdin registry.ejemplo.com

Los secrets nunca aparecen en los logs. Si intentas imprimir el valor de un secret, Forgejo lo reemplaza con ***.

Secrets predefinidos disponibles sin configuracion:

# Token con permisos en el repositorio actual
${{ secrets.FORGEJO_TOKEN }}

Ejemplo practico: CI para proyecto Node.js

Workflow completo que instala dependencias, ejecuta lint, pruebas y build:

name: CI

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

env:
  NODE_VERSION: "20"

jobs:
  ci:
    name: Lint, Test y Build
    runs-on: ubuntu-latest

    steps:
      - name: Checkout del codigo
        uses: actions/checkout@v4

      - name: Configurar Node.js ${{ env.NODE_VERSION }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: "npm"

      - name: Instalar dependencias
        run: npm ci

      - name: Verificar formato y lint
        run: npm run lint

      - name: Ejecutar pruebas unitarias
        run: npm test

      - name: Construir aplicacion
        run: npm run build

Ejemplo: tests en push y PR

Workflow diferenciado que ejecuta tests rapidos en PRs y tests completos en push a main:

name: Tests

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

jobs:
  test-rapido:
    name: Tests unitarios
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

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

      - run: npm ci
      - run: npm run test:unit

  test-integracion:
    name: Tests de integracion
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4

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

      - run: npm ci

      - name: Tests de integracion
        run: npm run test:integration
        env:
          DATABASE_URL: ${{ secrets.TEST_DATABASE_URL }}

El condicional if: github.event_name == 'push' hace que el job de integracion solo corra en pushes a main, no en cada PR.

Verificar ejecucion en la UI

Despues de hacer push con un archivo en .forgejo/workflows/, ve a la pestana Actions del repositorio. Veras:

Si el workflow no aparece, verifica que:

  1. El archivo este en .forgejo/workflows/ (no en .github/workflows/)
  2. El YAML sea valido (sin errores de indentacion)
  3. El trigger coincida con el evento que ocurrio

Siguiente: Capitulo 17: Workflows Avanzados —>