ci: Windows job 加 USERPROFILE 重定向 —— pnpm 的操作锁按它算路径
构建客户端 / 检查(类型 + 单元测试) (push) Successful in 1m9s
构建客户端 / macOS 通用(.app + .dmg) (push) Skipped
构建客户端 / Windows x64(NSIS 安装包) (push) Failing after 33s
构建客户端 / Linux x64(deb + AppImage) (push) Successful in 6m4s

run 9 的诊断2 已经把话说死了:

    LOCALAPPDATA = C:\Users\admin\runner\windows\cache\ci-localappdata   <- 重定向生效
    OK   ...\ci-localappdata\pnpm-store-operation-locks                  <- 目录能建
    Error: ERR_PNPM_STORE_DIR_OPEN_OPERATION_LOCK
      Failed to open the store operation lock at
      "C:\Users\admin\AppData\Local\pnpm-store-operation-locks\all-stores.lock"

也就是说 LOCALAPPDATA 指走了,pnpm 还是去开原来那个路径。本机复现出真正的规则:
只改 USERPROFILE(LOCALAPPDATA 不动)、store 换成一个全新的空目录时,
    <新 USERPROFILE>\AppData\Local\pnpm-store-operation-locks\all-stores.lock
    <新 USERPROFILE>\AppData\Local\pnpm-store-operation-locks\<hash>.lock
立刻出现 —— pnpm 是按 <USERPROFILE>\AppData\Local 算的,跟 LOCALAPPDATA 无关。

所以在那一步里再建一个 ci-profile,把 AppData\Local / AppData\Roaming 先建好,然后
把 USERPROFILE 写进 GITHUB_ENV。文件头第 5 条同步更新。
This commit is contained in:
2026-10-15 23:06:35 +08:00
parent 47ef7c63dd
commit f0538fa233
+17 -1
View File
@@ -79,7 +79,13 @@
# 处置:Windows job 把能重定向的都指到 runner 自己的工作目录 # 处置:Windows job 把能重定向的都指到 runner 自己的工作目录
# (C:\Users\admin\runner\windows\cache,job 内写探测实测可写)—— # (C:\Users\admin\runner\windows\cache,job 内写探测实测可写)——
# RUSTUP_HOME / CARGO_HOME / npm_config_cache / npm_config_store_dir / # RUSTUP_HOME / CARGO_HOME / npm_config_cache / npm_config_store_dir /
# RUNNER_TOOL_CACHE,加上 TEMP/TMP/TMPDIR 与 pnpm/action-setup 的 dest。 # RUNNER_TOOL_CACHE / LOCALAPPDATA / APPDATA,加上 TEMP/TMP/TMPDIR、
# pnpm/action-setup 的 dest,以及 **USERPROFILE**。
# 最后这个是被 pnpm 逼出来的:它的 store 操作锁不在 store-dir 下面,也不看
# LOCALAPPDATA,而是按 <USERPROFILE>\AppData\Local\pnpm-store-operation-locks
# 算 —— 只把 LOCALAPPDATA 指走它照样去开原来的路径(报错原文见 run 8 的日志),
# 把 USERPROFILE 指走它才跟着走(本机实测:探针 profile 下立刻出现
# all-stores.lock)。
# 想从根上解决:让 gitea-runner 以**中完整性**启动(在普通终端里跑 # 想从根上解决:让 gitea-runner 以**中完整性**启动(在普通终端里跑
# run-runner.ps1,而不是从被沙箱化的低完整性 shell 里拉起来),那样这些重定向 # run-runner.ps1,而不是从被沙箱化的低完整性 shell 里拉起来),那样这些重定向
# 就都可以撤掉。这台机器上 runner 由计划任务 GiteaRunner-Windows(admin / # 就都可以撤掉。这台机器上 runner 由计划任务 GiteaRunner-Windows(admin /
@@ -438,8 +444,18 @@ jobs:
Add-Content -Path $env:GITHUB_ENV -Value "TMP=$tmpRoot" -Encoding ascii Add-Content -Path $env:GITHUB_ENV -Value "TMP=$tmpRoot" -Encoding ascii
Add-Content -Path $env:GITHUB_ENV -Value "TMPDIR=$($tmpRoot -replace '\\', '/')" -Encoding ascii Add-Content -Path $env:GITHUB_ENV -Value "TMPDIR=$($tmpRoot -replace '\\', '/')" -Encoding ascii
# 第三个坑:pnpm 的 store 操作锁是按 <USERPROFILE>\AppData\Local\
# pnpm-store-operation-locks 算的 —— 实测只把 LOCALAPPDATA 指走它不跟,
# 只把 USERPROFILE 指走它就跟着走(换完 USERPROFILE 后探针目录里立刻出现
# all-stores.lock)。所以 USERPROFILE 也得指到能写的地方,并且先把
# AppData\Local、AppData\Roaming 建好。
$profileRoot = Join-Path (Split-Path -Parent $env:GITHUB_WORKSPACE) 'ci-profile'
New-Item -ItemType Directory -Force -Path (Join-Path $profileRoot 'AppData\Local'), (Join-Path $profileRoot 'AppData\Roaming') | Out-Null
Add-Content -Path $env:GITHUB_ENV -Value "USERPROFILE=$profileRoot" -Encoding ascii
"bash = $(Join-Path $gitBash 'bash.exe')" "bash = $(Join-Path $gitBash 'bash.exe')"
"TEMP/TMP/TMPDIR = $tmpRoot" "TEMP/TMP/TMPDIR = $tmpRoot"
"USERPROFILE = $profileRoot"
- name: 装 Rust(stable) - name: 装 Rust(stable)
uses: dtolnay/rust-toolchain@stable uses: dtolnay/rust-toolchain@stable