Exécution de workflow en attente d'approbation

Semaphore UI 2.19 est la plus grande version de la ligne 2.x. Elle introduit les Workflows avec un éditeur graphique, permet aux runners d’exécuter les tâches dans des conteneurs Docker et des pods Kubernetes, apprend à Semaphore à émettre des jetons d’identité JWT de courte durée pour les tâches en cours, ajoute la rotation des clés de chiffrement, corrige définitivement la fiabilité des runners et livre une longue liste de renforcements de sécurité.

La ligne couvre les versions v2.19.0 à v2.19.14. Les versions correctives sont listées à la fin.

Points forts

  • Workflows (Beta) — enchaînez des modèles de tâches en un pipeline avec des étapes d’approbation, dessiné dans un éditeur graphique et suivi en direct sur le même canevas.
  • Exécuteurs Docker et Kubernetes — les runners peuvent exécuter chaque tâche dans un conteneur ou un pod neuf (Pro / Enterprise).
  • Jetons d’identité JWT pour les tâches — authentification sans clé depuis les playbooks vers Vault, AWS, GCP, Azure et tout autre service acceptant des jetons OIDC.
  • Rotation des clés de chiffrement — un trousseau de clés étiquetées avec rechargement à chaud et une commande vaults check.
  • Variables de sondage en tant que variables d’environnement, plus les types int, text et un type enum remanié.
  • Véritable pagination côté serveur de l’historique des tâches — les projets avec des millions de tâches restent rapides.
  • Fiabilité des runners — statut en ligne/hors ligne, jetons d’enregistrement à usage unique hachés, et récupération automatique des tâches bloquées sur un runner mort.
  • Journalisation de débogage sélective avec SEMAPHORE_DEBUG_FILTER.
  • Renforcement de la sécurité : vérification du mot de passe actuel, validation de l’origine CSRF, cookies sécurisés, validation plus stricte des entrées dans toute l’API.
  • BoltDB supprimé — SQLite, MySQL et PostgreSQL uniquement.

Workflows (Beta)

Un workflow est un graphe de modèles de tâches qui s’exécute comme une seule unité. Chaque nœud est soit une tâche (exécute un modèle), soit une approbation (met l’exécution en pause jusqu’à ce qu’un utilisateur approuve ou rejette), soit une note (annotation libre qui ne s’exécute jamais). Les arêtes portent une condition : en cas de succès, en cas d’échec ou toujours.

Les workflows apparaissent sous un nouvel élément Workflows dans la barre latérale du projet, marqué d’une puce Beta. Ils sont disponibles dans l’édition Pro ; pendant la bêta, ils sont activés quel que soit le plan.

Éditeur graphique

Éditeur de workflow

L’éditeur est un canevas pleine page construit sur Drawflow :

  • glissez des nœuds depuis la palette, connectez-les en tirant depuis une poignée de nœud ;
  • cliquez sur une arête pour changer sa condition ; les arêtes sont codées par couleur et une légende se trouve dans le coin ;
  • cliquez sur un nœud pour modifier ses propriétés dans le panneau latéral : modèle, mode de convergence (tous les parents / n’importe quel parent), délai et message d’approbation, texte de la note ;
  • les boucles sur soi-même et les cycles sont rejetés au fur et à mesure que vous les dessinez, et un panneau Problèmes reflète la validation côté serveur afin qu’un graphe cassé ne puisse pas être enregistré ;
  • les positions des nœuds sont persistées ; les workflows créés via l’API sans positions reçoivent une mise en page topologique automatique ;
  • zoomez avec la barre d’outils ou Ctrl + molette de la souris, faites glisser le canevas pour le déplacer, repliez la palette pour gagner de l’espace ;
  • Version de départ amorce le versionnage des exécutions (1.4.0, 1.4.1, …) ; la version est propagée à chaque tâche lancée par l’exécution.

Panneau des propriétés du nœud

Vue d’exécution en direct

La vue d’exécution réutilise le même canevas. Chaque nœud affiche le statut de sa tâche, le nœud actif est mis en évidence, et les approbations en attente affichent des boutons Approuver / Rejeter directement sur le canevas. Un bouton Arrêter force l’arrêt de toutes les tâches de l’exécution, rejette les approbations en attente et marque l’exécution stopped.

Vue d'exécution en thème sombre

Les statuts d’exécution sont running, approval, success, failed et stopped. La progression du workflow est pilotée par le serveur : lorsqu’une tâche du workflow se termine, les nœuds suivants sont planifiés, de sorte qu’un modèle sans enfants en exécution automatique ne bloque plus l’exécution.

Liste des workflows

Paramètres de tâche par nœud

