Execução de workflow com uma aprovação, um nó de atraso e variáveis de execução

O Semaphore UI 2.20 adiciona um log de auditoria com exportação para SIEM, transforma os Workflows em um verdadeiro motor de pipelines com nós de atraso, revisões, saídas passadas entre tarefas e variáveis de workflow, reformula os roles para que um membro possa ter vários deles e os administradores ganhem roles válidos em toda a instância e mapeamentos de grupos do IdP, introduz a configuração de hosts para credenciais SSH e Git por host, move todas as variáveis extras do Ansible para arquivos criptografados com Vault e expõe métricas do Prometheus.

A linha começa em v2.20.0. As versões de correção serão listadas no final desta página conforme forem publicadas.

Destaques

  • Log de auditoria — quem fez o quê, de onde e com qual resultado; uma tela de administração, retenção e exportação via Syslog / Splunk HEC para SIEMs (exportação e filtros no Pro).
  • Workflows — nós de atraso, revisões imutáveis fixadas às execuções, saídas entregues como entradas da tarefa seguinte, variáveis de workflow solicitadas em um diálogo de execução, um editor redesenhado com atalhos e desfazer, e webhooks que iniciam workflows.
  • Vários roles por membro, roles com ids e slugs, roles globais com permissões válidas em toda a instância (Pro) e mapeamentos de grupo do IdP → role aplicados no login (Enterprise).
  • Identidades externas — os logins LDAP e OIDC são vinculados às contas pelo id estável do provedor, não pelo e‑mail; vários diretórios LDAP em uma única página de login.
  • Configuração de hosts — mapeie hosts SSH e URLs Git para credenciais do projeto, aplicadas a clones, Galaxy, módulos Terraform e Ansible.
  • As variáveis extras do Ansible nunca mais ficam na linha de comando; os segredos viajam em um arquivo criptografado com Ansible Vault e o Jinja2 dentro dos valores não é mais avaliado.
  • Modelos: diretório de trabalho do Ansible, nomes únicos e template_name na API de tarefas, notificações de erro suprimidas, Dry Run / Diff ocultos, opções de instalação do Galaxy, variáveis de survey de múltipla escolha, segredos de survey em runners remotos.
  • Repositórios monorepo compartilham um único checkout entre modelos; novas tentativas do Git, busca paralela de submódulos, verificação da chave de host SSH.
  • Métricas do Prometheus em /api/metrics.
  • Geração de pares de chaves SSH no servidor e cópia da chave pública a partir do Key Store.

Log de auditoria

Tela do log de auditoria

O Semaphore agora registra eventos relevantes para a segurança em um log dedicado, somente de acréscimo. Habilite-o com:

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

(SEMAPHORE_AUDIT_ENABLED, SEMAPHORE_AUDIT_INSTANCE_ID; instance_id é obrigatório e identifica a instalação em cada evento.)

O que é registrado. 116 tipos de evento em oito categorias: auth (logins, logouts, MFA, rejeições de token de API, requisições negadas, bloqueios de CSRF), iam (usuários, senhas, tokens de API, identidades, associações, roles, permissões de modelo), resource (projetos, backups, inventários, repositórios, modelos, agendamentos, integrações, configurações de host, workflows, grupos de variáveis), secret (credenciais e armazenamentos de segredos), task (início com seu disparo, conclusão com resultado e duração, aprovações, paradas, exclusão do histórico), runner (registro, alterações, relatórios rejeitados), system (configurações, licença) e audit em si (início, retenção, exportação). Senhas, tokens, valores de segredos, saída de tarefas e variáveis nunca são gravados.

Envelope do evento. Todo evento carrega um UUID, um número de sequência sem lacunas, um timestamp UTC com precisão de microssegundos, o ator (usuário / anônimo / sistema / runner / integração, com autenticação por sessão ou por token de API e uma impressão digital do token), o IP de origem e o User‑Agent, o alvo, o projeto, um id de requisição (também retornado no cabeçalho de resposta X-Request-ID), o id da instância e o id do nó de HA. Os resultados são success ou failure com uma lista fechada de motivos; uma ação que salvou o objeto mas falhou em uma etapa posterior é um sucesso com partial = true. Atrás de um proxy reverso, o X-Forwarded-For só é confiável quando vem de audit.trusted_proxy_cidrs.

