Esecuzione di un workflow con un'approvazione, un nodo di ritardo e variabili di esecuzione

Semaphore UI 2.20 aggiunge un log di audit con esportazione verso SIEM, trasforma i Workflow in un vero motore di pipeline con nodi di ritardo, revisioni, output passati tra le attività e variabili dei workflow, rielabora i ruoli così che un membro possa averne più di uno e gli amministratori ottengano ruoli validi per tutta l’istanza e mappature dei gruppi dell’IdP, introduce la configurazione degli host per credenziali SSH e Git per singolo host, sposta ogni variabile extra di Ansible in file cifrati con Vault ed espone le metriche Prometheus.

La linea parte da v2.20.0. Le release correttive saranno elencate alla fine di questa pagina man mano che vengono pubblicate.

Novità principali

  • Log di audit — chi ha fatto cosa, da dove e con quale risultato; una schermata di amministrazione, la conservazione dei dati e l’esportazione Syslog / Splunk HEC verso i SIEM (esportazione e filtri in Pro).
  • Workflow — nodi di ritardo, revisioni immutabili vincolate alle esecuzioni, output consegnati come input dell’attività successiva, variabili del workflow richieste in una finestra di avvio, un editor ridisegnato con scorciatoie e annullamento, e webhook che avviano i workflow.
  • Più ruoli per membro, ruoli con id e slug, ruoli globali con permessi validi per tutta l’istanza (Pro) e mappature gruppo IdP → ruolo applicate all’accesso (Enterprise).
  • Identità esterne — gli accessi LDAP e OIDC sono associati agli account tramite l’id stabile del provider, non tramite l’e‑mail; più directory LDAP su un’unica pagina di accesso.
  • Configurazione degli host — associa host SSH e URL Git alle credenziali del progetto, con applicazione ai cloni, a Galaxy, ai moduli Terraform e ad Ansible.
  • Le variabili extra di Ansible non compaiono più sulla riga di comando; i secret viaggiano in un file cifrato con Ansible Vault e Jinja2 all’interno dei valori non viene più valutato.
  • Modelli: directory di lavoro di Ansible, nomi univoci e template_name nell’API delle attività, notifiche di errore soppresse, Dry Run / Diff nascosti, opzioni di installazione Galaxy, variabili di survey a selezione multipla, secret di survey sui runner remoti.
  • I repository monorepo condividono un unico checkout tra i modelli; nuovi tentativi Git, fetch parallelo dei submodule, verifica delle host key SSH.
  • Metriche Prometheus su /api/metrics.
  • Generazione di coppie di chiavi SSH sul server e copia della chiave pubblica dal Key Store.

Log di audit

Schermata del log di audit

Semaphore registra ora gli eventi rilevanti per la sicurezza in un log dedicato e di sola aggiunta. Abilitalo con:

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

(SEMAPHORE_AUDIT_ENABLED, SEMAPHORE_AUDIT_INSTANCE_ID; instance_id è obbligatorio e identifica l’installazione in ogni evento.)

Cosa viene registrato. 116 tipi di evento in otto categorie: auth (accessi, disconnessioni, MFA, token API rifiutati, richieste negate, blocchi CSRF), iam (utenti, password, token API, identità, appartenenze, ruoli, permessi sui modelli), resource (progetti, backup, inventari, repository, modelli, pianificazioni, integrazioni, configurazioni degli host, workflow, gruppi di variabili), secret (credenziali e archiviazioni dei secret), task (avvio con il relativo trigger, completamento con risultato e durata, approvazioni, arresti, eliminazione della cronologia), runner (registrazione, modifiche, report rifiutati), system (impostazioni, licenza) e audit stesso (avvio, conservazione, esportazione). Password, token, valori dei secret, output delle attività e variabili non vengono mai scritti.

