---
type: log
tags: [开源, Zephyr, west, Python, 环境]
status: done
date: 2026-09-21
related: "[[2026Q4-参与Zephyr开源社区/!项目说明|!项目说明]]"
---

# 开源贡献 · 环境与流程

> 配套参考(系统讲解):`F:\0-Note\50-资源\Zephyr\Zephyr-CI与west全貌讲解.md` —— Zephyr CI 与 west PR #1006 的全貌讲解(科学定义 + 白话)。
>
> 本地文档构建(WSL2,已实测可用):见 [[03-本地文档构建-WSL2]]。

## Linux 环境(WSL2,2026-09-22)

用 WSL2 里的 **Ubuntu 26.04.1 LTS** 做 Linux 侧工作(2026-09-22 用户决定,不装双系统):

```bash
wsl.exe -d Ubuntu-26.04 -u root            # 进发行版(root 即可,无需 sudo)
wsl.exe --install Ubuntu-26.04 --no-launch # 当初的安装命令
```

内核是 `6.6.87.2-microsoft-standard-WSL2` —— **不能被用来做内核模块实验**,那部分等硬件/真机。文档构建、Python 工具链、west 相关操作均已验证可用。

## 本机环境(2026-09-21 实测)

| 项 | 值 |
|----|-----|
| Python | 3.14.6(scoop 安装,`C:\Users\23652\scoop\apps\python\current\python.exe`) |
| uv | 0.12.17(用 `python -m pip install uv` 装;本机没有独立 uv) |
| git | 2.53.0.windows.2 |
| gh | 已认证 Zzz210s,scopes:`repo` / `workflow` / `gist` / `read:org` / `delete_repo` |
| 工作副本 | `F:/0-code/20-active/oss-west`(fork:`Zzz210s/west`,upstream:`zephyrproject-rtos/west`) |
| 提交身份(仅此仓库) | `Zzz210s <chenchen237038@qq.com>` |

## 本地四项检查(west 的 `poe` 任务)

| 命令 | 实际执行 | 说明 |
|------|----------|------|
| `uv run poe test` | `python -m pytest -W error` | 基线 350 passed / 2 skipped / 1 xfailed(约 9 分钟,Windows 上偏慢) |
| `uv run poe lint` | `ruff check .` | |
| `uv run poe format` | `ruff format` | **会改写文件**,不是 `--check` |
| `uv run poe types` | `mypy --package west` | |
| `uv run poe all` | 上面四个依次跑 | 提交前跑这个 |

## 踩坑记录(重要)

- **`core.autocrlf=true` 会让 `poe format` 改写 22 个文件**:系统级 gitconfig(`C:/Program Files/Git/etc/gitconfig`)设了 `autocrlf=true`,检出的是 CRLF,而 `ruff format` 按仓库配置(`line-ending = "lf"`)写回 LF,于是工作树被"格式化"成 22 个文件的改动。
  **解决**:在本仓库执行 `git config core.autocrlf false` 后 `git checkout -- .`;之后 `poe format` 报 "22 files left unchanged",幂等。
  **注意**:west 仓库**没有 `.gitattributes`**,所以只能靠本地配置兜住。
- **`uv sync` 必须在仓库根执行**,否则拿不到 `uv.lock` 里的 dev 依赖组(poethepoet / ruff / pytest / mypy)。
- **`_import_ctx` 是 NamedTuple**:它的字段不能用 `+=` 重新绑定(`AttributeError: can't set attribute`),只能就地修改内部对象。

## 流程约定(来自 west CONTRIBUTING.rst)

- DCO:每个 commit 必须 `git commit --signoff`
- Zephyr git 工作流:每个 commit 自包含;**更新 PR 用 amend/rebase + force-push,禁止 fixup / merge commit**
- commit 标题形如 `area: 一句话`,标题约 80 字符以内
- PR 描述写清:解决哪个 issue、设计选择与理由、本地怎么验证
- 社区:Zephyr Discord 的 `#west` 频道、Zephyr devel 邮件列表

## 第二类工作:改 Zephyr 主仓文档

Zephyr 仓极大(1.5GB+),**不要完整 clone**。用 blobless + sparse,只取要改的目录(实测 `.git` 仅 12MB):

