Workflow-Lauf wartet auf Freigabe

Semaphore UI 2.19 ist das größte Release der 2.x-Linie. Es führt Workflows mit einem grafischen Editor ein, lässt Runner Aufgaben in Docker-Containern und Kubernetes-Pods ausführen, bringt Semaphore bei, laufenden Aufgaben kurzlebige JWT-Identitätstoken auszustellen, ergänzt die Rotation von Verschlüsselungsschlüsseln, behebt die Runner-Zuverlässigkeit endgültig und liefert eine lange Liste an Sicherheitshärtungen.

Die Linie umfasst die Releases v2.19.0 bis v2.19.14. Die Patch-Releases sind am Ende aufgeführt.

Highlights

  • Workflows (Beta) — Aufgabenvorlagen zu einer Pipeline mit Freigabestufen verketten, in einem grafischen Editor gezeichnet und live auf derselben Arbeitsfläche beobachtet.
  • Docker- und Kubernetes-Executoren — Runner können jede Aufgabe in einem frischen Container oder Pod ausführen (Pro / Enterprise).
  • JWT-Identitätstoken für Aufgaben — schlüssellose Authentifizierung aus Playbooks gegenüber Vault, AWS, GCP, Azure und allem anderen, das OIDC-Token akzeptiert.
  • Rotation von Verschlüsselungsschlüsseln — ein benannter Schlüsselbund mit Hot Reload und einem vaults check-Befehl.
  • Survey-Variablen als Umgebungsvariablen, plus die Typen int, text und ein neu gestaltetes enum.
  • Echte serverseitige Paginierung der Aufgabenhistorie — Projekte mit Millionen von Aufgaben bleiben schnell.
  • Runner-Zuverlässigkeit — Online-/Offline-Status, einmalige gehashte Registrierungstoken und automatische Wiederherstellung von Aufgaben, die auf einem toten Runner hängen.
  • Selektives Debug-Logging mit SEMAPHORE_DEBUG_FILTER.
  • Sicherheitshärtung: Prüfung des aktuellen Passworts, CSRF-Origin-Validierung, sichere Cookies, strengere Eingabevalidierung in der gesamten API.
  • BoltDB entfernt — nur noch SQLite, MySQL und PostgreSQL.

Workflows (Beta)

Ein Workflow ist ein Graph aus Aufgabenvorlagen, der als eine Einheit läuft. Jeder Knoten ist entweder eine Aufgabe (führt eine Vorlage aus), eine Freigabe (pausiert den Lauf, bis ein Benutzer genehmigt oder ablehnt) oder eine Notiz (freie Anmerkung, die nie ausgeführt wird). Kanten tragen eine Bedingung: bei Erfolg, bei Fehler oder immer.

Workflows erscheinen als neuer Eintrag Workflows in der Projekt-Seitenleiste, gekennzeichnet mit einem Beta-Chip. Sie sind in der Pro-Edition verfügbar; während der Beta sind sie unabhängig vom Plan aktiviert.

Grafischer Editor

Workflow-Editor

Der Editor ist eine ganzseitige Arbeitsfläche auf Basis von Drawflow:

  • Knoten aus der Palette ziehen und durch Ziehen von einem Knoten-Anschluss verbinden;
  • auf eine Kante klicken, um ihre Bedingung zu ändern; Kanten sind farblich kodiert und eine Legende sitzt in der Ecke;
  • auf einen Knoten klicken, um seine Eigenschaften im Seitenpanel zu bearbeiten: Vorlage, Konvergenzmodus (alle Eltern / ein beliebiger Elternknoten), Freigabe-Timeout und -Nachricht, Notiztext;
  • Selbstkanten und Zyklen werden bereits beim Zeichnen abgewiesen, und ein Probleme-Panel spiegelt die serverseitige Validierung, sodass ein defekter Graph nicht gespeichert werden kann;
  • Knotenpositionen werden gespeichert; über die API ohne Positionen erstellte Workflows erhalten automatisch ein topologisches Layout;
  • Zoomen über die Symbolleiste oder Ctrl + Mausrad, Arbeitsfläche zum Verschieben ziehen, Palette einklappen, um Platz zu gewinnen;
  • Startversion initialisiert die Versionierung der Läufe (1.4.0, 1.4.1, …); die Version wird an jede vom Lauf gestartete Aufgabe weitergegeben.

