mcpField
N
netbox-branching

netbox-branching

github.com/netboxlabs云与 DevOps2148 次安装2 周前更新
代码仓库

关于 netbox-branching

这是一份 NetBox Branching 操作指南,介绍如何在隔离的分支模式中修改、审查并同步 NetBox 数据,适合维护 NetBox 集成与变更流程的人员。内容涵盖版本差异、冲突处理和异步任务。

主要功能

  1. 01创建分支并检查就绪状态
  2. 02使用分支上下文调用 API
  3. 03审查变更差异与冲突
  4. 04执行同步、合并和回退
  5. 05异步任务轮询指南

适用场景

  1. 01隔离计划中的 NetBox 数据变更
  2. 02合并前检查冲突
  3. 03处理异步分支操作

MCP 相关

指南提及可通过已配置的 NetBox MCP 服务检查实时分支状态,并执行分支生命周期操作。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/netboxlabs/skills --skill netbox-branching

安装后在 Claude Code 中输入/netbox-branching确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
api-patterns.md
branch-aware-models.md
branch-lifecycle.md
conflict-resolution.md

详细介绍

NetBox Branching

Branching 为 NetBox 提供类似 Git 的变更隔离。每个分支使用独立的 PostgreSQL 架构——你通过一个特殊标头对其进行读写,然后将变更合并回主分支。

你对 NetBox Branching 的了解可能已经过时。 分支状态、合并策略和 API 行为会随插件版本更新而变化。请优先检索,而不要依赖预训练知识。

检索来源

来源URL / 方法用途
Branching 文档https://netboxlabs.com/docs/extensions/branching/完整参考、生命周期、配置
Branching REST APIhttps://netboxlabs.com/docs/extensions/branching/rest-api/端点详情
Branching 仓库https://github.com/netboxlabs/netbox-branching源码、更新日志、问题
NetBox MCP server如果已配置——验证分支状态、列出分支实时分支状态
NetBox Platform MCP如果已配置——完整的分支生命周期操作创建、同步、合并验证

首先:验证连接

确认已安装 Branching 插件,且你的令牌有权访问:

curl -s -H "Authorization: Bearer $NETBOX_TOKEN" "$NETBOX_URL/api/plugins/branching/branches/" | python -m json.tool

你应该会看到分页的分支列表(或空结果)。如果收到 404,说明未安装 Branching 插件。如果收到 403,说明你的令牌缺少 netbox_branching 权限。


插件: netbox_branching——有两个受支持的版本线,需根据 NetBox 版本选择:

NetBox插件版本线最新版本
4.7.x1.2.x(min_version 4.7.0;无法在 ≤4.6 上加载)1.2.2(2026-10-08)
4.4.1–4.6.x1.1.x(无法在 4.7 上加载)1.1.3(2026-08-26)

1.0.x/0.9.x 已被取代——升级到 NetBox 4.7 前,请先升级到 1.1.x;升级 NetBox 时再升级到 1.2.x。本技能覆盖的版本范围:NetBox 4.5–4.7。

1.2.0 是适配 NetBox 4.7 的版本。 NetBox 4.7 用 PostgreSQL ltree 替代了 django-mptt,并将路径及反规范化字段的维护移入数据库触发器;1.2.0 会将这些触发器复制到每个分支架构中,因此嵌套层级结构(区域、位置、租户组、模块托架……)在分支内的行为保持一致。两个版本线的端点、权限代号、squash 策略和 11 状态生命周期均相同;1.2 专属的 API 仅有 recover/(1.2.1)。请参阅版本说明。

核心概念

  • 分支 = 独立架构。 创建时进行配置,归档/删除时移除。每个分支都有自己的数据库表。
  • schema_id(8 位字母数字)是用于 API 访问的分支标识符——不是名称,也不是数字 ID。
  • 所有耗时操作均为异步——配置、同步、合并、还原都会返回一个 Job。请轮询直到操作完成。
  • 当主分支和分支修改了同一对象的字段时,会产生冲突。继续合并/同步前必须确认冲突。

分支生命周期

共 11 种状态。完整状态机请参阅 references/branch-lifecycle.md。

