
Semaphore UI 2.20 añade un registro de auditoría con exportación a SIEM, convierte los Flujos de trabajo en un verdadero motor de pipelines con nodos de retardo, revisiones, salidas transmitidas entre tareas y variables de flujo de trabajo, rehace los roles para que un miembro pueda tener varios y los administradores dispongan de roles de alcance global y asignaciones de grupos del IdP, introduce la configuración de hosts para credenciales SSH y Git por host, traslada todas las variables adicionales de Ansible a archivos cifrados con Vault y expone métricas de Prometheus.
La línea comienza en v2.20.0. Las versiones de parche se enumerarán al final de esta página a medida que se publiquen.
Aspectos destacados
- Registro de auditoría — quién hizo qué, desde dónde y con qué resultado; una pantalla de administración, retención y exportación a Syslog / Splunk HEC para SIEM (la exportación y los filtros, en Pro).
- Flujos de trabajo — nodos de retardo, revisiones inmutables fijadas a las ejecuciones, salidas entregadas como entradas de la tarea siguiente, variables de flujo de trabajo solicitadas en un diálogo de ejecución, un editor rediseñado con atajos de teclado y deshacer, y webhooks que inician flujos de trabajo.
- Varios roles por miembro, roles con ids y slugs, roles globales con permisos de alcance global (Pro) y asignaciones grupo del IdP → rol aplicadas al iniciar sesión (Enterprise).
- Identidades externas — los inicios de sesión LDAP y OIDC se vinculan a las cuentas por el id estable del proveedor, no por correo electrónico; varios directorios LDAP en una sola página de inicio de sesión.
- Configuración de hosts — asigna hosts SSH y URLs de Git a credenciales del proyecto, aplicadas a los clones, Galaxy, los módulos de Terraform y Ansible.
- Las variables adicionales de Ansible ya nunca van en la línea de comandos; los secretos viajan en un archivo cifrado con Ansible Vault y Jinja2 dentro de los valores ya no se evalúa.
- Plantillas: directorio de trabajo de Ansible, nombres únicos y
template_nameen la API de tareas, notificaciones de error silenciadas, Dry Run / Diff ocultos, opciones de instalación de Galaxy, variables de encuesta de selección múltiple, secretos de encuesta en runners remotos. - Repositorios monorepo comparten un único checkout entre plantillas; reintentos de Git, obtención paralela de submódulos, comprobación de claves de host SSH.
- Métricas de Prometheus en
/api/metrics. - Generación de pares de claves SSH en el servidor y copia de la clave pública desde el almacén de claves.
Registro de auditoría

Semaphore registra ahora los eventos relevantes para la seguridad en un log dedicado y de solo adición. Actívalo con:
"audit": {
"enabled": true,
"instance_id": "semaphore-prod"
}
(SEMAPHORE_AUDIT_ENABLED, SEMAPHORE_AUDIT_INSTANCE_ID; instance_id es obligatorio y nombra la
instalación en cada evento.)
Qué se registra. 116 tipos de evento en ocho categorías: auth (inicios y cierres de sesión, MFA, rechazos de
tokens de API, peticiones denegadas, bloqueos CSRF), iam (usuarios, contraseñas, tokens de API, identidades,
pertenencias, roles, permisos de plantilla), resource (proyectos, copias de seguridad, inventarios, repositorios,
plantillas, programaciones, integraciones, configuraciones de host, flujos de trabajo, grupos de variables), secret
(credenciales y almacenamientos de secretos), task (inicio con su disparador, finalización con resultado y duración,
aprobaciones, detenciones, eliminación del historial), runner (registro, cambios, informes rechazados), system
(ajustes, licencia) y audit en sí mismo (inicio, retención, exportación). Las contraseñas, los tokens, los valores de
secretos, la salida de las tareas y las variables nunca se escriben.
Envoltorio del evento. Cada evento lleva un UUID, un número de secuencia sin huecos, una marca de tiempo UTC con
precisión de microsegundos, el actor (usuario / anónimo / sistema / runner / integración, con autenticación por sesión o
token de API y una huella del token), la IP de origen y el User‑Agent, el objetivo, el proyecto, un id de petición
(devuelto también en la cabecera de respuesta X-Request-ID), el id de la instancia y el id del nodo HA. Los resultados
son success o failure con una lista cerrada de motivos; una acción que guardó el objeto pero falló en un paso
posterior es un éxito con partial = true. Detrás de un proxy inverso, X-Forwarded-For solo se considera de confianza
desde audit.trusted_proxy_cidrs.