Struttura dell’evento. Ogni evento contiene un UUID, un numero di sequenza senza interruzioni, un timestamp UTC al microsecondo, l’attore (utente / anonimo / sistema / runner / integrazione, con autenticazione tramite sessione o token API e l’impronta del token), l’IP di origine e lo User‑Agent, il target, il progetto, un id di richiesta (restituito anche nell’header di risposta X-Request-ID), l’id dell’istanza e l’id del nodo HA. I risultati sono success o failure con un elenco chiuso di motivi; un’azione che ha salvato l’oggetto ma ha fallito in un passaggio successivo è un successo con partial = true. Dietro un reverse proxy, X-Forwarded-For è attendibile solo se proviene da audit.trusted_proxy_cidrs.

Scheda di un evento di audit

Schermata di amministrazione. Log di audit nel menu utente (/audit-log) elenca gli eventi dal più recente, 50 per pagina, con la navigazione Più vecchi / Più recenti; una riga apre una scheda con le sezioni Chi, Oggetto, Dove, Quando, Dettagli e Tecnico e un pulsante che copia l’evento nel formato JSON inviato a un SIEM. L’accesso richiede il nuovo permesso globale Leggere il log di audit.

Conservazione. audit.retention_days elimina gli eventi più vecchi a blocchi, ogni ora con un jitter così che i nodi HA non si sovrappongano; ogni passaggio che elimina qualcosa viene a sua volta registrato.

Pro: filtri ed esportazione. Filtra per periodo, utente, progetto, tipo di evento, risultato e IP; usa qualsiasi valore della scheda come filtro; esporta la selezione corrente come CSV o JSON Lines.

Pro: esportazione verso SIEM. Due destinazioni, ognuna con il proprio cursore così che nulla venga saltato quando un ricevitore è fuori servizio: Syslog su TLS (RFC 5424, JSON dell’evento come corpo) tramite audit.syslog e Splunk HTTP Event Collector tramite audit.splunk_hec (url, token, index, source, sourcetype, ca_file, …). La consegna è at‑least‑once, ordinata per numero di sequenza; in HA solo un nodo esporta per destinazione, coordinato tramite un lease Redis. Tre serie Prometheus descrivono l’esportatore: semaphore_audit_export_pending_events, semaphore_audit_export_oldest_pending_seconds e semaphore_audit_export_errors_total.

Archiviazione: tabelle audit_event, audit_event_sequence, audit_export_state (migrazioni v2.20.9 a v2.20.11). API: GET /api/audit/events e GET /api/audit/events/export.


Workflow

I Workflow sono una funzionalità Pro; l’etichetta Beta è stata rimossa.

Nodi di ritardo

Un quarto tipo di nodo accanto ad attività, approvazione e nota: Ritardo mette in pausa l’esecuzione per un certo numero di secondi e poi rilascia i propri archi. La vista dell’esecuzione mostra un conto alla rovescia dal vivo sulla scheda; un’esecuzione interrotta annulla il ritardo. Campo delay_seconds, migrazione v2.20.2.

Revisioni

Ogni salvataggio di un workflow crea una nuova revisione del grafo; un’esecuzione si vincola alla revisione da cui è partita, così la modifica di un workflow non altera mai un’esecuzione in corso e non lascia mai orfani i nodi delle esecuzioni passate. L’editor mostra un chip rev. N e quante esecuzioni stanno ancora eseguendo una revisione precedente; la vista dell’esecuzione mostra quale revisione sta eseguendo. Le revisioni non referenziate da alcuna esecuzione vengono eliminate quando ne viene salvata una più recente. API: GET …/workflows/{id}/revisions e …/revisions/{revision_id}.

Output e input

Vista dell'esecuzione con i badge degli output

Un’attività può passare dati strutturati ai nodi successivi. Ogni attività avviata da un workflow riceve SEMAPHORE_OUTPUTS_FILE; tutto ciò che vi scrive come oggetto JSON diventa i suoi output:

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

Ansible produce output con ansible.builtin.set_stats tramite un plugin di callback incluso; gli output di Terraform, OpenTofu e Terragrunt vengono catturati automaticamente da output -json (i valori sensitive vengono saltati ed elencati come Non catturati). Gli output vengono letti solo quando l’attività riesce; i limiti sono 100 output, 32 KB ciascuno, 256 KB per file.

