文档:补 Runner 部署指南 §5.1.1/§5.1.2 与排障表(CI 首次全绿)
This commit is contained in:
@@ -432,8 +432,115 @@ Start-ScheduledTask -TaskName GiteaActionsRunner
|
||||
> **核对方法**:用 `check_env.ps1` 的「系统 PATH 视角」检查项,
|
||||
> 或以 SYSTEM 身份跑一次 `where python` 验证。
|
||||
|
||||
### 5.2 ⚠️ 关键坑:MSVC 的路径必须"标准"
|
||||
### 5.1.1 ⚠️⚠️ 关键坑:`pre-commit` 必须在「全局 site-packages」,装到用户态等于没装
|
||||
|
||||
这是 2026-10-02 排查 **L0 job 反复失败**(`::error::no Python with a SYSTEM-visible pre-commit`)的真正根因,
|
||||
也是本环境最隐蔽的一个坑。
|
||||
|
||||
**现象**:`pre-commit` 在你自己的终端里好好的(`pre-commit --version` 有输出),
|
||||
但 CI 的 `l0-gates` job 三个候选 Python 全部探测失败:
|
||||
|
||||
```
|
||||
::error::no Python with a SYSTEM-visible pre-commit. Tried:
|
||||
C:\msys64\ucrt64\bin\python.exe |
|
||||
<workdir>\.venv\Scripts\python.exe |
|
||||
C:\ProgramData\anaconda3\python.exe
|
||||
```
|
||||
|
||||
**根因(两层)**:
|
||||
|
||||
1. **用户态 site-packages 对 SYSTEM 不可见**。
|
||||
`pip install pre-commit`(不带提权)默认装到 **user-site**:
|
||||
`C:\Users\Administrator\AppData\Roaming\Python\Python312\site-packages`。
|
||||
而 SYSTEM 账户的 `%APPDATA%` 是
|
||||
`C:\Windows\system32\config\systemprofile\AppData\Roaming` —— **完全是另一个目录**,
|
||||
它根本看不到 Administrator 的 user-site。**任何 `python.exe` 路径都救不了这个**。
|
||||
|
||||
2. **pip 的「已满足」判定陷阱**(更阴)。
|
||||
就算你**提权**执行 `pip install --no-user pre-commit`,pip 在判断
|
||||
「这个包是不是已经装了」时看的是**整个 `sys.path`**——其中包含 user-site。
|
||||
既然 user-site 里已有同版本的包,pip 会直接打印
|
||||
`Requirement already satisfied: xxx in ...\roaming\...\site-packages`
|
||||
然后**完全跳过**安装到全局目录。
|
||||
结果:pip 报"成功",全局目录里却什么都没有。
|
||||
|
||||
> 实测:9 个依赖里 8 个因版本与用户态不同而被 pip 升级(侥幸落到全局),
|
||||
> 唯独 `cfgv` 用户态已是同版本 **3.5.0** → 被静默跳过 →
|
||||
> `-s` 视角下 `ModuleNotFoundError: No module named 'cfgv'`。
|
||||
|
||||
**诊断命令**(`-s` = 禁用 user-site,模拟 SYSTEM 视角):
|
||||
|
||||
```powershell
|
||||
# 看全局目录到底有没有(而不是 pip 怎么说)
|
||||
& 'C:\ProgramData\anaconda3\python.exe' -s -m pre_commit --version
|
||||
|
||||
# 逐个依赖点名,找出被静默跳过的那个
|
||||
& 'C:\ProgramData\anaconda3\python.exe' -s -c "import cfgv, identify, nodeenv, virtualenv, distlib, filelock, platformdirs, yaml; print('all ok')"
|
||||
|
||||
# 反查 pip 为何跳过(会显示 "Requirement already satisfied ... roaming ...")
|
||||
& 'C:\ProgramData\anaconda3\python.exe' -m pip install --no-user --dry-run cfgv
|
||||
```
|
||||
|
||||
**修复(必须提权)**:脚本 `install_precommit_global.ps1` +
|
||||
`install_precommit_global2.ps1`(逐包安装 + 逐个 import 复验);
|
||||
对**被静默跳过**的包补一支 `fix_cfgv_global.ps1`,核心是强制重装:
|
||||
|
||||
```powershell
|
||||
& $Py -m pip install --no-user --force-reinstall --no-deps `
|
||||
--disable-pip-version-check --no-warn-script-location cfgv
|
||||
```
|
||||
|
||||
> `--force-reinstall` 无视"已满足"判定,`--no-deps` 避免牵连其它包。
|
||||
> 三个脚本都在 `D:\Docker\act_runner\`。
|
||||
|
||||
**验证(四条全过才算好)**:
|
||||
|
||||
```powershell
|
||||
$Py = 'C:\ProgramData\anaconda3\python.exe'
|
||||
& $Py -s -m pre_commit --version # pre-commit 4.6.2
|
||||
Test-Path 'C:\ProgramData\anaconda3\Lib\site-packages\cfgv.py' # True
|
||||
# 关键:确认文件真在【全局】目录,而不是 roaming
|
||||
Get-ChildItem 'C:\ProgramData\anaconda3\Lib\site-packages' -Filter 'cfgv*'
|
||||
```
|
||||
|
||||
> ⚠️ 别再往 `.venv` 里装就以为 CI 能用了——CI 虽然会检查 `.venv\Scripts\python.exe`,
|
||||
> 但 `actions/checkout@v4` 拉的是**干净克隆**,`.venv` 是 gitignore 的,**根本不存在**。
|
||||
|
||||
### 5.1.2 ⚠️ 关键坑:`doc-links` 钩子「本地过、CI 挂」= 引用了 gitignore 的运行时文件
|
||||
|
||||
**现象**:`文档链接存在性 (D-3/D-7)` 钩子在**本地** `pre-commit run --all-files` 通过,
|
||||
一上 CI 就 `Failed`(exit 1),报的行/路径你在本地明明存在。
|
||||
|
||||
**根因**:CI 的 `actions/checkout@v4` 拉的是**干净克隆**,而钩子校验的是
|
||||
**仓库根相对路径是否存在**(`check_backtick_paths`,见 `scripts/check_doc_links.py`)。
|
||||
若文档引用了 **gitignore 的运行时产物**——
|
||||
如 `tools/serial_tool/state/meta.json`(运行时未创建,`.gitignore:132` 排除整个 `state/`)——
|
||||
你本机因为跑过工具所以文件在,**克隆里则不存在** → 判为失效引用。
|
||||
|
||||
**修复**:按 `docs/文档规范.md` §3.3 给该行加**状态词**(脚本的 `STATUS_HINTS`:
|
||||
`计划 / 未创建 / 尚未创建 / 已删除 / 删除 / 不存在 / 缺失 / 断链 / 待建 / 待创建`)。
|
||||
|
||||
```markdown
|
||||
| `tools/serial_tool/state/meta.json`(运行时未创建) | daemon 元数据(pid / 版本 / gen) |
|
||||
```
|
||||
|
||||
> ⚠️ **状态词必须与引用在【同一行】且 ≤40 字符**(`STATUS_PROXIMITY`)。
|
||||
> 把说明写在**上一行**是无效的——脚本逐行调用 `has_status_hint(line, ...)`,
|
||||
> 跨行的文字不在窗口内。
|
||||
|
||||
**本地复现 CI 条件的姿势**(否则永远测不出来):
|
||||
|
||||
```bash
|
||||
# 把运行时目录临时移开,模拟干净克隆,跑完再移回
|
||||
mv tools/serial_tool/state tools/serial_tool/state.bak_ci
|
||||
& '.venv\Scripts\python.exe' scripts/check_doc_links.py --all # 或全局 python -m pre_commit run doc-links --all-files
|
||||
mv tools/serial_tool/state.bak_ci tools/serial_tool/state
|
||||
```
|
||||
|
||||
> 更一般的教训:**任何校验"文件是否存在/数字是否一致"的钩子,都要在
|
||||
> "无本地产物"的干净克隆里验一次**,别只在开发机上跑。
|
||||
|
||||
### 5.2 ⚠️ 关键坑:MSVC 的路径必须"标准"
|
||||
CI 的 MSVC 探测(`l05` job)会去这几个**固定根目录**找
|
||||
`VC\Tools\MSVC\*\bin\Hostx64\x64\cl.exe`:
|
||||
|
||||
@@ -523,6 +630,12 @@ date +%s # 对比 last_online
|
||||
| 🔴 `Start-Service gitea-runner` 报 **无法启动服务**(错误 1053) | **`daemon` 不是服务型程序**,不向 SCM 回报 `SERVICE_RUNNING` | **删除该服务,改用任务计划程序**(§4.0 / §4.5) |
|
||||
| `Register-ScheduledTask` 报 **拒绝访问** | Shell 未提权(`IsAdmin=False`) | 右键 PowerShell → **以管理员身份运行**(§4.6) |
|
||||
| 任务 `LastTaskResult` 非 0 | 启动包装脚本路径/权限问题 | 看 `log\runner-stdout.log`;确认 `.cmd` 存在且为 ASCII 编码 |
|
||||
| 🔴 `l0-gates` 报 `no Python with a SYSTEM-visible pre-commit` | `pre-commit` 只装在**用户态** site-packages(SYSTEM 不可见);或 pip 因 user-site 已满足而**静默跳过**全局安装 | 提权装到**全局**(§5.1.1),务必用 `-s` 复验 |
|
||||
| `l0-gates` 报 `TerminatorExpectedAtEndOfString` / 缺少右引号 | `run:` 块含**中文**,被 WinPS 5.1 按 GBK 解码撞坏引号 | `run:` 块改**纯 ASCII**(中文只留 `name:`/注释) |
|
||||
| `l0-gates` 报 `Cannot find: pwsh in PATH` | `shell: pwsh` = PS7,本机只有 WinPS 5.1 | 改 `shell: powershell` |
|
||||
| `l0-gates` 报 `runner missing: cppcheck` | cppcheck 仅在用户级 PATH | workflow 内回落到 `C:\Program Files\Cppcheck` |
|
||||
| 🔴 `doc-links` 钩子本地过、CI 挂 | 引用了 **gitignore 的运行时文件**(如 `tools/serial_tool/state/*.json`),本地存在、干净克隆里没有 | 该行加状态词「未创建/不存在」等(§5.1.2) |
|
||||
| `l05` 日志 `::warning::runner has no MSVC` 但仍 **PASS** | 缺 MSVC 时 L0.5 **降级跳过**(不硬失败) | 装 VS BuildTools(§5.2),否则该层无覆盖 |
|
||||
| 任务跑满 72 小时被杀 | 计划任务默认 `ExecutionTimeLimit` | 设为 `0`(不限时长),见 §4.3 警示 |
|
||||
| `config set log.file ...` 报 `unknown config key` | **v4 的 log 段无 `file` 键** | 用 `log.job.dir` 或输出重定向(§3) |
|
||||
| **脚本报一堆 `源文本中包含无法识别的标记` / `字符串缺少终止符` / 中文显示成 `鐒跺悗鎵ц`** | 🔴 **`.ps1` 无 BOM,WinPS 5.1 按 GBK 解读 UTF-8** | **给脚本加 UTF-8 BOM**(§7.1) |
|
||||
@@ -710,9 +823,28 @@ powershell -ExecutionPolicy Bypass -File "D:\Docker\act_runner\deploy_runner_tas
|
||||
# -Principal (New-ScheduledTaskPrincipal -UserId SYSTEM -LogonType ServiceAccount -RunLevel Highest)
|
||||
# Start-ScheduledTask -TaskName GiteaActionsRunner
|
||||
|
||||
# 5) 回网页确认 runner 为 Idle → 然后(经你同意后)push 代码触发第一次 CI
|
||||
# 5) ⚠️⚠️ 把 pre-commit 装到【全局】site-packages(否则 L0 必挂,见 §5.1.1)
|
||||
# —— 这是本环境最容易漏、也最难自己看出来的一步(用户态对 SYSTEM 不可见)
|
||||
powershell -ExecutionPolicy Bypass -File "D:\Docker\act_runner\install_precommit_global.ps1"
|
||||
powershell -ExecutionPolicy Bypass -File "D:\Docker\act_runner\install_precommit_global2.ps1"
|
||||
# 若有包报"安装成功"但 import 失败(pip 静默跳过):
|
||||
powershell -ExecutionPolicy Bypass -File "D:\Docker\act_runner\fix_cfgv_global.ps1"
|
||||
|
||||
# 6) 复验(-s = 模拟 SYSTEM 视角,必须过)
|
||||
& 'C:\ProgramData\anaconda3\python.exe' -s -m pre_commit --version # pre-commit 4.6.2
|
||||
|
||||
# 7) 回网页确认 runner 为 Idle → 触发 CI
|
||||
# push 触发(注意:纯 .md 改动在 workflow 的 paths-ignore 里,不会触发);
|
||||
# 手动触发:
|
||||
# curl -u "<user>:<pass>" -X POST -H "Content-Type: application/json" `
|
||||
# -d '{"ref":"v2-on-ui"}' `
|
||||
# "https://gitea.bitnasdaq.vip/api/v1/repos/wandering1/STM32F4-Base/actions/workflows/ci.yml/dispatches"
|
||||
```
|
||||
|
||||
> **CI 验收标准**(2026-10-02 已达成,run#8):`action_run_job` 里两个 job 均 `status=1`——
|
||||
> `l0-gates`(14 个 pre-commit 钩子全 Passed,`内存/Flash` 在无 `.map` 时 Skipped)
|
||||
> + `l05-host-unit-tests`(MSVC 探测 + 39/39 单测)。
|
||||
|
||||
**配套脚本**(均在 `D:\Docker\act_runner\`,**均已加 UTF-8 BOM**,可直接在 WinPS 5.1 运行):
|
||||
|
||||
| 脚本 | 用途 | 需要管理员 |
|
||||
@@ -729,6 +861,7 @@ powershell -ExecutionPolicy Bypass -File "D:\Docker\act_runner\deploy_runner_tas
|
||||
|
||||
| 日期 | 变更 |
|
||||
|---|---|
|
||||
| 2026-10-02 | ✅ **首次 CI 全绿(run#8:L0 + L0.5 双 job Success)**。定位并修复最后两个拦路虎:① **§5.1.1 用户态 site-packages 陷阱**——`pre-commit` 只装在 `%APPDATA%\Roaming\Python\...`(SYSTEM 不可见);且提权 `pip install --no-user` 会因 pip 扫**整个 `sys.path`**、见 user-site 已满足而**静默跳过**全局安装(9 依赖中唯 `cfgv` 因版本相同被跳过→`-s` 下 `ModuleNotFoundError`)。修法:提权 + `--force-reinstall --no-deps` 强制落全局,并以 `-s` 复验。② **§5.1.2 doc-links 假阳性**——文档引用了 gitignore 的运行时文件 `tools/serial_tool/state/meta.json`,本地存在、干净克隆无 → 按《文档规范》§3.3 加同状态词「运行时未创建」。排障表补 6 条(pre-commit 不可见 / GBK 中文 / pwsh / cppcheck / doc-links / MSVC 降级)。新增配套脚本 `install_precommit_global.ps1`、`install_precommit_global2.ps1`、`fix_cfgv_global.ps1` |
|
||||
| 2026-10-02 | 🔴 **常驻方式重大修正(实测推翻)**:`Start-Service gitea-runner` 必然失败。经二进制逆向确认 `gitea-runner v4.0.1` **无任何服务管理代码**(命令集仅 `bug-report/cache-server/config/daemon/exec/register`,无 `service.go`;`OpenSCManagerW` 等符号来自 Docker SDK,非服务安装代码),`daemon` 是纯控制台程序、不向 SCM 回报 `SERVICE_RUNNING`。**§4 全节重写为「任务计划程序」方案**(新增 §4.0 根因分析、§4.2 `deploy_runner_task.ps1`、§4.3 手动命令 + 72h 超时警示、§4.5 清理遗留服务、§4.6 提权);删除失效的 `deploy_runner.ps1`/`install_service.ps1`;排障表补「错误 1053」「LastTaskResult 非 0」「72 小时被杀」3 条;拓扑图/§5.1/§7 日志/§10 TL;DR 同步更新。另修 `config.yaml` 的 `fetch_timeout` 5m→1m(超出 RPC 1m 会被截断并告警) |
|
||||
| 2026-10-02 | **修 `.ps1` 编码坑(实测)**:无 BOM 的 UTF-8 脚本被 WinPS 5.1 按 GBK 解读 → 中文乱码(`鐒跺悗鎵ц`)并撞坏引号配对,报 `源文本中包含无法识别的标记`/`字符串缺少终止符`。**新增 §7.1「给含中文的 `.ps1` 加 UTF-8 BOM」**(两种修法 + 解析器校验命令);排障表补该条目;配套脚本已统一加 BOM |
|
||||
| 2026-10-02 | **按实测修正为 v4.0.1**:act_runner 已更名 **`gitea-runner`**,发布页迁至 `gitea.com/gitea/runner`。**v4 移除 `daemon install/start/stop/status`**;**v4 `log` 段无 `file` 键**(§3 改用 `log.job.dir`);补 §1.3 命令集对照、§6.1 MySQL 直查核验、排障表(`accepts at most 0 arg(s)` / `unknown config key log.file` 等) |
|
||||
|
||||
Reference in New Issue
Block a user