
Semaphore UI 2.20 新增了带 SIEM 导出的审计日志,把工作流发展为真正的流水线引擎 —— 支持延迟节点、修订版本、在任务间传递的输出以及工作流变量;重构了角色,使一位成员可以持有多个角色,管理员也获得了实例级角色和 IdP 组映射;引入了用于逐主机配置 SSH 和 Git 凭据的主机配置;把每一个 Ansible 额外变量都移入Vault 加密的文件;并对外暴露了 Prometheus 指标。
本系列从 v2.20.0 开始。补丁版本会在发布时列于本页末尾。
亮点
- 审计日志 — 谁、从哪里、做了什么、结果如何;提供管理员界面、保留策略,以及面向 SIEM 的 Syslog / Splunk HEC 导出(导出和过滤为 Pro 功能)。
- 工作流 — 延迟节点、与运行绑定的不可变修订版本、作为下一个任务输入交付的输出、在运行对话框中询问的工作流变量、带快捷键和撤销的重新设计编辑器,以及可启动工作流的 webhook。
- 每位成员可拥有多个角色,角色带有 id 和 slug,全局角色可授予实例级权限 (Pro),并支持在登录时应用的 IdP 组 → 角色映射 (Enterprise)。
- 外部身份 — LDAP 和 OIDC 登录通过提供者的稳定 id 绑定到账户,而不再通过电子邮件;同一登录页可以展示多个 LDAP 目录。
- 主机配置 — 把 SSH 主机和 Git URL 映射到项目凭据,并应用于克隆、Galaxy、Terraform 模块和 Ansible。
- Ansible 额外变量不再出现在命令行上;密钥通过 Ansible Vault 加密的文件传递,值中的 Jinja2 也不再被求值。
- 模板:Ansible 工作目录、唯一名称以及任务 API 中的
template_name、可抑制的错误通知、可隐藏的 Dry Run / Diff、Galaxy 安装选项、多选调查变量、可传达到远程 runner 的调查密钥。 - Monorepo 仓库在多个模板之间共享同一份检出;Git 重试、并行子模块拉取、SSH 主机密钥校验。
- 位于
/api/metrics的 Prometheus 指标。 - 在服务端生成 SSH 密钥对,并可从密钥库复制公钥。
审计日志

Semaphore 现在会把与安全相关的事件记录到一个专用的仅追加日志中。通过以下配置启用:
"audit": {
"enabled": true,
"instance_id": "semaphore-prod"
}
(SEMAPHORE_AUDIT_ENABLED、SEMAPHORE_AUDIT_INSTANCE_ID;instance_id 为必填项,用于在每个事件中标识该安装实例。)
记录的内容。 八个类别中的 116 种事件类型:auth(登录、登出、MFA、API 令牌拒绝、被拒请求、CSRF 拦截)、iam(用户、密码、API 令牌、身份、成员关系、角色、模板权限)、resource(项目、备份、清单、仓库、模板、计划任务、集成、主机配置、工作流、变量组)、secret(凭据和密钥存储)、task(带触发来源的启动、带结果和耗时的完成、审批、停止、历史删除)、runner(注册、变更、被拒报告)、system(设置、许可证),以及 audit 自身(启动、保留、导出)。密码、令牌、密钥值、任务输出和变量永不写入。
事件信封。 每个事件都携带一个 UUID、一个无间断的序列号、一个微秒级 UTC 时间戳、操作者(用户 / 匿名 / 系统 / runner / 集成,附带会话或 API 令牌认证方式以及令牌指纹)、来源 IP 和 User‑Agent、目标、项目、请求 id(同时在 X-Request-ID 响应头中返回)、实例 id 和 HA 节点 id。结果为 success 或 failure,失败原因取自一个封闭列表;对象已保存但后续步骤失败的操作记为成功并带 partial = true。在反向代理之后,只有来自 audit.trusted_proxy_cidrs 的 X-Forwarded-For 才被信任。