Una connessione verso un nodo attività consegna gli input — riempie le variabili di survey del modello di destinazione con gli output del nodo di origine:

  • Per nome (predefinito): ogni output il cui nome corrisponde a una variabile di survey la riempie.
  • Mappatura esplicita degli input: elenca le coppie variable ← output key da consegnare; quando il workflow ha un’esecuzione conclusa il pannello suggerisce le chiavi prodotte da quella esecuzione.

Pannello della connessione con mappatura esplicita degli input

I valori vengono convertiti nel tipo della variabile, i nodi di approvazione e di ritardo trasmettono gli output, una mappatura esplicita prevale sulla consegna per nome e una variabile obbligatoria lasciata senza valore fa fallire l’attività del nodo prima che inizi, così l’esecuzione segue gli archi In caso di errore. La vista dell’esecuzione mostra un badge N output per nodo, la finestra dell’attività ha una tabella Output e il log dell’attività inizia con una riga Input "x" <- output "y" of node N per ogni valore consegnato. Gli output sono memorizzati in chiaro e non riempiono mai una variabile secret; un secret non può essere passato tramite gli output. Le attività sui runner remoti producono e ricevono output; gli esecutori Docker e Kubernetes non li catturano ancora.

Finestra dell'attività con la tabella Output

Variabili del workflow e finestra di avvio

Finestra di avvio che richiede le variabili del workflow

Un workflow ha le proprie variabili di survey, richieste una sola volta in una finestra Esegui “…” quando parte un’esecuzione (un workflow senza variabili parte immediatamente, come prima). Le risposte vengono memorizzate sull’esecuzione, mostrate come chip in una barra Variabili sopra la tela dell’esecuzione e raggiungono un’attività solo tramite un binding esplicito nel pannello del nodo — una variabile del workflow non finisce mai in un modello per corrispondenza di nome. I secret non sono ammessi come variabili del workflow. POST …/workflows/{id}/runs accetta {"environment": {"image_tag": "1.4.3"}}; una risposta non conforme al proprio tipo o un valore obbligatorio mancante impediscono l’avvio.

Ambiente di un’attività del workflow

Ogni attività avviata da un workflow riceve SEMAPHORE_WORKFLOW_ID, SEMAPHORE_WORKFLOW_RUN_ID, SEMAPHORE_WORKFLOW_URL (richiede web_host) e SEMAPHORE_OUTPUTS_FILE, per ogni app e sui runner remoti.

Editor ridisegnato

Editor dei workflow

  • Nuove schede dei nodi con riquadro del tipo, stato, durata, badge degli output e Approva / Rifiuta inline; etichette degli archi con un menu a tendina della condizione modificabile sul posto e un pulsante di eliminazione; una tela a griglia di punti.
  • Menu di aggiunta rapida dalla maniglia + di un nodo, con un clic destro sulla tela o dal pulsante dello stato vuoto: elenco ricercabile di tipi di nodo e modelli di attività, il nuovo nodo viene collegato in caso di successo.
  • Annulla / ripeti (Ctrl/⌘+Z, Ctrl/⌘+Shift+Z), rinomina inline del workflow, un menu Problemi che porta il focus sul nodo interessato, un badge Salva per le modifiche non salvate e una protezione all’abbandono della pagina.
  • Scorciatoie sulla tela: le frecce spostano la vista (Shift per un passo ampio), + / - zoom, 0 adatta il grafo, 1 reimposta lo zoom, Esc azzera la selezione; le schede dei nodi possono ricevere il focus da tastiera.
  • Controlli flottanti: zoom avanti / indietro, adatta la vista, auto‑layout Riordina, percentuale di zoom.
  • Un unico chevron comprime insieme la palette e la navigazione principale; lo stato viene ricordato.
  • L’overscroll del trackpad non attiva più il gesto Indietro del browser su macOS.

Menu di aggiunta rapida

I webhook avviano i workflow

Un’integrazione può ora eseguire un workflow invece di un modello (Esegue: Modello / Workflow nel modulo dell’integrazione). Ogni valore estratto diventa una risposta alla survey del workflow. La gestione di tali integrazioni richiede la funzionalità Pro workflow_integrations_management. Per le integrazioni di modelli, un valore Task Params estratto di nome git_branch imposta il branch dell’attività avviata quando il modello ne consente la sovrascrittura.