Pantalla de administración. Registro de auditoría en el menú de usuario (/audit-log) enumera los eventos del más
reciente al más antiguo, 50 por página, con paginación Más antiguos / Más recientes; una fila abre una tarjeta con las
secciones Quién, Objeto, Dónde, Cuándo, Detalles y Técnico y un botón que copia el evento como el JSON enviado
a un SIEM. El acceso requiere el nuevo permiso global Leer el registro de auditoría.
Retención. audit.retention_days elimina los eventos más antiguos por lotes, cada hora y con jitter para que los
nodos HA no colisionen; cada pasada que elimina algo queda a su vez registrada.
Pro: filtros y exportación. Filtra por periodo, usuario, proyecto, tipo de evento, resultado e IP; pivota desde cualquier valor de la tarjeta; exporta la selección actual como CSV o JSON Lines.
Pro: exportación a SIEM. Dos destinos, cada uno con su propio cursor para que nada se omita cuando un receptor está
caído: Syslog sobre TLS (RFC 5424, el JSON del evento como cuerpo) mediante audit.syslog y
Splunk HTTP Event Collector mediante audit.splunk_hec (url, token, index, source,
sourcetype, ca_file, …). La entrega es «al menos una vez», ordenada por secuencia; en HA solo un nodo
exporta por destino, coordinado mediante una concesión en Redis. Tres series de Prometheus describen el
exportador: semaphore_audit_export_pending_events, semaphore_audit_export_oldest_pending_seconds
y semaphore_audit_export_errors_total.
Almacenamiento: tablas audit_event, audit_event_sequence, audit_export_state (migraciones v2.20.9
a v2.20.11). API: GET /api/audit/events y GET /api/audit/events/export.
Flujos de trabajo
Los flujos de trabajo son una función Pro; la etiqueta Beta ha desaparecido.
Nodos de retardo
Un cuarto tipo de nodo junto a tarea, aprobación y nota: Retardo pausa la ejecución durante un número de
segundos y después libera sus aristas. La vista de ejecución muestra una cuenta atrás en vivo en la tarjeta; una ejecución
detenida cancela el retardo. Campo delay_seconds, migración v2.20.2.
Revisiones
Cada guardado de un flujo de trabajo crea una nueva revisión del grafo; una ejecución fija la revisión con la que
empezó, de modo que editar un flujo de trabajo nunca altera una ejecución en curso ni deja huérfanos los nodos de
ejecuciones pasadas. El editor muestra una etiqueta rev. N y cuántas ejecuciones siguen ejecutando una revisión
anterior; la vista de ejecución muestra qué revisión ejecuta. Las revisiones que ninguna ejecución referencia se eliminan
cuando se guarda una más reciente. API: GET …/workflows/{id}/revisions y …/revisions/{revision_id}.
Salidas y entradas

Una tarea puede entregar datos estructurados a los nodos posteriores. Cada tarea iniciada por un flujo de trabajo recibe
SEMAPHORE_OUTPUTS_FILE; lo que escriba allí como objeto JSON se convierte en sus salidas:
cat > "$SEMAPHORE_OUTPUTS_FILE" <<EOF
{"image_tag": "1.4.2", "replicas": 3, "subnet_ids": ["subnet-1", "subnet-2"]}
EOF
Ansible produce salidas con ansible.builtin.set_stats a través de un plugin de callback incluido; las salidas de
Terraform, OpenTofu y Terragrunt se capturan automáticamente de output -json
(los valores sensitive se omiten y se listan como No capturado). Las salidas solo se leen cuando la tarea
termina con éxito; los límites son 100 salidas, 32 KB cada una y 256 KB por archivo.
Una conexión hacia un nodo de tarea entrega entradas — rellena las variables de encuesta de la plantilla de destino con las salidas del nodo de origen:
- Por nombre (predeterminado): cada salida cuyo nombre coincide con una variable de encuesta la rellena.
- Asignar entradas explícitamente: enumera los pares
variable ← output keyque se entregan; una vez que el flujo de trabajo tiene una ejecución finalizada, el panel sugiere las claves que produjo esa ejecución.

