Skip to content

贡献指南

本文讲怎么搭开发环境、跑测试、刷新 golden、代码风格、提 PR,以及文档维护约定。系统原理见 内部原理

开发环境

需要 Python 3.11+。

bash
git clone https://github.com/chidakiko/dn42-control-backend.git
cd dn42-control-backend
python -m venv .venv
source .venv/bin/activate

# 一方包 + 应用 + 开发依赖(editable)
pip install \
  -e packages/dn42_common \
  -e packages/dn42_registry \
  -e packages/dn42_schemas \
  -e packages/dn42_runtime \
  -e packages/dn42_templates \
  -e apps/control-server \
  -e apps/auth-server \
  -e apps/registry-server \
  -e apps/node-agent \
  -e ".[dev]"

九个都要装。 漏装的包在 pytest 下仍能导入——pyproject.toml[tool.pytest.ini_options].pythonpath 兜了底——但纯 python -c "import ..." 与编辑器的 静态解析会失败,表现为「无法解析导入 dn42_registry」这类只在 IDE 里出现的红波浪线。 装完用这条自检(它不吃 pytest 的 pythonpath,比跑测试更能暴露漏装):

bash
python -c "import dn42_common, dn42_registry, dn42_schemas, dn42_runtime, dn42_templates; import app.main, authserver.main, registryserver.main, agent.main; print('ok')"

pip list | grep -i dn42 应列出九个包。若出现指向已不存在目录的残留编辑态安装(目录改名或组件下线后常见), pip uninstall 掉即可——editable 安装不会随目录消失而失效,只会在导入时报错。

跑测试

pyproject.toml 已配 testpathspythonpath

bash
python -m pytest                 # 全部(共享包 + control-server + node-agent)
python -m pytest tests/unit      # 仅共享包单测
python -m pytest tests/unit/test_desired_state_schema.py -q   # 指定文件
python -m compileall apps packages tests                      # 语法/导入检查

测试分层

目录覆盖
Control Serverapps/control-server/app/tests/health、DB repositories、注册、Bearer/WS 鉴权、admin CRUD、token/健康
Node Agentapps/node-agent/agent/tests/config、naming、CLI、持久化、orchestrator、watch、planner、apply backends、convergence、collectors
共享包tests/unit/校验器、labels/naming/communities、schemas、canonical IO、templates、runtime、agent 协议、导入、lab 示例
集成tests/integration/test_three_node_control_plane.py:真实多节点闭环(provision → 注册 → WS → reconcile → 上报)

Control Server 用 FastAPI TestClient + 临时 SQLite + WS test client;Node Agent 用 fake controller/docker/executor + tmp_path,多数单测不需 Docker。

Golden 渲染回归

tests/unit/test_golden_rendered_hkg1.pybuild_hkg1_example_state() 的渲染产物与 examples/rendered-hkg1/ 逐字节对比,保护模板输出不被意外改变。只有在 schema 默认值、模板或 runtime 输出有意改变时才刷新:

bash
python -c "from pathlib import Path; from dn42_schemas.testing import build_hkg1_example_state; from dn42_templates import render_desired_state; from dn42_runtime import write_rendered_files; write_rendered_files(render_desired_state(build_hkg1_example_state()), Path('examples/rendered-hkg1'))"
python -m pytest tests/unit/test_golden_rendered_hkg1.py -q

访问 Docker 的命令

多数单测不需 Docker。下面会连 Docker Engine(没起 Docker 时可能因连不上 socket/named pipe 失败):

bash
python -m agent.main --plan-only --state-dir .agent-state
python -m agent.main --once --state-dir .agent-state --desired-state state.json

代码风格

  • ruff(行宽 100):ruff check . / ruff format .
  • 公共 API 写 docstring;面向用户的文档放 docs/

提交 PR

  1. main 切分支。
  2. 提交信息用约定式前缀(feat: / fix: / docs: / chore: / refactor: …)。
  3. 确保 python -m pytest 全绿。
  4. 开 PR,说明动机与改动点。
  5. 协议模型是 Pydantic StrictModelextra=forbid:增删字段涉及 agent 与控制面的锁步发布顺序,规则见 锁步契约

文档维护约定

文档与代码同等重要,改了行为就改文档。

  1. 单一事实源——每个主题只在一处详写,其余处链接:
  2. 分层放置(Diátaxis)——手把手入门放 tutorials/;任务步骤放 guides/;查得到的事实放 reference/;为什么与怎么运转放 internals/。导航在 文档中心
  3. 与代码同步——改了接口、配置、表、运行模式或 schema,同步对应参考文档;schema 与模板变化要刷新 golden。
  4. 写当前状态,不写演进过程——文档描述系统现在是什么样,不叙述它曾经是什么样、也不按开发批次组织内容。历史只在解释「为什么是现在这样」时出现,且要说清约束而非编年。
  5. 中立表述——不用第一与第二人称。
  6. 示例可执行——命令能在仓库根直接复制运行,且已脱敏(不放真实 IP 与密钥)。
  7. 交叉引用代码——用文件路径指向源码,路径要指向当前实际存在的位置。
  8. 链接用相对路径,新增文档记得加进 文档中心 导航表。改文件名或拆分文档时,全量跑一遍链接检查。