Chaque nœud de tâche peut redéfinir les paramètres qu’il transmet à son modèle (variables, inventaire, branche, arguments, version, message), de la même manière qu’une exécution manuelle.

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}

Limitations connues de la bêta : pas de mini-carte, d’annuler/rétablir ni de sélection multiple ; les artefacts de workflow (valeurs set_stats) ne circulent pas encore entre les tâches exécutées sur des runners distants.


Exécuteurs Docker et Kubernetes (Pro / Enterprise)

Les runners peuvent exécuter chaque tâche dans un environnement isolé plutôt que directement sur l’hôte du runner. L’exécuteur est sélectionné une fois par processus runner avec runner.executor.type (local, docker, k8s).

Docker (runner.executor.docker, Pro) :

Option Variable d’env. Par défaut
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) :

Option Variable d’env. Par défaut
kubeconfig SEMAPHORE_RUNNER_K8S_KUBECONFIG dans le 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

Deux nouvelles images sont publiées par la CI : semaphoreui/job (Ansible, Terraform, OpenTofu, Terragrunt, paramiko) et semaphoreui/helper. Un modèle peut redéfinir l’image pour ses propres tâches grâce au nouveau champ Image de l’exécuteur du formulaire de modèle (affiché avec un badge Passer à PRO lorsque la fonctionnalité d’exécuteur n’est pas sous licence).

La connexion du runner a également gagné runner.connection.server_ca_cert_file et runner.connection.skip_tls_verify.


Jetons d’identité JWT pour les tâches

Semaphore peut agir comme un fournisseur d’identité de type OIDC pour les tâches en cours, de sorte qu’un playbook peut s’authentifier auprès de Vault, de points de terminaison STS cloud ou de services internes sans identifiants de longue durée.

Formulaire de modèle : options avancées avec JWT

  • Activez-le par modèle avec Émettre un JWT au runner de tâche ; définissez une ou plusieurs audiences et un TTL (plafonné par jwt.max_ttl).
  • La tâche reçoit le jeton dans la variable d’environnement SEMAPHORE_JWT.
  • Les jetons sont signés en ES256 (ECDSA P‑256) et ne contiennent que des identifiants : task_id, project_id, template_id, user_id plus les claims standard iss, sub, aud, exp, nbf, iat, jti.
  • Les clés publiques sont publiées sur GET /.well-known/jwks.json.

Configuration du serveur :

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

Variables d’environnement : SEMAPHORE_JWT_ENABLED, SEMAPHORE_JWT_ISSUER, SEMAPHORE_JWT_DEFAULT_TTL, SEMAPHORE_JWT_MAX_TTL.


Variables de sondage

Transmettre une variable en tant que variable d’environnement

Une variable de sondage dispose désormais d’un paramètre Transmettre la variable en tant que : la méthode CLI propre à l’application (--extra-vars pour Ansible, -var pour Terraform/OpenTofu, un argument CLI pour les scripts shell) ou une variable d’environnement du processus. Le nom de la variable est utilisé tel quel, de sorte qu’un utilisateur Terraform la nomme simplement TF_VAR_region. Les variables d’environnement n’apparaissent pas dans la liste des processus, ce qui en fait le choix le plus sûr pour les secrets.

Variable de sondage transmise en tant que variable d'environnement

Nouveaux types

  • int — saisie numérique avec validation ;
  • text — texte multiligne ;
  • enum — éditeur remanié avec des paires nom/valeur et une valeur par défaut.

Éditeur de variable de sondage de type enum

La boîte de dialogue de tâche affiche chaque type en conséquence :

Boîte de dialogue de nouvelle tâche avec variables de sondage typées

Stocké dans le JSON survey_vars existant — aucune migration requise.


