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
24 changes: 14 additions & 10 deletions src/hyrule_engineering_loop/gate_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

import json
import subprocess
import sys
from pathlib import Path
Expand Down Expand Up @@ -90,14 +91,17 @@ def select_gate_commands_for_mutations(paths: Iterable[str]) -> list[list[str]]:
if any(path.endswith(".py") for path in normalized):
return [[sys.executable, "-m", "compileall", "-q", "."]]
if all(path.startswith("docs/") or path.endswith((".md", ".txt", ".rst")) for path in normalized):
return [
[
sys.executable,
"-c",
(
"from pathlib import Path; "
"[p.read_text(encoding='utf-8') for p in Path('.').rglob('*') if p.is_file()]"
),
]
]
paths_literal = repr(json.dumps(normalized))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve colons in local docs paths

When a changed doc path itself contains a colon (valid in git paths on POSIX, e.g. docs/foo:bar.md from backend changed_paths), the normalization above treats it like a repo:path key and this new targeted list serializes only bar.md. The generated gate then sees bar.md missing and continues, so the actual mutated doc is never UTF-8 checked; a non-UTF-8 docs/foo:bar.md now passes even though the previous rglob scan failed. Please only strip repo prefixes for repo-scoped mutation keys, not arbitrary colon-containing paths.

Useful? React with 👍 / 👎.

script = (
"import json\n"
"from pathlib import Path\n"
f"for raw in json.loads({paths_literal}):\n"
" path = Path(raw)\n"
" if not path.exists():\n"
" continue\n"
" if not path.is_file():\n"
" raise SystemExit(f'not a file: {raw}')\n"
" path.read_text(encoding='utf-8')\n"
)
return [[sys.executable, "-c", script]]
return [[sys.executable, "-c", "from pathlib import Path; assert any(Path('.').rglob('*'))"]]
27 changes: 27 additions & 0 deletions tests/test_gate_runner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from __future__ import annotations

from hyrule_engineering_loop.gate_runner import run_gate_commands, select_gate_commands_for_mutations


def test_docs_gate_reads_only_mutated_text_paths(tmp_path) -> None:
(tmp_path / "docs").mkdir()
(tmp_path / "docs" / "note.md").write_text("hello\n", encoding="utf-8")
(tmp_path / "binary.bin").write_bytes(b"\xb8\x00not utf8")

commands = select_gate_commands_for_mutations(["engineering-loop:docs/note.md"])
results, errors = run_gate_commands(commands, cwd=tmp_path)

assert errors == []
assert results[0]["returncode"] == 0


def test_docs_gate_reports_non_utf8_mutated_file(tmp_path) -> None:
(tmp_path / "docs").mkdir()
(tmp_path / "docs" / "note.md").write_bytes(b"\xb8\x00not utf8")

commands = select_gate_commands_for_mutations(["docs/note.md"])
results, errors = run_gate_commands(commands, cwd=tmp_path)

assert results[0]["returncode"] == 1
assert errors
assert "UnicodeDecodeError" in errors[0]["stderr"]