Ejecución de flujo de trabajo esperando aprobación

Semaphore UI 2.19 es la versión más grande de la línea 2.x. Introduce Flujos de trabajo con un editor gráfico, permite a los runners ejecutar tareas en contenedores Docker y pods de Kubernetes, enseña a Semaphore a emitir tokens de identidad JWT de corta duración a las tareas en ejecución, añade rotación de claves de cifrado, corrige definitivamente la fiabilidad de los runners e incluye una larga lista de cambios de refuerzo de la seguridad.

La línea abarca las versiones v2.19.0 a v2.19.14. Las versiones de parche se enumeran al final.

Aspectos destacados

  • Flujos de trabajo (Beta) — encadena plantillas de tarea en un pipeline con puertas de aprobación, dibujado en un editor gráfico y observado en vivo en el mismo lienzo.
  • Ejecutores Docker y Kubernetes — los runners pueden ejecutar cada tarea en un contenedor o pod nuevo (Pro / Enterprise).
  • Tokens de identidad JWT para tareas — autenticación sin claves desde los playbooks hacia Vault, AWS, GCP, Azure y cualquier otro servicio que acepte tokens OIDC.
  • Rotación de claves de cifrado — un llavero etiquetado con recarga en caliente y un comando vaults check.
  • Variables de encuesta como variables de entorno, además de los tipos int, text y enum con nuevo estilo.
  • Paginación real del lado del servidor del historial de tareas — los proyectos con millones de tareas siguen siendo rápidos.
  • Fiabilidad de los runners — estado en línea/desconectado, tokens de registro de un solo uso con hash y recuperación automática de tareas atascadas en un runner caído.
  • Registro de depuración selectivo con SEMAPHORE_DEBUG_FILTER.
  • Refuerzo de la seguridad: comprobación de la contraseña actual, validación del origen CSRF, cookies seguras, validación más estricta de entradas en toda la API.
  • BoltDB eliminado — solo SQLite, MySQL y PostgreSQL.

Flujos de trabajo (Beta)

Un flujo de trabajo es un grafo de plantillas de tarea que se ejecuta como una sola unidad. Cada nodo es una tarea (ejecuta una plantilla), una aprobación (pausa la ejecución hasta que un usuario aprueba o rechaza) o una nota (anotación libre que nunca se ejecuta). Las aristas llevan una condición: en caso de éxito, en caso de fallo o siempre.

Los flujos de trabajo aparecen como un nuevo elemento Flujos de trabajo en la barra lateral del proyecto, marcado con una etiqueta Beta. Están disponibles en la edición Pro; durante la beta están habilitados independientemente del plan.

Editor gráfico

Editor de flujos de trabajo

El editor es un lienzo a página completa construido sobre Drawflow:

  • arrastra nodos desde la paleta y conéctalos arrastrando desde el conector de un nodo;
  • haz clic en una arista para cambiar su condición; las aristas tienen códigos de color y hay una leyenda en la esquina;
  • haz clic en un nodo para editar sus propiedades en el panel lateral: plantilla, modo de convergencia (todos los padres / cualquier padre), tiempo de espera y mensaje de aprobación, texto de la nota;
  • las aristas hacia el propio nodo y los ciclos se rechazan mientras los dibujas, y un panel Problemas refleja la validación del lado del servidor para que un grafo roto no pueda guardarse;
  • las posiciones de los nodos se conservan; los flujos de trabajo creados mediante la API sin posiciones reciben una disposición topológica automática;
  • haz zoom con la barra de herramientas o Ctrl + rueda del ratón, arrastra el lienzo para desplazarte, contrae la paleta para ganar espacio;
  • Versión inicial inicializa el versionado de las ejecuciones (1.4.0, 1.4.1, …); la versión se propaga a cada tarea que lanza la ejecución.

Panel de propiedades del nodo

Vista de ejecución en vivo

La vista de ejecución reutiliza el mismo lienzo. Cada nodo muestra el estado de su tarea, el nodo activo se resalta, y las aprobaciones pendientes muestran botones Aprobar / Rechazar directamente en el lienzo. Un botón Detener fuerza la detención de todas las tareas de la ejecución, rechaza las aprobaciones pendientes y marca la ejecución como stopped.

Vista de ejecución en tema oscuro