Modèles et tâches

  • Sélecteur de playbook dynamique. Le champ Chemin vers le fichier playbook liste les playbooks trouvés dans le dépôt (GET /api/project/{id}/repositories/{repository_id}/playbooks). La liste suit la branche sélectionnée et revient à la saisie libre lorsque le dépôt ne peut pas être lu.

  • Ignorer l’installation de galaxy — option par modèle, éventuellement redéfinissable par tâche, pour ignorer l’installation des rôles et collections depuis requirements.yml.

  • Variables typées dans les groupes de variables, y compris les nombres :

    Groupe de variables avec variables typées

  • Pagination de l’historique des tâches. La page Historique récupérait auparavant les 200 tâches les plus récentes et les paginait côté client, si bien que tout ce qui était plus ancien était inaccessible. Le backend renvoie désormais une page à la fois à l’aide d’un curseur keyset (?count=20&before=<task_id>, en-tête de réponse X-Has-Next) sans COUNT(*) ni OFFSET. Le pied de page propose Lignes par page et des contrôles précédent/suivant. La même pagination s’applique à la liste des tâches par modèle et au tableau de bord.

    Historique avec pagination côté serveur

  • Les listes de tâches se rechargent au plus une fois toutes les 5 secondes ; plusieurs requêtes redondantes ont été supprimées.

  • Les planifications sont validées avec l’analyseur cron côté serveur, de sorte que le client et le serveur ne sont plus en désaccord.

  • La redéfinition de branche dans une tâche n’est acceptée que lorsque le modèle l’autorise.

  • Les opérations Git sont sérialisées par répertoire de dépôt. Les modèles avec Autoriser les tâches parallèles partagent une seule copie de travail, et des git pull / git checkout concurrents pouvaient la corrompre. La mise à jour et le checkout forment désormais une seule section critique, tant pour l’exécution locale que sur runner, y compris pour les dépôts d’inventaire.


Runners

Page des runners avec statut en ligne/hors ligne

  • Statut en ligne / hors ligne sur la page Runners, dérivé de la vivacité des battements de cœur.

  • Jetons d’enregistrement à usage unique. Un runner peut être créé d’abord dans l’interface puis enregistré plus tard avec un jeton smrs_… affiché une seule fois, stocké uniquement sous forme de hachage SHA‑256 et expirant après une heure. La boîte de dialogue affiche des commandes prêtes à copier pour les variables d’env., le fichier de configuration et Docker. Régénérer le jeton réinitialise un runner déjà enregistré afin qu’il puisse être enregistré à nouveau.

    Boîte de dialogue du jeton d'enregistrement du 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
    
  • Récupération des tâches bloquées. Les runners envoient l’heure de démarrage de leur processus (X-Runner-Started-At). Un runner qui cesse d’interroger le serveur est marqué hors ligne après runners.offline_timeout_sec (120 s) : il ne reçoit plus de nouvelles tâches et ses tâches starting sont réassignées. Après runners.task_fail_timeout_sec (420 s), ses tâches running sont mises en échec avec un message clair. Un runner qui a redémarré et perdu son pool de jobs en mémoire est détecté immédiatement. La réconciliation s’exécute toutes les runners.reconcile_interval_sec (30 s).

  • Les tâches réassignées depuis un runner sont terminées sur l’ancien runner.

  • Le repli sur runner obsolète a disparu : lorsque tous les runners sont hors ligne, les tâches attendent dans la file au lieu d’être envoyées à un runner qui n’a pas interrogé le serveur depuis jusqu’à 30 minutes.

  • Clés de chiffrement RSA par runner supprimées. Le trafic runner‑serveur repose sur TLS ; cela supprime l’étape d’échange de clés de l’enregistrement et de setup.

  • Correction d’une fuite de connexions TCP dans le client runner ; les jetons d’enregistrement invalides renvoient 400.


Secrets et chiffrement

  • Rotation des clés de chiffrement. Le nouveau bloc encryption décrit un trousseau de clés étiquetées : des keys en ligne (valeur ou fichier), ou un keys_folder où chaque fichier est une clé nommée d’après son nom de fichier, plus des pointeurs active pour la clé des secrets et la clé des options. Le texte chiffré porte désormais un identifiant de clé, ce qui permet de faire tourner les clés sans rechiffrement massif. encryption.keys_file avec keys_poll_interval (par défaut 15s) recharge le trousseau à chaud. Nouvelle CLI : semaphore vaults check ; semaphore vaults rekey a été réécrit autour du trousseau. L’ancien access_key_encryption à plat fonctionne toujours.
  • option_encryption — une clé distincte pour les options stockées dans la base de données.
  • Type de stockage de secrets OpenBao (routé via le fournisseur Vault) avec sa propre icône.
  • AWS Secrets Manager sans identifiants statiques — une case à cocher Utiliser un rôle IAM.
  • Option d’ignorer la vérification TLS pour les stockages Vault/OpenBao.
  • Les champs de secrets synchronisés et en lecture seule ne sont plus effacés lors de la mise à jour.

Observabilité

  • Journalisation de débogage par espace de noms. --debug-filter / SEMAPHORE_DEBUG_FILTER sélectionne les sous-systèmes qui émettent une sortie de débogage, à la manière de debug de Node.js : runner, runner,task_pool, task_*, *, *,-db. Espaces de noms disponibles : runner, task_pool, task_runner, task_logger, git, terraform, session, ldap, schedule, db, ha. Le filtre ne s’applique que lorsque le niveau de journalisation est DEBUG ; il n’élève jamais le niveau. Les hooks Syslog respectent le même filtre.
  • De nombreuses nouvelles instructions de débogage contextuelles dans les runners, les tâches et l’authentification ; l’espace de travail sélectionné est affiché au démarrage.