Knoten-Eigenschaftenpanel

Live-Laufansicht

Die Laufansicht verwendet dieselbe Arbeitsfläche. Jeder Knoten zeigt seinen Aufgabenstatus, der aktive Knoten ist hervorgehoben, und ausstehende Freigaben zeigen die Schaltflächen Genehmigen / Ablehnen direkt auf der Arbeitsfläche. Eine Stopp-Schaltfläche stoppt jede Aufgabe des Laufs erzwungen, lehnt ausstehende Freigaben ab und markiert den Lauf als stopped.

Laufansicht im dunklen Design

Die Laufstatus sind running, approval, success, failed und stopped. Der Fortschritt eines Workflows wird vom Server gesteuert: Sobald eine Workflow-Aufgabe endet, werden die nächsten Knoten eingeplant, sodass eine Vorlage ohne Autorun-Kinder den Lauf nicht mehr zum Stillstand bringt.

Workflow-Liste

Aufgabenparameter pro Knoten

Jeder Aufgabenknoten kann die Parameter überschreiben, die er an seine Vorlage übergibt (Variablen, Inventar, Branch, Argumente, Version, Nachricht), genau wie ein manueller Lauf.

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}

Bekannte Einschränkungen der Beta: keine Minimap, kein Undo/Redo und keine Mehrfachauswahl; Workflow-Artefakte (set_stats-Werte) fließen noch nicht zwischen Aufgaben, die auf entfernten Runnern ausgeführt werden.


Docker- und Kubernetes-Executoren (Pro / Enterprise)

Runner können jede Aufgabe in einer isolierten Umgebung ausführen statt direkt auf dem Runner-Host. Der Executor wird einmal pro Runner-Prozess mit runner.executor.type ausgewählt (local, docker, k8s).

Docker (runner.executor.docker, Pro):

Option Umgebungsvariable Standard
host SEMAPHORE_RUNNER_DOCKER_HOST lokaler Socket
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):

Option Umgebungsvariable Standard
kubeconfig SEMAPHORE_RUNNER_K8S_KUBECONFIG In-Cluster
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

Zwei neue Images werden von der CI veröffentlicht: semaphoreui/job (Ansible, Terraform, OpenTofu, Terragrunt, paramiko) und semaphoreui/helper. Eine Vorlage kann das Image für ihre eigenen Aufgaben mit dem neuen Feld Executor-Image im Vorlagenformular überschreiben (mit einem Upgrade to PRO-Badge angezeigt, wenn die Executor-Funktion nicht lizenziert ist).

Die Runner-Verbindung erhielt außerdem runner.connection.server_ca_cert_file und runner.connection.skip_tls_verify.


JWT-Identitätstoken für Aufgaben

Semaphore kann für laufende Aufgaben als Identitätsanbieter im OIDC-Stil auftreten, sodass sich ein Playbook ohne langlebige Zugangsdaten bei Vault, Cloud-STS-Endpunkten oder internen Diensten authentifizieren kann.

Vorlagenformular: Erweiterte Optionen mit JWT

  • Pro Vorlage mit JWT an Task-Runner ausstellen aktivieren; eine oder mehrere Audiences und eine TTL festlegen (begrenzt durch jwt.max_ttl).
  • Die Aufgabe erhält das Token in der Umgebungsvariable SEMAPHORE_JWT.
  • Token sind ES256-signiert (ECDSA P-256) und tragen nur IDs: task_id, project_id, template_id, user_id plus die Standard-Claims iss, sub, aud, exp, nbf, iat, jti.
  • Öffentliche Schlüssel werden unter GET /.well-known/jwks.json veröffentlicht.

Serverkonfiguration:

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

Umgebungsvariablen: SEMAPHORE_JWT_ENABLED, SEMAPHORE_JWT_ISSUER, SEMAPHORE_JWT_DEFAULT_TTL, SEMAPHORE_JWT_MAX_TTL.


Survey-Variablen

Eine Variable als Umgebungsvariable übergeben

