Exécution de workflow avec une approbation, un nœud de délai et des variables d'exécution

Semaphore UI 2.20 ajoute un journal d’audit avec export SIEM, fait des Workflows un véritable moteur de pipeline avec des nœuds de délai, des révisions, des sorties transmises entre les tâches et des variables de workflow, remanie les rôles pour qu’un membre puisse en détenir plusieurs et que les administrateurs disposent de rôles à l’échelle de l’instance et de correspondances de groupes IdP, introduit la configuration des hôtes pour des identifiants SSH et Git par hôte, déplace toutes les variables supplémentaires Ansible dans des fichiers chiffrés par Vault, et expose des métriques Prometheus.

La ligne démarre à v2.20.0. Les versions correctives seront listées à la fin de cette page au fur et à mesure de leur publication.

Points forts

  • Journal d’audit — qui a fait quoi, depuis où, avec quel résultat ; un écran d’administration, une rétention et un export Syslog / Splunk HEC vers les SIEM (export et filtres en Pro).
  • Workflows — nœuds de délai, révisions immuables épinglées aux exécutions, sorties livrées comme entrées de la tâche suivante, variables de workflow demandées dans une boîte de dialogue d’exécution, un éditeur redessiné avec raccourcis clavier et annulation, et des webhooks qui démarrent des workflows.
  • Plusieurs rôles par membre, des rôles avec identifiants et slugs, des rôles globaux dotés de permissions à l’échelle de l’instance (Pro), et des correspondances groupe IdP → rôle appliquées à la connexion (Enterprise).
  • Identités externes — les connexions LDAP et OIDC sont liées aux comptes par l’identifiant stable du fournisseur, et non par e-mail ; plusieurs annuaires LDAP sur une seule page de connexion.
  • Configuration des hôtes — associez des hôtes SSH et des URL Git aux identifiants du projet, appliqués aux clones, à Galaxy, aux modules Terraform et à Ansible.
  • Les variables supplémentaires Ansible ne sont plus jamais sur la ligne de commande ; les secrets voyagent dans un fichier chiffré par Ansible Vault, et le Jinja2 contenu dans les valeurs n’est plus évalué.
  • Modèles : répertoire de travail Ansible, noms uniques et template_name dans l’API des tâches, notifications d’erreur supprimées, Dry Run / Diff masqués, options d’installation Galaxy, variables de sondage à sélection multiple, secrets de sondage sur les runners distants.
  • Les dépôts monorepo partagent un seul checkout entre les modèles ; nouvelles tentatives Git, récupération parallèle des sous-modules, vérification des clés d’hôte SSH.
  • Métriques Prometheus sur /api/metrics.
  • Générez des paires de clés SSH sur le serveur et copiez la clé publique depuis le Magasin de clés.

Journal d’audit

Écran du journal d'audit

Semaphore enregistre désormais les événements pertinents pour la sécurité dans un journal dédié, en ajout seul. Activez-le avec :

"audit": {
  "enabled": true,
  "instance_id": "semaphore-prod"
}

(SEMAPHORE_AUDIT_ENABLED, SEMAPHORE_AUDIT_INSTANCE_ID ; instance_id est requis et nomme l’installation sur chaque événement.)

Ce qui est enregistré. 116 types d’événements en huit catégories : auth (connexions, déconnexions, MFA, rejets de jetons d’API, requêtes refusées, blocages CSRF), iam (utilisateurs, mots de passe, jetons d’API, identités, appartenances, rôles, permissions de modèles), resource (projets, sauvegardes, inventaires, dépôts, modèles, planifications, intégrations, configurations d’hôtes, workflows, groupes de variables), secret (identifiants et stockages de secrets), task (démarrage avec son déclencheur, achèvement avec résultat et durée, approbations, arrêts, suppression de l’historique), runner (enregistrement, modifications, rapports rejetés), system (paramètres, licence) et audit lui-même (démarrage, rétention, export). Les mots de passe, les jetons, les valeurs de secrets, la sortie des tâches et les variables ne sont jamais écrits.