管理员界面。 用户菜单中的 Audit log(/audit-log)按时间从新到旧列出事件,每页 50 条,提供 Older / Newer 翻页;点击一行会打开一张卡片,包含 Who、Object、Where、When、Details 和 Technical 等区块,以及一个把事件按发送给 SIEM 的 JSON 格式复制出来的按钮。访问需要新增的 Read the audit log 全局权限。
保留策略。 audit.retention_days 会分批删除更早的事件,每小时执行一次并带抖动,以免 HA 节点互相冲突;每一次删除了内容的清理本身也会被记录。
Pro:过滤与导出。 按时间段、用户、项目、事件类型、结果和 IP 过滤;从任意卡片值快速下钻;把当前选择导出为 CSV 或 JSON Lines。
Pro:SIEM 导出。 两种目标,各有自己的游标,因此接收端故障时不会跳过任何内容:通过 audit.syslog 的 TLS 上的 Syslog(RFC 5424,事件 JSON 作为消息体),以及通过 audit.splunk_hec 的 Splunk HTTP Event Collector(url、token、index、source、sourcetype、ca_file,……)。投递至少一次,并按序列号排序;在 HA 中每个目标只有一个节点负责导出,通过 Redis 租约协调。三个 Prometheus 指标序列描述该导出器:semaphore_audit_export_pending_events、semaphore_audit_export_oldest_pending_seconds 和 semaphore_audit_export_errors_total。
存储:audit_event、audit_event_sequence、audit_export_state 表(迁移 v2.20.9 到 v2.20.11)。API:GET /api/audit/events 和 GET /api/audit/events/export。
工作流
工作流是 Pro 功能;Beta 标记已移除。
延迟节点
继任务、审批和注释之后的第四种节点类型:延迟节点会把运行暂停若干秒,然后释放其出边。运行视图会在卡片上显示实时倒计时;停止运行会取消延迟。字段 delay_seconds,迁移 v2.20.2。
修订版本
每次保存工作流都会创建图的一个新修订版本;一次运行会固定它启动时所用的修订版本,因此编辑工作流永远不会改变正在进行的运行,也不会让过往运行的节点失去归属。编辑器会显示一个 rev. N 标签以及仍在执行较旧修订版本的运行数量;运行视图会显示它所执行的修订版本。保存更新的修订版本时,没有任何运行引用的修订版本会被删除。API:GET …/workflows/{id}/revisions 和 …/revisions/{revision_id}。
输出与输入

一个任务可以把结构化数据交给其后的节点。由工作流启动的每个任务都会获得 SEMAPHORE_OUTPUTS_FILE;它写入其中的任何 JSON 对象都会成为该任务的输出:
cat > "$SEMAPHORE_OUTPUTS_FILE" <<EOF
{"image_tag": "1.4.2", "replicas": 3, "subnet_ids": ["subnet-1", "subnet-2"]}
EOF
Ansible 通过内置的回调插件以 ansible.builtin.set_stats 产生输出;Terraform、OpenTofu 和 Terragrunt 的输出会自动从 output -json 中捕获(sensitive 值会被跳过,并标记为 Not captured)。只有任务成功时才会读取输出;限制为 100 个输出、每个 32 KB、每个文件 256 KB。
一条进入任务节点的连接会交付输入 —— 它用源节点的输出填充目标模板的调查变量:
- 按名称(默认):名称与某个调查变量相同的每个输出都会填充该变量。
- 显式映射输入:列出要交付的
variable ← output key对;一旦工作流有过一次完成的运行,面板就会提示该次运行产生的键。

值会被强制转换为变量类型,审批节点和延迟节点会把输出透传,显式映射优先于按名称交付,而一个必填变量若没有取到值,会在节点的任务启动前就使其失败,从而让运行沿着 失败时 的边继续。运行视图会为每个节点显示一个 N outputs 徽标,任务对话框中有一个输出表格,任务日志开头会为每个已交付的值打印一行 Input "x" <- output "y" of node N。输出以明文存储,永不填充 secret 变量;secret 不能通过输出传递。远程 runner 上的任务既能产生也能接收输出;Docker 和 Kubernetes 执行器尚不捕获输出。

