Skip to content

Commit a162c4a

Browse files
committed
fix: give the verdict tests their own env file so they pass in CI
The new test file could not pass in CI, and the review caught it with the failing run: `Fast tests` was red on this PR while local `quality-check.sh` was green. Reproduced both sides before fixing. Cause: request-pr-review.sh posts its trigger through scripts/gh-agent.sh, which reads a real BESS_AGENT_TOKEN and exits 1 before `gh` is reached. Shimming `gh` on PATH does not help -- gh-agent.sh is invoked by a repo-relative path, not looked up on PATH. Worse, it resolves its env file from the MAIN checkout (`dirname $(git rev-parse --git-common-dir)`), so this worktree having no `.env` of its own was irrelevant: the developer's real token was read anyway. CI provisions no `.env` and no such secret, so the suite failed unconditionally there. The abandoned `(d / "scripts").mkdir(...)` in the fixture was an attempt at this that did nothing. Fixed with the seam gh-agent.sh already documents for exactly this (`BESS_ENV_FILE`, "a seam tests use to point at a fixture .env instead"), so no production code changes: each test now supplies its own env file carrying a dummy token. Also adds a test that PINS that dependency, because the fix is otherwise invisible and could be dropped again silently: point the seam at an empty file and the script must fail before polling, naming the missing token. Worth recording how I nearly mis-verified this: my first attempt set BESS_ENV_FILE from OUTSIDE pytest and saw the tests still pass, which looked like proof of CI-safety. It was not -- the test sets that variable in the subprocess env, so it overrides any outer value and the experiment could not fail. The in-test pin above is the version that can actually discriminate. Full backend suite: 507 passed.
1 parent d2cf70b commit a162c4a

1 file changed

Lines changed: 76 additions & 17 deletions

File tree

backend/tests/test_request_pr_review.py

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,31 @@ def _write(path: Path, body: str) -> None:
3232
def bin_dir(tmp_path: Path) -> Path:
3333
d = tmp_path / "bin"
3434
d.mkdir()
35-
# The trigger comment goes through gh-agent.sh; make it a no-op.
36-
(d / "scripts").mkdir(parents=True, exist_ok=True)
3735
return d
3836

3937

38+
@pytest.fixture
39+
def env_file(tmp_path: Path) -> Path:
40+
"""A fixture `.env` for `scripts/gh-agent.sh`, via its `BESS_ENV_FILE` seam.
41+
42+
The script posts its trigger comment through gh-agent.sh, which reads a real
43+
token and exits 1 before `gh` is ever reached:
44+
45+
token="${!token_var:-}"
46+
if [ -z "$token" ]; then echo "... is not set in ${env_file}"; exit 1; fi
47+
48+
Shimming `gh` on PATH does not help, because gh-agent.sh is invoked by a
49+
repo-relative path rather than looked up on PATH. Without this the suite
50+
needs a real `BESS_AGENT_TOKEN` in the gitignored `.env`, so it passes on a
51+
developer machine and fails unconditionally in CI — which is exactly what
52+
happened: `Fast tests` went red while local `quality-check.sh` was green,
53+
because a real local `.env` papered over the gap.
54+
"""
55+
p = tmp_path / "fixture.env"
56+
p.write_text("BESS_AGENT_TOKEN=dummy-token-for-tests\n")
57+
return p
58+
59+
4060
def _gh(bin_dir: Path, reviews: list, run_state: str) -> None:
4161
"""A `gh` answering the two queries the script makes.
4262
@@ -91,11 +111,14 @@ def _review(state: str, at: str = "2099-01-01T00:00:01Z", body: str = "x") -> di
91111
return {"state": state, "submittedAt": at, "body": body, "author": {"login": "bot"}}
92112

93113

94-
def _run(bin_dir: Path, timeout: int = 2) -> subprocess.CompletedProcess:
114+
def _run(
115+
bin_dir: Path, env_file: Path, timeout: int = 2
116+
) -> subprocess.CompletedProcess:
95117
env = dict(
96118
os.environ,
97119
PATH=f"{bin_dir}:{os.environ['PATH']}",
98120
REVIEW_POLL_INTERVAL="1",
121+
BESS_ENV_FILE=str(env_file),
99122
)
100123
return subprocess.run(
101124
["bash", str(SCRIPT), "622", str(timeout)],
@@ -106,21 +129,49 @@ def _run(bin_dir: Path, timeout: int = 2) -> subprocess.CompletedProcess:
106129
)
107130

108131

109-
def test_approved_returns_immediately(bin_dir: Path) -> None:
132+
def test_a_missing_token_fails_loudly_and_is_why_the_seam_exists(
133+
bin_dir: Path, tmp_path: Path
134+
) -> None:
135+
"""Pins the dependency the other tests satisfy, so the seam cannot be
136+
quietly dropped again.
137+
138+
Every other test passes its own `BESS_ENV_FILE`. Without one, gh-agent.sh
139+
resolves the env file from the MAIN checkout — `dirname $(git
140+
rev-parse --git-common-dir)` — so a worktree with no `.env` of its own still
141+
read the developer's real token and the suite passed locally while failing
142+
unconditionally in CI, where no `.env` is provisioned.
143+
144+
Point the seam at an empty file and the script must fail before polling,
145+
with the reason named.
146+
"""
147+
empty = tmp_path / "empty.env"
148+
empty.write_text("")
149+
_gh(bin_dir, [_review("APPROVED")], "finished")
150+
151+
proc = _run(bin_dir, empty)
152+
153+
assert proc.returncode != 0
154+
assert "VERDICT" not in proc.stdout
155+
assert "BESS_AGENT_TOKEN is not set" in proc.stderr
156+
157+
158+
def test_approved_returns_immediately(bin_dir: Path, env_file: Path) -> None:
110159
_gh(bin_dir, [_review("APPROVED")], "running")
111-
proc = _run(bin_dir)
160+
proc = _run(bin_dir, env_file)
112161
assert proc.returncode == 0
113162
assert "VERDICT APPROVED" in proc.stdout
114163

115164

116-
def test_changes_requested_returns_immediately(bin_dir: Path) -> None:
165+
def test_changes_requested_returns_immediately(bin_dir: Path, env_file: Path) -> None:
117166
_gh(bin_dir, [_review("CHANGES_REQUESTED")], "running")
118-
proc = _run(bin_dir)
167+
proc = _run(bin_dir, env_file)
119168
assert proc.returncode == 0
120169
assert "VERDICT CHANGES_REQUESTED" in proc.stdout
121170

122171

123-
def test_commented_while_running_is_not_a_verdict(bin_dir: Path) -> None:
172+
def test_commented_while_running_is_not_a_verdict(
173+
bin_dir: Path, env_file: Path
174+
) -> None:
124175
"""The bug, three rounds running.
125176
126177
The bot posts an early permission-check comment and keeps working for
@@ -133,49 +184,57 @@ def test_commented_while_running_is_not_a_verdict(bin_dir: Path) -> None:
133184
[_review("COMMENTED", body="test permission check - ignore")],
134185
"running",
135186
)
136-
proc = _run(bin_dir)
187+
proc = _run(bin_dir, env_file)
137188