Cartão de evento de auditoria

Tela de administração. Log de auditoria no menu do usuário (/audit-log) lista os eventos dos mais recentes aos mais antigos, 50 por página, com paginação Mais antigos / Mais recentes; uma linha abre um cartão com as seções Quem, Objeto, Onde, Quando, Detalhes e Técnico e um botão que copia o evento como o JSON enviado a um SIEM. O acesso exige a nova permissão global Ler o log de auditoria.

Retenção. audit.retention_days exclui os eventos mais antigos em lotes, a cada hora e com jitter, para que os nós de HA não colidam; cada passagem que exclui algo também é registrada.

Pro: filtros e exportação. Filtre por período, usuário, projeto, tipo de evento, resultado e IP; pivote a partir de qualquer valor do cartão; exporte a seleção atual como CSV ou JSON Lines.

Pro: exportação para SIEM. Dois destinos, cada um com seu próprio cursor para que nada seja ignorado quando um receptor estiver indisponível: Syslog sobre TLS (RFC 5424, o JSON do evento no corpo) via audit.syslog e Splunk HTTP Event Collector via audit.splunk_hec (url, token, index, source, sourcetype, ca_file, …). A entrega é at‑least‑once, ordenada por sequência; em HA apenas um nó exporta por destino, coordenado por um lease no Redis. Três séries do Prometheus descrevem o exportador: semaphore_audit_export_pending_events, semaphore_audit_export_oldest_pending_seconds e semaphore_audit_export_errors_total.

Armazenamento: tabelas audit_event, audit_event_sequence, audit_export_state (migrações v2.20.9 a v2.20.11). API: GET /api/audit/events e GET /api/audit/events/export.


Workflows

Os workflows são um recurso Pro; o rótulo Beta foi removido.

Nós de atraso

Um quarto tipo de nó ao lado de tarefa, aprovação e nota: o Atraso pausa a execução por um número de segundos e depois libera suas arestas. A visualização da execução mostra uma contagem regressiva ao vivo no cartão; uma execução interrompida cancela o atraso. Campo delay_seconds, migração v2.20.2.

Revisões

Cada gravação de um workflow cria uma nova revisão do grafo; uma execução fixa a revisão a partir da qual começou, de modo que editar um workflow nunca altera uma execução em andamento nem deixa órfãos os nós de execuções passadas. O editor exibe um chip rev. N e quantas execuções ainda estão rodando uma revisão anterior; a visualização da execução mostra qual revisão ela executa. As revisões que nenhuma execução referencia são excluídas quando uma mais nova é salva. API: GET …/workflows/{id}/revisions e …/revisions/{revision_id}.

Saídas e entradas

Visualização da execução com selos de saídas

Uma tarefa pode entregar dados estruturados aos nós seguintes. Toda tarefa iniciada por um workflow recebe SEMAPHORE_OUTPUTS_FILE; o que ela escrever ali como um objeto JSON torna-se suas saídas:

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

O Ansible produz saídas com ansible.builtin.set_stats por meio de um plugin de callback embutido; as saídas de Terraform, OpenTofu e Terragrunt são capturadas automaticamente de output -json (valores sensitive são ignorados e listados como Não capturado). As saídas só são lidas quando a tarefa é bem‑sucedida; os limites são 100 saídas, 32 KB cada e 256 KB por arquivo.

Uma conexão que chega a um nó de tarefa entrega entradas — ela preenche as variáveis de survey do modelo de destino com as saídas do nó de origem:

  • Por nome (padrão): cada saída cujo nome é igual ao de uma variável de survey a preenche.
  • Mapear entradas explicitamente: liste os pares variable ← output key a entregar; quando o workflow já tem uma execução concluída, o painel sugere as chaves que ela produziu.