工作流变量与运行对话框
工作流拥有自己的调查变量,在运行启动时通过一个 Run “…” 对话框一次性询问(没有变量的工作流会像以前一样立即启动)。答案存储在该次运行上,以标签形式显示在运行画布上方的变量条中,并且只能通过节点面板中的显式绑定到达任务 —— 工作流变量永远不会按名称泄漏进模板。不允许把密钥用作工作流变量。POST …/workflows/{id}/runs 接受 {"environment": {"image_tag": "1.4.3"}};与类型不符的答案或缺失的必填值会导致启动被拒绝。
工作流任务的环境
由工作流启动的每个任务都会收到 SEMAPHORE_WORKFLOW_ID、SEMAPHORE_WORKFLOW_RUN_ID、SEMAPHORE_WORKFLOW_URL(需要 web_host)和 SEMAPHORE_OUTPUTS_FILE,对所有应用以及远程 runner 均适用。
重新设计的编辑器

- 新的节点卡片带有类型图块、状态、耗时、输出徽标以及内联的 Approve / Reject;边标签带有就地条件下拉框和删除按钮;画布采用点阵网格。
- 快速添加菜单,可从节点的
+把手、画布上的右键菜单或空状态按钮打开:可搜索的节点类型与任务模板列表,新节点会以 成功时 连接。 - 撤销 / 重做(
Ctrl/⌘+Z、Ctrl/⌘+Shift+Z)、工作流的内联重命名、可定位到出错节点的 Problems 菜单、提示未保存更改的 Save 徽标,以及离开页面的保护提示。 - 画布上的快捷键:方向键平移(按
Shift为大步长)、+/-缩放、0适应图形、1重置缩放、Esc清除选择;节点卡片支持键盘聚焦。 - 浮动控件:放大 / 缩小、适应视图、Tidy up 自动布局、缩放百分比。
- 一个折叠箭头可同时折叠面板和主导航;该状态会被记住。
- 触控板的过度滚动不再在 macOS 上触发浏览器的返回手势。

Webhook 启动工作流
集成现在可以运行工作流而不是模板(集成表单中的 Runs: Template / Workflow)。每个提取出的值都会成为工作流调查的一个答案。管理这类集成需要 Pro 的 workflow_integrations_management 功能。对于模板集成,若提取出的 Task Params 值名为 git_branch,则在模板允许覆盖时会设置所启动任务的分支。
API 变更
POST …/workflows/{id}/run 已重命名为 POST …/workflows/{id}/runs,并接受 environment 请求体。运行详情会携带 revision_id、revision、每个节点的 delay 对象以及 task.artifacts。任务上由客户端提供的 workflow_run_id、workflow_node_id 和 artifacts 会被忽略,因此一个任务无法冒充他人运行中的节点。
角色与访问控制
每位成员可拥有多个角色

项目成员持有一组角色,在团队页面上以标签形式编辑。API 在旧的 role 之外还接受 roles: ["manager", "release_approver"];响应只对单角色成员保留标量 role。非管理员无法从最后一位所有者手中拿走内置的 Owner 角色。
带 id、slug 和作用域的角色
角色现在是带整数 id 和 slug(^[A-Za-z0-9_-]{1,100}$,由表单中的名称派生)的数据行;四个内置角色也是数据行,不再能被自定义角色遮蔽。角色具有作用域:内置、共享(可在任意项目中使用)或项目级。删除正在使用的角色会返回 409 并附带其影响范围(成员、项目、模板权限、映射),可以带 ?force=true 重试 —— 即 UI 中的 Delete with assignments。迁移 v2.20.12 和 v2.20.13 会重建角色表;参见升级说明。
全局角色与权限 (Pro)