Eine Survey-Variable hat jetzt die Einstellung Variable übergeben als: der app-spezifische CLI-Weg (--extra-vars für Ansible, -var für Terraform/OpenTofu, ein CLI-Argument für Shell-Skripte) oder eine Prozess-Umgebungsvariable. Der Variablenname wird unverändert verwendet, ein Terraform-Nutzer nennt sie also einfach TF_VAR_region. Umgebungsvariablen erscheinen nicht in Prozesslisten, was sie zur sichereren Wahl für Secrets macht.

Survey-Variable als Umgebungsvariable übergeben

Neue Typen

  • int — numerische Eingabe mit Validierung;
  • text — mehrzeiliger Text;
  • enum — neu gestalteter Editor mit Name/Wert-Paaren und einem Standardwert.

Editor für Enum-Survey-Variablen

Der Aufgabendialog stellt jeden Typ entsprechend dar:

Dialog für neue Aufgabe mit typisierten Survey-Variablen

Gespeichert im bestehenden survey_vars-JSON — keine Migration erforderlich.


Vorlagen und Aufgaben

  • Dynamische Playbook-Auswahl. Das Feld Pfad zur Playbook-Datei listet die im Repository gefundenen Playbooks auf (GET /api/project/{id}/repositories/{repository_id}/playbooks). Die Liste folgt dem gewählten Branch und fällt auf Freitext zurück, wenn das Repository nicht gelesen werden kann.

  • Ansible-Galaxy-Installation überspringen — Option pro Vorlage, optional pro Aufgabe überschreibbar, um die Installation von Rollen und Collections aus requirements.yml zu überspringen.

  • Typisierte Variablen in Variablengruppen, einschließlich Zahlen:

    Variablengruppe mit typisierten Variablen

  • Paginierung der Aufgabenhistorie. Die Historie-Seite lud bisher die neuesten 200 Aufgaben und blätterte clientseitig durch sie, sodass alles Ältere unerreichbar war. Das Backend liefert jetzt jeweils eine Seite über einen Keyset-Cursor (?count=20&before=<task_id>, Antwort-Header X-Has-Next) ohne COUNT(*) und ohne OFFSET. Die Fußzeile bietet Zeilen pro Seite sowie Zurück-/Weiter-Steuerung. Dieselbe Paginierung gilt für die Aufgabenliste pro Vorlage und das Dashboard.

    Historie mit serverseitiger Paginierung

  • Aufgabenlisten werden höchstens alle 5 Sekunden neu geladen; mehrere redundante Anfragen wurden entfernt.

  • Zeitpläne werden mit dem serverseitigen Cron-Parser validiert, sodass Client und Server nicht mehr voneinander abweichen.

  • Das Überschreiben des Branch in einer Aufgabe wird nur akzeptiert, wenn die Vorlage es erlaubt.

  • Git-Operationen werden pro Repository-Verzeichnis serialisiert. Vorlagen mit Parallele Aufgaben erlauben teilen sich eine Arbeitskopie, und gleichzeitige git pull / git checkout konnten sie beschädigen. Update und Checkout bilden jetzt einen einzigen kritischen Abschnitt, sowohl bei lokaler als auch bei Runner-Ausführung, einschließlich Inventar-Repositories.


Runner