Los valores se convierten al tipo de la variable, los nodos de aprobación y de retardo transmiten las salidas, una
asignación explícita prevalece sobre la entrega por nombre y una variable obligatoria que queda sin valor
hace fallar la tarea del nodo antes de que empiece, de modo que la ejecución sigue sus aristas en caso de fallo. La vista
de ejecución muestra una insignia N salidas por nodo, el diálogo de tarea incluye una tabla Salidas y el log de la
tarea empieza con una línea Input "x" <- output "y" of node N por cada valor entregado. Las salidas se almacenan en
texto plano y nunca rellenan una variable secret; un secret no puede transmitirse mediante salidas. Las tareas
en runners remotos producen y reciben salidas; los ejecutores Docker y Kubernetes todavía no las capturan.

Variables de flujo de trabajo y el diálogo de ejecución
Un flujo de trabajo tiene sus propias variables de encuesta, solicitadas una sola vez en un diálogo Ejecutar “…” al
iniciar una ejecución (un flujo de trabajo sin variables se inicia de inmediato, como antes). Las respuestas se almacenan
en la ejecución, se muestran como chips en una franja Variables sobre el lienzo de la ejecución y llegan a una tarea
solo mediante un enlace explícito en el panel del nodo — una variable de flujo de trabajo nunca se filtra a una
plantilla por nombre. Los secretos no se admiten como variables de flujo de trabajo. POST …/workflows/{id}/runs acepta
{"environment": {"image_tag": "1.4.3"}}; una respuesta que no encaja con su tipo o un valor obligatorio que falta
rechaza el inicio.
Entorno de una tarea de flujo de trabajo
Cada tarea iniciada por un flujo de trabajo recibe SEMAPHORE_WORKFLOW_ID, SEMAPHORE_WORKFLOW_RUN_ID,
SEMAPHORE_WORKFLOW_URL (necesita web_host) y SEMAPHORE_OUTPUTS_FILE, para todas las aplicaciones y también en
runners remotos.
Editor rediseñado

- Nuevas tarjetas de nodo con mosaico de tipo, estado, duración, insignia de salidas y Aprobar / Rechazar en línea; etiquetas de arista con un desplegable de condición in situ y un botón de eliminar; un lienzo con cuadrícula de puntos.
- Menú de adición rápida desde el conector
+de un nodo, con clic derecho en el lienzo o con el botón del estado vacío: lista buscable de tipos de nodo y plantillas de tarea, el nuevo nodo se conecta en caso de éxito. - Deshacer / rehacer (
Ctrl/⌘+Z,Ctrl/⌘+Shift+Z), renombrado en línea del flujo de trabajo, un menú Problemas que enfoca el nodo infractor, una insignia Guardar para los cambios sin guardar y una protección al salir de la página. - Atajos de teclado en el lienzo: las flechas desplazan (
Shiftpara un paso grande),+/-hacen zoom,0ajusta el grafo,1restablece el zoom,Escborra la selección; las tarjetas de nodo admiten foco por teclado. - Controles flotantes: acercar / alejar, ajustar vista, autodisposición Ordenar, porcentaje de zoom.
- Un solo chevrón contrae la paleta y la navegación principal a la vez; el estado se recuerda.
- El desbordamiento de desplazamiento del trackpad ya no activa el gesto Atrás del navegador en macOS.