状态含义
new已创建,尚未预配
provisioning正在复制架构(异步)
ready可用 — 允许读写
syncing正在将 main 拉取到分支(异步)
migrating正在应用数据库迁移(异步)
merging正在将分支推送到 main(异步)
reverting正在撤销合并(异步)
merged已成功合并;只读
archived架构已删除,元数据保留
pending-migrationsNetBox 升级后需要迁移
failed预配或迁移失败;终止状态 — 删除并重新创建

过渡状态(provisioning、syncing、migrating、merging、reverting)无法中断。发生已捕获的故障时,它们会恢复到之前的稳定状态(syncing/merging → ready,reverting → merged),但 provisioning 和 migrating 会变为 failed。

**工作进程被终止(OOM、kill -9、Pod 被驱逐):**不会执行故障处理流程,因此分支会停留在过渡状态,相关操作也会被禁用。(1.2.1+ / NetBox 4.7) 每小时运行的任务会重置该状态(auto_recover_stuck_branches,默认值为 True),也可以按需执行:POST /api/plugins/branching/branches/<id>/recover/(需要 change_branch;如果任务看起来仍在运行,则使用 {"force": true};使用 {"retry": true} 可重新运行被中断的同步/迁移)。重置目标:provisioning→failed,syncing/merging→ready,migrating→pending-migrations,reverting→merged。1.1.x 没有恢复端点。

快速参考 — 常见工作流

创建并等待就绪
POST /api/plugins/branching/branches/
Content-Type: application/json
Authorization: Bearer <token>

{"name": "add-new-site", "description": "Adding London site"}

响应中包含 schema_id。系统会自动预配。轮询直到就绪:

GET /api/plugins/branching/branches/<id>/

检查 status 字段 — 等待其变为 ready。根据数据库大小,通常需要几秒到几分钟。

激活分支上下文

在分支上下文中发起所有 API/GraphQL 请求时,添加以下标头:

X-NetBox-Branch: <schema_id>

其值为 schema_id(例如 a1b2c3d4),而不是分支名称或 ID。

其他方法(仅限 UI,不适用于 API 自动化):

  • Cookie:active_branch=<schema_id>
  • 查询参数:?_branch=<schema_id>

分支必须处于 ready 状态,否则请求会被拒绝 — (1.2.2+) 返回 400 Selected branch is not ready.(1.2.2 之前返回 500)。响应中会有意不包含分支名称或其状态(此响应会在 REST 身份验证之前返回),因此请轮询分支的 status 并等待其变为 ready。

在分支中进行更改

使用常规 NetBox API 端点并附上分支标头:

POST /api/dcim/sites/
X-NetBox-Branch: a1b2c3d4
Content-Type: application/json

{"name": "London", "slug": "london", "status": "planned"}

更改仅影响分支架构,不会影响 main。

查看更改(ChangeDiffs)
GET /api/plugins/branching/changes/?branch_id=<id>

返回 ChangeDiff 记录,展示更改内容 — 对象类型、操作(创建/更新/删除)、原始数据与修改后数据。

从 main 同步

将 main 的最新更改拉取到分支:

POST /api/plugins/branching/branches/<id>/sync/
Content-Type: application/json

{"commit": true}

返回一个 Job 对象。轮询 Job URL 以确认完成。如果 main 中删除了父对象,同步可能会级联删除分支中仅有的子对象。

试运行:{"commit": false} — 验证但不应用更改。

合并到主分支
POST /api/plugins/branching/branches/<id>/merge/
Content-Type: application/json

{"commit": true}

返回一个 Job。成功后,分支状态变为 merged(只读)。

合并策略:

  • 迭代式(默认)——按时间顺序将分支上的每个 ObjectChange 重放到主分支,同时保留每次更改的用户和时间归属。除非此策略失败,否则请使用此策略。
  • 压缩式——按外键依赖顺序,将每个对象的更改合并为一个净操作(从 1.1.1 起支持任意长度的外键循环)。CREATE+DELETE = 跳过。主分支的变更日志中,操作归属用户为执行合并的用户。可用于从重复对象或中间状态错误中恢复。

REST 不支持策略参数。 merge/ 仅接受 commit 和 acknowledge_conflicts;API 合并采用迭代式策略。压缩式策略只能在 UI 合并表单中选择(REST 序列化器中不包含 merge_strategy)。合并验证器(例如 Changes 插件的已批准 CR 门禁)由 job 检查,而非由端点检查:请求会返回 200 + Job,随后 job 会报错 Merging this branch is not permitted.。试运行(commit: false)会跳过验证器。

