Skip to content

Release Protection

konodoki edited this page Jul 2, 2026 · 11 revisions

发布保护与公开版同步

发布保护的目标是:内部 dev 分支可以保留高危动作状态、模型和动作文件;公开 main 分支只接收脚本脱敏后的内容。

当前采用清单文件驱动:

src/bxi_example_py_elf3/config/release_protection.yaml

发布脚本:

tools/sanitize_release.py

1. 清单示例

protected_states:
  <state_name>:
    behavior:
      - <StateClassName>
    model_keys: [<model_member_name>]
    files:
      - ../data/<model_or_motion_file>

2. protected_states.

protected_states.<state> 是受保护状态名。

脚本会尝试从状态机配置的 states 中删除同名状态:

states:
  <state_name>:
    behavior: <StateClassName>

如果该状态因为公开状态依赖而不能安全删除,脚本会输出 warning,并尽量保留相关引用,不直接中断。

3. behavior

可以写字符串:

behavior: <StateClassName>

也可以写数组:

behavior:
  - <BaseStateClassName>
  - <StateClassName>

影响:

  • robot_states.py 删除对应 Python class。
  • 加入 self-check token 检查。
  • 只有当对应状态确实被删除时才删除 behavior。

数组适合有基类或辅助类的状态。脚本会避免误删仍被公开状态引用的类。

behaviorsbehavior 等价:

behaviors:
  - <BaseStateClassName>
  - <StateClassName>

4. 状态机事件

不需要在 release_protection.yaml 里声明事件。

脚本会从状态机配置的 states.*.transitions.on_event 自动推导和被删除状态相关的 event。例如公开状态里有一个事件进入受保护状态:

<public_state>:
  transitions:
    on_event:
      <event_name>:
        to: <state_name>

删除受保护状态时,脚本会自动识别相关 event。

影响状态机配置:

  • remote_events 删除这些 event。
  • 删除指向受保护状态的 transitions.on_event
  • 删除指向受保护状态的 transitions.after

影响遥控器配置:

  • 脚本从 remote_events.<event> 推导底层输出。
  • 如果这个输出只服务受保护 event,从 xbox_default.yamloutputs.level / outputs.edge 删除对应 binding。
  • 删除 binding 后,如果相关 controls 和 sources 没有被公开功能引用,也可以继续清理。

保留规则:

  • 如果推导出的 event 仍被非保护状态用于非保护目标或 action,脚本不强删,输出 warning。
  • 如果底层 output 同时服务公开 event,脚本不强删,输出 warning。
  • warning 不会中断脚本。

5. model_keys

model_keys: [<model_member_name>]

影响:

  • bxi_example_demo.py 删除 self.<model_key> = ... 形式的模型初始化代码块。
  • 加入 self-check token 检查。

model_keys 不会删除任何模型文件。要删除的 .npz.onnx 或其他资源文件必须统一写在 files 字段里。

例如:

self.<model_member_name> = SomePolicy(
    model_file("<relative_model_or_motion_file>"),
)

匹配逻辑是:

self.<model_key> =

如果是多行调用,脚本按括号深度删除整个赋值块。

6. files

files:
  - ../data/<model_or_motion_file>

影响:

  • 从公开树删除这些文件。
  • 相对路径按 release_protection.yaml 所在目录解析。
  • 如果路径以 srctools.github 开头,按仓库根目录解析。
  • 只有当对应状态确实被删除时才生效。

7. paths

一般不需要写。脚本会按清单所在 package 自动推导:

config/elf3_state_machine.yaml
<python_package>/robot_states.py
<python_package>/bxi_example_demo.py

特殊 example 可以覆盖:

paths:
  state_machine: elf3_state_machine.yaml
  robot_states: ../bxi_example_py_elf3/robot_states.py
  demo_node: ../bxi_example_py_elf3/bxi_example_demo.py

8. 运行脚本

python3 tools/sanitize_release.py \
  --manifest src/bxi_example_py_elf3/config/release_protection.yaml \
  --out dist/public_release \
  --self-check

多个 example:

python3 tools/sanitize_release.py \
  --manifest src/bxi_example_py_elf3/config/release_protection.yaml \
  --manifest src/another_example/config/release_protection.yaml \
  --out dist/public_release \
  --self-check

9. GitHub Action 流程

当前流程:

dev push
  -> 生成 dist/public_release
  -> 推送公开树到 public/main-sync
  -> 创建或更新 public/main-sync -> main 的 PR
  -> 自动以 merge commit 合并 PR
  -> main 分支自己的 workflow 独立运行

这样公开分支不会直接拿 dev 原始历史,也不会发布受保护内容。

10. PUBLIC_RELEASE_TOKEN

PUBLIC_RELEASE_TOKEN 需要作为 repository secret 添加。

推荐 fine-grained PAT 权限:

Contents: Read and write
Pull requests: Read and write
Workflows: Read and write

如果 main 是保护分支,并且 workflow 要用 --admin 合并 PR,token 对应账号必须有绕过保护规则的权限。

11. 固定删除项

公开树会删除:

release_protection.yaml
tools/sanitize_release.py
.github/workflows/sync_public_main.yml

每个传入的 manifest 本身也会删除,例如:

src/bxi_example_py_elf3/config/release_protection.yaml

公开树保留 main 分支自己的 workflow,例如 auto_release.yml

12. 检查公开树

rg "<StateClassName>|<state_name>|<model_member_name>" dist/public_release

如果使用 --self-check,脚本会自动做类似扫描。

注意:如果某个 token 因为公开功能仍需要保留,脚本会 warning 并从 self-check 中排除,避免误报。

更多脚本细节见:

tools/README.md

Clone this wiki locally