Sécurité

Le changement de mot de passe exige le mot de passe actuel

  • Le changement de mot de passe exige désormais le mot de passe actuel (CWE‑620).
  • Validation Origin / Referer sur les requêtes modifiant l’état (renforcement CSRF).
  • Les cookies de session sont marqués Secure lorsqu’ils sont servis via HTTPS.
  • Les jetons d’enregistrement des runners sont stockés hachés et expirent ; les clés de chiffrement par runner ont été supprimées.
  • La création de rôles personnalisés vérifie les permissions de l’appelant (correctif d’élévation de privilèges).
  • Validation des URL Git ; --end-of-options est transmis à git afin qu’une référence forgée ne puisse pas être lue comme un drapeau ; le format des hachages de commit est vérifié ; les branches sont validées avant la navigation dans le dépôt ; les chemins de playbook sont validés.
  • Les charges utiles des clés d’accès et le champ app du modèle sont validés.
  • Les claims JWT ne contiennent que des identifiants — aucun nom ni e‑mail ne fuite vers des systèmes externes.
  • Les jetons des runners ne sont plus écrits dans les sauvegardes de projet.
  • L’API s’interrompt après une erreur d’écriture au lieu de continuer avec une réponse partiellement écrite.
  • SLA de sécurité publié dans SECURITY.md ; les artefacts de version sont signés avec la clé GPG [email protected].

Interface et localisation

Sélecteur de langue avec le tchèque

  • Traduction en tchèque.
  • Cartes déroulantes pour les sections JWT et planification du formulaire de modèle.
  • L’icône de copie dans le presse-papiers est visible en mode clair ; indicateurs de chargement des tâches en cours corrigés ; marges du formulaire de modèle corrigées ; étiquette Beta des workflows.
  • L’extraction des variables d’intégration préserve les objets et tableaux JSON au lieu de les convertir en chaînes.

Notes de mise à niveau

Changements cassants et comportementaux

  1. BoltDB a disparu. bolt n’est plus un dialecte valide ; le serveur refuse de démarrer avec “Bolt is not supported starting from version 2.19”. Migrez d’abord vers SQLite, MySQL ou PostgreSQL.
  2. Clés de chiffrement des runners supprimées. Le serveur et les runners doivent tous être en 2.19. Assurez-vous que le trafic runner‑serveur est protégé par TLS. Le provisionnement scripté des runners qui attendait la clé doit être mis à jour.
  3. Les API de liste de tâches sont paginées. GET /api/project/{id}/tasks/last accepte count et before ; limit est toujours accepté, mais les clients qui comptaient sur les 200 tâches les plus récentes en une seule réponse doivent paginer.
  4. Plus de repli sur runner obsolète. Avec tous les runners hors ligne, les tâches restent en file d’attente.
  5. Drapeau active du runner supprimé de l’enregistrement.
  6. Les sauvegardes de projet ne contiennent plus les jetons des runners.
  7. SQLite : v2.19.14 reconstruit les tables session et task pour ajouter de véritables clés étrangères (corrige la suppression d’utilisateurs). Les sessions orphelines sont supprimées. Sauvegardez la base de données avant la mise à niveau.

Nouvelle configuration

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. Toutes sont optionnelles ; les configurations existantes continuent de fonctionner. config.schema.yaml et la documentation de référence de la configuration ont été régénérés.

Migrations de base de données

v2.18.6 (jwt_params du modèle), v2.18.15 (tables de workflow), 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 (reconstruction SQLite de session/task). Compatibilité des migrations avec MariaDB 12.1 corrigée.


Versions correctives

Version Changements
2.19.8 Correction de la migration SQLite ; correction de la suppression d’utilisateurs (clés étrangères session/task) ; comparaison de chaînes insensible à la casse dans les requêtes DB
2.19.9 Variable d’env. SEMAPHORE_RUNNER_EXECUTOR_TYPE ; nettoyage des omitempty de la configuration
2.19.10 Correction de la configuration de l’exécuteur ; correction de l’option de build Docker
2.19.11 Espace de travail sélectionné affiché dans les journaux ; tag latest pour l’image helper ; tests de migration DB
2.19.12 Correction d’un pointeur nil dans les options de configuration du runner ; correction de la propagation des erreurs
2.19.14 Correction de la gestion de l’ancien secrets_path dans la configuration

Dépendances

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. Documentation ajoutée en tant que sous-module git ; THIRD-PARTY-LICENSES.md régénéré.

You might find this interesting