处理冲突

如果 ChangeDiff 存在字段冲突,同步/合并会返回 409 和冲突详情:

{
  "detail": "All conflicts must be acknowledged before this action can proceed.",
  "conflicts": [{"id": 6, "object_type": "dcim.device", "object_id": 42, "object_repr": "switch-01",
    "action": {"value": "update", "label": "Updated"},
    "conflicts": ["name", "status"],
    "conflicting_data": {
      "original": {"name": "old"}, "branch": {"name": "branch-val"}, "main": {"name": "main-val"}
    }}]
}

如需继续,请重新提交并设置 "acknowledge_conflicts": true。确认冲突后,以分支上的值为准。

详情请参阅 references/conflict-resolution.md。

还原已合并的分支
POST /api/plugins/branching/branches/<id>/revert/
Content-Type: application/json

{"commit": true}

仅适用于状态为 merged 的分支。将分支恢复为 ready 状态。异步 job。

归档
POST /api/plugins/branching/branches/<id>/archive/

仅适用于状态为 merged 的分支(否则返回 400)。同步执行——返回更新后的分支,不返回 job。删除架构,保留元数据和事件历史;归档后的分支无法再还原。终止状态。(1.1.2+) 设置 auto_archive_days,可在已合并分支达到 n 天后自动归档。

异步 Job 轮询模式

所有耗时操作都会返回一个带有 url 字段的 Job 对象。轮询该对象:

GET <job_url>

Job 的 status 值:pending、running、completed、errored、failed。等待其进入终止状态。使用指数退避(从 1s 开始,最长 30s)。

所需权限: netbox_branching.sync_branch、netbox_branching.merge_branch、netbox_branching.revert_branch、netbox_branching.archive_branch、netbox_branching.migrate_branch(应用待处理的迁移),以及 recover/ 所需的 netbox_branching.change_branch(1.2.1+)。

支持分支的模型

大多数 DCIM、IPAM、Circuits、Tenancy、Virtualization、VPN 和 Wireless 模型都支持分支。不支持分支的模型(全局/立即生效):自定义字段、webhook、事件规则、导出模板、已保存筛选器,以及所有 core.* 模型。

发现端点: GET /api/plugins/branching/branchable-models/ 会准确列出当前安装中支持分支的模型——请使用此端点,不要猜测。(受支持的两个版本线 1.1.x 和 1.2.x 均提供此端点。)实际上,大多数核心运营模型(DCIM、IPAM、Circuits 等)都支持分支;基础设施模型(自定义字段、webhook、core.*)、branching 和 Changes 插件自身的模型,以及 exempt_models 中的所有模型均不支持分支。其他插件中记录更改的模型默认支持分支。

参阅 references/branch-aware-models.md。

与变更请求集成

NetBox Branching 可与 netbox-changes 插件配合,用于受管控的变更工作流:

  1. 在 netbox-changes 中创建变更请求(CR)
  2. 为该 CR 创建分支
  3. 在分支上下文中进行更改
  4. 提交 CR 以供审核/批准
  5. CR 获批后合并分支

集成后,如果关联的 CR 尚未获批,合并操作会被阻止。通过 REST 执行时,阻止响应不是 4xx:merge/ 返回 200 + Job,且作业报错 Merging this branch is not permitted.(界面会显示原因:No change request has been approved for this branch.)。试运行合并不受此限制。

版本配对: Changes 1.1.3 可与 NetBox ≤4.6 上的 branching 1.1.x 配合使用,也可与 NetBox 4.7 上的 branching 1.2.x 配合使用——两个插件必须与运行中的 NetBox 版本匹配,否则 NetBox 将无法启动。有关 CR 生命周期的详情,请参阅 netbox-changes skill。