Modifiche all’API

POST …/workflows/{id}/run è stato rinominato in POST …/workflows/{id}/runs e accetta il corpo environment. I dettagli dell’esecuzione contengono revision_id, revision, un oggetto delay per nodo e task.artifacts. I campi workflow_run_id, workflow_node_id e artifacts forniti dal client su un’attività vengono ignorati, così un’attività non può spacciarsi per un nodo dell’esecuzione di qualcun altro.


Ruoli e controllo degli accessi

Più ruoli per membro

Pagina del team con più ruoli per membro

Un membro del progetto detiene un insieme di ruoli, modificabile come chip nella pagina del team. L’API accetta roles: ["manager", "release_approver"] accanto al vecchio role; la risposta mantiene il campo scalare role solo per i membri con un unico ruolo. Un non amministratore non può togliere il ruolo integrato Owner all’ultimo proprietario.

Ruoli con id, slug e ambiti

I ruoli sono ora righe con un id intero e uno slug (^[A-Za-z0-9_-]{1,100}$, derivato dal nome nel modulo); anche i quattro ruoli integrati sono righe e non possono più essere oscurati da un ruolo personalizzato. I ruoli hanno un ambito: integrato, condiviso (utilizzabile in qualsiasi progetto) o di progetto. L’eliminazione di un ruolo in uso risponde 409 con il relativo impatto (membri, progetti, permessi sui modelli, mappature) e può essere ripetuta con ?force=true — Elimina con le assegnazioni nell’interfaccia. Le migrazioni v2.20.12 e v2.20.13 ricostruiscono le tabelle dei ruoli; vedi le note di aggiornamento.

Ruoli e permessi globali (Pro)

Scheda dei ruoli globali della pagina degli utenti

I diritti validi per tutta l’istanza non si limitano più al flag di amministratore. Un ruolo globale concede una maschera di quattro permessi — Gestire gli utenti, Gestire i ruoli globali, Gestire le impostazioni di sistema, Leggere il log di audit — e viene assegnato agli utenti nella scheda Ruoli della pagina degli utenti (/users/roles) e nella scheda Ruoli globali della finestra dell’utente, che mostra anche i permessi effettivi e quale ruolo concede ciascuno. Ogni route di amministrazione è protetta da uno dei quattro bit; GET /api/user restituisce global_permissions. Un’istanza conserva sempre almeno un amministratore, garantito con un lock di riga sicuro tra i nodi HA. Un utente con Gestire gli utenti non può modificare un amministratore né chiunque detenga un permesso che lui non ha. API: /api/global-roles, /api/users/{id}/global-roles, /api/users/{id}/global-permissions, catalogo su /api/global-roles/permissions.

Ruoli globali di un utente

Mappature dei ruoli dei gruppi (Enterprise)

Pagina delle mappature dei gruppi

Associa un gruppo del provider di identità a un ruolo di progetto nella nuova pagina Mappature dei gruppi (/role-mappings): provider, gruppo, progetto, ruolo. A ogni accesso OIDC i ruoli mappati dell’utente vengono allineati ai gruppi presenti nel token (groups_claim del provider). I ruoli mappati compaiono nella pagina del team come chip bloccati con un tooltip provider: group e non possono essere rimossi come ruoli di membro; i ruoli mappati non contano come ultimo proprietario del progetto. Un accesso con password o LDAP azzera i ruoli mappati, perché non porta alcun gruppo. API: /api/role_mappings.


Autenticazione e identità