Runner-Seite mit Online-/Offline-Status

  • Online-/Offline-Status auf der Runner-Seite, abgeleitet aus der Heartbeat-Erreichbarkeit.

  • Einmalige Registrierungstoken. Ein Runner kann zuerst in der UI angelegt und später mit einem smrs_…-Token registriert werden, das einmal angezeigt wird, nur als SHA-256-Hash gespeichert ist und nach einer Stunde abläuft. Der Dialog zeigt fertige Befehle zum Kopieren für Umgebungsvariablen, Konfigurationsdatei und Docker. Das Neugenerieren des Tokens setzt einen bereits registrierten Runner zurück, sodass er erneut registriert werden kann.

    Dialog für Runner-Registrierungstoken

    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
    
  • Wiederherstellung hängender Aufgaben. Runner senden ihre Prozess-Startzeit (X-Runner-Started-At). Ein Runner, der nicht mehr abfragt, wird nach runners.offline_timeout_sec (120 s) als offline markiert: Er erhält keine neuen Aufgaben, und seine starting-Aufgaben werden neu zugewiesen. Nach runners.task_fail_timeout_sec (420 s) werden seine running-Aufgaben mit einer klaren Meldung als fehlgeschlagen markiert. Ein Runner, der neu gestartet wurde und seinen In-Memory-Job-Pool verloren hat, wird sofort erkannt. Der Abgleich läuft alle runners.reconcile_interval_sec (30 s).

  • Aufgaben, die einem Runner entzogen und neu zugewiesen werden, werden auf dem alten Runner beendet.

  • Der Fallback auf veraltete Runner ist weg: Sind alle Runner offline, warten Aufgaben in der Warteschlange, statt an einen Runner verteilt zu werden, der bis zu 30 Minuten nicht abgefragt hat.

  • RSA-Verschlüsselungsschlüssel pro Runner entfernt. Der Runner-Server-Verkehr stützt sich auf TLS; damit entfällt der Schlüsselaustausch-Schritt bei Registrierung und setup.

  • Ein TCP-Verbindungsleck im Runner-Client wurde behoben; ungültige Registrierungstoken liefern 400.


Secrets und Verschlüsselung

  • Rotation von Verschlüsselungsschlüsseln. Der neue encryption-Block beschreibt einen benannten Schlüsselbund: Inline-keys (Wert oder Datei) oder ein keys_folder, in dem jede Datei ein Schlüssel mit dem Dateinamen als Name ist, plus active-Zeiger für den Secret-Schlüssel und den Options-Schlüssel. Chiffretext trägt jetzt eine Schlüssel-ID, sodass Schlüssel ohne eine Big-Bang-Neuverschlüsselung rotiert werden können. encryption.keys_file mit keys_poll_interval (Standard 15s) lädt den Schlüsselbund im laufenden Betrieb neu. Neue CLI: semaphore vaults check; semaphore vaults rekey wurde rund um den Schlüsselbund neu geschrieben. Das alte flache access_key_encryption funktioniert weiterhin.
  • option_encryption — ein separater Schlüssel für in der Datenbank gespeicherte Optionen.
  • OpenBao-Secret-Speichertyp (über den Vault-Provider geleitet) mit eigenem Symbol.
  • AWS Secrets Manager ohne statische Zugangsdaten — ein Kontrollkästchen IAM-Rolle verwenden.
  • TLS-Skip-Verify-Option für Vault-/OpenBao-Speicher.
  • Synchronisierte und schreibgeschützte Secret-Felder werden beim Aktualisieren nicht mehr gelöscht.

Observability

  • Debug-Logging mit Namensräumen. --debug-filter / SEMAPHORE_DEBUG_FILTER wählt aus, welche Subsysteme Debug-Ausgaben erzeugen, im Stil von Node.js debug: runner, runner,task_pool, task_*, *, *,-db. Verfügbare Namensräume: runner, task_pool, task_runner, task_logger, git, terraform, session, ldap, schedule, db, ha. Der Filter greift nur, wenn der Log-Level DEBUG ist; er hebt den Level nie an. Syslog-Hooks beachten denselben Filter.
  • Viele neue kontextbezogene Debug-Ausgaben in Runnern, Aufgaben und Auth; der gewählte Workspace wird beim Start ausgegeben.

Sicherheit

Passwortänderung erfordert das aktuelle Passwort

  • Das Ändern eines Passworts erfordert jetzt das aktuelle Passwort (CWE-620).
  • Origin-/Referer-Validierung bei zustandsändernden Anfragen (CSRF-Härtung).
  • Session-Cookies werden bei Auslieferung über HTTPS als Secure markiert.
  • Runner-Registrierungstoken werden gehasht gespeichert und laufen ab; Verschlüsselungsschlüssel pro Runner wurden entfernt.
  • Das Anlegen eigener Rollen prüft die Berechtigungen des Aufrufers (Fix einer Rechteausweitung).
  • Git-URL-Validierung; --end-of-options wird an Git übergeben, damit eine manipulierte Ref nicht als Flag gelesen werden kann; Commit-Hashes werden auf ihr Format geprüft; Branches werden vor dem Durchsuchen des Repositorys validiert; Playbook-Pfade werden validiert.
  • Access-Key-Payloads und das app-Feld der Vorlage werden validiert.
  • JWT-Claims tragen nur IDs — keine Namen oder E-Mail-Adressen gelangen an externe Systeme.
  • Runner-Token werden nicht mehr in Projekt-Backups geschrieben.
  • Die API bricht nach einem Schreibfehler ab, statt mit einer teilweise geschriebenen Antwort fortzufahren.
  • Sicherheits-SLA in SECURITY.md veröffentlicht; Release-Artefakte werden mit dem GPG-Schlüssel [email protected] signiert.