实例级权限不再只有管理员标志。一个全局角色授予由四项权限组成的掩码 —— Manage users、Manage global roles、Manage system settings、Read the audit log —— 并在用户页面的 Roles 标签页(/users/roles)以及用户对话框的 Global roles 标签页中分配给用户,后者还会显示生效的权限以及各项权限由哪个角色授予。每个管理路由都由这四个位之一守护;GET /api/user 会返回 global_permissions。实例始终至少保留一位管理员,这通过一个在 HA 节点间也安全的行锁来强制保证。拥有 Manage users 的用户无法编辑管理员,也无法编辑任何持有其所不具备权限的人。API:/api/global-roles、/api/users/{id}/global-roles、/api/users/{id}/global-permissions,权限目录位于 /api/global-roles/permissions。
组角色映射 (Enterprise)

在新的组映射页面(/role-mappings)把身份提供者的组映射到项目角色:提供者、组、项目、角色。每次 OIDC 登录时,用户的映射角色都会与令牌中的组(提供者的 groups_claim)保持一致。映射得到的角色在团队页面上显示为带 provider: group 提示的锁定标签,无法作为成员角色移除;映射角色不计入项目的最后一位所有者。密码或 LDAP 登录会清除映射角色,因为它们不带组信息。API:/api/role_mappings。
认证与身份

- 外部身份。 LDAP 和 OIDC 登录通过提供者的稳定 id(OIDC 的
sub、LDAP 的 DN)绑定到 Semaphore 账户,记录在新的user__external_identity表中,而不再通过电子邮件。这就消除了这一类缺陷:接受任意输入地址的 IdP 会接管别人的账户。external_auth_email_matching(默认auto,另有always、never)控制一个尚无身份的既有外部用户是否仍可按电子邮件匹配一次;本地密码账户永不会被接管。只有当email_verified为真且提供者设置了require_verified_email时,OIDC 电子邮件才会被采纳。用户可以自行在账户对话框中关联和解除关联身份(/api/users/{id}/identities、POST /api/user/identities/ldap、/api/auth/oidc/{provider}/login?link=1)。 - 多个 LDAP 目录。
ldap_providers是一个按名称索引的目录映射,每个目录都有自己的服务器、绑定、搜索、映射、颜色和顺序;旧的扁平ldap_*配置块继续作为名为ldap的提供者生效。登录页在标签页多于一个时会显示切换器,而内部标签页永远不会把密码发送给某个目录。GET /api/auth/login会返回ldap_providers和login_with_password。 - LDAPS 证书默认会被校验。 对于自签名证书,请设置
ldap_tls_skip_verify(扁平配置块)或tls_skip_verify(按提供者)。 - 会话绝对生命周期。
auth.max_session_life_hours(SEMAPHORE_AUTH_MAX_SESSION_LIFE_HOURS)会在登录后固定时间使会话过期,无论其活跃情况;0表示只保留不活跃超时。 - 没有项目且无权创建项目的用户会看到 No projects yet 页面,而不是一个他无法提交的表单;此时
POST /api/projects会返回403。 - 在用户菜单中选择的语言会存储在服务端,并随用户跨浏览器生效(
/api/user/options中的lang)。
主机配置