反模式

  1. 创建后务必轮询 — 分支只有在状态为 ready 时才能使用。在 provisioning 状态下使用会返回 400 Selected branch is not ready.(1.2.2+;此前为 500)——响应不会指出具体是哪个分支,因此请检查 status。
  2. 过期分支 — 如果分支的 last_sync(或从未同步时的 created)早于 NetBox 的 CHANGELOG_RETENTION(默认 90 天),该分支就会过期,无法再同步:同步作业会报错 Syncing this branch is not permitted.。REST 表示中没有 is_stale/stale_warning 字段——请自行计算 now − (last_sync or created);界面会提前 stale_warning_threshold 天发出警告(默认 7 天)。请在保留期结束前同步,或归档/删除分支。
  3. 分支数量上限 — 插件配置中的 max_branches(非归档分支总数)和 max_working_branches 设定了数量上限。超出上限时,创建操作会因 ValidationError 而失败。
  4. 无法删除当前活动分支 — 请先停用它。
  5. 合并要么全部成功,要么全部回滚 — 任何验证失败都会回滚整个事务。
  6. 冲突需要确认 — 在传入 acknowledge_conflicts: true 前,操作会返回 409。分支中的值优先。
  7. 同步会级联删除 — 如果主分支中的父对象已删除,同步时会为仅存在于分支中的子对象创建合成 DELETE 记录。
  8. 架构 = 磁盘空间 — 每个分支都会复制所有可分支表。请为大型数据库规划容量。
  9. pending-migrations — NetBox 升级后,现有分支需先迁移才能使用。
  10. 数据库权限 — PostgreSQL 用户需要 CREATE ON DATABASE 权限才能创建架构(NetBox 4.7 自动安装 ltree 扩展也需要相同权限)。
  11. ?background=true + X-NetBox-Branch 会将写入操作应用到主分支(NetBox 4.7.0–4.7.2;已在 4.7.3 修复)——请参阅 NetBox 4.7 交互。
  12. 编程式写入需要 obj.snapshot() — 脚本、nbshell 和插件作业如果在分支中修改对象前未创建快照,便会得到空的 prechange_data:差异无法显示更改前后的状态,且该对象的冲突检测会静默失效。请在修改前调用 snapshot()。

API 端点摘要

端点用途
POST /api/plugins/branching/branches/创建分支
GET /api/plugins/branching/branches/<id>/分支详情/状态
POST .../branches/<id>/sync/从主分支同步
POST .../branches/<id>/merge/合并到主分支
POST .../branches/<id>/revert/撤销已合并的分支
POST .../branches/<id>/archive/归档已合并的分支(同步并返回分支)
POST .../branches/<id>/recover/重置卡在过渡状态的分支(1.2.1+)
GET /api/plugins/branching/changes/ChangeDiff 记录
GET /api/plugins/branching/branch-events/分支事件日志
GET /api/plugins/branching/branchable-models/查找可分支模型

NetBox 4.7 交互