UI und Lokalisierung

Sprachauswahl mit Tschechisch

  • Tschechische Übersetzung.
  • Dropdown-Karten für die JWT- und Zeitplan-Abschnitte des Vorlagenformulars.
  • Das Symbol zum Kopieren in die Zwischenablage ist im hellen Modus sichtbar; Spinner laufender Aufgaben behoben; Innenabstand des Vorlagenformulars behoben; Workflow-Beta-Label.
  • Die Extraktion von Integrationsvariablen bewahrt JSON-Objekte und -Arrays, statt sie in Strings umzuwandeln.

Hinweise zum Upgrade

Breaking Changes und Verhaltensänderungen

  1. BoltDB ist weg. bolt ist kein gültiger Dialekt mehr; der Server verweigert den Start mit “Bolt is not supported starting from version 2.19”. Migrieren Sie zuerst zu SQLite, MySQL oder PostgreSQL.
  2. Runner-Verschlüsselungsschlüssel entfernt. Server und Runner müssen beide auf 2.19 sein. Stellen Sie sicher, dass der Runner-Server-Verkehr per TLS geschützt ist. Skriptgesteuerte Runner-Bereitstellung, die den Schlüssel erwartete, muss angepasst werden.
  3. Aufgabenlisten-APIs sind paginiert. GET /api/project/{id}/tasks/last nimmt count und before entgegen; limit wird weiterhin akzeptiert, aber Clients, die sich auf die neuesten 200 Aufgaben in einer Antwort verlassen haben, müssen blättern.
  4. Kein Fallback auf veraltete Runner. Sind alle Runner offline, bleiben Aufgaben in der Warteschlange.
  5. Runner-Flag active entfernt aus der Registrierung.
  6. Projekt-Backups enthalten keine Runner-Token mehr.
  7. SQLite: v2.19.14 baut die Tabellen session und task neu auf, um korrekte Fremdschlüssel hinzuzufügen (behebt das Löschen von Benutzern). Verwaiste Sessions werden entfernt. Sichern Sie die Datenbank vor dem Upgrade.

Neue Konfiguration

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. Alle sind optional; bestehende Konfigurationen funktionieren weiterhin. config.schema.yaml und die Konfigurationsreferenz-Dokumentation wurden neu generiert.

Datenbankmigrationen

v2.18.6 (Vorlage jwt_params), v2.18.15 (Workflow-Tabellen), 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 (SQLite-Neuaufbau von session/task). Kompatibilität der Migration mit MariaDB 12.1 behoben.


Patch-Releases

Version Änderungen
2.19.8 SQLite-Migration behoben; Löschen von Benutzern behoben (Fremdschlüssel session/task); Groß-/Kleinschreibung ignorierender Stringvergleich in DB-Abfragen
2.19.9 Umgebungsvariable SEMAPHORE_RUNNER_EXECUTOR_TYPE; Bereinigung von omitempty in der Konfiguration
2.19.10 Fix der Executor-Konfiguration; Fix der Docker-Build-Option
2.19.11 Gewählter Workspace wird in den Logs ausgegeben; latest-Tag für das Helper-Image; Tests für DB-Migrationen
2.19.12 Nil-Pointer in den Runner-Konfigurationsoptionen behoben; Fix der Fehlerweitergabe
2.19.14 Behandlung des alten secrets_path in der Konfiguration behoben

Abhängigkeiten

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. Docs als Git-Submodul hinzugefügt; THIRD-PARTY-LICENSES.md neu generiert.

You might find this interesting