Los estados de ejecución son running, approval, success, failed y stopped. La progresión del flujo de trabajo la dirige el servidor: cuando cualquier tarea del flujo termina, se programan los siguientes nodos, de modo que una plantilla sin hijos con ejecución automática ya no bloquea la ejecución.

Lista de flujos de trabajo

Parámetros de tarea por nodo

Cada nodo de tarea puede sobrescribir los parámetros que pasa a su plantilla (variables, inventario, rama, argumentos, versión, mensaje), del mismo modo que una ejecución manual.

API

GET/POST   /api/project/{id}/workflows
GET/PUT/DELETE /api/project/{id}/workflows/{workflow_id}
POST       /api/project/{id}/workflows/{workflow_id}/run
GET        /api/project/{id}/workflows/{workflow_id}/runs
GET        /api/project/{id}/workflows/{workflow_id}/runs/{run_id}
POST       /api/project/{id}/workflows/{workflow_id}/runs/{run_id}/stop
GET        /api/project/{id}/workflows/{workflow_id}/runs/{run_id}/artifacts
GET        /api/project/{id}/workflows/{workflow_id}/runs/{run_id}/approvals
POST       /api/project/{id}/workflows/{workflow_id}/runs/{run_id}/approvals/{node_id}

Limitaciones conocidas de la beta: sin minimapa, deshacer/rehacer ni selección múltiple; los artefactos del flujo de trabajo (valores de set_stats) todavía no fluyen entre tareas ejecutadas en runners remotos.


Ejecutores Docker y Kubernetes (Pro / Enterprise)

Los runners pueden ejecutar cada tarea en un entorno aislado en lugar de directamente en el host del runner. El ejecutor se selecciona una vez por proceso del runner con runner.executor.type (local, docker, k8s).

Docker (runner.executor.docker, Pro):

Opción Variable de entorno Valor predeterminado
host SEMAPHORE_RUNNER_DOCKER_HOST socket local
tls_verify, cert_path SEMAPHORE_RUNNER_DOCKER_TLS_VERIFY, …_CERT_PATH
image SEMAPHORE_RUNNER_DOCKER_IMAGE semaphoreui/job:latest
helper_image SEMAPHORE_RUNNER_DOCKER_HELPER_IMAGE semaphoreui/helper:latest
network SEMAPHORE_RUNNER_DOCKER_NETWORK bridge
pull_policy SEMAPHORE_RUNNER_DOCKER_PULL_POLICY if-not-present
cpu_limit, memory_limit SEMAPHORE_RUNNER_DOCKER_CPU_LIMIT, …_MEMORY_LIMIT
privileged SEMAPHORE_RUNNER_DOCKER_PRIVILEGED false
poll_interval_seconds, cleanup_grace_seconds …_POLL_INTERVAL_SECONDS, …_CLEANUP_GRACE_SECONDS 2, 30

Kubernetes (runner.executor.k8s, Enterprise):

Opción Variable de entorno Valor predeterminado
kubeconfig SEMAPHORE_RUNNER_K8S_KUBECONFIG dentro del clúster
namespace SEMAPHORE_RUNNER_K8S_NAMESPACE semaphore
image SEMAPHORE_RUNNER_K8S_IMAGE semaphoreui/job:latest
helper_image SEMAPHORE_RUNNER_K8S_HELPER_IMAGE semaphoreui/helper:latest
service_account SEMAPHORE_RUNNER_K8S_SERVICE_ACCOUNT default
pull_secrets SEMAPHORE_RUNNER_K8S_PULL_SECRETS
poll_interval_seconds, cleanup_grace_seconds …_POLL_INTERVAL_SECONDS, …_CLEANUP_GRACE_SECONDS 3, 30

CI publica dos imágenes nuevas: semaphoreui/job (Ansible, Terraform, OpenTofu, Terragrunt, paramiko) y semaphoreui/helper. Una plantilla puede sobrescribir la imagen para sus propias tareas con el nuevo campo Imagen del ejecutor en el formulario de plantilla (se muestra con una insignia Actualizar a PRO cuando la función de ejecutor no está licenciada).

La conexión del runner también incorpora runner.connection.server_ca_cert_file y runner.connection.skip_tls_verify.


Tokens de identidad JWT para tareas