需要分支 1.2.x。已使用 NetBox 4.7.2 + 插件 1.2.1 验证。

  • 在 NetBox 4.7.0–4.7.2 上,?background=true 批量写入会忽略分支标头。 这些版本会在工作进程中根据快照重建请求,而快照只包含主机/转发标头——X-NetBox-Branch、Cookie 和 ?_branch= 都会被丢弃——因此,延迟执行的批量写入不会激活任何分支,并会写入 main(或者在启用 Changes protect_main 时遭到拒绝)。NetBox 4.7.3+ 会将请求标头和查询字符串(不含 background;Authorization 会被剥离,因为认证已完成)传递给工作进程,因此写入会落在分支中(netbox-community/netbox#23247)。在 ≤ 4.7.2 上,切勿将 ?background=true 与 X-NetBox-Branch 一起使用——应改为在分支上下文中发送同步批量请求(每次调用 ≤ 几百个对象);在 4.7.3+ 上,像处理其他后台写入一样,轮询作业直到状态终结。
  • 分支中的层级结构: NetBox 4.7 将区域/站点组/位置/租户组/模块机箱路径保存在由数据库触发器维护的 ltree 列中。1.2.0 会在每个分支架构中安装这些触发器,因此,在分支中移动或重命名父级只会级联影响该分支中的后代,合并时会重放父级变更(main 上的路径由 main 的触发器重新计算)。如果你是从 pg_dump 恢复的 NetBox 4.7.0,请先在 main 上运行 rebuild_ltree_paths --check,再创建新分支——分支会原样复制 main 的表和触发器。
  • Custom Objects 插件 ≥ 0.6 支持分支中的自定义对象实例(版本要求取决于插件,而非 NetBox);0.5.x 会拒绝在分支中写入实例。参见 netbox-custom-objects。
  • 批量错误格式: 在分支上下文中,同步批量写入失败时会返回 4.7 的逐对象 {"detail", "errors": [{"index": N, ...}]} 格式——与 main 相同。参见 netbox-api-integration。
  • NetBox Designs 会将方案部署到分支。 目标为分支的设计部署只会写入该分支;像往常一样在 NetBox 中合并或删除分支,部署也会随之变化(移至 main,或显示 Branch gone)。参见 netbox-designs。
  • pynetbox ≥ 7.8.0 除了旧版 nb.activate_branch() 上下文管理器,还提供了 BranchingExtension(branch.sync()/merge()/revert()/archive())。在 NetBox 4.7 上请使用 ≥ 7.9.0(2026-10-08;Python 3.12+)——这是首个声明支持 4.7 的 pynetbox 版本,并修复了保存带有多选自定义字段的对象时的问题——参见 references/api-patterns.md。

配置快速参考

PLUGINS_CONFIG['netbox_branching']。完整列表:插件仓库中的 docs/configuration.md。

参数默认值起始版本说明
max_branches / max_working_branchesNone0.4 / 0.5非归档分支总数 / 非合并且非归档分支数上限
exempt_models[]0.5'plugin.model' 或 'plugin.*';绝不豁免与某个分支模型相关的模型
job_timeout36000.8.2同步/合并/还原任务超时时间(秒)
stale_warning_threshold70.9在 UI 中于过期前多少天发出警告;0 表示禁用
provision_workers41.1.0并行复制/索引工作进程数;使用共享数据库时建议调低至 1–2
auto_archive_daysNone1.1.2合并后经过 n 天自动归档分支(会删除架构 → 无法还原)
auto_recover_stuck_branchesTrue1.2.1每小时重置因工作进程崩溃而孤立的分支
stuck_job_grace_period3001.2.1超过 job_timeout 后,经过多少秒才将“运行中”任务视为已死亡
*_validators(sync/merge/migrate/revert/archive)[]0.6操作前验证器的导入路径

还需在 NetBox 的 EVENTS_PIPELINE 中,将 'netbox_branching.events.add_branch_context' 放在 extras.events.process_event_queue 之前,以便在事件规则条件、Webhook 负载和脚本 data 中获取 active_branch(id、name、schema_id 或 null)。

版本说明

NetBox 4.7.3(2026-10-13)
  • ?background=true 批量写入现在会将 X-NetBox-Branch / ?_branch= 传递给工作进程,因此后台批量写入会落在分支中(#23247;在 4.7.0–4.7.2 中则会落在主库)。请运行 ≥ 4.7.3。
插件 1.2.x — 仅支持 NetBox 4.7(2026-09-02)
  • **1.2.0:**在分支架构中复制 ltree 和反规范化触发器。需要 NetBox ≥ 4.7.0;请运行 ≥ 4.7.3(4.7.0/4.7.1 会将通过后台批量请求创建的明文令牌泄露到任务结果中;4.7.3 会将分支标头传递给后台批量任务,并恢复配置上下文省略优化)。
  • **1.2.1:**卡住分支恢复功能——recover/ 端点、auto_recover_stuck_branches、stuck_job_grace_period;修复 ObjectChange.undo(),使其能在还原时恢复已删除的对象。
  • 1.2.2(2026-10-08):在压缩合并或还原后重新计算线缆路径(#469);合并失败报告包含底层验证错误(#632);同步分支时冲突基线会前移(#640);压缩合并时解决循环 DELETE 依赖(#668);删除记录前先取消分支预配(#641);未安装插件时脚本会跳过分支激活(#649)。
插件 1.1.x — NetBox 4.4.1–4.6.x(2026-06 → 2026-08)
  • **1.1.0:**并行预配(provision_workers),大型数据库上的速度最高提升约 4 倍。
  • **1.1.1:**压缩合并可解决任意长度的外键循环;修复了 MPTT 组件模型(模块托架、库存项)的迭代式合并。
  • 1.1.2:auto_archive_days。
  • **1.1.3:**对象更新期间的冲突现在会记录到 ChangeDiff 中(此前会漏掉部分更新冲突)。
插件 1.0.x(已被取代)
  • 1.0.4:同步时的冲突解决结果在合并时得以保留;为不记录变更的模型提供插件解析器钩子。1.0.5:合并时保留未修改的 JSON 字典键。所有 1.0.x 版本 → 升级到 1.1.3(≤4.6)或 1.2.2(4.7)。

参考资料

评论

支持 Markdown