Painel da conexão com mapeamento explícito de entradas

Os valores são convertidos para o tipo da variável, os nós de aprovação e de atraso repassam as saídas, um mapeamento explícito prevalece sobre a entrega por nome, e uma variável obrigatória deixada sem valor faz a tarefa do nó falhar antes de iniciar, de modo que a execução siga suas arestas em caso de falha. A visualização da execução mostra um selo N saídas por nó, o diálogo da tarefa tem uma tabela Saídas, e o log da tarefa começa com uma linha Input "x" <- output "y" of node N por valor entregue. As saídas são armazenadas em texto plano e nunca preenchem uma variável secret; um secret não pode ser passado por saídas. As tarefas em runners remotos produzem e recebem saídas; os executores Docker e Kubernetes ainda não as capturam.

Diálogo da tarefa com a tabela Saídas

Variáveis de workflow e o diálogo de execução

Diálogo de execução solicitando variáveis de workflow

Um workflow tem suas próprias variáveis de survey, solicitadas uma única vez em um diálogo Run “…” quando uma execução começa (um workflow sem variáveis inicia imediatamente, como antes). As respostas são armazenadas na execução, exibidas como chips em uma faixa Variáveis acima do canvas da execução, e chegam a uma tarefa apenas por meio de uma vinculação explícita no painel do nó — uma variável de workflow nunca vaza para um modelo por nome. Segredos não são permitidos como variáveis de workflow. POST …/workflows/{id}/runs aceita {"environment": {"image_tag": "1.4.3"}}; uma resposta que não corresponde ao seu tipo ou um valor obrigatório ausente rejeita o início.

Ambiente de uma tarefa de workflow

Toda tarefa iniciada por um workflow recebe SEMAPHORE_WORKFLOW_ID, SEMAPHORE_WORKFLOW_RUN_ID, SEMAPHORE_WORKFLOW_URL (requer web_host) e SEMAPHORE_OUTPUTS_FILE, para todas as aplicações e também em runners remotos.

Editor redesenhado

Editor de workflow

  • Novos cartões de nó com bloco de tipo, status, duração, selo de saídas e Aprovar / Rejeitar inline; rótulos de aresta com um menu de condição no próprio local e um botão de exclusão; um canvas com grade de pontos.
  • Menu de adição rápida a partir da alça + de um nó, de um clique com o botão direito no canvas ou do botão do estado vazio: lista pesquisável de tipos de nó e de modelos de tarefa; o novo nó é conectado em caso de sucesso.
  • Desfazer / refazer (Ctrl/⌘+Z, Ctrl/⌘+Shift+Z), renomeação inline do workflow, um menu Problemas que foca o nó problemático, um selo Salvar para alterações não salvas e uma proteção ao sair da página.
  • Atalhos de teclado no canvas: as setas movem a visão (Shift para um passo maior), + / - dão zoom, 0 ajusta o grafo, 1 redefine o zoom, Esc limpa a seleção; os cartões de nó podem receber foco pelo teclado.
  • Controles flutuantes: aumentar / reduzir zoom, ajustar a visão, auto‑layout Organizar e porcentagem de zoom.
  • Um único chevron recolhe a paleta e a navegação principal juntas; o estado é memorizado.
  • O overscroll do trackpad não dispara mais o gesto Voltar do navegador no macOS.

Menu de adição rápida

Webhooks iniciam workflows

Uma integração agora pode executar um workflow em vez de um modelo (Runs: Template / Workflow no formulário da integração). Cada valor extraído torna-se uma resposta ao survey do workflow. Gerenciar essas integrações exige o recurso Pro workflow_integrations_management. Para integrações de modelo, um valor de Task Params extraído chamado git_branch define a branch da tarefa iniciada quando o modelo permite sobrescrevê-la.

Mudanças na API