Los webhooks inician flujos de trabajo
Una integración puede ahora ejecutar un flujo de trabajo en lugar de una plantilla (Ejecuta: Plantilla / Flujo de
trabajo en el formulario de integración). Cada valor extraído se convierte en una respuesta a la encuesta del flujo de
trabajo. Gestionar esas integraciones requiere la función Pro workflow_integrations_management. En las integraciones de
plantilla, un valor extraído de Parámetros de tarea llamado git_branch establece la rama de la tarea iniciada cuando
la plantilla permite sobrescribirla.
Cambios en la API
POST …/workflows/{id}/run se renombró a POST …/workflows/{id}/runs y acepta el cuerpo
environment. Los detalles de la ejecución llevan revision_id, revision, un objeto delay por nodo y
task.artifacts. Los workflow_run_id, workflow_node_id y artifacts suministrados por el cliente en una tarea
se ignoran, de modo que una tarea no puede hacerse pasar por un nodo de la ejecución de otro.
Roles y control de acceso
Varios roles por miembro

Un miembro del proyecto tiene un conjunto de roles, editado como chips en la página Equipo. La API acepta
roles: ["manager", "release_approver"] junto al role heredado; la respuesta conserva el role escalar
solo para los miembros con un único rol. Un usuario que no es administrador no puede quitar el rol integrado Owner al
último propietario.
Roles con ids, slugs y alcances
Los roles son ahora filas con un id entero y un slug (^[A-Za-z0-9_-]{1,100}$, derivado del
nombre en el formulario); los cuatro roles integrados también son filas y ya no pueden ser enmascarados por un rol
personalizado. Los roles tienen un alcance: integrado, compartido (utilizable en cualquier proyecto) o de proyecto.
Eliminar un rol en uso responde 409 con su impacto (miembros, proyectos, permisos de plantilla, asignaciones)
y puede repetirse con ?force=true — Eliminar con asignaciones en la interfaz. Las migraciones v2.20.12
y v2.20.13 reconstruyen las tablas de roles; consulta las notas de actualización.
Roles y permisos globales (Pro)

Los derechos de alcance global ya no se reducen al indicador de administrador. Un rol global concede una máscara de
cuatro permisos — Gestionar usuarios, Gestionar roles globales, Gestionar ajustes del sistema, Leer el registro de
auditoría — y se asigna a los usuarios en la pestaña Roles de la página Usuarios (/users/roles) y en la
pestaña Roles globales del diálogo de usuario, que muestra además los permisos efectivos y qué rol
concede cada uno. Toda ruta de administración está protegida por uno de los cuatro bits; GET /api/user devuelve
global_permissions. Una instancia conserva siempre al menos un administrador, garantizado con un bloqueo de fila
seguro entre nodos HA. Un usuario con Gestionar usuarios no puede editar a un administrador ni a nadie que tenga
un permiso del que él carece. API: /api/global-roles, /api/users/{id}/global-roles,
/api/users/{id}/global-permissions, catálogo en /api/global-roles/permissions.
Asignaciones de roles por grupo (Enterprise)

Asigna un grupo del proveedor de identidad a un rol de proyecto en la nueva página Asignaciones de grupo
(/role-mappings): proveedor, grupo, proyecto, rol. En cada inicio de sesión OIDC, los roles asignados del usuario
se ajustan a los grupos presentes en el token (groups_claim del proveedor). Los roles asignados aparecen en la
página Equipo como chips bloqueados con un tooltip provider: group y no pueden eliminarse como roles de miembro; los
roles asignados no cuentan como el último propietario del proyecto. Un inicio de sesión con contraseña o LDAP borra los
roles asignados, porque no aporta grupos. API: /api/role_mappings.
Autenticación e identidades