Enveloppe d’événement. Chaque événement porte un UUID, un numéro de séquence sans trou, un horodatage UTC à la microseconde, l’acteur (utilisateur / anonyme / système / runner / intégration, avec authentification par session ou par jeton d’API et une empreinte de jeton), l’IP source et le User-Agent, la cible, le projet, un identifiant de requête (également renvoyé dans l’en-tête de réponse X-Request-ID), l’identifiant de l’instance et celui du nœud HA. Les résultats sont success ou failure avec une liste fermée de raisons ; une action qui a enregistré l’objet mais a échoué à une étape ultérieure est un succès avec partial = true. Derrière un reverse proxy, X-Forwarded-For n’est accepté que depuis audit.trusted_proxy_cidrs.

Carte d'événement d'audit

Écran d’administration. Journal d’audit dans le menu utilisateur (/audit-log) liste les événements du plus récent au plus ancien, 50 par page, avec une pagination Plus anciens / Plus récents ; une ligne ouvre une carte avec les sections Qui, Objet, Où, Quand, Détails et Technique, et un bouton qui copie l’événement sous la forme du JSON envoyé à un SIEM. L’accès nécessite la nouvelle permission globale Lire le journal d’audit.

Rétention. audit.retention_days supprime les événements plus anciens par lots, toutes les heures avec un décalage aléatoire pour que les nœuds HA n’entrent pas en collision ; chaque passage qui supprime quelque chose est lui-même enregistré.

Pro : filtres et export. Filtrez par période, utilisateur, projet, type d’événement, résultat et IP ; rebondissez depuis n’importe quelle valeur d’une carte ; exportez la sélection courante en CSV ou JSON Lines.

Pro : export SIEM. Deux destinations, chacune avec son propre curseur pour que rien ne soit sauté quand un récepteur est indisponible : Syslog sur TLS (RFC 5424, le JSON de l’événement comme corps) via audit.syslog et Splunk HTTP Event Collector via audit.splunk_hec (url, token, index, source, sourcetype, ca_file, …). La livraison est au moins une fois, ordonnée par numéro de séquence ; en HA, un seul nœud exporte par destination, coordonné par un bail Redis. Trois séries Prometheus décrivent l’exporteur : semaphore_audit_export_pending_events, semaphore_audit_export_oldest_pending_seconds et semaphore_audit_export_errors_total.

Stockage : tables audit_event, audit_event_sequence, audit_export_state (migrations v2.20.9 à v2.20.11). API : GET /api/audit/events et GET /api/audit/events/export.


Workflows

Les workflows sont une fonctionnalité Pro ; l’étiquette Beta a disparu.

Nœuds de délai

Un quatrième type de nœud à côté de tâche, approbation et note : Délai met l’exécution en pause pendant un nombre de secondes donné puis libère ses arêtes. La vue d’exécution affiche un décompte en direct sur la carte ; une exécution arrêtée annule le délai. Champ delay_seconds, migration v2.20.2.

Révisions

Chaque enregistrement d’un workflow crée une nouvelle révision du graphe ; une exécution épingle la révision depuis laquelle elle a démarré, de sorte que modifier un workflow ne change jamais une exécution en cours et n’orpheline jamais les nœuds des exécutions passées. L’éditeur affiche une puce rev. N et le nombre d’exécutions qui exécutent encore une révision plus ancienne ; la vue d’exécution indique quelle révision elle exécute. Les révisions qu’aucune exécution ne référence sont supprimées lorsqu’une plus récente est enregistrée. API : GET …/workflows/{id}/revisions et …/revisions/{revision_id}.

Sorties et entrées

Vue d'exécution avec des badges de sorties

Une tâche peut transmettre des données structurées aux nœuds qui la suivent. Chaque tâche démarrée par un workflow reçoit SEMAPHORE_OUTPUTS_FILE ; tout ce qu’elle y écrit sous forme d’objet JSON devient ses sorties :

cat > "$SEMAPHORE_OUTPUTS_FILE" <<EOF
{"image_tag": "1.4.2", "replicas": 3, "subnet_ids": ["subnet-1", "subnet-2"]}
EOF

Ansible produit des sorties avec ansible.builtin.set_stats via un plugin de callback intégré ; les sorties Terraform, OpenTofu et Terragrunt sont capturées automatiquement depuis output -json (les valeurs sensitive sont ignorées et listées comme Non capturées). Les sorties ne sont lues que si la tâche réussit ; les limites sont de 100 sorties, 32 Ko chacune, 256 Ko par fichier.