Pagina di accesso con più directory LDAP

  • Identità esterne. Gli accessi LDAP e OIDC sono associati agli account Semaphore tramite l’id stabile del provider (sub OIDC, DN LDAP) nella nuova tabella user__external_identity, non tramite l’e‑mail. Questo chiude la classe di bug in cui un IdP che accetta qualsiasi indirizzo digitato fa prendere possesso dell’account di qualcun altro. external_auth_email_matching (auto predefinito, always, never) controlla se un utente esterno esistente senza identità possa ancora essere associato una volta tramite e‑mail; gli account locali con password non vengono mai adottati. L’e‑mail OIDC vale solo quando email_verified è presente e il provider imposta require_verified_email. Gli utenti collegano e scollegano le identità da soli nella finestra dell’account (/api/users/{id}/identities, POST /api/user/identities/ldap, /api/auth/oidc/{provider}/login?link=1).
  • Più directory LDAP. ldap_providers è una mappa di directory con nome, ognuna con il proprio server, bind, ricerca, mappature, colore e ordine; il vecchio blocco piatto ldap_* continua a funzionare come provider ldap. La pagina di accesso mostra un selettore quando c’è più di una scheda e la scheda interna non invia mai una password a una directory. GET /api/auth/login restituisce ldap_providers e login_with_password.
  • I certificati LDAPS sono verificati per impostazione predefinita. Imposta ldap_tls_skip_verify (blocco piatto) o tls_skip_verify (per provider) per un certificato autofirmato.
  • Durata assoluta della sessione. auth.max_session_life_hours (SEMAPHORE_AUTH_MAX_SESSION_LIFE_HOURS) fa scadere una sessione a un intervallo fisso dall’accesso, indipendentemente dall’attività; 0 mantiene solo il timeout di inattività.
  • Un utente senza progetti che non può crearne uno vede una pagina Nessun progetto invece di un modulo che non può inviare; in quel caso POST /api/projects risponde 403.
  • La lingua scelta nel menu utente viene memorizzata sul server e segue l’utente tra i browser (lang in /api/user/options).

Configurazione degli host

Pagina della configurazione degli host