POST …/workflows/{id}/run foi renomeado para POST …/workflows/{id}/runs e aceita o corpo environment. Os detalhes da execução carregam revision_id, revision, um objeto delay por nó e task.artifacts. Os campos workflow_run_id, workflow_node_id e artifacts enviados pelo cliente em uma tarefa são ignorados, de modo que uma tarefa não possa se passar por um nó da execução de outra pessoa.


Roles e controle de acesso

Vários roles por membro

Página da equipe com vários roles por membro

Um membro do projeto possui um conjunto de roles, editado como chips na página Equipe. A API aceita roles: ["manager", "release_approver"] ao lado do role legado; a resposta mantém o role escalar apenas para membros com um único role. Um não administrador não pode tirar o role interno Owner do último proprietário.

Roles com ids, slugs e escopos

Agora os roles são registros com um id inteiro e um slug (^[A-Za-z0-9_-]{1,100}$, derivado do nome no formulário); os quatro roles internos também são registros e não podem mais ser sombreados por um role personalizado. Os roles têm um escopo: interno, compartilhado (utilizável em qualquer projeto) ou de projeto. Excluir um role em uso responde 409 com o seu impacto (membros, projetos, permissões de modelo, mapeamentos) e pode ser repetido com ?force=true — Excluir com atribuições na UI. As migrações v2.20.12 e v2.20.13 reconstroem as tabelas de roles; veja as notas de atualização.

Roles e permissões globais (Pro)

Aba de roles globais da página de usuários

Os direitos válidos em toda a instância não são mais apenas o flag de administrador. Um role global concede uma máscara de quatro permissões — Gerenciar usuários, Gerenciar roles globais, Gerenciar configurações do sistema, Ler o log de auditoria — e é atribuído aos usuários na aba Roles da página de usuários (/users/roles) e na aba Roles globais do diálogo do usuário, que também mostra as permissões efetivas e qual role concede cada uma. Toda rota de administração é protegida por um dos quatro bits; GET /api/user retorna global_permissions. Uma instância sempre mantém ao menos um administrador, garantido por um bloqueio de linha seguro entre nós de HA. Um usuário com Gerenciar usuários não pode editar um administrador nem alguém que tenha uma permissão que ele não possui. API: /api/global-roles, /api/users/{id}/global-roles, /api/users/{id}/global-permissions, catálogo em /api/global-roles/permissions.

Roles globais de um usuário

Mapeamentos de grupo para role (Enterprise)

Página de mapeamentos de grupo

Mapeie um grupo do provedor de identidade para um role de projeto na nova página Mapeamentos de grupo (/role-mappings): provedor, grupo, projeto, role. A cada login OIDC, os roles mapeados do usuário são ajustados para corresponder aos grupos presentes no token (groups_claim do provedor). Os roles mapeados aparecem na página Equipe como chips bloqueados com uma dica provider: group e não podem ser removidos como roles do membro; roles mapeados não contam como o último proprietário do projeto. Um login por senha ou LDAP limpa os roles mapeados, porque não traz grupos. API: /api/role_mappings.


Autenticação e identidades