Une connexion vers un nœud de tâche livre des entrées — elle remplit les variables de sondage du modèle de destination à partir des sorties du nœud source :

  • Par nom (par défaut) : chaque sortie dont le nom est égal à une variable de sondage la remplit.
  • Mapper les entrées explicitement : listez les paires variable ← output key à livrer ; dès que le workflow a une exécution terminée, le panneau suggère les clés produites par cette exécution.

Panneau de connexion avec mappage explicite des entrées

Les valeurs sont converties vers le type de la variable, les nœuds d’approbation et de délai transmettent les sorties, un mappage explicite prime sur une livraison par nom, et une variable requise laissée sans valeur fait échouer la tâche du nœud avant son démarrage, de sorte que l’exécution suit ses arêtes En cas d’échec. La vue d’exécution affiche un badge N sorties par nœud, la boîte de dialogue de tâche comporte un tableau Sorties, et le journal de la tâche commence par une ligne Input "x" <- output "y" of node N par valeur livrée. Les sorties sont stockées en clair et ne remplissent jamais une variable secret ; un secret ne peut pas être transmis via les sorties. Les tâches sur des runners distants produisent et reçoivent des sorties ; les exécuteurs Docker et Kubernetes ne les capturent pas encore.

Boîte de dialogue de tâche avec le tableau des sorties

Variables de workflow et boîte de dialogue d’exécution

Boîte de dialogue d'exécution demandant les variables de workflow

Un workflow possède ses propres variables de sondage, demandées une seule fois dans une boîte de dialogue Exécuter « … » au démarrage d’une exécution (un workflow sans variables démarre immédiatement, comme avant). Les réponses sont stockées sur l’exécution, affichées sous forme de puces dans un bandeau Variables au-dessus du canevas d’exécution, et n’atteignent une tâche que par une liaison explicite dans le panneau du nœud — une variable de workflow ne fuit jamais dans un modèle par son nom. Les secrets ne sont pas autorisés comme variables de workflow. POST …/workflows/{id}/runs accepte {"environment": {"image_tag": "1.4.3"}} ; une réponse qui ne correspond pas à son type ou une valeur requise manquante fait échouer le démarrage.

Environnement d’une tâche de workflow

Chaque tâche démarrée par un workflow reçoit SEMAPHORE_WORKFLOW_ID, SEMAPHORE_WORKFLOW_RUN_ID, SEMAPHORE_WORKFLOW_URL (nécessite web_host) et SEMAPHORE_OUTPUTS_FILE, pour chaque application et sur les runners distants.

Éditeur redessiné

Éditeur de workflow

  • Nouvelles cartes de nœud avec vignette de type, statut, durée, badge de sorties et Approuver / Rejeter en ligne ; étiquettes d’arête avec une liste déroulante de condition sur place et un bouton de suppression ; un canevas à grille de points.
  • Menu d’ajout rapide depuis la poignée + d’un nœud, un clic droit sur le canevas ou le bouton de l’état vide : liste recherchable des types de nœuds et des modèles de tâches, le nouveau nœud est connecté en cas de succès.
  • Annuler / rétablir (Ctrl/⌘+Z, Ctrl/⌘+Shift+Z), renommage en ligne du workflow, un menu Problèmes qui met au point le nœud fautif, un badge Enregistrer pour les modifications non enregistrées et une protection avant de quitter la page.
  • Raccourcis clavier sur le canevas : les flèches déplacent la vue (Shift pour un grand pas), + / - zooment, 0 ajuste le graphe, 1 réinitialise le zoom, Esc efface la sélection ; les cartes de nœud peuvent recevoir le focus clavier.
  • Contrôles flottants : zoom avant / arrière, ajuster la vue, mise en page automatique Ranger, pourcentage de zoom.
  • Un seul chevron replie la palette et la navigation principale ensemble ; l’état est mémorisé.
  • Le dépassement de défilement au pavé tactile ne déclenche plus le geste Retour du navigateur sur macOS.

Menu d'ajout rapide

Les webhooks démarrent des workflows

Une intégration peut désormais exécuter un workflow au lieu d’un modèle (Exécute : Modèle / Workflow dans le formulaire d’intégration). Chaque valeur extraite devient une réponse au sondage du workflow. La gestion de telles intégrations nécessite la fonctionnalité Pro workflow_integrations_management. Pour les intégrations de modèles, une valeur Paramètres de tâche extraite nommée git_branch définit la branche de la tâche démarrée lorsque le modèle autorise sa redéfinition.

Changements d’API