- Identidades externas. Los inicios de sesión LDAP y OIDC se vinculan a las cuentas de Semaphore por el id estable del
proveedor (
subde OIDC, DN de LDAP) en la nueva tablauser__external_identity, no por correo electrónico. Esto cierra la clase de fallo en la que un IdP que acepta cualquier dirección escrita adopta la cuenta de otra persona.external_auth_email_matching(autopor defecto,always,never) controla si un usuario externo existente sin identidad puede aún emparejarse una vez por correo electrónico; las cuentas locales con contraseña nunca se adoptan. El correo electrónico de OIDC solo cuenta cuando estáemail_verifiedy el proveedor establecerequire_verified_email. Los usuarios vinculan y desvinculan identidades por sí mismos en el diálogo de cuenta (/api/users/{id}/identities,POST /api/user/identities/ldap,/api/auth/oidc/{provider}/login?link=1). - Varios directorios LDAP.
ldap_providerses un mapa de directorios con nombre, cada uno con su propio servidor, bind, búsqueda, mapeos, color y orden; el bloque plano heredadoldap_*sigue funcionando como el proveedorldap. La página de inicio de sesión muestra un selector cuando hay más de una pestaña, y la pestaña interna nunca envía una contraseña a un directorio.GET /api/auth/logindevuelveldap_providersylogin_with_password. - Los certificados LDAPS se verifican por defecto. Define
ldap_tls_skip_verify(bloque plano) otls_skip_verify(por proveedor) para un certificado autofirmado. - Vida absoluta de la sesión.
auth.max_session_life_hours(SEMAPHORE_AUTH_MAX_SESSION_LIFE_HOURS) caduca una sesión un tiempo fijo después del inicio de sesión, con independencia de su actividad;0conserva solo el tiempo de espera por inactividad. - Un usuario sin proyectos que no puede crear ninguno ve una página Todavía no hay proyectos en lugar de un formulario
que no puede enviar;
POST /api/projectsresponde403en ese caso. - El idioma elegido en el menú de usuario se almacena en el servidor y acompaña al usuario entre
navegadores (
langen/api/user/options).
Configuración de hosts

