Skip to content

Commit de74a49

Browse files
improvements
1 parent 3da7019 commit de74a49

2 files changed

Lines changed: 38 additions & 46 deletions

File tree

.github/workflows/consumer_test.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,13 @@ jobs:
4242
egress-policy: audit
4343

4444
- name: Checkout PR
45-
uses: actions/checkout@v4.2.2
45+
uses: actions/checkout@v6.0.2
4646

4747
- name: Prepare Python
48-
run: |
49-
bazel run //:ide_support
48+
run: bazel run //:ide_support
5049

5150
- name: Run Consumer tests
52-
run: .venv_docs/bin/python -m pytest -vv src/tests/ -k "$CONSUMER"
51+
run: .venv_docs/bin/python -m pytest -vv -s src/tests/test_consumer.py -k "$CONSUMER"
5352
env:
5453
FORCE_COLOR: "1"
5554
TERM: xterm-256color

src/tests/test_consumer.py

Lines changed: 35 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -13,31 +13,25 @@
1313
"""
1414
Consumer tests: verify that downstream repos build successfully against this branch.
1515
16-
Run all tests:
16+
Via Python (requires ide_support to have been run first):
17+
bazel run //:ide_support # once, to set up .venv_docs
1718
python -m pytest src/tests/test_consumer.py -s
18-
19-
Filter by repo or override type (pytest -k):
2019
python -m pytest src/tests/test_consumer.py -k "score and local"
2120
python -m pytest src/tests/test_consumer.py -k "process_description"
22-
23-
Use a temp dir instead of the persistent cache:
2421
python -m pytest src/tests/test_consumer.py --disable-cache
2522
2623
Known non-passing tests are sometimes marked xfail and do not count as failures.
2724
"""
2825

29-
import atexit
30-
import random
3126
import re
3227
import shutil
3328
import subprocess
29+
import warnings
3430
from dataclasses import dataclass
3531
from pathlib import Path
3632

3733
import pytest
38-
from _pytest.config import Config
3934
from pytest import TempPathFactory
40-
from rich.console import Console
4135

4236
from src.helper_lib import find_git_root, get_current_git_hash, get_github_base_url
4337

@@ -46,9 +40,6 @@
4640
# ---------------------------------------------------------------------------
4741

4842
CACHE_DIR = Path.home() / ".cache" / "docs_as_code_consumer_tests"
49-
_log_fp = open("consumer_test.log", "a", encoding="utf-8") # noqa: SIM115
50-
atexit.register(_log_fp.close)
51-
_console = Console(file=_log_fp, force_terminal=False, width=120, color_system=None)
5243

5344
# ---------------------------------------------------------------------------
5445
# Data model
@@ -130,7 +121,7 @@ def _strip_score_docs_overrides(content: str) -> str:
130121
return "\n".join(result) + ("\n" if content.endswith("\n") else "")
131122

132123

133-
_BAZEL_DEP_PATTERN = r'bazel_dep\(name = "score_docs_as_code"(?:, version = "[^"]+")?\)'
124+
_BAZEL_DEP_PATTERN = r"""^bazel_dep\(name = ["']score_docs_as_code["'](?:, version = ["'][^"']+["'])?\)"""
134125

135126

