关于 establishing-code-ownership
介绍如何使用 `hogli owners:*` 根据分布式 `owners.yaml` 解析 PostHog 代码归属,并说明解析规则及备用信息来源,帮助贡献者识别负责人而无需手动解读归属文件。
主要功能
- 01按单个路径或批量解析代码归属
- 02列出没有负责人的已跟踪文件
- 03说明继承规则和就近文件优先级
- 04区分代码归属与 CODEOWNERS 审批
- 05追溯生成文件的源文件归属
适用场景
- 01查询路径的负责人和 Slack 频道
- 02审查仓库区域内无人负责的文件
- 03确定负责某段代码树的团队
- 04检查生成产物的实际源代码负责人
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ posthog/ posthog --skill establishing-code-ownership安装后在 Claude Code 中输入/establishing-code-ownership确认已加载。
详细介绍
建立代码所有权
所有权由一个工具 hogli owners:* 通过分散的 owners.yaml 文件解析。
不要手动重新解析所有权文件;语义由解析器定义,也是 CI 强制执行的依据。
快速方式:hogli owners:*
开发机器上都有 flox/hogli,因此直接在 Shell 中调用解析器即可。
hogli owners:who posthog/hogql/printer.py # who owns this path (+ the file that decided it)
hogli owners:resolve --json posthog/api/survey.py products/surveys/backend/api.py # batch, JSON keyed by path
hogli owners:unowned # every tracked file with no owner (append a prefix to scope: `owners:unowned products/`)
owners:who 会打印解析后的 owners、status、Slack 频道和 source——即决定结果的 owners.yaml/product.yaml 文件。
频道取自主所有者在根目录 teams: 注册表中的条目,否则根据名称生成 #<slug>;主所有者为 @handle 的路径没有频道。
owners:resolve 接受作为参数传入的路径,也接受以换行符分隔的标准输入,因此可以通过管道传入文件列表:git ls-files posthog/hogql | hogli owners:resolve --json。
没有 hogli/flox?轻量依赖的备用方案只需要 pyyaml:git ls-files posthog/hogql | PYTHONPATH=packages/owners-yaml python -m owners_yaml(标准输入路径 → 相同的 JSON)。
解析算法(解析器的工作方式)
对于某个路径,解析器会从仓库根目录向下遍历到该路径,收集所有权文件,然后按最近文件优先合并:
owners.yaml——权威的分布式来源。 每个目录都可以包含一个此文件。字段(owners、status、inherit、每路径的rules)会沿用最近的祖先目录中的值,除非被覆盖。inherit: false会截断遍历(Gerrit 的set noparent)——其上方的内容都不会生效。在一个文件中,所有匹配的规则都会按顺序应用,每条规则只替换其设置的字段。owners: null表示有意设为无所有者(免于覆盖率检查),与目录完全没有文件(确实没有所有者)不同。additions:指定目录下新增内容的所有者,而非其中文件的所有者(由使用方决定哪些内容算作新增);它不会改变owners,并会沿遍历路径累加,因此嵌套文件无法删除祖先目录中的条目。sensitive: true用于标记少量改动也很重要的路径(例如 CI 基线、豁免列表),因此审查分派器会在每次改动中请求这些路径的所有者审查,不论改动大小;它与status一样按最近值优先,product.yaml也可以设置此项,而且它本身不会要求审查。products/<name>/product.yaml——受支持的别名。 根目录的owners.yaml通过alias_files: [product.yaml]启用此别名。当产品目录中没有owners.yaml时,其product.yaml的owners:列表会被视为products/<name>/**的所有权,其sensitive:标记也适用于该目录树(product.yaml的其他字段都会被忽略)。同时存在这两个文件的目录会触发 lint 错误;此时以owners.yaml为准。.github/CODEOWNERS——用于阻止合并的审批,不参与遍历。 它保留 GitHub 原生语义,由人工维护(主要用于基础设施,例如team-security),并由 GitHub 自身强制执行。解析器不会读取此文件——如果需要确认是否还必须获得阻止合并的审批,请直接查看该文件。它不会改变解析后的owners,这里的任何内容都不会写入该文件。 只能读取 CODEOWNERS 的工具会改为获取所有权映射的生成投影,该投影由hogli owners:codeowners提供(参见 packages/owners-yaml/README.md);该投影涵盖测试文件,且绝不是.github/CODEOWNERS。
所有者列表由团队 slug(team-devex、conversations、logs——去掉 @PostHog/ 的 GitHub 团队句柄)和个人的**@handle**组成;第一个条目是主所有者。
team → 代码(这个团队负责哪些内容?)
没有单一的“team → 文件”命令;请解析目录树并按 slug 过滤:
git ls-files | hogli owners:resolve --json | jq -r 'to_entries[] | select(.value.owners | index("team-surveys")) | .key'
也可以在 products/*/product.yaml 中搜索该 slug——每个匹配项都涵盖对应的 products/<name>/**;一个团队通常负责多个产品,因此不要找到第一个就停下。
负责的路径包括后端和 frontend/src/...;请同时覆盖两者,或者一开始就说明你只处理其中一部分。
生成的文件
生成的产物通常会被解析到一个宽泛的父级所有者或无人负责。
将其追溯到它由之生成的输入,并将那个团队报告为逻辑所有者(例如 services/mcp/src/tools/generated/<x>.ts 来自 products/<name>/mcp/tools.yaml)。
区分逻辑所有者(拥有源文件的团队——即要报告的对象)与生成路径上解析器的字面结果,并标记这一差异,以便操作员决定是否用 rules: 条目将其固定。
最后手段:功能归属手册,然后 Slack
如果解析器和 product.yaml 都无法解析它,请查阅功能归属手册——它粒度较粗(是宽泛领域,而非文件)且为手工维护,因此优先使用仓库文件,并将任何来自手册的答案标记为可能已过时。
如果连这也失败,并且 Slack MCP 可用,则搜索 Slack——其权威性最低(观点、过时的讨论串),因此请对照仓库文件进行核实,并将答案标记为来自 Slack。
Slug 与 handle
- Handle(
CODEOWNERS):@PostHog/<slug>,例如@PostHog/team-replay。 - Slug(
owners.yaml/product.yaml):handle 去掉@PostHog/,例如team-replay。 - 并不统一:有些带有
team-(team-self-driving),有些不带(conversations、logs)。如果某个名称无法解析,请尝试两种形式。