工作流
Semaphore 目前将每个任务模板视为独立单元——没有内置方法将多个模板链接成多步骤执行管道。此功能引入工作流——具有条件分支、步骤间变量传递和可选人工审批关卡的任务模板有向无环图(DAG)。设计参考了 AWX Workflow Job Templates、Rundeck 作业工作流以及 Jenkins/GitLab CI 管道概念。
Pro
- 工作流模板 — 引入一个新的顶级实体,定义由带有条件(
on_success、on_failure、always)的有向边连接的任务模板节点 DAG,在项目内实现多步骤自动化管道。(#3182, #2334, #1383, #836) - 工作流执行引擎 — 按拓扑顺序执行工作流节点,遵守边条件并行执行独立分支,对具有多个父节点的节点采用 ALL 收敛。(#2281, #3088)
- 工作流执行面板 — 提供工作流执行的统一视图,显示带有每个节点状态(等待中、运行中、成功、失败、跳过)的 DAG 图、可点击的节点日志和总体时间。
- 节点间变量传递 — 允许任务模板生成输出变量(通过已知文件或 Ansible
set_stats),自动作为额外变量注入到下游节点。(#3182) - 工作流调度和 API 触发 — 支持工作流的 cron 调度、API 触发执行和 webhook 触发,以及工作流级别的可选调查变量。(#3088)
- 可视化工作流编辑器 — 拖拽式图形编辑器,用于在界面中设计工作流,具有实时 DAG 验证、节点定位和边上的条件选择器。
- 节点级覆盖 — 在工作流节点级别覆盖模板的清单、凭据、变量组或 CLI 参数,允许在单个工作流内跨不同环境重用同一模板。
- 审批关卡 — 在指定点暂停工作流执行以等待人工审批,具有可配置的超时、审批者通知以及来自界面或 API 的审批/拒绝操作。
Enterprise
- 工作流 RBAC — 用于创建、编辑、执行和审批工作流的细粒度权限,基于角色的审批关卡分配和审计日志。
- 跨项目工作流 — 在工作流中引用其他项目的任务模板,实现跨基础设施、应用和监控项目的组织级自动化管道。
- 工作流版本控制和回滚 — 维护工作流定义的版本历史(含差异比较),恢复以前的版本,并记录每次运行使用的版本。
LDAP 和 OpenID 组映射
Semaphore 支持 LDAP 和 OpenID Connect (OIDC) 进行认证,但集成仅限于登录——没有基于身份提供商组成员身份的自动角色或项目分配。每个 OIDC/LDAP 用户在首次登录后必须手动分配项目和角色。此外,OIDC 重定向处理、声明解析和 LDAP 配置中存在多个缺陷,导致认证体验不可靠。
Community
- 按声明限制 OIDC 登录 — 仅允许具有特定声明值(例如必需的组成员身份或电子邮件域)的用户登录。(#2626, #2938)
- SSO 自动登录 — 绕过登录页面直接重定向到 OIDC/SSO 提供商,并提供故障恢复 URL 以便在 SSO 不可用时恢复。(#2548, #2899)
- OIDC PKCE 支持 — 按照 RFC 9700 的建议,在 OIDC 授权码流程中添加 Proof Key for Code Exchange。(#3072)
- OIDC 环境变量配置 — 允许通过环境变量而非仅配置文件来配置 OIDC 提供商,简化容器中的密钥管理。(#2528, #3120)
- 修复 web_host/web_root 下的 OIDC 重定向 — 解决 OIDC 登录后当
web_host为空或web_root设置为子路径时的 404 错误。(#2681, #1524, #2532, #3121) - 修复 OIDC 声明处理 — 解决
username_claim被忽略、email声明未被识别以及client_secret_file产生格式错误请求的问题。(#1731, #2818, #3122) - 修复 LDAP 声明表达式 — 解决 LDAP 映射中损坏的模板表达式(例如
mail | {{ .username }}@domain.com解析为<no value>)。(#3127) - 修复 LDAP 用户名分配 — 确保 LDAP 用户获得其实际的 LDAP 用户名,而非随机生成的字符串。(#3688)
- LDAP 本地认证回退 — 允许本地管理员账户在启用 LDAP 时仍然可以登录,防止 LDAP 服务器不可用时被锁定。(#1363)
- LDAP 调试日志 — 添加 LDAP 认证失败的有用日志输出,使故障排查成为可能。(#2932)
- OIDC/LDAP 用户与本地账户关联 — 允许将现有本地账户转换或关联到外部身份提供商,而不创建重复账户。(#3339)
- OIDC 提供商登出 — 在退出 Semaphore 时结束 IdP 会话(例如 Keycloak),实现正确的账户切换。(#1496)
Pro
- 将 LDAP 凭据同步到访问密钥 — 可选地在 LDAP 密码于登录时更改后自动更新访问密钥密码,保持 Ansible 凭据同步。(#3696)
Enterprise
- OIDC 组到角色映射 — 基于 OIDC 声明(例如
groups声明)自动分配 Semaphore 角色和项目成员身份,消除首次登录后的手动用户设置。(#1499, #2483) - LDAP 组到角色映射 — 将 Active Directory / LDAP 组映射到 Semaphore 角色,包括通过组成员身份分配管理员角色。(#3226, #1316)
- 具有 LDAP/OIDC 集成的完整 RBAC — 实现细粒度的基于角色的访问控制(全局管理员、项目管理员、项目用户、只读),并从外部身份提供商组自动分配角色。(#891)
- 可插拔认证架构 — 将认证抽象为提供商接口,以支持多个认证后端并简化添加新提供商的过程。(#465, #1820)
- 修复用户删除留下孤立数据 — 确保删除用户时清理
project__user映射,防止团队视图崩溃。(#3514)
内置清单管理系统
如今,Semaphore 将清单视为不透明的数据块——用户要么将原始 INI/YAML 粘贴到单个文本框中,要么指向仓库中的文件。没有结构化的方法从 UI 添加主机、将主机组织成组或设置主机和组变量。此功能引入内置清单管理系统:一个结构化的、由 UI 管理的清单编辑器(类似于 AWX 清单),其中主机、组和变量是存储在 Semaphore 中并可直接在 Web 界面中编辑的一等对象,同时仍可完全导出为标准 Ansible 清单。
Community
- 结构化的主机和组编辑器 — 通过 UI 管理主机、其地址/别名以及主机组,而非手动编辑原始清单文本框,并支持主机和组的添加/移除/重命名操作。(#836)
- UI 中的主机和组变量 — 为每个主机和每个组将
host_vars和group_vars定义为结构化的键/值对,从而不再需要手动将连接设置和自定义变量嵌入清单正文中。 - 改进的内联清单编辑器 — 用更大的、可调整大小的编辑器替换小型清单文本框,该编辑器具有 YAML/INI 语法高亮和验证,使现有的内联编辑模式真正可用。(#698, #1650)
- 导入现有清单 — 通过导入现有的 INI/YAML 清单文件或粘贴其内容来引导托管清单,将其解析为结构化的主机、组和变量。
- 声明式清单定义 — 通过 Semaphore 管理的 YAML 文档声明式地定义清单(主机、组、变量),实现与项目和模板并列的版本控制、可复现的清单设置。(#3109)
- 导出为标准 Ansible 清单 — 在任务运行时将托管清单渲染为标准 Ansible 清单文件,使 playbook 和
ansible-inventory看到完全相同的结构,无论它是如何编写的。
Pro
- 可复用的主机组 — 一次性定义主机组并在多个清单和项目之间共享,使组成员身份或组变量的更改传播到使用该组的所有位置。
- 清单变更历史 — 为每个清单保留修订历史记录,包含主机、组和变量更改的差异,并允许恢复以前的版本。
Enterprise
- 范围限定的主机管理角色 — 引入一种操作员风格的角色,可以在指定清单中添加、编辑和移除主机(并运行预定义模板),而无需授予完整的项目管理权限。(#2989)
- 清单变更审批 — 要求在对受保护清单的更改生效之前进行审查/审批,并提供审计追踪,记录谁在何时更改了哪个主机、组或变量。
灵活的通知系统
Semaphore UI 中当前的通知系统仅通过 config.json 进行配置,支持有限的渠道(电子邮件、Telegram、Slack、MS Teams),并在全局级别运行,每个项目的自定义选项极少。此功能从头开始重新设计通知,使其可通过 UI 管理、可扩展,并可在项目和模板粒度上进行配置。
Community
- 可扩展的渠道架构 — 为通知渠道定义通用接口,并针对每个渠道实现,使添加新渠道变得简单而无需修改核心逻辑。考虑采用通用通知库(例如
nikoksr/notify)或网关(例如 Apprise)来一次性覆盖多个提供商。(#2325, #1290) - UI 管理的通知配置 — 将通知设置从配置文件移至 Web UI,支持按项目和按模板粒度配置,并支持同一渠道类型的多个实例。(#3387, #1821, #3588)
- 基于模板的消息自定义 — 支持用户自定义的消息模板,以文件形式存储在磁盘上而非数据库中。
- 按项目选择渠道 — 允许用户通过项目设置按项目配置哪些通知渠道处于活跃状态。(#3588)
- 出站 Webhook 事件 — 定义事件类型(START、SUCCESS、FAILURE),并允许按项目创建具有可配置 URL、请求头和 HMAC 认证的 Webhook 模板。(#1825, #2594, #3066)
- 新通知渠道 — 添加对 Discord (#2924)、Ntfy (#3383)、Google Chat (#1148)、Rocket.Chat (#1091) 和 Pushover (#2594) 的支持。
- "已修复"通知 — 在失败后首次成功运行时发送通知,类似于 GitLab CI 恢复告警。(#3380)
- 按模板禁用所有通知 — 在现有的"禁用成功通知"复选框旁添加"禁用所有通知"选项。(#3724)
- 成功时发送电子邮件 — 在成功通知路径中加入电子邮件(目前仅 Telegram/Slack/MS Teams 在成功时触发)。(#3503)
- 修复通知中的任务 URL — 确保所有渠道(电子邮件、Slack、MS Teams)收到带有协议和主机名的完全限定任务 URL,而非相对路径。(#2097, #2311, #3292)
- 修复电子邮件发送问题 — 解决 SMTP 端口 465(隐式 TLS)支持、auth-before-TLS 排序和 Date 头格式问题。(#2201, #2971, #3542, #3209)
- Telegram 话题/主题支持 — 允许通过
message_thread_id向特定 Telegram 群组话题发送通知,可按项目和模板配置。(#3493, #1456) - Slack 模板改进 — 暴露顶级字段(
title、text、color)以兼容 Slack Workflow Builder。(#2607) - 告警代理支持 — 允许为出站通知请求配置 HTTP 代理,而无需系统级代理。(#1484)
Pro
- Pro 专属通知渠道 — 在 Pro 计划中支持特定的独占通知渠道。
- 长时间运行任务告警 — 当任务超过可配置的持续时间阈值时触发通知。(#1393)
Enterprise
- 通知审计日志 — 维护所有已发送通知的可搜索日志,包含投递状态、时间戳和收件人详细信息。改进错误日志以包含失败时的收件人上下文。(#3410)
- 与事件管理平台集成 — 与 PagerDuty、Opsgenie 和 ServiceNow 的原生集成,用于自动创建事件和生命周期跟踪。
- 基于角色的通知访问控制 — 根据组织角色和权限限制谁可以配置通知规则和渠道。
用户自有密钥
Semaphore 的密钥库目前在所有项目成员之间共享。任何具有项目访问权限的用户都可以使用(在某些情况下还可以查看)所有存储的凭据。这在多用户环境中造成安全隐患,因为团队成员应只能访问自己的凭据。此外,密钥库在加密、密钥更新和引用完整性方面存在多个缺陷,并且缺乏与外部密钥管理系统的集成。
Community
- 个人密钥库 — 提供按用户的密钥库,使个人凭据(SSH 密钥、sudo 密码)与其他项目成员隔离,不通过项目级密钥库共享。(#1483, #1373)
- 修复密钥更新行为 — 解决编辑密钥环境变量看似成功但值实际未持久化的问题。(#2546)
- 从进程列表中隐藏密钥 — 停止通过操作系统进程列表中可见的命令行参数传递密钥 extra-vars;改用安全机制(例如临时文件、stdin)。(#3219)
- 密钥库中的 SSH 证书支持 — 允许在密钥库中将 SSH 证书与 SSH 密钥一起存储,以支持基于证书的认证工作流。(#3171)
- 显示 SSH 公钥 — 在密钥库 UI 中显示已存储 SSH 密钥的公钥部分,方便使用。(#1643)
- Docker 密钥支持 — 支持
_FILEenv var 模式(例如POSTGRES_PASSWORD_FILE),使 Docker/Kubernetes 密钥可以挂载并读取,而非通过环境变量传递。(#1268) - 修复 Docker 中的加密密钥处理 — 确保
SEMAPHORE_ACCESS_KEY_ENCRYPTIONenv var 被正确使用,不会在容器重启时被随机密钥覆盖。(#2228, #3068, #3204) - 修复密钥库重命名导致引用断裂 — 解决重命名密钥库条目会破坏所有关联清单和模板的问题。(#3188)
- 修复 Vault 密码 API — 允许通过 REST API 设置和更新 Ansible Vault 密码,不再出现重复键约束错误。(#3413, #2773)
Pro
- 外部密钥存储集成 — 在运行时从 HashiCorp Vault、Azure Key Vault、AWS KMS 或 Bitwarden 拉取密钥,而非存储在 Semaphore 的数据库中。(#2248, #658)
Enterprise
- 全局访问密钥 — 通过集中管理和跨项目链接,跨项目共享密钥库条目而无需重复。(#110)
- 密钥访问审计追踪 — 记录密钥库条目和密钥变量的所有访问和使用情况,用于合规性和取证。
requirements.yml 的凭据 阅读
Ansible playbook 经常在 requirements.yml 中声明位于私有 Git 仓库中的私有角色和集合。Semaphore 目前没有一等的方法来针对这些仓库对 ansible-galaxy install 进行认证——用户只能将令牌嵌入 URL、将 SSH 密钥烘焙到运行器镜像中,或维护自定义准备脚本。此功能允许用户将一个或多个密钥库凭据附加到任务模板(或 playbook 运行),并在解析角色和集合的准备阶段自动使用它们。
Community
- 将凭据附加到 playbook 运行 — 允许在任务模板上选择一个或多个密钥库条目(SSH 密钥、Git 令牌、用户名/密码),并在
ansible-galaxy install期间应用,以便可以从私有 Git 仓库拉取requirements.yml中列出的私有角色和集合。(#3677, #3708, #897) - 按主机模式的凭据映射 — 当附加多个凭据时,将它们映射到主机名模式(例如
github.com、gitlab.internal),使每个私有源使用正确的密钥或令牌而不发生冲突。(#3677) - 修复环境变量传播到 galaxy install 阶段 — 确保环境变量(包括密钥变量)在
ansible-galaxy install期间导出,而不仅仅在 playbook 执行期间,使基于令牌的认证适用于requirements.yml。(#2966, #3178) - 按 playbook 的 requirements 文件 — 允许在模板级别覆盖默认的
roles/requirements.yml/collections/requirements.yml路径,适用于将多个具有不同依赖集的 playbook 分组的项目。(#1366) - 自定义
ansible-galaxyCLI 参数 — 暴露一个字段,用于传递给ansible-galaxy install的额外参数(例如--ignore-certs、--force、自定义服务器),覆盖隔离网络和内部 Galaxy 镜像设置。(#2348)
持久化仓库缓存
目前,Semaphore 会为每个任务模板将仓库克隆(或拉取)到单独的目录中,这对于大型仓库来说速度较慢,并且浪费磁盘 I/O。此功能为每个仓库添加一个标志,切换为共享的持久化克隆,该克隆在后台定期更新——类似于 AWX 处理项目更新的方式。启用后,引用该仓库的所有模板共享一个工作副本(与 Semaphore 中本地仓库已有的模型相同),单个任务运行不再触发克隆或拉取。
Community
- 仓库设置中的"缓存仓库"标志 — 为每个仓库添加一个开关,启用后保留单个持久化克隆,而不是每次任务运行时都进行克隆。该克隆在使用该仓库的所有模板之间共享,与本地仓库已有的行为一致。(#1212)
- 后台定期同步 — 启用缓存标志后,在后台工作线程中按可配置的间隔(例如每 5 分钟)拉取更新,而不是在任务启动时拉取,这样任务总是能够立即针对最近的检出启动。
- 手动同步操作 — 在仓库 UI 中提供"立即同步"按钮以及相应的 API 端点,以便在定期计划之外触发即时拉取。
- 强制推送/历史重写容错 — 优雅地处理上游强制推送(例如
git fetch --all && git reset --hard origin/<branch>),而不是在正常拉取时失败。(#800) - 脏工作树恢复 — 在拉取之前自动检测并清理脏工作树(例如残留的
.retry文件),防止"本地更改"错误。(#308) - 过期克隆清理 — 对已删除或 URL 已更改的仓库的缓存克隆进行垃圾回收,回收磁盘空间。(#1497, #2679)
- 同步状态可见性 — 在仓库详情页面显示上次同步的时间戳和状态(成功/失败),以便用户了解工作副本的新鲜程度。
- 按仓库同步计划 — 允许在单个仓库上覆盖全局同步间隔(例如高频变更仓库每分钟同步,稳定仓库每小时同步)。
每个模板多个清单
Ansible CLI 原生支持传递多个 -i 参数来组合清单(例如 ansible-playbook -i common_vars.yml -i staging_hosts.yml)。Semaphore 目前将每个任务模板限制为单个清单,迫使用户采用清单脚本、合并文件或额外环境变量等变通方法。此功能取消了该限制,并解决了更广泛的清单管理问题。
Community
- 多清单支持 — 允许将多个清单附加到单个任务模板,作为顺序
-i参数传递给 Ansible(例如ansible-playbook -i common_vars.yml -i staging_hosts.yml)。解决了每个模板只能使用一个清单的限制。(#2093) - 可选清单字段 — 对于
ansible.cfg已指定清单来源的情况,使模板上的清单字段变为可选。(#1574) - URL/HTTP 清单来源 — 支持从远程 URL 或 API 端点获取清单,这对于没有文件系统访问权限的托管/SaaS 环境至关重要。(#1924)
- 运行时清单选择 — 允许用户在任务启动时通过下拉菜单选择清单,取代当前的自由文本变通方法。(#1354)
- 修复计划任务清单持久化 — 确保在计划对话框中选择的清单被保存并在执行时使用,而不是回退到模板默认值。(#3566, #3293)
- 修复项目导出/恢复丢失清单仓库链接 — 清单到仓库的关联在项目导出时被丢弃,导入时未恢复。(#3369, #3177)
- 将环境变量传递给动态清单 — 确保容器/主机环境变量可供动态清单脚本和插件使用(例如 Python 脚本、
microsoft.ad.ldap)。(#2724, #2783) - 修复基于 git 的清单认证 — 在获取远程分支用于清单时使用仓库凭据,修复未认证的访问尝试。(#3539)
- 按主机覆盖凭据 — 停止使用全局
--extra-vars覆盖清单中定义的按主机ansible_user和连接变量。允许多用户清单模式。(#1464, #1621) - 在 UI 中查看清单内容 — 在 UI 中显示基于文件的和动态清单内容以供检查和调试,并提供指向外部仓库中源文件的链接。(#3169, #1555, #3543)
- 在任务上下文中暴露清单名称 — 使清单名称在
semaphore_vars中可用或作为环境变量,以便 playbook 可以引用当前活跃的清单。(#1580)
Pro
- 清单到运行器的亲和性 — 将清单主机与运行器标签关联,以便任务仅被分派到对目标主机具有网络访问权限的运行器,避免多网络环境中的故障。(#3322)
- 每个清单多个 SSH 密钥 — 允许为单个清单分配多个密钥库条目,适用于每台主机使用唯一 SSH 密钥的集群。(#3336)
- 虚拟化平台清单集成 — 与虚拟化平台 API(VMware、Proxmox)原生集成,自动生成和刷新动态清单。(#2709)
- 主机组管理 API — 提供 API 用于在清单组中添加/移除主机,而无需重写整个清单数据。(#1560)