138189
assert proc.returncode == 2
139190
assert "VERDICT" not in proc.stdout
140191
assert "still running" in proc.stderr
141192

142193

143-
def test_commented_after_the_run_finished_is_the_verdict(bin_dir: Path) -> None:
194+
def test_commented_after_the_run_finished_is_the_verdict(
195+
bin_dir: Path, env_file: Path
196+
) -> None:
144197
"""The opposite failure. `pr-review.yml` lists COMMENT as one of three final
145198
verdicts, so once the run is over a COMMENTED last word IS the answer —
146199
swallowing it made the script report "no summary" while findings sat on the
147200
PR."""
148201
_gh(bin_dir, [_review("COMMENTED")], "finished")
149-
proc = _run(bin_dir)
202+
proc = _run(bin_dir, env_file)
150203

151204
assert proc.returncode == 0
152205
assert "VERDICT COMMENTED" in proc.stdout
153206

154207

155-
def test_a_failed_run_reports_at_once_instead_of_waiting(bin_dir: Path) -> None:
208+
def test_a_failed_run_reports_at_once_instead_of_waiting(
209+
bin_dir: Path, env_file: Path
210+
) -> None:
156211
"""A dead run and a thinking one are both silence if you only poll reviews.
157212
#623's run died on `Reached maximum number of turns (60)` and the wait
158213
continued for 16 minutes."""
159214
_gh(bin_dir, [], "failed")
160-
proc = _run(bin_dir, timeout=60)
215+
proc = _run(bin_dir, env_file, timeout=60)
161216

162217
assert proc.returncode == 2
163218
assert "FAILED" in proc.stderr
164219
assert "not a slow one" in proc.stderr
165220

166221

167-
def test_no_run_at_all_is_reported_as_a_trigger_fault(bin_dir: Path) -> None:
222+
def test_no_run_at_all_is_reported_as_a_trigger_fault(
223+
bin_dir: Path, env_file: Path
224+
) -> None:
168225
"""#619 failed this way twice: the trigger never reached the workflow, which
169226
needs a different response from a stalled review."""
170227
_gh(bin_dir, [], "none")
171-
proc = _run(bin_dir)
228+
proc = _run(bin_dir, env_file)
172229

173230
assert proc.returncode == 2
174231
assert "No PR Review run started at all" in proc.stderr
175232
assert "actor gate" in proc.stderr
176233

177234

178-
def test_a_decisive_verdict_wins_over_an_earlier_commented(bin_dir: Path) -> None:
235+
def test_a_decisive_verdict_wins_over_an_earlier_commented(
236+
bin_dir: Path, env_file: Path
237+
) -> None:
179238
"""Ordering, not recency of any state: the stub is older, the verdict newer."""
180239
_gh(
181240
bin_dir,
@@ -185,7 +244,7 @@ def test_a_decisive_verdict_wins_over_an_earlier_commented(bin_dir: Path) -> Non
185244
],
186245
"running",
187246
)
188-
proc = _run(bin_dir)
247+
proc = _run(bin_dir, env_file)
189248

190249
assert proc.returncode == 0
191250
assert "VERDICT CHANGES_REQUESTED" in proc.stdout

0 commit comments

Comments
 (0)