Página de login com vários diretórios LDAP

  • Identidades externas. Os logins LDAP e OIDC são vinculados às contas do Semaphore pelo id estável do provedor (sub do OIDC, DN do LDAP) na nova tabela user__external_identity, e não pelo e‑mail. Isso elimina a classe de falha em que um IdP que aceita qualquer endereço digitado assume a conta de outra pessoa. external_auth_email_matching (auto por padrão, always, never) controla se um usuário externo já existente e sem identidade ainda pode ser associado por e‑mail uma única vez; contas locais com senha nunca são assumidas. O e‑mail do OIDC só vale quando há email_verified e o provedor define require_verified_email. Os usuários vinculam e desvinculam identidades por conta própria no diálogo da conta (/api/users/{id}/identities, POST /api/user/identities/ldap, /api/auth/oidc/{provider}/login?link=1).
  • Vários diretórios LDAP. ldap_providers é um mapa de diretórios nomeados, cada um com seu próprio servidor, bind, busca, mapeamentos, cor e ordem; o bloco plano ldap_* legado continua funcionando como o provedor ldap. A página de login exibe um seletor quando há mais de uma aba, e a aba interna nunca envia uma senha para um diretório. GET /api/auth/login retorna ldap_providers e login_with_password.
  • Os certificados LDAPS são verificados por padrão. Defina ldap_tls_skip_verify (bloco plano) ou tls_skip_verify (por provedor) para um certificado autoassinado.
  • Tempo de vida absoluto da sessão. auth.max_session_life_hours (SEMAPHORE_AUTH_MAX_SESSION_LIFE_HOURS) expira uma sessão um tempo fixo após o login, qualquer que seja a sua atividade; 0 mantém apenas o tempo limite de inatividade.
  • Um usuário sem projetos que não pode criar nenhum vê uma página Ainda não há projetos em vez de um formulário que não consegue enviar; POST /api/projects responde 403 nesse caso.
  • O idioma escolhido no menu do usuário é armazenado no servidor e acompanha o usuário entre navegadores (lang em /api/user/options).

Configuração de hosts

Página de configuração de hosts

