Skip to content

Release Protection

konodoki edited this page May 13, 2026 · 11 revisions

发布保护与公开版同步

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

当前采用清单文件驱动:

src/bxi_example_py_elf3/config/release_protection.yaml

发布脚本:

tools/sanitize_release.py

1. 清单示例

protected_states:
  back_flip:
    behavior:
      - FlipState
      - BackFlipState
    events: [back_flip]
    model_keys: [back_flip]
    files:
      - ../data/back_flip.npz

  forward_flip:
    behavior:
      - FlipState
      - ForwardFlipState
    events: [forward_flip]
    model_keys: [forward_flip]
    files:
      - ../data/forward_flip.npz

2. protected_states.

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

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

states:
  back_flip:
    behavior: BackFlipState

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

3. behavior

可以写字符串:

behavior: BackFlipState

也可以写数组:

behavior:
  - FlipState
  - BackFlipState

影响:

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

数组适合有基类或辅助类的状态。例如 BackFlipStateForwardFlipState 共享 FlipState,可以都写上 FlipState。脚本会避免误删仍被公开状态引用的类。

behaviorsbehavior 等价:

behaviors:
  - FlipState
  - BackFlipState

4. events

events: [back_flip]

影响状态机配置:

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

影响遥控器配置:

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

保留规则:

  • 如果非保护状态还引用这个 event,脚本不强删,输出 warning。
  • 如果底层 output 同时服务公开 event,脚本不强删,输出 warning。
  • warning 不会中断脚本。

5. model_keys

model_keys: [back_flip]

影响:

  • 从 launch 文件的模型字典中删除对应 key。
  • 支持 npz_file_dict / onnx_file_dict 这类一行一个 key 的字典写法。
  • 删除从字典项推导出来的模型文件。
  • bxi_example_demo.py 删除 self.<model_key> = ... 形式的模型初始化代码块。
  • 加入 self-check token 检查。

例如:

self.back_flip = DanceMotionPolicyGravityIsaaclab(
    self.npz_file_dict["back_flip"],
    self.onnx_file_dict["back_flip"],
    start_frame=40,
)

匹配逻辑是:

self.<model_key> =

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

6. files

files:
  - ../data/back_flip.npz

影响:

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

7. paths

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

config/elf3_state_machine.yaml
<python_package>/robot_states.py
<python_package>/bxi_example_demo.py
launch/*.launch.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
  launch_glob: ../launch/*.launch.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 "BackFlipState|ForwardFlipState|back_flip|forward_flip" dist/public_release

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

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

更多脚本细节见:

tools/README.md

Clone this wiki locally