Una nueva página de proyecto, Configuración de hosts, asigna hosts SSH y URLs de Git a credenciales del proyecto:
- una asignación de tipo Host (
bastion.example.com) adjunta una clave SSH, como un bloqueHostde unssh_configgenerado; - una asignación de tipo URL (
https://github.com/acme/, un prefijo terminado en/cubre un grupo) adjunta una clave SSH o un usuario/contraseña (solo HTTPS), como una reescriturainsteadOfde Git; gana la URL más específica.
Las asignaciones se aplican al repositorio de la plantilla y sus submódulos, a los roles y colecciones de
requirements.yml, a los módulos de terraform init, a los comandos git ejecutados por un playbook, a los repositorios de
inventario y a los hosts de inventario, y a la exploración de ramas y playbooks; se envían a los runners remotos. Las claves
privadas nunca tocan el disco — un agente SSH por asignación, vinculado con IdentityAgent; las contraseñas pasan por
GIT_CONFIG_PARAMETERS y las URLs de repositorio se redactan en los logs de las tareas. Una clave referenciada por una
asignación no puede eliminarse. Las asignaciones forman parte de las copias de seguridad del proyecto. Requiere git_client: cmd_git.
Tabla project__host_config, migración v2.20.7; API /api/project/{id}/host_configs.
Plantillas y tareas

-
Directorio de trabajo de Ansible. Directorio de trabajo distinto ejecuta
ansible-playbookdesde un subdirectorio del repositorio; la ruta debe permanecer dentro del checkout (working_directory, migraciónv2.20.3). -
Nombres de plantilla únicos por proyecto (migración
v2.20.4), yPOST /api/project/{id}/tasksaceptatemplate_nameen lugar detemplate_id. -
Silenciar las notificaciones de error por plantilla, junto al silenciado de éxito ya existente; las alertas por correo electrónico respetan ambos por primera vez (
suppress_error_alerts, migraciónv2.20.5). -
Ocultar Dry Run / Diff del diálogo de tarea por plantilla; el servidor también deja de añadir
--check/--diffpara esa plantilla (task_params.hide_dry_run,hide_diff). -
Opciones de instalación de Galaxy — una sección contraíble con Omitir la instalación de Galaxy, argumentos de CLI separados para
ansible-galaxy role installycollection install(una lista de permitidos de flags;--token,--api-keyy los flags de ruta se rechazan) y la solicitud de sobrescritura por tarea. -
El selector de playbooks enumera los subdirectorios a medida que escribes, filtrados por aplicación (
.ymlpara Ansible, directorios de primer nivel para Terraform / OpenTofu / Terragrunt / Pulumi,.sh,.py,.ps1), omite los directorios de la estructura de Ansible y los directorios con punto, está limitado a 30 entradas y explora un clon superficial confinado a la raíz del repositorio. -
Variables de encuesta de selección múltiple — el nuevo tipo
selectacepta varios valores, representados como chips en el diálogo de tarea;default_valuepuede ser un array.
-
Los secretos de encuesta llegan a los runners remotos. Una respuesta de encuesta
secretllegaba antes vacía a un runner. Ahora se almacena cifrada como una clave de acceso ligada a la tarea (access_key.task_id,expire_at, migraciónv2.20.1), se descifra en el nodo HA que atienda al runner, se elimina cuando la tarea termina y se limpia cada hora; está oculta para el almacén de claves, las copias de seguridad y la API de claves. -
Variables adicionales en YAML. El editor de grupos de variables incorpora un conmutador Tabla | JSON | YAML y un editor a pantalla completa; las conversiones son estrictas (las fechas siguen siendo cadenas, se rechazan las raíces que no son objetos y los números no finitos). El almacenamiento no cambia.

-
La página de la tarea nombra y enlaza la programación o integración que la inició, y marca un origen eliminado como
#id (deleted). Las marcas de tiempo del log ya no se seleccionan al copiar un log. -
Las programaciones validan la expresión en el servidor antes de guardarla, así que se acepta
@hourly, y el aviso de zona horaria puede descartarse.
-
Detener una tarea local termina todo su grupo de procesos:
SIGTERM, un periodo de gracia de 15 s y despuésSIGKILL; los procesosssho de proveedor huérfanos ya no sobreviven a la tarea. Un plan de Terraform detenido ya no continúa; un plan que sale con0anteSIGTERMno se interpreta como éxito. -
El
repository_iddel inventario se conserva solo para el tipofiley debe pertenecer al proyecto. -
Los logs del servidor nombran al usuario en las entradas Task added to queue / Task started.
Secretos y Ansible Vault
-
Las variables adicionales viajan en archivos, no en la línea de comandos. Los grupos de variables, las respuestas de encuesta, las entradas del flujo de trabajo y los detalles de la tarea se escriben en un archivo YAML
0600pasado como--extra-vars @file. Los secretos — las respuestas de encuestasecrety los secretos de los grupos de variables — van a un segundo archivo cifrado en el formato Ansible Vault 1.1 / AES‑256 por una implementación nativa en Go (no se necesita el binarioansible-vault), desbloqueado con una contraseña de un solo uso respondida al--vault-id <uuid>@promptdeansible-playbook. Ni los valores ni la contraseña aparecen enps, y ambos archivos se eliminan cuando la tarea termina. -
Jinja2 en los valores es dato, no código. Toda cadena que contenga
{{,{%,{#o una cabecera#jinja2:se etiqueta como!unsafe, de forma recursiva, así que una respuesta de encuesta como{{ lookup('pipe', 'id') }}se pasa literalmente. Las cadenas sin delimitador se dejan sin etiquetar a propósito: ansible‑core ≥ 2.19 vuelve a resolver los escalares!unsafe, lo que convertiría"2026.08"en un float. -
Un nuevo espacio de nombres de depuración
extra_vars(SEMAPHORE_DEBUG_FILTER=extra_vars) registra cómo se reparten y escriben las variables — solo nombres, archivos y tamaños, nunca valores. -
Generar un par de claves SSH en el servidor. Generar clave SSH en el almacén de claves crea una clave RSA; la clave pública se guarda junto a la clave, se muestra con Mostrar / Ocultar y un botón de copiar, y se ofrece en un diálogo justo después de la creación (
generate_ssh_key).
-
Una actualización de clave escribe
type,secrety la parte pública solo cuando Override está activado, de modo que un cliente no puede alterar la carga útil de una clave sin reemplazar el secreto. -
La lectura de una credencial desde una variable de entorno o un archivo del servidor bajo
dirs.secretsestá ahora documentada (pestañas Env / File del formulario del almacén de claves).
Repositorios y Git
- Monorepo: un único checkout para todas las plantillas. Una opción del repositorio lo clona una sola vez
y lo comparte entre plantillas en lugar de una copia por plantilla; el checkout se bloquea para el
fetch y el pull, y las tareas se ejecutan después en paralelo. Las plantillas de un repositorio así no pueden tener una rama
propia y sus tareas no pueden sobrescribir la rama ni el commit (
monorepo, migraciónv2.20.11). - Reintentos de Git.
cloneypullse reintentan con un retardo exponencial limitado a un minuto;git_attempts(SEMAPHORE_GIT_ATTEMPTS, por defecto4). - Submódulos en paralelo.
git_submodule_jobs(SEMAPHORE_GIT_SUBMODULE_JOBS, por defecto4) se pasa como--jobs. - Comprobación de claves de host SSH. Nueva sección
ssh:config_path,known_hosts_file(SEMAPHORE_SSH_KNOWN_HOSTS_FILE) ystrict_host_key_checking—no(por defecto),yesoaccept-new— aplicada a Git sobre SSH. - La exploración del repositorio usa un clon superficial por rama; las credenciales se codifican en porcentaje para los clones en bare‑metal y se redactan en los logs y en el feed de eventos.
Runners e integraciones
-
runner.check_interval_seconds(SEMAPHORE_RUNNER_CHECK_INTERVAL_SECONDS, por defecto5) define con qué frecuencia sondea un runner; un conmutador Opciones avanzadas en la página Runners lo incluye en los fragmentos generados de variables de entorno, configuración y Docker (publicado env2.19.17). -
runner.connection.timeout_seconds(SEMAPHORE_RUNNER_CONNECTION_TIMEOUT_SECONDS, por defecto3) limita por separado la conexión, el handshake TLS y las cabeceras de respuesta; las subidas de logs no se cortan. -
runners.default_global_runners_mode(SEMAPHORE_DEFAULT_GLOBAL_RUNNERS_MODE:disable,prefer,require) sustituye al obsoletouse_remote_runner;runners.registration_tokensustituye alrunner_registration_tokende primer nivel. -
Diagnósticos de runner del lado del servidor con
SEMAPHORE_DEBUG_FILTER=runner: motivos de rechazo de tokens, detección de reinicio y de estado en línea, informes de progreso rechazados, trazado del despacho. -
Las peticiones
unregisterde un runner se autentican; el cliente del runner rechaza las redirecciones HTTP. -
Autenticación de webhooks con HMAC‑SHA512 (
hmac-sha512) junto a la existente HMAC‑SHA256; la cabecera de la firma es configurable.
-
Se rechaza un webhook cuya integración pertenece a otro proyecto.
Observabilidad
-
Métricas de Prometheus.
GET /api/metricstras HTTP Basic Auth con una credencial de servicio estática:"metrics": { "enabled": true, "username": "prometheus", "password": "…" }(
SEMAPHORE_METRICS_ENABLED,SEMAPHORE_METRICS_USERNAME,SEMAPHORE_METRICS_PASSWORD.) Series:semaphore_tasks_running,semaphore_tasks_total{status}, los colectores estándargo_*yprocess_*, y los medidores de exportación de auditoría en Pro. -
Nuevos espacios de nombres de depuración
extra_varsyrunner; la exploración de repositorios registra la salida de Git en DEBUG. -
La exportación y la restauración de las copias de seguridad de proyecto se registran.
Seguridad
- Vinculación de identidades por id del proveedor en lugar de por correo electrónico; verificación de certificados LDAPS activada por defecto.
- Variables adicionales fuera de la línea de comandos; secretos cifrados con Vault; Jinja2 en los valores sin evaluar.
- Los
workflow_run_id,workflow_node_idyartifactsfalsificados se eliminan de las tareas del cliente. - Las rutas de administración están protegidas por permisos globales explícitos en lugar del indicador de administrador; se rechazan los bits de permiso desconocidos; protección contra la escalada de privilegios en la gestión de usuarios.
- El selector de playbooks está confinado a la raíz del repositorio (
OpenRoot), limitado y filtrado. - Se validan las raíces de las variables adicionales y los números YAML; los argumentos de CLI de Galaxy están en una lista de permitidos.
- Las credenciales de repositorio se redactan en los logs y en el feed de eventos;
=se escapa en los parámetros de configuración de Git. - Los endpoints de auditoría rechazan las lecturas entre sitios y los cursores mal formados; se validan las redes de proxy de confianza.
- El
unregisterdel runner se autentica; el cliente del runner rechaza las redirecciones. - Se verifican los ids de proyecto e integración de los webhooks.
- Las tareas locales se detienen junto con todo su grupo de procesos.
Notas de actualización
Cambios incompatibles y de comportamiento
- Los nombres de plantilla deben ser únicos por proyecto. La migración
v2.20.4añade un índice único; renombra los duplicados antes de actualizar. - Las tablas de roles se reconstruyen (
v2.20.12/v2.20.13). Haz una copia de seguridad primero. Un rol personalizado cuyo slug colisione sin distinguir mayúsculas con uno integrado o con otro rol se renombra (queda registrado); los permisos de plantilla que apuntan a un rol no resoluble se descartan (queda registrado). La pertenencia pasó aproject__user_role; la columnaproject__user.roleha desaparecido. GET /api/project/{id}/usersdevuelverolesolo para los miembros con un único rol — leeroles./roles*pasó del indicador de administrador al permiso Gestionar roles globales; los administradores no se ven afectados.- Los certificados LDAPS se verifican por defecto. Define
ldap_tls_skip_verifyo eltls_skip_verifyde un proveedor para certificados autofirmados. ansible-playbookse invoca de forma distinta:--extra-vars @file, más un segundo archivo y un--vault-id <uuid>@promptcuando la tarea tiene secretos, incluso para plantillas sin vault. Todo lo que analice la línea de comandos, o unansible.cfgque prohíba las solicitudes de vault, queda afectado.- Jinja2 dentro de los valores de las variables adicionales ya no se evalúa. Un playbook que dependía del templating de un valor de webhook o de encuesta dejará de hacerlo.
- El endpoint de ejecución de flujos de trabajo se renombró:
POST …/workflows/{id}/run→…/runs. - Los repositorios monorepo prevalecen sobre la plantilla: sin rama por plantilla, sin sobrescritura de rama ni de commit en las tareas.
- El
repository_iddel inventario se descarta para todos los tipos salvofile. - Detener una tarea local mata su grupo de procesos (todavía sin equivalente en Windows).
- Las salidas de los flujos de trabajo aún no las capturan los ejecutores Docker y Kubernetes; los secretos de encuesta todavía no llegan a esos ejecutores.
Nueva configuración
audit, metrics, auth.max_session_life_hours, ssh.{config_path,known_hosts_file,strict_host_key_checking},
git_attempts, git_submodule_jobs, ldap_providers, ldap_tls_skip_verify,
external_auth_email_matching, groups_claim y require_verified_email por proveedor OIDC,
runner.check_interval_seconds, runner.connection.timeout_seconds,
runners.{default_global_runners_mode,registration_token}. Todas opcionales. Los campos de configuración de tipo puntero
pueden definirse ahora desde variables de entorno. Las páginas de referencia de la configuración y de la CLI se
generan a partir del código fuente.
Migraciones de base de datos
v2.20.0 identidades externas · v2.20.1 secretos de encuesta ligados a la tarea · v2.20.2 nodos de retardo ·
v2.20.3 directorio de trabajo · v2.20.4 nombres de plantilla únicos · v2.20.5 silenciado de alertas de error ·
v2.20.7 configuración de hosts · v2.20.8 revisiones de flujo de trabajo · v2.20.9–v2.20.11 registro de auditoría e
índices, asignaciones de entradas en las aristas, indicador monorepo · v2.20.12–v2.20.13 tablas de roles, variables de
flujo de trabajo · v2.20.14 integraciones de flujo de trabajo y asignaciones de grupo · v2.20.16 roles globales.
Dependencias
Go 1.26; imágenes Docker sobre Alpine 3.24; se añade prometheus/client_golang 1.23; go-oidc 3.21,
go-ldap 3.4.14, golang.org/x/crypto 0.57, modernc.org/sqlite 1.59, logrus 1.10; en el frontend
js-yaml 5 y cron-parser 5.10. Nuevos despliegues con un clic: Cloudzy, RepoCloud y Pethost.