Semaphore puede actuar como un proveedor de identidad de tipo OIDC para las tareas en ejecución, de modo que un playbook pueda autenticarse ante Vault, endpoints STS en la nube o servicios internos sin credenciales de larga duración.

Formulario de plantilla: opciones avanzadas con JWT

  • Actívalo por plantilla con Emitir JWT al ejecutor de la tarea; define una o más audiencias y un TTL (limitado por jwt.max_ttl).
  • La tarea recibe el token en la variable de entorno SEMAPHORE_JWT.
  • Los tokens se firman con ES256 (ECDSA P‑256) y solo contienen IDs: task_id, project_id, template_id, user_id más los claims estándar iss, sub, aud, exp, nbf, iat, jti.
  • Las claves públicas se publican en GET /.well-known/jwks.json.

Configuración del servidor:

"jwt": {
  "enabled": true,
  "issuer": "https://semaphore.example.com",
  "default_ttl": "1h",
  "max_ttl": "24h"
}

Variables de entorno: SEMAPHORE_JWT_ENABLED, SEMAPHORE_JWT_ISSUER, SEMAPHORE_JWT_DEFAULT_TTL, SEMAPHORE_JWT_MAX_TTL.


Variables de encuesta

Entregar una variable como variable de entorno

Una variable de encuesta ahora tiene un ajuste Pasar variable como: la forma propia de la CLI de cada aplicación (--extra-vars para Ansible, -var para Terraform/OpenTofu, un argumento de CLI para scripts de shell) o una variable de entorno del proceso. El nombre de la variable se usa tal cual, así que un usuario de Terraform simplemente la llama TF_VAR_region. Las variables de entorno no aparecen en los listados de procesos, lo que las convierte en la opción más segura para secretos.

Variable de encuesta entregada como variable de entorno

Nuevos tipos

  • int — entrada numérica con validación;
  • text — texto multilínea;
  • enum — editor con nuevo estilo, pares nombre/valor y un valor predeterminado.

Editor de variable de encuesta de tipo enum

El diálogo de tarea muestra cada tipo según corresponde:

Diálogo de nueva tarea con variables de encuesta tipadas

Se almacenan en el JSON survey_vars existente — no se requiere migración.


Plantillas y tareas

  • Selector dinámico de playbooks. El campo Ruta al archivo del playbook enumera los playbooks encontrados en el repositorio (GET /api/project/{id}/repositories/{repository_id}/playbooks). La lista sigue la rama seleccionada y vuelve a texto libre cuando el repositorio no puede leerse.

  • Omitir la instalación de Ansible Galaxy — opción por plantilla, opcionalmente sobrescribible por tarea, para omitir la instalación de roles y colecciones desde requirements.yml.

  • Variables tipadas en los grupos de variables, incluidos números:

    Grupo de variables con variables tipadas

  • Paginación del historial de tareas. La página Historial antes obtenía las 200 tareas más recientes y las paginaba en el cliente, por lo que todo lo anterior era inaccesible. El backend ahora devuelve una página cada vez usando un cursor keyset (?count=20&before=<task_id>, cabecera de respuesta X-Has-Next) sin COUNT(*) ni OFFSET. El pie de página ofrece Filas por página y controles de anterior/siguiente. La misma paginación se aplica a la lista de tareas por plantilla y al panel de control.

    Historial con paginación del lado del servidor

  • Las listas de tareas se recargan como máximo una vez cada 5 segundos; se eliminaron varias peticiones redundantes.

  • Las programaciones se validan con el analizador cron del lado del servidor, así que cliente y servidor ya no discrepan.

  • La sobrescritura de rama en una tarea solo se acepta cuando la plantilla lo permite.

  • Las operaciones Git se serializan por directorio de repositorio. Las plantillas con Permitir tareas paralelas comparten una única copia de trabajo, y git pull / git checkout concurrentes podían corromperla. La actualización y el checkout ahora forman una única sección crítica, tanto para la ejecución local como en runners, incluidos los repositorios de inventario.


Runners

