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
9 changes: 9 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Windows launcher scripts MUST be CRLF (rant 2026-08-12T12:30:41).
# LF-only .cmd files are misparsed by cmd.exe: the whole file is joined into
# one serial command stream (@echo off ignored, PATH collisions produce
# arbitrary errors, exit code non-zero) → the installer aborts with
# "stop-emrg.cmd exit code 1". .ps1 is PowerShell (LF-tolerant) but kept CRLF
# for consistency. Git normalizes checkout to CRLF on every platform.
*.cmd text eol=crlf
*.bat text eol=crlf
*.ps1 text eol=crlf
2 changes: 1 addition & 1 deletion Agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,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` (729) — import check: `uv run python -c "from emrg.client.app import run_client"`
Python: `uv run pytest tests/ -v` (730) — import check: `uv run python -c "from emrg.client.app import run_client"`
GUI: `cd emrg/gui && npm test` (221: 43 daemon_client + 19 conn-manager + 22 app-commands + 100 renderer smoke + 15 i18n + 7 integration + 3 commands + 5 build-config + 7 gui-state) — syntax: `node --check main.js preload.js daemon_client.js renderer/js/*.js`
CI: `uv run pytest` + 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
9 changes: 8 additions & 1 deletion bin/stop-git.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,11 @@ Get-CimInstance Win32_Process |
Start-Sleep -Milliseconds 300

$left = @(Get-CimInstance Win32_Process | Where-Object { $_.ExecutablePath -like $prefix })
if ($left.Count -gt 0) { exit 1 } else { exit 0 }
if ($left.Count -gt 0) {
# Truthful failure (rant 2026-08-12T12:30:41): never report success while a
# process still holds the prefix. Name the survivors so the installer can
# show a useful message instead of a silent bogus exit=0.
$left | ForEach-Object { Write-Host ("still running: {0} (pid {1})" -f $_.Name, $_.ProcessId) }
exit 1
}
exit 0
39 changes: 39 additions & 0 deletions tests/test_cmd_crlf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Guard: Windows batch/PowerShell files MUST be CRLF (rant 2026-08-12T12:30:41).

Root cause of the 0.2.25/0.2.26/0.2.27 installer "exit code 1" series: the
repo's bin/*.cmd were LF-only, so cmd.exe misparsed them (whole file joined
serially → @echo off ignored → arbitrary commands executed → non-zero exit
→ installer aborted). .gitattributes (`*.cmd/*.bat/*.ps1 text eol=crlf`)
enforces CRLF at checkout; this test verifies the working tree never
regresses (a future PR that adds a LF-only .cmd fails CI).
"""

import subprocess
from pathlib import Path

REPO_ROOT = Path(__file__).resolve().parent.parent
WIN_SCRIPT_EXTS = (".cmd", ".bat", ".ps1")


def _win_scripts():
out = subprocess.check_output(["git", "ls-files"], cwd=str(REPO_ROOT), text=True)
for rel in out.splitlines():
if rel.lower().endswith(WIN_SCRIPT_EXTS):
yield REPO_ROOT / rel


def test_windows_scripts_are_crlf():
files = list(_win_scripts())
assert files, "expected at least one tracked .cmd/.bat/.ps1 file"
bad = []
for p in files:
data = p.read_bytes()
crlf = data.count(b"\r\n")
lf = data.count(b"\n")
if crlf != lf: # bare-LF lines present (LF-only or mixed endings)
bad.append(f"{p.relative_to(REPO_ROOT)}: {lf - crlf} bare-LF line(s)")
assert not bad, (
"Windows scripts must use CRLF line endings (LF-only .cmd files are "
"misparsed by cmd.exe → installer 'exit code 1'; see rant "
"2026-08-12T12:30:41):\n" + "\n".join(bad)
)
6 changes: 5 additions & 1 deletion tests/test_installer_stop.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,11 @@ def test_stop_git_ps1_guilt_by_association():
assert "Stop-Process -Id $_.ProcessId -Force" in content
# 退出码语义:无残留(或本来无进程)→ 0;仍有存活 → 1
assert "exit 1" in content and "exit 0" in content
assert 'if ($left.Count -gt 0) { exit 1 } else { exit 0 }' in content
# rant 2026-08-12T12:30:41(spec B):存活检查用最新快照 + 如实报失败——
# 幸存进程必须点名输出(不静默吞掉),有存活即 exit 1,绝不误报成功
assert 'if ($left.Count -gt 0) {' in content
assert "still running: {0} (pid {1})" in content
assert "Write-Host" in content
# 独立脚本 + 非交互(无 cmd 内联转义问题,0.2.26 转义 bug 根因规避)
assert "$ErrorActionPreference = 'SilentlyContinue'" in content

Expand Down
Loading