Una nuova pagina di progetto, Configurazione degli host, associa host SSH e URL Git alle credenziali del progetto:

  • una mappatura Host (bastion.example.com) collega una chiave SSH, come blocco Host di un ssh_config generato;
  • una mappatura URL (https://github.com/acme/, un prefisso che termina con / copre un gruppo) collega una chiave SSH o una coppia login/password (solo HTTPS), come riscrittura Git insteadOf; vince l’URL più specifico.
Modulo di mappatura dell'host

Le mappature si applicano al repository del modello e ai suoi submodule, ai ruoli e alle collection di requirements.yml, ai moduli di terraform init, ai comandi git eseguiti da un playbook, ai repository di inventario e agli host di inventario, e alla navigazione di branch e playbook; vengono inviate ai runner remoti. Le chiavi private non toccano mai il disco — un agente SSH per mappatura, collegato con IdentityAgent; le password passano tramite GIT_CONFIG_PARAMETERS e gli URL dei repository vengono oscurati nei log delle attività. Una chiave referenziata da una mappatura non può essere eliminata. Le mappature fanno parte dei backup del progetto. Richiede git_client: cmd_git. Tabella project__host_config, migrazione v2.20.7; API /api/project/{id}/host_configs.


Modelli e attività

Modulo del modello con la directory di lavoro e le opzioni di notifica

  • Directory di lavoro di Ansible. Directory di lavoro differente esegue ansible-playbook da una sottodirectory del repository; il percorso deve restare dentro il checkout (working_directory, migrazione v2.20.3).

  • Nomi dei modelli univoci per progetto (migrazione v2.20.4), e POST /api/project/{id}/tasks accetta template_name invece di template_id.

  • Soppressione delle notifiche di errore per modello, accanto alla soppressione dei successi già esistente; gli avvisi e‑mail rispettano per la prima volta entrambe le opzioni (suppress_error_alerts, migrazione v2.20.5).

  • Nascondere Dry Run / Diff dalla finestra dell’attività per modello; il server smette anche di aggiungere --check / --diff per quel modello (task_params.hide_dry_run, hide_diff).

  • Opzioni di installazione Galaxy — una sezione comprimibile con Salta l’installazione Galaxy, argomenti CLI separati per ansible-galaxy role install e collection install (una allow‑list di flag; --token, --api-key e i flag di percorso vengono rifiutati) e la richiesta di sovrascrittura per singola attività.

  • Il selettore dei playbook elenca le sottodirectory mentre digiti, filtrate per app (.yml per Ansible, directory di primo livello per Terraform / OpenTofu / Terragrunt / Pulumi, .sh, .py, .ps1), salta le directory di layout di Ansible e le directory nascoste, è limitato a 30 voci e naviga un clone shallow confinato alla radice del repository.

  • Variabili di survey a selezione multipla — il nuovo tipo select accetta più valori, resi come chip nella finestra dell’attività; default_value può essere un array.

    Finestra della nuova attività con una variabile di survey a selezione multipla
  • I secret di survey raggiungono i runner remoti. Una risposta di survey di tipo secret arrivava vuota su un runner. Ora viene memorizzata cifrata come chiave di accesso vincolata all’attività (access_key.task_id, expire_at, migrazione v2.20.1), decifrata dal nodo HA che serve il runner, eliminata al termine dell’attività e rimossa ogni ora; è nascosta dal Key Store, dai backup e dall’API delle chiavi.

  • Variabili extra in YAML. L’editor dei gruppi di variabili ha guadagnato un selettore Tabella | JSON | YAML e un editor a schermo intero; le conversioni sono rigorose (le date restano stringhe, le radici non oggetto e i numeri non finiti vengono rifiutati). L’archiviazione è invariata.

    Editor dei gruppi di variabili in modalità YAML

  • La pagina dell’attività indica e collega la pianificazione o integrazione che l’ha avviata e contrassegna un’origine eliminata come #id (deleted). I timestamp del log non vengono più selezionati quando si copia un log.

  • Le pianificazioni validano l’espressione sul server prima del salvataggio, così @hourly viene accettato, e il banner del fuso orario può essere chiuso.

    Modulo della pianificazione
  • L’arresto di un’attività locale termina tutto il suo gruppo di processi: SIGTERM, un periodo di grazia di 15 s, poi SIGKILL; i processi ssh o dei provider rimasti orfani non sopravvivono più all’attività. Un piano Terraform interrotto non continua più; un piano che esce con 0 su SIGTERM non viene interpretato come successo.

  • Il campo repository_id dell’inventario viene mantenuto solo per il tipo file e deve appartenere al progetto.

  • I log del server indicano l’utente nelle voci Task added to queue / Task started.


Secret e Ansible Vault

  • Le variabili extra viaggiano in file, non sulla riga di comando. Gruppi di variabili, risposte di survey, input dei workflow e dettagli dell’attività vengono scritti in un file YAML 0600 passato come --extra-vars @file. I secret — le risposte di survey di tipo secret e i secret dei gruppi di variabili — finiscono in un secondo file cifrato nel formato Ansible Vault 1.1 / AES‑256 da un’implementazione nativa in Go (non serve il binario ansible-vault), sbloccato con una password monouso fornita al --vault-id <uuid>@prompt di ansible-playbook. Né i valori né la password compaiono in ps, ed entrambi i file vengono rimossi al termine dell’attività.

  • Jinja2 nei valori è dato, non codice. Ogni stringa che contiene {{, {%, {# o un’intestazione #jinja2: viene marcata !unsafe, in modo ricorsivo, così una risposta di survey come {{ lookup('pipe', 'id') }} viene passata letteralmente. Le stringhe senza delimitatore restano volutamente non marcate: ansible‑core ≥ 2.19 ri‑risolve gli scalari !unsafe, il che trasformerebbe "2026.08" in un numero in virgola mobile.

  • Un nuovo namespace di debug extra_vars (SEMAPHORE_DEBUG_FILTER=extra_vars) registra come le variabili vengono suddivise e scritte — solo nomi, file e dimensioni, mai i valori.

  • Generazione di una coppia di chiavi SSH sul server. Generate SSH Key nel Key Store crea una chiave RSA; la chiave pubblica viene conservata con la chiave, mostrata con Mostra / Nascondi e un pulsante di copia, e proposta in una finestra subito dopo la creazione (generate_ssh_key).

    Chiave con una coppia di chiavi SSH generata
  • L’aggiornamento di una chiave scrive type, secret e la parte pubblica solo quando Override è impostato, così un client non può alterare il payload di una chiave senza sostituire il secret.

  • La lettura di una credenziale da una variabile d’ambiente del server o da un file sotto dirs.secrets è ora documentata (schede Env / File del modulo del Key Store).


Repository e Git

Modulo del repository con l'opzione di checkout unico
  • Monorepo: un unico checkout per tutti i modelli. Un’opzione del repository clona il repository una sola volta e lo condivide tra i modelli invece di una copia per modello; il checkout viene bloccato durante fetch e pull, poi le attività vengono eseguite in parallelo. I modelli di un repository di questo tipo non possono avere un branch proprio e le loro attività non possono sovrascrivere branch o commit (monorepo, migrazione v2.20.11).
  • Nuovi tentativi Git. clone e pull vengono ritentati con un ritardo esponenziale limitato a un minuto; git_attempts (SEMAPHORE_GIT_ATTEMPTS, predefinito 4).
  • Submodule in parallelo. git_submodule_jobs (SEMAPHORE_GIT_SUBMODULE_JOBS, predefinito 4) viene passato come --jobs.
  • Verifica delle host key SSH. Nuova sezione ssh: config_path, known_hosts_file (SEMAPHORE_SSH_KNOWN_HOSTS_FILE) e strict_host_key_checking — no (predefinito), yes o accept-new — applicata a Git su SSH.
  • La navigazione del repository usa un clone shallow indicizzato per branch; le credenziali vengono codificate in percent‑encoding per i cloni bare‑metal e oscurate nei log e nel feed degli eventi.

Runner e integrazioni

  • runner.check_interval_seconds (SEMAPHORE_RUNNER_CHECK_INTERVAL_SECONDS, predefinito 5) imposta la frequenza di polling di un runner; un interruttore Opzioni avanzate nella pagina dei runner lo inserisce negli snippet generati di env, configurazione e Docker (pubblicato in v2.19.17).

  • runner.connection.timeout_seconds (SEMAPHORE_RUNNER_CONNECTION_TIMEOUT_SECONDS, predefinito 3) limita separatamente connessione, handshake TLS e header di risposta; i caricamenti dei log non vengono interrotti.

  • runners.default_global_runners_mode (SEMAPHORE_DEFAULT_GLOBAL_RUNNERS_MODE: disable, prefer, require) sostituisce il deprecato use_remote_runner; runners.registration_token sostituisce il runner_registration_token di primo livello.

  • Diagnostica dei runner lato server sotto SEMAPHORE_DEBUG_FILTER=runner: motivi di rifiuto dei token, rilevamento di riavvio e stato online, report di avanzamento rifiutati, tracciamento dell’assegnazione.

  • Le richieste di unregister dei runner sono autenticate; il client runner rifiuta i redirect HTTP.

  • Autenticazione dei webhook con HMAC‑SHA512 (hmac-sha512) accanto all’esistente HMAC‑SHA256; l’header della firma è configurabile.

    Modulo dell'integrazione con HMAC-SHA512
  • Un webhook la cui integrazione appartiene a un altro progetto viene rifiutato.


Osservabilità

  • Metriche Prometheus. GET /api/metrics protetto da HTTP Basic Auth con una credenziale di servizio statica:

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

    (SEMAPHORE_METRICS_ENABLED, SEMAPHORE_METRICS_USERNAME, SEMAPHORE_METRICS_PASSWORD.) Serie: semaphore_tasks_running, semaphore_tasks_total{status}, i collector standard go_* e process_*, e gli indicatori dell’esportazione di audit in Pro.

  • Nuovi namespace di debug extra_vars e runner; la navigazione del repository registra l’output di Git a livello DEBUG.

  • L’esportazione e il ripristino dei backup di progetto vengono registrati.


Sicurezza

  • Collegamento delle identità tramite l’id del provider invece dell’e‑mail; verifica dei certificati LDAPS attiva per impostazione predefinita.
  • Variabili extra fuori dalla riga di comando; secret cifrati con Vault; Jinja2 nei valori non valutato.
  • workflow_run_id, workflow_node_id e artifacts contraffatti rimossi dalle attività dei client.
  • Route di amministrazione protette da permessi globali espliciti invece del flag di amministratore; bit di permesso sconosciuti rifiutati; protezione contro l’escalation dei privilegi nella gestione degli utenti.
  • Selettore dei playbook confinato alla radice del repository (OpenRoot), limitato e filtrato.
  • Radici delle variabili extra e numeri YAML validati; argomenti CLI di Galaxy in allow‑list.
  • Credenziali dei repository oscurate nei log e nel feed degli eventi; = sottoposto a escape nei parametri di configurazione Git.
  • Gli endpoint di audit rifiutano le letture cross‑site e i cursori malformati; reti dei proxy attendibili validate.
  • unregister dei runner autenticato; redirect rifiutati dal client runner.
  • Id di progetto e di integrazione dei webhook verificati.
  • Attività locali interrotte insieme a tutto il loro gruppo di processi.

Note di aggiornamento

Modifiche incompatibili e di comportamento

  1. I nomi dei modelli devono essere univoci per progetto. La migrazione v2.20.4 aggiunge un indice univoco; rinomina i duplicati prima di aggiornare.
  2. Le tabelle dei ruoli vengono ricostruite (v2.20.12 / v2.20.13). Esegui prima un backup. Un ruolo personalizzato il cui slug collide senza distinzione tra maiuscole e minuscole con uno integrato o con un altro ruolo viene rinominato (registrato nel log); i permessi sui modelli che puntano a un ruolo non risolvibile vengono eliminati (registrato nel log). L’appartenenza è stata spostata in project__user_role; la colonna project__user.role non esiste più.
  3. GET /api/project/{id}/users restituisce role solo per i membri con un unico ruolo — leggi roles.
  4. /roles* è passato dal flag di amministratore al permesso Gestire i ruoli globali; gli amministratori non sono interessati.
  5. I certificati LDAPS sono verificati per impostazione predefinita. Imposta ldap_tls_skip_verify o il tls_skip_verify di un provider per i certificati autofirmati.
  6. ansible-playbook viene invocato in modo diverso: --extra-vars @file, più un secondo file e un --vault-id <uuid>@prompt quando l’attività ha dei secret, anche per i modelli senza vault. Tutto ciò che analizza la riga di comando, o un ansible.cfg che vieta i prompt del vault, ne è interessato.
  7. Jinja2 all’interno dei valori delle variabili extra non viene più valutato. Un playbook che contava sul templating di un valore di webhook o di survey smetterà di funzionare in quel modo.
  8. Endpoint di esecuzione dei workflow rinominato: POST …/workflows/{id}/run → …/runs.
  9. I repository monorepo prevalgono sul modello: nessun branch per modello, nessuna sovrascrittura di branch o commit nelle attività.
  10. Il campo repository_id dell’inventario viene eliminato per ogni tipo tranne file.
  11. L’arresto di un’attività locale termina il suo gruppo di processi (nessun equivalente su Windows per ora).
  12. Gli output dei workflow non vengono ancora catturati dagli esecutori Docker e Kubernetes; i secret di survey non raggiungono ancora quegli esecutori.

Nuova configurazione

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 e require_verified_email per provider OIDC, runner.check_interval_seconds, runner.connection.timeout_seconds, runners.{default_global_runners_mode,registration_token}. Sono tutti facoltativi. I campi di configurazione di tipo puntatore possono ora essere impostati da variabili d’ambiente. Le pagine di riferimento della configurazione e della CLI sono generate dal codice sorgente.

Migrazioni del database

v2.20.0 identità esterne · v2.20.1 secret di survey vincolati all’attività · v2.20.2 nodi di ritardo · v2.20.3 directory di lavoro · v2.20.4 nomi dei modelli univoci · v2.20.5 soppressione degli avvisi di errore · v2.20.7 configurazione degli host · v2.20.8 revisioni dei workflow · v2.20.9–v2.20.11 log di audit e indici, mappature degli input degli archi, flag monorepo · v2.20.12–v2.20.13 tabelle dei ruoli, variabili dei workflow · v2.20.14 integrazioni dei workflow e mappature dei gruppi · v2.20.16 ruoli globali.

Dipendenze

Go 1.26; immagini Docker su Alpine 3.24; aggiunto 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; frontend js-yaml 5 e cron-parser 5.10. Nuovi deployment one‑click: Cloudzy, RepoCloud e Pethost.