Skip to content

Commit b22dfa6

Browse files
committed
🐛 fix: reject dual stdin for review suggestions
1 parent 0e8d984 commit b22dfa6

4 files changed

Lines changed: 46 additions & 1 deletion

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,8 @@ gh-llm pr review-submit \
245245

246246
`pr comment-edit`, `issue comment-edit`, `thread-reply`, `review-comment`, `review-suggest`, and `review-submit` all support `--body-file -` to read multi-line text from standard input. `review-suggest` also supports `--suggestion-file -` for the suggestion block itself.
247247

248+
> Note: `review-suggest --body-file - --suggestion-file -` is intentionally rejected because standard input can only be consumed once. Use separate files when both the reason text and suggestion block need external input.
249+
248250
Submit behavior:
249251

250252
- If you already have a pending review on this PR, `review-submit` submits that pending review.

src/gh_llm/commands/options.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def resolve_file_or_inline_text(
2020
default: str = "",
2121
) -> str:
2222
file_path = getattr(args, file_attr, None)
23-
if file_path:
23+
if file_path is not None:
2424
return read_text_from_path_or_stdin(str(file_path))
2525
text = getattr(args, text_attr, None)
2626
if text is None:

src/gh_llm/commands/pr.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,13 @@ def _resolve_suggestion_argument(args: Any) -> str:
361361
return resolve_file_or_inline_text(args, text_attr="suggestion", file_attr="suggestion_file")
362362

363363

364+
def _validate_review_suggest_stdin_sources(args: Any) -> None:
365+
if getattr(args, "body_file", None) == "-" and getattr(args, "suggestion_file", None) == "-":
366+
raise RuntimeError(
367+
"`--body-file -` cannot be combined with `--suggestion-file -`; standard input can only be consumed once"
368+
)
369+
370+
364371
def _resolve_review_submit_body(args: Any) -> str:
365372
return _resolve_body_argument(args)
366373

@@ -1083,6 +1090,7 @@ def cmd_pr_review_comment(args: Any) -> int:
10831090

10841091

10851092
def cmd_pr_review_suggest(args: Any) -> int:
1093+
_validate_review_suggest_stdin_sources(args)
10861094
client = GitHubClient()
10871095
meta = _resolve_pr_meta(client=client, args=args)
10881096
_validate_pr_head_snapshot(meta=meta, requested_head=_resolve_requested_head(args))

tests/test_cli.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2373,6 +2373,41 @@ def test_pr_review_suggest_rejects_suggestion_and_suggestion_file_together(
23732373
assert "argument --suggestion-file: not allowed with argument --suggestion" in err
23742374

23752375

2376+
def test_pr_review_suggest_rejects_dual_stdin_inputs(
2377+
monkeypatch: pytest.MonkeyPatch,
2378+
capsys: pytest.CaptureFixture[str],
2379+
) -> None:
2380+
responder = GhResponder()
2381+
monkeypatch.setattr(github_api.subprocess, "run", responder.run)
2382+
monkeypatch.setattr(sys, "stdin", _FakeStdin("shared stdin\n"))
2383+
2384+
code = cli.run(
2385+
[
2386+
"pr",
2387+
"review-suggest",
2388+
"--path",
2389+
"python/test_file.py",
2390+
"--line",
2391+
"20",
2392+
"--side",
2393+
"RIGHT",
2394+
"--body-file",
2395+
"-",
2396+
"--suggestion-file",
2397+
"-",
2398+
"--pr",
2399+
"77928",
2400+
"--repo",
2401+
"PaddlePaddle/Paddle",
2402+
]
2403+
)
2404+
2405+
assert code == 1
2406+
err = capsys.readouterr().err
2407+
assert "`--body-file -` cannot be combined with `--suggestion-file -`" in err
2408+
assert not any(call[:3] == ["gh", "api", "graphql"] for call in responder.calls)
2409+
2410+
23762411
def _extract_form(cmd: list[str], key: str) -> str:
23772412
for idx, token in enumerate(cmd):
23782413
if token == "-f" and idx + 1 < len(cmd):

0 commit comments

Comments
 (0)