POST …/workflows/{id}/run a été renommé en POST …/workflows/{id}/runs et accepte le corps environment. Les détails d’exécution portent revision_id, revision, un objet delay par nœud et task.artifacts. Les workflow_run_id, workflow_node_id et artifacts fournis par le client sur une tâche sont ignorés, de sorte qu’une tâche ne peut pas se faire passer pour un nœud de l’exécution de quelqu’un d’autre.


Rôles et contrôle d’accès

Plusieurs rôles par membre

Page Équipe avec plusieurs rôles par membre

Un membre de projet détient un ensemble de rôles, modifié sous forme de puces sur la page Équipe. L’API accepte roles: ["manager", "release_approver"] à côté du role historique ; la réponse ne conserve le role scalaire que pour les membres à rôle unique. Un non-administrateur ne peut pas retirer le rôle intégré Owner au dernier propriétaire.

Rôles avec identifiants, slugs et portées

Les rôles sont désormais des lignes dotées d’un id entier et d’un slug (^[A-Za-z0-9_-]{1,100}$, dérivé du nom dans le formulaire) ; les quatre rôles intégrés sont aussi des lignes et ne peuvent plus être masqués par un rôle personnalisé. Les rôles ont une portée : intégrée, partagée (utilisable dans n’importe quel projet) ou projet. Supprimer un rôle en cours d’utilisation répond 409 avec son impact (membres, projets, permissions de modèles, correspondances) et peut être répété avec ?force=true — Supprimer avec les affectations dans l’interface. Les migrations v2.20.12 et v2.20.13 reconstruisent les tables de rôles ; voir les notes de mise à niveau.

Rôles et permissions globaux (Pro)

Onglet Rôles globaux de la page Utilisateurs

Les droits à l’échelle de l’instance ne se résument plus au drapeau administrateur. Un rôle global accorde un masque de quatre permissions — Gérer les utilisateurs, Gérer les rôles globaux, Gérer les paramètres système, Lire le journal d’audit — et est attribué aux utilisateurs dans l’onglet Rôles de la page Utilisateurs (/users/roles) et dans l’onglet Rôles globaux de la boîte de dialogue utilisateur, qui montre aussi les permissions effectives et quel rôle accorde chacune. Chaque route d’administration est protégée par l’un des quatre bits ; GET /api/user renvoie global_permissions. Une instance conserve toujours au moins un administrateur, garanti par un verrou de ligne sûr entre les nœuds HA. Un utilisateur disposant de Gérer les utilisateurs ne peut pas modifier un administrateur ni quiconque détient une permission qu’il n’a pas. API : /api/global-roles, /api/users/{id}/global-roles, /api/users/{id}/global-permissions, catalogue sur /api/global-roles/permissions.

Rôles globaux d'un utilisateur

Correspondances de rôles par groupe (Enterprise)

Page des correspondances de groupes

Associez un groupe de fournisseur d’identité à un rôle de projet sur la nouvelle page Correspondances de groupes (/role-mappings) : fournisseur, groupe, projet, rôle. À chaque connexion OIDC, les rôles associés de l’utilisateur sont alignés sur les groupes présents dans le jeton (groups_claim du fournisseur). Les rôles associés apparaissent sur la page Équipe sous forme de puces verrouillées avec une infobulle provider: group et ne peuvent pas être retirés en tant que rôles de membre ; les rôles associés ne comptent pas comme dernier propriétaire du projet. Une connexion par mot de passe ou LDAP efface les rôles associés, car elle n’apporte aucun groupe. API : /api/role_mappings.


Authentification et identités

