Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Agent.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -118,7 +118,7 @@ Community needs voiced in HN agent-UI discussions map directly to EMRG's design:
pkill -f "emrg.server"; rm -f ~/.emrg/emrgd.port; python -m emrg
```

Python: `uv run pytest tests/ -v` (958) — import check: `uv run python -c "from emrg.client.app import run_client"`
Python: `uv run pytest tests/ -v` (959) — import check: `uv run python -c "from emrg.client.app import run_client"`
GUI: `cd emrg/gui && npm test` (260: 45 daemon_client + 19 conn-manager + 22 app-commands + 131 renderer smoke + 16 i18n + 7 integration + 3 commands + 8 build-config + 7 gui-state + 2 tool-group) — syntax: `node --check main.js preload.js daemon_client.js renderer/js/*.js`
CI: `uv run pytest` (ubuntu + **windows-2025 matrix** — Windows pytest 回归在 PR CI 即失败,v0.2.29 教训 #725) + GUI tests + **actionlint workflow lint** (`rhysd/actionlint@v1.7.12` gate, #444 — workflow 解析错误在 PR CI 即失败,如 `if:` secrets 上下文)
Re-trigger: `scripts/re-trigger-ci.sh [branch]` (workflow_dispatch, #527 — 替代空 commit 重触发:Actions outage 会整段丢弃 push 事件,dispatch 走 API 路径不受影响)
Expand Down
26 changes: 26 additions & 0 deletions packaging/make-installer.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -413,6 +413,32 @@ begin
// (从不杀自己),#847 self-held 归属已处理自身锁,且 stop_all 纯标准库从不加载
// websockets。恢复 v0.2.49 的 "{PythonExe}" "{StopScript}",无需任何替代 flag。
LogFile := ExpandConstant('{tmp}\stop_all.log');
// rant 2026-08-19T00:44:52 — 安装器韧性:旧版 runtime python 可能已被早期失败安装
// (v0.2.49/v0.2.50 的 -I 事故)损坏,启动即崩 "Failed to import encodings"(连
// stop_all.log 都没有)→ 用坏 python 跑 stop_all 必然失败 → 升级安装被硬中止。
// 宿主实测:删除旧 install\bin 后走"干净安装"分支即成功 —— v0.2.51 包本身完好,
// 脆弱点在升级路径。修复:跑 stop_all 前先健康检查旧 python 能否启动
// (-c "import encodings, sys",python-build-standalone 启动即加载 encodings),
// 启动失败 → 跳过 stop_all 继续安装(宁可旧进程锁文件让安装器报 DeleteFile、
// 可重试可重启恢复,也不能因坏 python 卡死升级)。健康检查与 stop_all 同款:
// 经 {cmd} 重定向到日志,失败信息进日志 + Setup log。
if Exec(ExpandConstant('{cmd}'), '/c ""' + PythonExe + '" -c "import encodings, sys" > "' + LogFile + '" 2>&1"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
begin
if ResultCode <> 0 then
begin
LogText := '';
if FileExists(LogFile) then
LoadStringFromFile(LogFile, LogText);
Log('PrepareToInstall: old runtime python failed health check (exit ' + IntToStr(ResultCode) + '), skipping stop_all and continuing install. ' + LogText);
Exit;
end;
end
else
begin
Log('PrepareToInstall: could not run old runtime python health check, skipping stop_all and continuing install.');
Exit;
end;
// 健康检查通过:旧 python 可启动 → 正常跑 stop_all(保留现有逻辑)
if Exec(ExpandConstant('{cmd}'), '/c ""' + PythonExe + '" "' + StopScript + '" > "' + LogFile + '" 2>&1"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
begin
if ResultCode <> 0 then
Expand Down
27 changes: 27 additions & 0 deletions tests/test_installer_stop.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,6 +15,9 @@
PrepareToInstall 用 runtime python 运行 {tmp} 提取版
5. build-runtime.sh 把 emrg/_stop_all.py 复制进 runtime bin/stop_all.py
(stop-emrg.cmd 不再打包;CRLF 转换循环只剩 emrg.cmd emrgd.cmd)
6. PrepareToInstall 旧 python 健康检查(rant 2026-08-19T00:44:52):
stop_all 前先 -c "import encodings, sys" 验证旧 runtime python 可启动,
损坏(encodings 崩)→ 跳过 stop_all 继续安装(不硬中止升级)
"""

from pathlib import Path
Expand DownExpand Up@@ -279,6 +282,30 @@ def test_make_installer_iss_has_prepare_to_install():
assert "restart the computer" in content


def test_make_installer_iss_old_python_health_check():
"""rant 2026-08-19T00:44:52 — 安装器韧性:旧版 python-dist 损坏(encodings 崩,
v0.2.49/v0.2.50 -I 事故遗留)时,升级安装不得因坏 python 硬中止。

宿主实测:v0.2.51 升级报 `ModuleNotFoundError: No module named 'encodings'`
(连 stop_all.log 都没有,启动即崩);删除旧 install\\bin 后走干净安装分支
即成功 —— 包本身完好,脆弱点在 PrepareToInstall 用旧 python 跑 stop_all。
修复 = 跑 stop_all 前先健康检查旧 python 可启动(-c "import encodings, sys"),
失败 → 跳过 stop_all(干净安装路径,不中止)。
"""
content = _read("packaging/make-installer.sh")
# 健康检查命令与 stop_all 同款:经 {cmd} 重定向到日志(2>&1)
assert '''""' + PythonExe + '" -c "import encodings, sys"''' in content
assert content.count("2>&1") >= 2 # 健康检查 + stop_all 两处 Exec 重定向
# 失败 → 跳过 stop_all 继续安装(Result 保持 '' → 不中止),信息进日志
assert "skipping stop_all" in content
assert "health check" in content
assert "Log('PrepareToInstall: old runtime python failed health check" in content
# 健康检查必须先于 stop_all 执行
assert content.index("import encodings, sys") < content.index('''""' + PythonExe + '" "' + StopScript''')
# 健康检查通过后仍保留原 stop_all 调用
assert '''""' + PythonExe + '" "' + StopScript''' in content


def test_build_runtime_copies_stop_all_not_stop_emrg():
content = _read("packaging/build-runtime.sh")
# 复制 emrg/_stop_all.py → bin/stop_all.py(不再复制 stop-emrg.cmd)
Expand Down
Loading