Uma nova página de projeto, Configuração de hosts, mapeia hosts SSH e URLs Git para credenciais do projeto:

  • um mapeamento de Host (bastion.example.com) associa uma chave SSH, como um bloco Host de um ssh_config gerado;
  • um mapeamento de URL (https://github.com/acme/, um prefixo terminado em / cobre um grupo) associa uma chave SSH ou um login/senha (somente HTTPS), como uma reescrita insteadOf do Git; a URL mais específica prevalece.
Formulário de mapeamento de host

Os mapeamentos se aplicam ao repositório do modelo e aos seus submódulos, às roles e collections do requirements.yml, aos módulos do terraform init, aos comandos git executados por um playbook, aos repositórios de inventário e aos hosts de inventário, e também à navegação por branches e playbooks; eles são enviados aos runners remotos. As chaves privadas nunca chegam ao disco — um agente SSH por mapeamento, vinculado com IdentityAgent; as senhas passam por GIT_CONFIG_PARAMETERS, e as URLs dos repositórios são ocultadas nos logs das tarefas. Uma chave referenciada por um mapeamento não pode ser excluída. Os mapeamentos fazem parte dos backups do projeto. Requer git_client: cmd_git. Tabela project__host_config, migração v2.20.7; API /api/project/{id}/host_configs.


Modelos e tarefas

Formulário do modelo com diretório de trabalho e opções de notificação

  • Diretório de trabalho do Ansible. Diretório de trabalho diferente executa o ansible-playbook a partir de um subdiretório do repositório; o caminho deve permanecer dentro do checkout (working_directory, migração v2.20.3).

  • Nomes de modelo únicos por projeto (migração v2.20.4), e POST /api/project/{id}/tasks aceita template_name em vez de template_id.

  • Supressão das notificações de erro por modelo, ao lado da supressão de sucesso já existente; os alertas por e‑mail respeitam ambas pela primeira vez (suppress_error_alerts, migração v2.20.5).

  • Ocultar Dry Run / Diff do diálogo da tarefa por modelo; o servidor também deixa de acrescentar --check / --diff para esse modelo (task_params.hide_dry_run, hide_diff).

  • Opções de instalação do Galaxy — uma seção recolhível com Ignorar a instalação do Galaxy, argumentos de CLI separados para ansible-galaxy role install e collection install (uma lista de flags permitidas; --token, --api-key e flags de caminho são recusadas) e o prompt de sobrescrita por tarefa.

  • O seletor de playbook lista os subdiretórios conforme você digita, filtrado por aplicação (.yml para Ansible, diretórios de primeiro nível para Terraform / OpenTofu / Terragrunt / Pulumi, .sh, .py, .ps1), ignora os diretórios da estrutura do Ansible e os diretórios ocultos, é limitado a 30 entradas e navega em um clone raso confinado à raiz do repositório.

  • Variáveis de survey de múltipla escolha — o novo tipo select aceita vários valores, exibidos como chips no diálogo da tarefa; default_value pode ser um array.

    Diálogo de nova tarefa com uma variável de survey de múltipla escolha
  • Os segredos de survey chegam aos runners remotos. Uma resposta de survey do tipo secret costumava chegar vazia a um runner. Agora ela é armazenada criptografada como uma chave de acesso vinculada à tarefa (access_key.task_id, expire_at, migração v2.20.1), descriptografada pelo nó de HA que atende o runner, excluída quando a tarefa termina e varrida a cada hora; ela fica oculta no Key Store, nos backups e na API de chaves.

  • Variáveis extras em YAML. O editor de grupos de variáveis ganhou um alternador Tabela | JSON | YAML e um editor em tela cheia; as conversões são estritas (as datas continuam strings, raízes que não são objetos e números não finitos são rejeitados). O armazenamento não mudou.

    Editor de grupo de variáveis no modo YAML

  • A página da tarefa nomeia e vincula o agendamento ou a integração que iniciou a tarefa, e marca uma origem excluída como #id (deleted). Os timestamps do log não são mais selecionados ao copiar um log.

  • Os agendamentos validam a expressão no servidor antes de salvar, então @hourly é aceito, e o banner de fuso horário pode ser dispensado.

    Formulário de agendamento
  • Interromper uma tarefa local encerra todo o seu grupo de processos: SIGTERM, um período de tolerância de 15 s e então SIGKILL; processos ssh ou de provedores órfãos não sobrevivem mais à tarefa. Um plano do Terraform interrompido não continua mais; um plano que sai com 0 no SIGTERM não é interpretado como sucesso.

  • O repository_id do inventário é mantido apenas para o tipo file e deve pertencer ao projeto.

  • Os logs do servidor nomeiam o usuário nas entradas Task added to queue / Task started.


Segredos e Ansible Vault

  • As variáveis extras viajam em arquivos, não na linha de comando. Os grupos de variáveis, as respostas de survey, as entradas de workflow e os detalhes da tarefa são gravados em um arquivo YAML 0600 passado como --extra-vars @file. Os segredos — respostas de survey do tipo secret e segredos de grupos de variáveis — vão para um segundo arquivo criptografado no formato Ansible Vault 1.1 / AES‑256 por uma implementação nativa em Go (sem necessidade do binário ansible-vault), desbloqueado com uma senha de uso único respondida no --vault-id <uuid>@prompt do ansible-playbook. Nem os valores nem a senha aparecem no ps, e ambos os arquivos são removidos quando a tarefa termina.

  • O Jinja2 nos valores é dado, não código. Toda string que contenha {{, {%, {# ou um cabeçalho #jinja2: é marcada como !unsafe, recursivamente, de modo que uma resposta de survey como {{ lookup('pipe', 'id') }} seja passada literalmente. Strings sem delimitador ficam sem marcação de propósito: o ansible‑core ≥ 2.19 reavalia escalares !unsafe, o que transformaria "2026.08" em um número de ponto flutuante.

  • Um novo namespace de depuração extra_vars (SEMAPHORE_DEBUG_FILTER=extra_vars) registra como as variáveis são divididas e gravadas — apenas nomes, arquivos e tamanhos, nunca valores.

  • Geração de um par de chaves SSH no servidor. Generate SSH Key no Key Store cria uma chave RSA; a chave pública é guardada junto com a chave, exibida com Mostrar / Ocultar e um botão de cópia, e oferecida em um diálogo imediatamente após a criação (generate_ssh_key).

    Chave com um par de chaves SSH gerado
  • A atualização de uma chave grava type, secret e a parte pública somente quando Override está marcado, de modo que um cliente não possa alterar o conteúdo de uma chave sem substituir o segredo.

  • A leitura de uma credencial a partir de uma variável de ambiente do servidor ou de um arquivo em dirs.secrets agora está documentada (abas Env / File do formulário do Key Store).


Repositórios e Git

Formulário do repositório com a opção de checkout único
  • Monorepo: um único checkout para todos os modelos. Uma opção do repositório clona o repositório uma única vez e o compartilha entre os modelos, em vez de uma cópia por modelo; o checkout é bloqueado para fetch e pull, e as tarefas então rodam em paralelo. Os modelos de um repositório desses não podem ter uma branch própria e suas tarefas não podem sobrescrever branch ou commit (monorepo, migração v2.20.11).
  • Novas tentativas do Git. clone e pull são repetidos com um atraso exponencial limitado a um minuto; git_attempts (SEMAPHORE_GIT_ATTEMPTS, padrão 4).
  • Submódulos em paralelo. git_submodule_jobs (SEMAPHORE_GIT_SUBMODULE_JOBS, padrão 4) é passado como --jobs.
  • Verificação da chave de host SSH. Nova seção ssh: config_path, known_hosts_file (SEMAPHORE_SSH_KNOWN_HOSTS_FILE) e strict_host_key_checking — no (padrão), yes ou accept-new — aplicada ao Git sobre SSH.
  • A navegação pelo repositório usa um clone raso indexado por branch; as credenciais são codificadas em percent‑encoding para clones em bare metal e ocultadas nos logs e no feed de eventos.

Runners e integrações

  • runner.check_interval_seconds (SEMAPHORE_RUNNER_CHECK_INTERVAL_SECONDS, padrão 5) define com que frequência um runner faz polling; um interruptor de Opções avançadas na página Runners o insere nos trechos gerados de variáveis de ambiente, de configuração e de Docker (lançado na v2.19.17).

  • runner.connection.timeout_seconds (SEMAPHORE_RUNNER_CONNECTION_TIMEOUT_SECONDS, padrão 3) limita separadamente a conexão, o handshake TLS e os cabeçalhos de resposta; os envios de log não são cortados.

  • runners.default_global_runners_mode (SEMAPHORE_DEFAULT_GLOBAL_RUNNERS_MODE: disable, prefer, require) substitui o obsoleto use_remote_runner; runners.registration_token substitui o runner_registration_token de nível superior.

  • Diagnósticos de runner no lado do servidor com SEMAPHORE_DEBUG_FILTER=runner: motivos de rejeição de token, detecção de reinício e de estado online, relatórios de progresso rejeitados, rastreamento do despacho.

  • As requisições de unregister do runner são autenticadas; o cliente do runner recusa redirecionamentos HTTP.

  • Autenticação de webhook por HMAC‑SHA512 (hmac-sha512) ao lado do HMAC‑SHA256 existente; o cabeçalho da assinatura é configurável.

    Formulário de integração com HMAC-SHA512
  • Um webhook cuja integração pertence a outro projeto é rejeitado.


Observabilidade

  • Métricas do Prometheus. GET /api/metrics atrás de HTTP Basic Auth com uma credencial de serviço estática:

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

    (SEMAPHORE_METRICS_ENABLED, SEMAPHORE_METRICS_USERNAME, SEMAPHORE_METRICS_PASSWORD.) Séries: semaphore_tasks_running, semaphore_tasks_total{status}, os coletores padrão go_* e process_*, e os gauges de exportação de auditoria no Pro.

  • Novos namespaces de depuração extra_vars e runner; a navegação pelo repositório registra a saída do Git em DEBUG.

  • A exportação e a restauração de backups de projeto são registradas.


Segurança

  • Vinculação de identidade pelo id do provedor em vez do e‑mail; verificação de certificado LDAPS ativada por padrão.
  • Variáveis extras fora da linha de comando; segredos criptografados com Vault; Jinja2 nos valores não avaliado.
  • workflow_run_id, workflow_node_id e artifacts forjados são removidos das tarefas enviadas pelo cliente.
  • Rotas de administração protegidas por permissões globais explícitas em vez do flag de administrador; bits de permissão desconhecidos rejeitados; proteção contra escalação de privilégios no gerenciamento de usuários.
  • Seletor de playbook confinado à raiz do repositório (OpenRoot), limitado e filtrado.
  • Raízes das variáveis extras e números YAML validados; argumentos de CLI do Galaxy em lista de permissões.
  • Credenciais de repositório ocultadas nos logs e no feed de eventos; = escapado nos parâmetros de configuração do Git.
  • Os endpoints de auditoria recusam leituras cross‑site e cursores malformados; redes de proxy confiáveis validadas.
  • unregister do runner autenticado; redirecionamentos recusados pelo cliente do runner.
  • Ids de projeto e de integração do webhook verificados.
  • Tarefas locais interrompidas junto com todo o seu grupo de processos.

Notas de atualização

Mudanças incompatíveis e de comportamento

  1. Os nomes dos modelos devem ser únicos por projeto. A migração v2.20.4 adiciona um índice único; renomeie os duplicados antes de atualizar.
  2. As tabelas de roles são reconstruídas (v2.20.12 / v2.20.13). Faça backup primeiro. Um role personalizado cujo slug colida, sem diferenciar maiúsculas, com um role interno ou com outro role é renomeado (registrado em log); as permissões de modelo que apontam para um role não resolvível são descartadas (registrado em log). As associações foram movidas para project__user_role; a coluna project__user.role deixou de existir.
  3. GET /api/project/{id}/users retorna role apenas para membros com um único role — leia roles.
  4. /roles* passou do flag de administrador para a permissão Gerenciar roles globais; os administradores não são afetados.
  5. Os certificados LDAPS são verificados por padrão. Defina ldap_tls_skip_verify ou o tls_skip_verify de um provedor para certificados autoassinados.
  6. O ansible-playbook é invocado de forma diferente: --extra-vars @file, mais um segundo arquivo e um --vault-id <uuid>@prompt quando a tarefa tem segredos, mesmo para modelos sem vault. Qualquer coisa que analise a linha de comando, ou um ansible.cfg que proíba prompts de vault, é afetada.
  7. O Jinja2 dentro dos valores das variáveis extras não é mais avaliado. Um playbook que dependia da renderização de um valor de webhook ou de survey deixará de fazê-lo.
  8. Endpoint de execução de workflow renomeado: POST …/workflows/{id}/run → …/runs.
  9. Repositórios monorepo prevalecem sobre o modelo: sem branch por modelo, sem sobrescrita de branch ou de commit nas tarefas.
  10. O repository_id do inventário é descartado para todos os tipos exceto file.
  11. Interromper uma tarefa local mata o seu grupo de processos (ainda sem equivalente no Windows).
  12. As saídas de workflow ainda não são capturadas pelos executores Docker e Kubernetes; os segredos de survey ainda não chegam a esses executores.

Nova configuração

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 por provedor OIDC, runner.check_interval_seconds, runner.connection.timeout_seconds, runners.{default_global_runners_mode,registration_token}. Todas opcionais. Os campos de configuração do tipo ponteiro agora podem ser definidos por variáveis de ambiente. As páginas de referência de configuração e de CLI são geradas a partir do código‑fonte.

Migrações do banco de dados

v2.20.0 identidades externas · v2.20.1 segredos de survey vinculados à tarefa · v2.20.2 nós de atraso · v2.20.3 diretório de trabalho · v2.20.4 nomes de modelo únicos · v2.20.5 supressão de alertas de erro · v2.20.7 configuração de hosts · v2.20.8 revisões de workflow · v2.20.9–v2.20.11 log de auditoria e índices, mapeamentos de entrada das arestas, flag de monorepo · v2.20.12–v2.20.13 tabelas de roles, variáveis de workflow · v2.20.14 integrações de workflow e mapeamentos de grupo · v2.20.16 roles globais.

Dependências

Go 1.26; imagens Docker em Alpine 3.24; prometheus/client_golang 1.23 adicionado; 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. Novas implantações em um clique: Cloudzy, RepoCloud e Pethost.