Page de connexion avec plusieurs annuaires LDAP

  • Identités externes. Les connexions LDAP et OIDC sont liées aux comptes Semaphore par l’identifiant stable du fournisseur (sub OIDC, DN LDAP) dans la nouvelle table user__external_identity, et non par e-mail. Cela ferme la classe de bogues où un IdP qui accepte n’importe quelle adresse saisie s’approprie le compte de quelqu’un d’autre. external_auth_email_matching (auto par défaut, always, never) contrôle si un utilisateur externe existant sans identité peut encore être rapproché une fois par e-mail ; les comptes locaux à mot de passe ne sont jamais adoptés. L’e-mail OIDC ne compte que si email_verified est vrai et que le fournisseur définit require_verified_email. Les utilisateurs lient et délient eux-mêmes leurs identités dans la boîte de dialogue de compte (/api/users/{id}/identities, POST /api/user/identities/ldap, /api/auth/oidc/{provider}/login?link=1).
  • Plusieurs annuaires LDAP. ldap_providers est une table d’annuaires nommés, chacun avec son propre serveur, bind, recherche, correspondances, couleur et ordre ; l’ancien bloc plat ldap_* continue de fonctionner comme le fournisseur ldap. La page de connexion affiche un sélecteur dès qu’il y a plus d’un onglet, et l’onglet interne n’envoie jamais de mot de passe à un annuaire. GET /api/auth/login renvoie ldap_providers et login_with_password.
  • Les certificats LDAPS sont vérifiés par défaut. Définissez ldap_tls_skip_verify (bloc plat) ou tls_skip_verify (par fournisseur) pour un certificat auto-signé.
  • Durée de vie absolue des sessions. auth.max_session_life_hours (SEMAPHORE_AUTH_MAX_SESSION_LIFE_HOURS) fait expirer une session un temps fixe après la connexion, quelle que soit son activité ; 0 ne conserve que le délai d’inactivité.
  • Un utilisateur sans projet qui n’a pas le droit d’en créer voit une page Aucun projet pour l’instant au lieu d’un formulaire qu’il ne peut pas soumettre ; POST /api/projects répond 403 dans ce cas.
  • La langue choisie dans le menu utilisateur est stockée sur le serveur et suit l’utilisateur d’un navigateur à l’autre (lang dans /api/user/options).

Configuration des hôtes

Page de configuration des hôtes