新的项目页面主机配置把 SSH 主机和 Git URL 映射到项目凭据:
- Host 映射(
bastion.example.com)关联一个 SSH 密钥,表现为生成的ssh_config中的一个Host块; - URL 映射(
https://github.com/acme/,以/结尾的前缀可覆盖整个组)关联一个 SSH 密钥或一组登录名/密码(仅限 HTTPS),表现为 Git 的insteadOf重写;最具体的 URL 优先。
映射会应用于模板仓库及其子模块、requirements.yml 中的角色和集合、terraform init 的模块、由 playbook 运行的 git 命令、清单仓库和清单主机,以及分支与 playbook 浏览;它们也会下发到远程 runner。私钥永不落盘 —— 每个映射一个 SSH agent,通过 IdentityAgent 绑定;密码通过 GIT_CONFIG_PARAMETERS 传递,仓库 URL 在任务日志中会被脱敏。被映射引用的密钥无法删除。映射也是项目备份的一部分。需要 git_client: cmd_git。表 project__host_config,迁移 v2.20.7;API /api/project/{id}/host_configs。
模板与任务

-
Ansible 工作目录。 Different working directory 会从仓库的某个子目录运行
ansible-playbook;该路径必须位于检出目录内(working_directory,迁移v2.20.3)。 -
模板名称在项目内唯一(迁移
v2.20.4),并且POST /api/project/{id}/tasks可以接受template_name代替template_id。 -
按模板抑制错误通知,与既有的成功通知抑制并列;电子邮件告警首次同时遵循这两项设置(
suppress_error_alerts,迁移v2.20.5)。 -
按模板从任务对话框中隐藏 Dry Run / Diff;服务端也会停止为该模板附加
--check/--diff(task_params.hide_dry_run、hide_diff)。 -
Galaxy 安装选项 —— 一个可折叠的区块,包含 Skip Galaxy install、分别用于
ansible-galaxy role install和collection install的 CLI 参数(采用标志白名单;--token、--api-key和路径类标志会被拒绝),以及按任务覆盖的提示。 -
Playbook 选择器会在输入时列出子目录,并按应用过滤(Ansible 为
.yml,Terraform / OpenTofu / Terragrunt / Pulumi 为顶层目录,另有.sh、.py、.ps1),跳过 Ansible 布局目录和点目录,最多 30 条,并且只在限定于仓库根目录的浅克隆中浏览。 -
多选调查变量 —— 新的
select类型接受多个值,在任务对话框中以标签形式渲染;default_value可以是数组。
-
调查密钥可传达到远程 runner。 过去
secret类型的调查答案到达 runner 时是空的。现在它会作为与任务绑定的访问密钥加密存储(access_key.task_id、expire_at,迁移v2.20.1),由为该 runner 提供服务的任一 HA 节点解密,任务结束时删除,并每小时清扫一次;它对密钥库、备份和密钥 API 均不可见。 -
YAML 额外变量。 变量组编辑器新增了 Table | JSON | YAML 切换和全屏编辑器;转换是严格的(日期保持为字符串,非对象根和非有限数值会被拒绝)。存储方式未变。

-
任务页面会显示并链接到启动该任务的计划任务或集成,并把已删除的来源标记为
#id (deleted)。复制日志时不再选中日志时间戳。 -
计划任务会在保存前由服务端校验表达式,因此
@hourly也被接受,并且时区提示条可以关闭。
-
停止本地任务会终止其整个进程组:先
SIGTERM,15 秒宽限期后再SIGKILL;被遗弃的ssh或提供者进程不再比任务活得更久。被停止的 Terraform plan 不再继续执行;在SIGTERM下以0退出的 plan 不会被当作成功。 -
清单的
repository_id只对file类型保留,并且必须属于该项目。 -
服务器日志会在 Task added to queue / Task started 条目中标明用户。
密钥与 Ansible Vault
-
额外变量通过文件传递,而不是命令行。 变量组、调查答案、工作流输入和任务详情会被写入一个权限为
0600的 YAML 文件,并以--extra-vars @file传入。密钥 ——secret类型的调查答案和变量组密钥 —— 会进入第二个文件,由原生 Go 实现以 Ansible Vault 1.1 / AES‑256 格式加密(无需ansible-vault二进制文件),并通过回答ansible-playbook的--vault-id <uuid>@prompt使用一次性密码解锁。无论是这些值还是该密码都不会出现在ps中,任务结束时两个文件都会被删除。 -
值中的 Jinja2 是数据,不是代码。 每个包含
{{、{%、{#或#jinja2:头的字符串都会被递归地标记为!unsafe,因此像{{ lookup('pipe', 'id') }}这样的调查答案会按字面量传递。不含分隔符的字符串是有意不加标记的:ansible‑core ≥ 2.19 会重新解析!unsafe标量,那会把"2026.08"变成浮点数。 -
新的
extra_vars调试命名空间(SEMAPHORE_DEBUG_FILTER=extra_vars)会记录变量是如何拆分和写入的 —— 只记录名称、文件和大小,永不记录值。 -
在服务端生成 SSH 密钥对。 密钥库中的 Generate SSH Key 会创建一个 RSA 密钥;公钥与该密钥一起保存,可通过 Show / Hide 查看并有复制按钮,创建后还会立即在对话框中提供(
generate_ssh_key)。
-
更新密钥时,只有设置了 Override 才会写入
type、secret和公钥部分,因此客户端无法在不替换密钥值的情况下改变密钥的载荷。 -
从服务器环境变量或
dirs.secrets下的文件读取凭据的方式现在已有文档说明(密钥库表单的 Env / File 标签页)。
仓库与 Git
- Monorepo:所有模板共用一次检出。 一个仓库选项会只克隆仓库一次并在多个模板之间共享,而不是为每个模板各复制一份;检出目录在 fetch 和 pull 期间加锁,之后任务便可并行运行。这类仓库的模板不能拥有自己的分支,其任务也不能覆盖分支或提交(
monorepo,迁移v2.20.11)。 - Git 重试。
clone和pull会以指数延迟重试,上限为一分钟;git_attempts(SEMAPHORE_GIT_ATTEMPTS,默认4)。 - 并行子模块。
git_submodule_jobs(SEMAPHORE_GIT_SUBMODULE_JOBS,默认4)会作为--jobs传入。 - SSH 主机密钥校验。 新增
ssh配置区块:config_path、known_hosts_file(SEMAPHORE_SSH_KNOWN_HOSTS_FILE)和strict_host_key_checking—— 取值no(默认)、yes或accept-new—— 应用于 SSH 上的 Git。 - 浏览仓库使用按分支作键的浅克隆;裸机克隆的凭据会进行百分号编码,并在日志和事件流中脱敏。
Runner 与集成
-
runner.check_interval_seconds(SEMAPHORE_RUNNER_CHECK_INTERVAL_SECONDS,默认5)设置 runner 的轮询频率;Runner 页面上的 Advanced options 开关会把它写入生成的环境变量、配置和 Docker 代码片段(随v2.19.17发布)。 -
runner.connection.timeout_seconds(SEMAPHORE_RUNNER_CONNECTION_TIMEOUT_SECONDS,默认3)分别限制连接、TLS 握手和响应头的耗时;日志上传不会被中断。 -
runners.default_global_runners_mode(SEMAPHORE_DEFAULT_GLOBAL_RUNNERS_MODE:disable、prefer、require)取代了已弃用的use_remote_runner;runners.registration_token取代了顶层的runner_registration_token。 -
SEMAPHORE_DEBUG_FILTER=runner下的服务端 runner 诊断:令牌拒绝原因、重启与上线检测、被拒的进度报告、派发追踪。 -
Runner 的
unregister请求会被认证;runner 客户端拒绝 HTTP 重定向。 -
在既有的 HMAC‑SHA256 之外新增 HMAC‑SHA512 webhook 认证(
hmac-sha512);签名头可配置。
-
集成属于其他项目的 webhook 会被拒绝。
可观测性
-
Prometheus 指标。
GET /api/metrics,受 HTTP Basic Auth 和一组静态服务凭据保护:"metrics": { "enabled": true, "username": "prometheus", "password": "…" }(
SEMAPHORE_METRICS_ENABLED、SEMAPHORE_METRICS_USERNAME、SEMAPHORE_METRICS_PASSWORD。)指标序列:semaphore_tasks_running、semaphore_tasks_total{status}、标准的go_*和process_*采集器,以及 Pro 中的审计导出计量值。 -
新增调试命名空间
extra_vars和runner;浏览仓库会在 DEBUG 级别记录 Git 输出。 -
项目备份的导出和恢复都会被记录。
安全
- 按提供者 id 而非电子邮件关联身份;LDAPS 证书校验默认开启。
- 额外变量不再出现在命令行上;密钥经 Vault 加密;值中的 Jinja2 不再被求值。
- 从客户端任务中剥离伪造的
workflow_run_id、workflow_node_id和artifacts。 - 管理路由由显式的全局权限守护,而不是管理员标志;未知的权限位会被拒绝;用户管理上增加了权限提升防护。
- Playbook 选择器被限制在仓库根目录内(
OpenRoot),并有数量上限和过滤。 - 额外变量的根和 YAML 数值会被校验;Galaxy CLI 参数采用白名单。
- 仓库凭据在日志和事件流中脱敏;Git 配置参数中的
=会被转义。 - 审计端点拒绝跨站读取和格式错误的游标;受信任代理网段会被校验。
- Runner 的
unregister会被认证;runner 客户端拒绝重定向。 - 校验 webhook 的项目和集成 id。
- 本地任务会连同整个进程组一起停止。
升级说明
破坏性变更与行为变更
- 模板名称在项目内必须唯一。 迁移
v2.20.4会添加唯一索引;请在升级前重命名重复项。 - 角色表会被重建(
v2.20.12/v2.20.13)。请先备份。slug 与内置角色或其他角色不区分大小写冲突的自定义角色会被重命名(并记录日志);指向无法解析的角色的模板权限会被丢弃(并记录日志)。成员关系已迁移到project__user_role;project__user.role列已移除。 GET /api/project/{id}/users只对单角色成员返回role—— 请读取roles。/roles*已从管理员标志改为由 Manage global roles 权限控制;管理员不受影响。- LDAPS 证书默认会被校验。 对于自签名证书,请设置
ldap_tls_skip_verify或某个提供者的tls_skip_verify。 ansible-playbook的调用方式已改变:使用--extra-vars @file;当任务含有密钥时,还会追加第二个文件和--vault-id <uuid>@prompt,即使模板没有 vault 也是如此。任何解析该命令行的程序,或禁止 vault 提示的ansible.cfg,都会受到影响。- 额外变量值中的 Jinja2 不再被求值。 依赖对 webhook 或调查值做模板渲染的 playbook 将不再生效。
- 工作流运行端点已重命名:
POST …/workflows/{id}/run→…/runs。 - Monorepo 仓库会覆盖模板设置:没有按模板的分支,任务中也不能覆盖分支或提交。
- 清单的
repository_id对除file以外的所有类型都会被丢弃。 - 停止本地任务会杀死其进程组(Windows 上暂无对应实现)。
- Docker 和 Kubernetes 执行器尚不捕获工作流输出;调查密钥也尚未传达到这些执行器。
新增配置
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、按 OIDC 提供者的 groups_claim 和 require_verified_email、runner.check_interval_seconds、runner.connection.timeout_seconds、runners.{default_global_runners_mode,registration_token}。全部为可选。指针类型的配置字段现在也可以通过环境变量设置。配置和 CLI 参考文档页面由源码生成。
数据库迁移
v2.20.0 外部身份 · v2.20.1 与任务绑定的调查密钥 · v2.20.2 延迟节点 · v2.20.3 工作目录 · v2.20.4 唯一模板名称 · v2.20.5 错误告警抑制 · v2.20.7 主机配置 · v2.20.8 工作流修订版本 · v2.20.9–v2.20.11 审计日志与索引、边输入映射、monorepo 标志 · v2.20.12–v2.20.13 角色表、工作流变量 · v2.20.14 工作流集成与组映射 · v2.20.16 全局角色。
依赖项
Go 1.26;Docker 镜像基于 Alpine 3.24;新增 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;前端 js-yaml 5 和 cron-parser 5.10。新增一键部署:Cloudzy、RepoCloud 和 Pethost。