```bash
gh repo fork zephyrproject-rtos/zephyr --clone=false
git clone --depth 1 --filter=blob:none --sparse https://github.com/<账号>/zephyr.git <目录>
cd <目录>
git config core.autocrlf false          # 关键!见下
git sparse-checkout set doc/develop/west
git remote add upstream https://github.com/zephyrproject-rtos/zephyr.git
git fetch --depth 1 upstream main && git checkout -b <分支> FETCH_HEAD
```

- **CRLF 陷阱**:全局 `core.autocrlf=true` 会让工作树文件变 CRLF,而 Zephyr 的 `.gitattributes` **没有** `text=auto` → 不处理就会把 CRLF 原样提交。修法:`git config core.autocrlf false` 后 `git rm --cached -r -q . && git reset --hard`(整树以 LF 重写)。
- **稀疏 + 单分支 clone 的副作用**:`origin/<自己的分支>` 不会被追踪,`--force-with-lease` 会报 `stale info`;改用 `--force-with-lease=<分支>:<期望的旧 sha>` 显式指定。
- **提交信息**:Zephyr 用 `doc: <子域>: <祈使句>`,标题 ≤ ~72 字符;**不要**同时手写 `Signed-off-by` 又加 `--signoff`(会出现两条),用 `git commit -F <file>` 一次写好。
- **Zephyr 合规检查的两条硬规矩(实测会 fail)**:
  - **UC2**:`Signed-off-by` 必须是**两词全名** —— 规则实现是 `re.search(r"(^)Signed-off-by: ([-'\w.]+) ([-'\w.]+) (.*)")`,`ChenChen` 这种单字姓名直接 fail
  - **UC4**:提交**正文单行上限 75 字符**(超一行即 fail)
  - 本机确定的上游署名:**`Chen Chen <chenchen237038@qq.com>`**(用户 2026-09-22 确认);west 用的 `zephyrproject-rtos/action-dco` 正则较宽松(`^([^<>]+) <([^<>\s]+)>$`,只要求与作者一致),不卡两词,但为统一也用它
- **无法本地构建文档**(Windows):退而做三项检查 —— docutils 解析、`:ref:` 目标存在性、标题下划线长度;真正的检查交给 CI。
- 环境:Zephyr 贡献也需真实姓名署名(与 west 一致)。

### 提交信息本地预检(可复用)

`开源贡献/check-commit-msg.py` —— 复刻 Zephyr 的 gitlint 规则(UC2 两词全名、UC4 正文 ≤75、UC3 标题格式、UC5 标题 ≤72、UC6 正文至少 2 有效行),不依赖 gitlint:

```bash
python check-commit-msg.py            # 检查 HEAD
python check-commit-msg.py <rev>      # 检查指定提交
python check-commit-msg.py --msgfile <路径>
```

**双向验证过**:拿被 CI 判失败的旧提交跑,复现出**与 CI 完全相同的 4 条违规**(UC2 一条 + UC4 三条);改后的提交跑出通过。提 PR 前先跑它,能免掉一轮合规失败。

**实际抓到过**:第二轮改 west 文档时,提交信息有 3 行 76-77 字符(超 UC4 的 75),就是这个脚本先报出来的,没再麻烦 CI。

### RST 单文件预检(可复用)

`开源贡献/check-rst.py` —— Windows 上跑不动 Zephyr 完整文档构建时的替代检查:

```bash
python check-rst.py doc/develop/west/workspaces.rst --root .
```

它做三件事:docutils 结构解析(Sphinx 专有角色/指令注册为空实现,不误报)、`:ref:` 目标是否在仓库里存在、标题下划线是否够长;还有一条**内联字面量跨行**检查(一行里双反引号数为奇数 = 有 ``...`` 从上一行延续)。

**内联字面量跨行是个值得记的坑**:` ``west\nupdate`` ` 这种写法里,换行会被**原样渲染**进输出(HTML 里 `<code>` 内部真带一个换行,PDF 里直接断行),而 **Sphinx 不会给任何 warning** —— 构建照样绿,CI 也拓不到。实测:本页 44 个内联字面量里就有一个这样(Sphinx 没报)。只能靠静态检查抓。

已做反向验证:故意加一个不存在的 ref,它能正确报出;拿修前的文件跑,能报出自己引入的那处跨行字面量。

完整文档构建的替代:维护者提示可用 rstcheck 单文件跑(见 `02-zephyr-docs.md` 的实测命令)。