136127
def _write_module_bazel(
@@ -155,20 +146,20 @@ def _write_module_bazel(
155146
)"""
156147

157148
(repo_path / "MODULE.bazel").write_text(
158-
re.sub(_BAZEL_DEP_PATTERN, replacement, base), encoding="utf-8"
149+
re.sub(_BAZEL_DEP_PATTERN, replacement, base, flags=re.MULTILINE), encoding="utf-8"
159150
)
160151

161152

162153
# ---------------------------------------------------------------------------
163154
# Repo helpers
164155
# ---------------------------------------------------------------------------
165156

166-
_cloned: set[str] = set()
157+
_cloned: set[Path] = set()
167158

168159

169160
def _ensure_repo(repo_path: Path, git_url: str, use_cache: bool) -> None:
170-
"""Clone or update a repo exactly once per session per repo name."""
171-
if repo_path.name in _cloned:
161+
"""Clone or update a repo exactly once per session per path."""
162+
if repo_path in _cloned:
172163
return
173164
if repo_path.exists():
174165
if use_cache:
@@ -199,23 +190,25 @@ def _ensure_repo(repo_path: Path, git_url: str, use_cache: bool) -> None:
199190
capture_output=True,
200191
cwd=repo_path.parent,
201192
)
202-
_cloned.add(repo_path.name)
193+
_cloned.add(repo_path)
203194

204195

205196
def _cleanup_before_cmd(cwd: Path, cmd: str) -> None:
197+
# ubproject.toml is created by :docs
206198
for p in cwd.glob("*/ubproject.toml"):
207199
p.unlink()
200+
201+
# _build is created by :docs
208202
shutil.rmtree(cwd / "_build", ignore_errors=True)
203+
204+
# for ide_support, also clear the venv and bazel cache to ensure a clean slate
209205
if cmd == "bazel run //:ide_support":
210206
shutil.rmtree(cwd / ".venv_docs", ignore_errors=True)
211-
subprocess.run(["bazel", "clean", "--async"], text=True, cwd=cwd)
207+
subprocess.run(["bazel", "clean", "--async"], check=True, text=True, cwd=cwd)
212208

213209

214210
def _run_bazel_cmd(cmd: str, repo_name: str, cwd: Path) -> None:
215-
"""Stream a bazel command to the log file; fail on non-zero exit or warnings."""
216-
_console.print(f"\n[cyan]{'=' * 80}[/cyan]")
217-
_console.print(f"[cornflower_blue]{repo_name}: {cmd}[/cornflower_blue]")
218-
211+
"""Stream a bazel command to stdout; fail on non-zero exit, warn on WARNING lines."""
219212
process = subprocess.Popen(
220213
cmd.split(),
221214
stdout=subprocess.PIPE,
@@ -226,16 +219,12 @@ def _run_bazel_cmd(cmd: str, repo_name: str, cwd: Path) -> None:
226219
)
227220

228221
assert process.stdout is not None
229-
for line in iter(process.stdout.readline, ""):
230-
_console.print(line.rstrip())
222+
for line in process.stdout:
223+
print(line, end="")
231224
if "WARNING" in line:
232-
process.terminate()
233-
process.wait()
234-
pytest.fail(
235-
f"Unexpected warning in {repo_name} `{cmd}`: {line.strip()}",
236-
pytrace=False,
237-
)
225+
warnings.warn(f"{repo_name} `{cmd}`: {line.strip()}", stacklevel=2)
238226
process.stdout.close()
227+
239228
rc = process.wait()
240229
if rc != 0:
241230
pytest.fail(
@@ -250,20 +239,20 @@ def _run_bazel_cmd(cmd: str, repo_name: str, cwd: Path) -> None:
250239

251240

252241
@pytest.fixture(scope="module")
253-
def sphinx_base_dir(tmp_path_factory: TempPathFactory, pytestconfig: Config) -> Path:
242+
def repos_base_dir(tmp_path_factory: TempPathFactory, pytestconfig: pytest.Config) -> Path:
254243
if pytestconfig.getoption("--disable-cache"):
255244
return tmp_path_factory.mktemp("consumer_tests")
256245
CACHE_DIR.mkdir(parents=True, exist_ok=True)
257246
return CACHE_DIR
258247

259248

260249
@pytest.fixture(scope="module")
261-
def consumer_env(sphinx_base_dir: Path) -> tuple[str, str]:
250+
def consumer_env(repos_base_dir: Path) -> tuple[str, str]:
262251
"""Resolve git metadata and set up the local symlink used by local_path_override."""
263252
git_root = find_git_root()
264253
assert git_root, "Git root not found"
265254

266-
dest = sphinx_base_dir / "docs_as_code"
255+
dest = repos_base_dir / "docs_as_code"
267256
if dest.is_symlink():
268257
dest.unlink()
269258
elif dest.is_dir():
@@ -279,7 +268,7 @@ def consumer_env(sphinx_base_dir: Path) -> tuple[str, str]:
279268

280269

281270
def _check_remote_available() -> tuple[bool, str]:
282-
"""Return (available, skip_reason). Called once at module import."""
271+
"""Return (available, reason). Called once at module import."""
283272
git_root = find_git_root()
284273
if git_root is None:
285274
return False, "git root not found"
@@ -329,12 +318,13 @@ def _make_params() -> list[pytest.param]: # type: ignore[type-arg]
329318
for override in ("local", "remote"):
330319
for cmd in repo.commands:
331320
marks = []
332-
if override == "remote" and not _REMOTE_AVAILABLE:
333-
marks.append(pytest.mark.skip(reason=_REMOTE_SKIP_REASON))
334-
if repo.name == "module_template" and random.choice([True, False]):
321+
if (
322+
repo.name == "module_template"
323+
and cmd == "bazel build //:needs_json"
324+
):
335325
marks.append(
336326
pytest.mark.xfail(
337-
reason="module_template is currently broken",
327+
reason="needs_json in module_template is currently broken",
338328
strict=False,
339329
)
340330
)
@@ -355,14 +345,17 @@ def test_consumer_repo(
355345
repo: ConsumerRepo,
356346
override_type: str,
357347
cmd: str,
358-
sphinx_base_dir: Path,
348+
repos_base_dir: Path,
359349
consumer_env: tuple[str, str],
360-
pytestconfig: Config,
350+
pytestconfig: pytest.Config,
361351
) -> None:
352+
if override_type == "remote" and not _REMOTE_AVAILABLE:
353+
pytest.fail(_REMOTE_SKIP_REASON, pytrace=False)
354+
362355
gh_url, current_hash = consumer_env
363356
use_cache = not bool(pytestconfig.getoption("--disable-cache"))
364357

365-
repo_path = sphinx_base_dir / repo.name
358+
repo_path = repos_base_dir / repo.name
366359
_ensure_repo(repo_path, repo.git_url, use_cache)
367360
_write_module_bazel(repo_path, override_type, current_hash, gh_url)
368361
_cleanup_before_cmd(repo_path, cmd)

0 commit comments

Comments
 (0)