Une nouvelle page de projet, Configuration des hôtes, associe des hôtes SSH et des URL Git aux identifiants du projet :

  • une correspondance Hôte (bastion.example.com) attache une clé SSH, sous forme de bloc Host d’un ssh_config généré ;
  • une correspondance URL (https://github.com/acme/, un préfixe terminé par / couvre un groupe) attache une clé SSH ou un couple login/mot de passe (HTTPS uniquement), sous forme de réécriture Git insteadOf ; l’URL la plus spécifique gagne.
Formulaire de correspondance d'hôte

Les correspondances s’appliquent au dépôt du modèle et à ses sous-modules, aux rôles et collections de requirements.yml, aux modules de terraform init, aux commandes git lancées par un playbook, aux dépôts d’inventaire et aux hôtes d’inventaire, ainsi qu’à la navigation dans les branches et les playbooks ; elles sont expédiées aux runners distants. Les clés privées ne touchent jamais le disque — un agent SSH par correspondance, lié avec IdentityAgent ; les mots de passe passent par GIT_CONFIG_PARAMETERS, et les URL de dépôt sont masquées dans les journaux de tâches. Une clé référencée par une correspondance ne peut pas être supprimée. Les correspondances font partie des sauvegardes de projet. Nécessite git_client: cmd_git. Table project__host_config, migration v2.20.7 ; API /api/project/{id}/host_configs.


Modèles et tâches

Formulaire de modèle avec répertoire de travail et options de notification

  • Répertoire de travail Ansible. Répertoire de travail différent exécute ansible-playbook depuis un sous-répertoire du dépôt ; le chemin doit rester à l’intérieur du checkout (working_directory, migration v2.20.3).

  • Noms de modèles uniques par projet (migration v2.20.4), et POST /api/project/{id}/tasks accepte template_name au lieu de template_id.

  • Supprimer les notifications d’erreur par modèle, à côté de la suppression des notifications de succès existante ; les alertes e-mail respectent les deux pour la première fois (suppress_error_alerts, migration v2.20.5).

  • Masquer Dry Run / Diff dans la boîte de dialogue de tâche par modèle ; le serveur cesse également d’ajouter --check / --diff pour ce modèle (task_params.hide_dry_run, hide_diff).

  • Options d’installation Galaxy — une section repliable avec Ignorer l’installation Galaxy, des arguments CLI distincts pour ansible-galaxy role install et collection install (une liste blanche de drapeaux ; --token, --api-key et les drapeaux de chemin sont refusés) et l’invite de redéfinition par tâche.

  • Le sélecteur de playbook liste les sous-répertoires à mesure que vous tapez, filtré par application (.yml pour Ansible, répertoires de premier niveau pour Terraform / OpenTofu / Terragrunt / Pulumi, .sh, .py, .ps1), ignore les répertoires de la disposition Ansible et les répertoires cachés, est plafonné à 30 entrées et parcourt un clone superficiel confiné à la racine du dépôt.

  • Variables de sondage à sélection multiple — le nouveau type select accepte plusieurs valeurs, rendues sous forme de puces dans la boîte de dialogue de tâche ; default_value peut être un tableau.

    Boîte de dialogue de nouvelle tâche avec une variable de sondage à sélection multiple
  • Les secrets de sondage atteignent les runners distants. Une réponse de sondage secret arrivait auparavant vide sur un runner. Elle est désormais stockée chiffrée comme une clé d’accès liée à la tâche (access_key.task_id, expire_at, migration v2.20.1), déchiffrée par le nœud HA qui sert le runner, supprimée à la fin de la tâche et nettoyée toutes les heures ; elle est masquée du Magasin de clés, des sauvegardes et de l’API des clés.

  • Variables supplémentaires en YAML. L’éditeur de groupes de variables a gagné un sélecteur Table | JSON | YAML et un éditeur plein écran ; les conversions sont strictes (les dates restent des chaînes, les racines non-objet et les nombres non finis sont rejetés). Le stockage est inchangé.

    Éditeur de groupe de variables en mode YAML

  • La page de tâche nomme et lie la planification ou l’intégration qui a démarré une tâche, et marque une origine supprimée comme #id (deleted). Les horodatages du journal ne sont plus sélectionnés lors de la copie d’un journal.

  • Les planifications valident l’expression sur le serveur avant l’enregistrement, de sorte que @hourly est accepté, et la bannière de fuseau horaire peut être masquée.

    Formulaire de planification
  • L’arrêt d’une tâche locale termine tout son groupe de processus : SIGTERM, un délai de grâce de 15 s, puis SIGKILL ; les processus ssh ou de fournisseur orphelins ne survivent plus à la tâche. Un plan Terraform arrêté ne continue plus ; un plan qui se termine par 0 sur SIGTERM n’est pas interprété comme un succès.

  • Le repository_id d’inventaire n’est conservé que pour le type file et doit appartenir au projet.

  • Les journaux du serveur nomment l’utilisateur dans les entrées Task added to queue / Task started.


Secrets et Ansible Vault

  • Les variables supplémentaires voyagent dans des fichiers, pas sur la ligne de commande. Les groupes de variables, les réponses de sondage, les entrées de workflow et les détails de la tâche sont écrits dans un fichier YAML 0600 passé comme --extra-vars @file. Les secrets — réponses de sondage secret et secrets des groupes de variables — vont dans un second fichier chiffré au format Ansible Vault 1.1 / AES-256 par une implémentation Go native (aucun binaire ansible-vault nécessaire), déverrouillé avec un mot de passe à usage unique fourni à l’invite --vault-id <uuid>@prompt d’ansible-playbook. Ni les valeurs ni le mot de passe n’apparaissent dans ps, et les deux fichiers sont supprimés à la fin de la tâche.

  • Le Jinja2 dans les valeurs est une donnée, pas du code. Chaque chaîne contenant {{, {%, {# ou un en-tête #jinja2: est marquée !unsafe, récursivement, de sorte qu’une réponse de sondage telle que {{ lookup('pipe', 'id') }} est transmise littéralement. Les chaînes sans délimiteur sont laissées sans marquage à dessein : ansible-core ≥ 2.19 réévalue les scalaires !unsafe, ce qui transformerait "2026.08" en flottant.

  • Un nouvel espace de noms de débogage extra_vars (SEMAPHORE_DEBUG_FILTER=extra_vars) journalise la manière dont les variables sont réparties et écrites — noms, fichiers et tailles seulement, jamais les valeurs.

  • Générer une paire de clés SSH sur le serveur. Générer une clé SSH dans le Magasin de clés crée une clé RSA ; la clé publique est conservée avec la clé, affichée avec Afficher / Masquer et un bouton de copie, et proposée dans une boîte de dialogue juste après la création (generate_ssh_key).

    Clé avec une paire de clés SSH générée
  • Une mise à jour de clé n’écrit type, secret et la partie publique que si Remplacer est coché, de sorte qu’un client ne peut pas modifier la charge utile d’une clé sans remplacer le secret.

  • La lecture d’un identifiant depuis une variable d’environnement du serveur ou un fichier sous dirs.secrets est désormais documentée (onglets Env / Fichier du formulaire du Magasin de clés).


Dépôts et Git

Formulaire de dépôt avec l'option de checkout unique
  • Monorepo : un seul checkout pour tous les modèles. Une option du dépôt clone le dépôt une seule fois et le partage entre les modèles au lieu d’une copie par modèle ; le checkout est verrouillé pour le fetch et le pull, les tâches s’exécutent ensuite en parallèle. Les modèles d’un tel dépôt ne peuvent pas avoir leur propre branche et leurs tâches ne peuvent pas redéfinir la branche ni le commit (monorepo, migration v2.20.11).
  • Nouvelles tentatives Git. clone et pull sont réessayés avec un délai exponentiel plafonné à une minute ; git_attempts (SEMAPHORE_GIT_ATTEMPTS, par défaut 4).
  • Sous-modules en parallèle. git_submodule_jobs (SEMAPHORE_GIT_SUBMODULE_JOBS, par défaut 4) est passé comme --jobs.
  • Vérification des clés d’hôte SSH. Nouvelle section ssh : config_path, known_hosts_file (SEMAPHORE_SSH_KNOWN_HOSTS_FILE) et strict_host_key_checking — no (par défaut), yes ou accept-new — appliquée à Git sur SSH.
  • La navigation dans un dépôt utilise un clone superficiel indexé par branche ; les identifiants sont encodés en pourcentage pour les clones bare-metal et masqués dans les journaux et le flux d’événements.

Runners et intégrations

  • runner.check_interval_seconds (SEMAPHORE_RUNNER_CHECK_INTERVAL_SECONDS, par défaut 5) définit la fréquence d’interrogation d’un runner ; un commutateur Options avancées sur la page Runners l’ajoute aux extraits d’env., de configuration et Docker générés (livré dans v2.19.17).

  • runner.connection.timeout_seconds (SEMAPHORE_RUNNER_CONNECTION_TIMEOUT_SECONDS, par défaut 3) borne séparément la connexion, la négociation TLS et les en-têtes de réponse ; les téléversements de journaux ne sont pas coupés.

  • runners.default_global_runners_mode (SEMAPHORE_DEFAULT_GLOBAL_RUNNERS_MODE : disable, prefer, require) remplace use_remote_runner, déprécié ; runners.registration_token remplace le runner_registration_token de premier niveau.

  • Diagnostics de runner côté serveur sous SEMAPHORE_DEBUG_FILTER=runner : raisons de rejet des jetons, détection des redémarrages et de la mise en ligne, rapports de progression rejetés, traçage de la distribution.

  • Les requêtes unregister des runners sont authentifiées ; le client runner refuse les redirections HTTP.

  • Authentification de webhook HMAC-SHA512 (hmac-sha512) à côté de la HMAC-SHA256 existante ; l’en-tête de signature est configurable.

    Formulaire d'intégration avec HMAC-SHA512
  • Un webhook dont l’intégration appartient à un autre projet est rejeté.


Observabilité

  • Métriques Prometheus. GET /api/metrics derrière une authentification HTTP Basic avec un identifiant de service statique :

    "metrics": { "enabled": true, "username": "prometheus", "password": "…" }
    

    (SEMAPHORE_METRICS_ENABLED, SEMAPHORE_METRICS_USERNAME, SEMAPHORE_METRICS_PASSWORD.) Séries : semaphore_tasks_running, semaphore_tasks_total{status}, les collecteurs standard go_* et process_*, et les jauges d’export d’audit en Pro.

  • Nouveaux espaces de noms de débogage extra_vars et runner ; la navigation dans un dépôt journalise la sortie Git en DEBUG.

  • L’export et la restauration des sauvegardes de projet sont journalisés.


Sécurité

  • Liaison des identités par identifiant de fournisseur au lieu de l’e-mail ; vérification des certificats LDAPS activée par défaut.
  • Variables supplémentaires hors de la ligne de commande ; secrets chiffrés par Vault ; Jinja2 dans les valeurs non évalué.
  • workflow_run_id, workflow_node_id et artifacts forgés retirés des tâches envoyées par les clients.
  • Routes d’administration protégées par des permissions globales explicites au lieu du drapeau administrateur ; bits de permission inconnus rejetés ; garde-fou contre l’élévation de privilèges dans la gestion des utilisateurs.
  • Sélecteur de playbook confiné à la racine du dépôt (OpenRoot), plafonné et filtré.
  • Racines des variables supplémentaires et nombres YAML validés ; arguments CLI Galaxy en liste blanche.
  • Identifiants de dépôt masqués dans les journaux et le flux d’événements ; = échappé dans les paramètres de configuration Git.
  • Les points de terminaison d’audit refusent les lectures intersites et les curseurs malformés ; les réseaux de proxys de confiance sont validés.
  • unregister des runners authentifié ; redirections refusées par le client runner.
  • Identifiants de projet et d’intégration des webhooks vérifiés.
  • Tâches locales arrêtées avec tout leur groupe de processus.

Notes de mise à niveau

Changements cassants et comportementaux

  1. Les noms de modèles doivent être uniques par projet. La migration v2.20.4 ajoute un index unique ; renommez les doublons avant la mise à niveau.
  2. Les tables de rôles sont reconstruites (v2.20.12 / v2.20.13). Sauvegardez d’abord. Un rôle personnalisé dont le slug entre en collision, sans distinction de casse, avec un rôle intégré ou un autre rôle est renommé (journalisé) ; les permissions de modèles pointant vers un rôle non résoluble sont supprimées (journalisé). L’appartenance a été déplacée vers project__user_role ; la colonne project__user.role a disparu.
  3. GET /api/project/{id}/users ne renvoie role que pour les membres à rôle unique — lisez roles.
  4. /roles* est passé du drapeau administrateur à la permission Gérer les rôles globaux ; les administrateurs ne sont pas affectés.
  5. Les certificats LDAPS sont vérifiés par défaut. Définissez ldap_tls_skip_verify ou le tls_skip_verify d’un fournisseur pour les certificats auto-signés.
  6. ansible-playbook est invoqué différemment : --extra-vars @file, plus un second fichier et un --vault-id <uuid>@prompt lorsque la tâche a des secrets, même pour les modèles sans vault. Tout ce qui analyse la ligne de commande, ou un ansible.cfg qui interdit les invites de vault, est affecté.
  7. Le Jinja2 contenu dans les valeurs des variables supplémentaires n’est plus évalué. Un playbook qui comptait sur le templating d’une valeur de webhook ou de sondage cessera de le faire.
  8. Point de terminaison d’exécution de workflow renommé : POST …/workflows/{id}/run → …/runs.
  9. Les dépôts monorepo prennent le pas sur le modèle : pas de branche par modèle, pas de redéfinition de branche ni de commit dans les tâches.
  10. Le repository_id d’inventaire est abandonné pour tous les types sauf file.
  11. L’arrêt d’une tâche locale tue son groupe de processus (pas encore d’équivalent sous Windows).
  12. Les sorties de workflow ne sont pas encore capturées par les exécuteurs Docker et Kubernetes ; les secrets de sondage n’atteignent pas encore ces exécuteurs.

Nouvelle configuration

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 et require_verified_email par fournisseur OIDC, runner.check_interval_seconds, runner.connection.timeout_seconds, runners.{default_global_runners_mode,registration_token}. Toutes optionnelles. Les champs de configuration de type pointeur peuvent désormais être définis depuis des variables d’environnement. Les pages de référence de la configuration et de la CLI sont générées depuis les sources.

Migrations de base de données

v2.20.0 identités externes · v2.20.1 secrets de sondage liés à la tâche · v2.20.2 nœuds de délai · v2.20.3 répertoire de travail · v2.20.4 noms de modèles uniques · v2.20.5 suppression des alertes d’erreur · v2.20.7 configuration des hôtes · v2.20.8 révisions de workflow · v2.20.9–v2.20.11 journal d’audit et index, mappages d’entrées des arêtes, drapeau monorepo · v2.20.12–v2.20.13 tables de rôles, variables de workflow · v2.20.14 intégrations de workflow et correspondances de groupes · v2.20.16 rôles globaux.

Dépendances

Go 1.26 ; images Docker sur Alpine 3.24 ; prometheus/client_golang 1.23 ajouté ; go-oidc 3.21, go-ldap 3.4.14, golang.org/x/crypto 0.57, modernc.org/sqlite 1.59, logrus 1.10 ; frontend js-yaml 5 et cron-parser 5.10. Nouveaux déploiements en un clic : Cloudzy, RepoCloud et Pethost.