Página de runners con estado en línea/desconectado

  • Estado en línea / desconectado en la página Runners, derivado de la actividad del heartbeat.

  • Tokens de registro de un solo uso. Un runner puede crearse primero en la interfaz y registrarse después con un token smrs_… que se muestra una sola vez, se almacena únicamente como hash SHA‑256 y caduca al cabo de una hora. El diálogo muestra comandos listos para copiar para variables de entorno, archivo de configuración y Docker. Regenerar el token restablece un runner ya registrado para que pueda volver a registrarse.

    Diálogo de token de registro del runner

    SEMAPHORE_WEB_ROOT=https://semaphore.example.com \
    SEMAPHORE_RUNNER_REGISTRATION_TOKEN=smrs_… \
    semaphore runner register --config ./config.runner.json
    
    semaphore runner start --config ./config.runner.json
    
  • Recuperación de tareas colgadas. Los runners envían la hora de inicio de su proceso (X-Runner-Started-At). Un runner que deja de sondear se marca como desconectado tras runners.offline_timeout_sec (120 s): no recibe nuevas tareas y sus tareas en estado starting se reasignan. Tras runners.task_fail_timeout_sec (420 s) sus tareas running se marcan como fallidas con un mensaje claro. Un runner que se reinició y perdió su pool de trabajos en memoria se detecta de inmediato. La reconciliación se ejecuta cada runners.reconcile_interval_sec (30 s).

  • Las tareas reasignadas desde un runner se terminan en el runner antiguo.

  • El mecanismo de respaldo de runners obsoletos ha desaparecido: cuando todos los runners están desconectados, las tareas esperan en la cola en lugar de enviarse a un runner que no ha sondeado durante hasta 30 minutos.

  • Claves de cifrado RSA por runner eliminadas. El tráfico runner‑servidor se apoya en TLS; esto elimina el paso de intercambio de claves del registro y de setup.

  • Corregida una fuga de conexiones TCP en el cliente del runner; los tokens de registro no válidos devuelven 400.


Secretos y cifrado

  • Rotación de claves de cifrado. El nuevo bloque encryption describe un llavero etiquetado: keys en línea (valor o archivo), o un keys_folder donde cada archivo es una clave con el nombre del archivo, además de punteros active para la clave de secretos y la clave de opciones. El texto cifrado ahora lleva un ID de clave, de modo que las claves pueden rotarse sin un recifrado masivo. encryption.keys_file con keys_poll_interval (por defecto 15s) recarga el llavero en caliente. Nueva CLI: semaphore vaults check; semaphore vaults rekey se reescribió en torno al llavero. El antiguo access_key_encryption plano sigue funcionando.
  • option_encryption — una clave independiente para las opciones almacenadas en la base de datos.
  • Tipo de almacenamiento de secretos OpenBao (enrutado a través del proveedor de Vault) con su propio icono.
  • AWS Secrets Manager sin credenciales estáticas — una casilla Usar rol IAM.
  • Opción para omitir la verificación TLS en los almacenamientos Vault/OpenBao.
  • Los campos de secretos sincronizados y de solo lectura ya no se borran al actualizar.

Observabilidad

  • Registro de depuración por espacios de nombres. --debug-filter / SEMAPHORE_DEBUG_FILTER selecciona qué subsistemas emiten salida de depuración, al estilo de debug de Node.js: runner, runner,task_pool, task_*, *, *,-db. Espacios de nombres disponibles: runner, task_pool, task_runner, task_logger, git, terraform, session, ldap, schedule, db, ha. El filtro solo se aplica cuando el nivel de registro es DEBUG; nunca eleva el nivel. Los hooks de syslog respetan el mismo filtro.
  • Muchas nuevas sentencias de depuración contextuales en runners, tareas y autenticación; el espacio de trabajo seleccionado se imprime al arrancar.

Seguridad

Cambiar la contraseña requiere la contraseña actual

  • Cambiar la contraseña ahora requiere la contraseña actual (CWE‑620).
  • Validación de Origin / Referer en las peticiones que cambian el estado (refuerzo contra CSRF).
  • Las cookies de sesión se marcan como Secure cuando se sirven por HTTPS.
  • Los tokens de registro de runners se almacenan con hash y caducan; se eliminaron las claves de cifrado por runner.
  • La creación de roles personalizados comprueba los permisos de quien la solicita (corrección de escalada de privilegios).
  • Validación de URLs de Git; se pasa --end-of-options a git para que una referencia manipulada no pueda leerse como una opción; se comprueba el formato de los hashes de commit; las ramas se validan antes de explorar el repositorio; las rutas de playbook se validan.
  • Se validan las cargas útiles de las claves de acceso y el campo app de la plantilla.
  • Los claims JWT solo llevan IDs — no se filtran nombres ni correos electrónicos a sistemas externos.
  • Los tokens de runner ya no se escriben en las copias de seguridad del proyecto.
  • La API retorna tras un error de escritura en lugar de continuar con una respuesta parcialmente escrita.
  • SLA de seguridad publicado en SECURITY.md; los artefactos de las versiones se firman con la clave GPG [email protected].

