Anexo: Forgejo Actions

Anexo: Forgejo Actions

Recientemente expliqué cómo configurar tu propio servidor Git con Forgejo y Drone.

De pasada caí en la cuenta de que Forgejo dispone de su propio sistema de Actions, el cual queda mucho mejor integrado ya que podemos ver todos los reportes de las actions dentro de la misma aplicación, evitando así tener que acudir al servicio externo de Drone para ello.

Basándonos en el artículo anterior, deberíamos tener un docker-compose.yml que además de Forgejo levanta una instancia de Drone y su runner. Ahora vamos a crear un nuevo docker-compose que se encargará de levantar y enlazar el runner a nuestro proyecto (o tantos como queramos)

En la carpeta donde tenemos el docker-compose de Forgejo, crearemos una nueva carpeta llamada forgejo-runner:

mkdir forgejo-runner

Dentro, crearemos el siguiente docker-compose:

services:
  docker-in-docker:
    image: docker:dind
    privileged: true
    command: ["dockerd", "-H", "tcp://0.0.0.0:2375", "--tls=false"]

  register:
    image: code.forgejo.org/forgejo/runner:3.3.0
    links:
      - docker-in-docker
    environment:
      DOCKER_HOST: tcp://docker-in-docker:2375
    volumes:
      - ./runner-data:/data
    user: 0:0
    command: >-
      bash -ec '
      if [ -f config.yml ]; then
        exit 0
      fi

      forgejo-runner register \
        --no-interactive \
        --name forgejo-runner \
        --token $FORGEJO_TOKEN \
        --instance $FORGEJO_HOST;

      forgejo-runner generate-config > config.yml;
      chown -R 1000:1000 /data;
      '

  daemon:
    image: code.forgejo.org/forgejo/runner:3.3.0
    restart: unless-stopped
    environment:
      DOCKER_HOST: "tcp://docker-in-docker:2375"
    env_file:
      - '.env'
    links:
      - docker-in-docker
    depends_on:
      register:
        condition: service_completed_successfully
    volumes:
      - ./runner-data:/data

Este docker-compose requiere de un archivo .env en el mismo directorio con las siguientes variables de entorno:

FORGEJO_TOKEN=forgejo-token
FORGEJO_HOST=forgejo-url

Reemplazaremos forgejo-url por la dirección donde tengamos desplegado nuestro servicio, y obtendremos el forgejo-token acudiendo al panel de configuración de Forgejo vía Configuración -> Acciones -> Nodos -> Crear nuevo nodo:

Una vez configurado, desde la carpeta forgejo-runner lanzamos el nuevo conjunto de contenedores con docker compose up -d

Si todo ha ido bien, deberíamos ver el nuevo nodo en el panel de control:

Configurar un workflow

Los workflows tienen una sintaxis muy similar a los de Github Actions. Por defecto tendrán que agregarse a la carpeta .forgejo/workflows para que el runner pueda detectarlos y ejecutarlos.

En el proyecto de prueba que creé ayer, he añadido el archivo .forgejo/workflows/cy.yml:

on: [push]
jobs:
  build:
    runs-on: docker
    container:
      image: node:20
    steps:
      - uses: actions/checkout@v3
      - run: npm install
      - run: npm run build

Si no hemos modificado la configuración, el runner tendrá la etiqueta docker por defecto, así que es importante poner esa etiqueta en el runs-on para que ese runner se encargue de las acciones. En container configuraremos la imagen de docker que queremos desplegar para efectuar el CI y en steps los pasos que hará el workflow, en este caso un checkout, una instalación y una build.

Cuando subimos los cambios, si vamos a la pestaña Actions de nuestro repositorio podemos ver como se ha agregado esta nuevo workflow y el runner lo ejecutará tan pronto como esté disponible:

Con esto ya tendríamos Forgejo Actions configurado en nuestra instancia y podemos prescindir de Drone, por lo que podríamos retirar los contenedores asociados del docker-compose de Forgejo y eliminar la aplicación Oauth que configuramos anteriormente.

El runner tiene un fichero de configuración que creará un volumen en forgejo-runner/runner-data dentro tenemos un fichero config.yml donde podremos configurar diversos parámetros. En mi caso, sólo he aumentado el valor del parámetro capacity para que ejecute tareas de forma concurrente siempre que sea posible.