开发工作流 💻#
本指南介绍 Ultralytics 员工和贡献者如何在 Ultralytics 项目(包括 YOLO 和相关代码库)中规划、实现、审查、测试和合并变更。
工作流刻意保持轻量:变更范围要明确,便于审查,运行适当的检查,并留下足够的背景信息,让队友日后能理解相关决策。
行为准则 🤝#
所有贡献者都必须遵守行为准则。在问题、PR、评审、内部讨论和公开社区空间中,都应保持尊重、表达清晰并坚持专业态度。有关公开贡献要求,请参阅官方贡献指南。
协作节奏 🛰️#
- 协作日(周二/周三/周四): 将这些日子用于代码评审、设计讨论、调试会议,以及适合实时协作的决策。
- 周一/周五: 优先安排深度工作、书面进度更新、PR 准备和异步评审。如果需要实时对齐才能解决关键阻碍,请将相关事项移至下一个协作日。
- 站会与评审: 站会控制在 15 分钟以内。尽可能在协作日安排设计和架构评审。
- 决策记录: 将重要决策记录在 PR 描述、问题、文档或运维手册中,避免相关背景信息在聊天中丢失。
范围与职责归属 🧭#
此工作流适用于 Ultralytics 在产品、Ultralytics Platform、YOLO、基础设施、文档、自动化和安全敏感系统方面的工程工作。各代码库可以增加更严格的要求,但不应降低本页面规定的基本要求。
每项工作都应有明确的负责人:
- 作者: 实施变更、及时更新 PR,并提供验证证据。
- 评审者: 确认正确性、可维护性、风险和对文档的影响。
- 领域负责人: 评审影响专业领域的变更,例如模型行为、基础设施、安全、隐私、许可或面向客户的工作流。
- 分流负责人: 将新收到的问题、事故、漏洞报告和维护工作分配给合适的负责人。
新工程工作应按影响、优先级、负责人和风险进行分流。安全、生产、影响客户和合规相关的工作应明确指定负责人和后续处理路径,不应一直停留在无人认领的问题或聊天线程中。
拉取请求流程 🔄#
1. Fork 或同步代码库#
外部贡献者应将相关 Ultralytics 代码库(例如 ultralytics/ultralytics)Fork 到自己的 GitHub 账户。
拥有写入权限的员工应在创建分支前同步 main:
# External contributors
git clone https://github.com/YOUR_USERNAME/ultralytics.git
cd ultralytics
# Employees with write access
git checkout main
git pull origin main2. 创建功能分支#
创建分支,并使用清晰、具体且能体现工作内容的名称:
git checkout -b fix-issue-123fix-export-timeout用于修复错误add-training-metrics用于新功能update-docs-training用于文档ci-link-check用于自动化或基础设施
3. 进行变更#
遵循代码库现有的模式和风格
避免引入新的警告、回归问题或无关改动
确保 PR 聚焦于一个明确的结果
4. 测试变更#
请求评审前,根据变更的风险运行相应的检查:
pytest tests/为新功能添加测试,并为错误修复添加回归测试。如果无法在本地运行相关检查,请在 PR 中说明原因并附上手动验证记录。
5. 提交变更#
使用简洁、清晰的说明进行提交:
git commit -m "Fix #123: Corrected calculation error"- 使用现在时(“Add feature”,而不是“Added feature”)
- 适用时注明问题编号
- 主题行控制在 72 个字符以内
6. 创建拉取请求#
从你的分支向 main 提交 PR:
- 标题清晰地描述变更
- 描述涵盖目的、范围和验证情况
- 关联相关问题
- 明确负责人和所需评审者
- 注明风险、兼容性问题或发布步骤
- UI 变更需附上截图
- 本地测试通过
7. 签署 CLA#
外部贡献者必须签署贡献者许可协议(CLA),以便根据 AGPL-3.0 许可证正确授权贡献内容。
提交 PR 后,添加以下评论:
I have read the CLA Document and I sign the CLA
CLA 机器人将引导你完成此流程。有关许可的更多详情,请参阅我们的贡献指南。
8. 处理评审反馈#
回复评审者的评论、推送更新;如果范围发生变化,请及时更新 PR 描述。再次请求评审前,解决所有阻塞性反馈。
Google 风格文档字符串 📝#
对于代码库要求使用文档字符串的公开函数和类,应采用 Google 风格文档字符串。确保文档字符串准确、简洁,并对未来的维护者有所帮助。
标准函数#
def example_function(arg1, arg2=4):
"""Example function demonstrating Google-style docstrings.
Args:
arg1 (int): The first argument.
arg2 (int): The second argument.
Returns:
(bool): True if arguments are equal, False otherwise.
Examples:
>>> example_function(4, 4) # True
>>> example_function(1, 2) # False
"""
return arg1 == arg2命名返回值#
def example_function(arg1, arg2=4):
"""Example function with named return.
Args:
arg1 (int): The first argument.
arg2 (int): The second argument.
Returns:
equals (bool): True if arguments are equal, False otherwise.
Examples:
>>> example_function(4, 4) # True
"""
equals = arg1 == arg2
return equals多个返回值#
def example_function(arg1, arg2=4):
"""Example function with multiple returns.
Args:
arg1 (int): The first argument.
arg2 (int): The second argument.
Returns:
equals (bool): True if arguments are equal, False otherwise.
added (int): Sum of both input arguments.
Examples:
>>> equals, added = example_function(2, 2) # True, 4
"""
equals = arg1 == arg2
added = arg1 + arg2
return equals, added重要: 函数返回多个值时,应分别记录每个返回值,而不是把重要细节都藏在通用的元组说明中。
✅ 良好示例:
Returns:
(np.ndarray): Predicted masks with shape HxWxN.
(list): Confidence scores for each instance.❌ 错误示例:
Returns:
(tuple): Tuple containing:
- (np.ndarray): Predicted masks with shape HxWxN.
- (list): Confidence scores for each instance.带类型提示#
def example_function(arg1: int, arg2: int = 4) -> bool:
"""Example function with type hints.
Args:
arg1: The first argument.
arg2: The second argument.
Returns:
True if arguments are equal, False otherwise.
Examples:
>>> example_function(1, 1) # True
"""
return arg1 == arg2单行文档字符串#
def example_small_function(arg1: int, arg2: int = 4) -> bool:
"""Example function with a single-line docstring."""
return arg1 == arg2代码规范 📐#
Python 风格#
| 标准 | 要求 | 示例 |
|---|---|---|
| 行宽 | 遵循代码库配置,通常为 120 个字符 | 确保代码行易读、便于快速浏览 |
| 文档字符串 | Google 风格 | 在有帮助时使用类型和示例 |
| 导入 | 优先使用 pathlib,而不是手动处理路径字符串 | 使用现代的跨平台路径 |
| 类型提示 | 在有助于提升清晰度时使用 | 公开 API、复杂结构和返回数据 |
| 函数 | 保持专注且便于测试 | 将复杂逻辑拆分为命名明确的辅助函数 |
代码质量#
- 不保留未使用的导入或变量
- 命名保持一致(
lowercase_with_underscores) - 使用清晰的变量名;除循环计数器外,避免使用单字母变量名
最佳实践#
复用现有的辅助函数和模式
优先提交目标明确的 PR,而不是包含多种内容的大范围变更
在有助于提高清晰度时,消除复杂性
保留公共 API 和用户工作流
覆盖新增行为和回归问题
遵循仓库的格式化工具要求
安全框架 🛡️#
Ultralytics 的工程实践应符合公认的安全开发指南,包括 OWASP 安全软件开发生命周期、OWASP 应用安全验证标准和 OWASP 十大安全风险。团队应在规划安全设计、审查、测试和修复工作时参考这些指南。
资产管理 🗂️#
工程资产应有明确的负责人和可靠的权威信息源。这包括代码仓库、服务、云资源、CI/CD 运行器、域名、数据集、模型制品、API 密钥、机密信息、部署环境和第三方集成。
创建、更改或退役资产时:
- 指定负责人和维护联系人。
- 记录用途、环境、访问要求和生命周期状态。
- 检查访问权限,并遵循最小权限原则。
- 不要将机密信息和凭据放入代码、日志、屏幕截图或文档中。
- 当所有权或行为发生变化时,更新运行手册、图表、清单或文档。
- 退役不再使用的资产,以降低安全、成本和维护风险。
文档审查 📝#
文档应与当前的角色、所有权、工作流和安全要求保持一致。流程变更时,应尽可能在同一个 PR 中更新相关的员工手册页面、公开文档、运行手册或 README。
文档审查人员应检查:
- 角色名称、所有权和升级处理路径是否为最新信息。
- 安全、合规和许可相关表述是否符合当前政策。
- 链接、图表、命令和屏幕截图是否仍与产品或工作流相符。
- 新增或变更的流程是否明确了负责人和审查周期。
- 公开文档是否未暴露仅供内部使用的信息、机密信息、客户数据或敏感运营细节。
测试要求 ✅#
所有 PR 都应包含与变更风险相匹配的验证:
pytest tests/
# When coverage is relevant
pytest --cov=ultralytics tests/对于模型行为变更,在可行时注明数据集、模型、命令、硬件以及变更前后的指标。对于文档变更,在本地构建文档;如果布局有变化,还应附上屏幕截图或预览链接。CI 详情请参阅 CI/测试。
代码审查指南 👀#
贡献者须知#
- 让 PR 聚焦于一项功能、一处修复或一项文档更新。
- 说明问题、解决方案、验证方式和风险。
- 及时回复反馈。
- 把审查视为工作的一部分,而非针对个人的评判。
- 如果范围发生变化,请更新 PR 描述。
审查者须知#
- 在一到两个工作日内完成审查,或尽快将审查任务转交他人。
- 检查新行为的测试和验证证据。
- 审查面向用户的变更所涉及的文档更新。
- 评估对性能、兼容性、安全、隐私和可维护性的影响。
- 确认相关 CI 检查已通过。
- 提供有建设性且具体的反馈。
- 区分阻塞问题和建议。
Git 最佳实践 🌳#
提交#
- 使用现在时:“Add feature”,而不是“Added feature”。
- 编写清晰且具有描述性的提交消息。
- 让每次提交聚焦明确且逻辑清晰。
- 避免将纯格式调整与行为变更混在一起。
分支#
- 创建分支前,拉取最新的
main。 - 如果分支已落后于主线,在最终提交前,将最新的
main变基或合并到分支中。 - 合并后删除分支。
报告 Bug 🐞#
通过 GitHub Issues 报告 Bug:
- 先检查现有 issue
- 提供最小可复现示例
- 描述环境:操作系统、Python 版本、库版本、硬件(使用
yolo checks进行诊断) - 说明预期行为与实际行为的差异,并附上错误消息
有关常见问题和解决方案,请参阅我们的故障排除指南。
许可证 📜#
许多 Ultralytics 代码仓库采用 AGPL-3.0 许可证。如果你在项目中使用受 AGPL 许可的 Ultralytics 代码,你的项目也可能需要根据 AGPL-3.0 开源。如果你需要闭源或商业用途,请查看企业许可证。