Interfaz y localización

Selector de idioma con checo

  • Traducción al checo.
  • Tarjetas desplegables para las secciones JWT y programación del formulario de plantilla.
  • El icono de copiar al portapapeles es visible en el modo claro; corregidos los indicadores giratorios de tareas en ejecución; corregido el relleno del formulario de plantilla; etiqueta Beta en los flujos de trabajo.
  • La extracción de variables de integración conserva los objetos y arrays JSON en lugar de convertirlos en cadenas.

Notas de actualización

Cambios incompatibles y de comportamiento

  1. BoltDB ha desaparecido. bolt ya no es un dialecto válido; el servidor se niega a arrancar con “Bolt is not supported starting from version 2.19”. Migra primero a SQLite, MySQL o PostgreSQL.
  2. Claves de cifrado de runners eliminadas. El servidor y los runners deben estar ambos en 2.19. Asegúrate de que el tráfico runner‑servidor esté protegido con TLS. El aprovisionamiento de runners mediante scripts que esperaba la clave debe actualizarse.
  3. Las API de listas de tareas están paginadas. GET /api/project/{id}/tasks/last acepta count y before; limit sigue aceptándose, pero los clientes que dependían de recibir las 200 tareas más recientes en una sola respuesta deben paginar.
  4. Sin respaldo de runners obsoletos. Con todos los runners desconectados, las tareas permanecen en cola.
  5. Indicador active del runner eliminado del registro.
  6. Las copias de seguridad del proyecto ya no contienen tokens de runner.
  7. SQLite: v2.19.14 reconstruye las tablas session y task para añadir claves foráneas correctas (corrige la eliminación de usuarios). Se eliminan las sesiones huérfanas. Haz una copia de seguridad de la base de datos antes de actualizar.

Nueva configuración

jwt, runners, encryption, option_encryption, secrets_path, db.dialect, runner.executor.{type,docker,k8s}, runner.connection.{server_ca_cert_file,skip_tls_verify}, runner.registration_token_file, runner.token_file. Todas son opcionales; las configuraciones existentes siguen funcionando. Se regeneraron config.schema.yaml y la documentación de referencia de la configuración.

Migraciones de base de datos

v2.18.6 (jwt_params de plantilla), v2.18.15 (tablas de flujos de trabajo), v2.19.2 (runner.started_at), v2.19.11 (project__workflow_node.task_params_id), v2.19.12 (project__template.executor_image), v2.19.14 (reconstrucción de session/task en SQLite). Corregida la compatibilidad de migraciones con MariaDB 12.1.


Versiones de parche

Versión Cambios
2.19.8 Corregida la migración de SQLite; corregida la eliminación de usuarios (claves foráneas de session/task); comparación de cadenas sin distinguir mayúsculas en las consultas a la BD
2.19.9 Variable de entorno SEMAPHORE_RUNNER_EXECUTOR_TYPE; limpieza de omitempty en la configuración
2.19.10 Corrección de la configuración del ejecutor; corrección de la opción de build de Docker
2.19.11 El espacio de trabajo seleccionado se imprime en los logs; etiqueta latest para la imagen helper; pruebas de migración de BD
2.19.12 Corregido puntero nulo en las opciones de configuración del runner; corrección de la propagación de errores
2.19.14 Corregido el manejo del secrets_path heredado en la configuración

Dependencias

Go 1.26; go-git 5.19, go-oidc 3.19, golang.org/x/crypto 0.53, go-ldap 3.4.13, modernc.org/sqlite 1.52. Documentación añadida como submódulo de git; THIRD-PARTY-LICENSES.md regenerado.

You might find this interesting