11#!/usr/bin/env python3
22"""localpibox.stack.release tests: docs readiness (verdict/gate math, state
3- from real git repos, docs-ready end-to-end with stub generate.py + fake
4- mike , idempotency, re-flag after drift) and release-state VERSION-only
5- conflict handling (devstack stable branch)."""
3+ from real git repos, docs-ready end-to-end with stub generate.py +
4+ intercepted mkdocs build , idempotency, re-flag after drift) and
5+ release-state VERSION-only conflict handling (devstack stable branch)."""
66from __future__ import annotations
77
88from testharness import run_lpbx_suite , _quiet_console
99
1010import os
11- import stat
1211import subprocess
1312from unittest import mock
1413
2221print("stub generate ok")
2322"""
2423
25- _FAKE_MIKE = """#!/bin/sh
26- if [ "$1" = "build" ]; then
27- mkdir -p docs/site
28- echo built > docs/site/.marker
29- fi
30- exit 0
31- """
32-
3324
3425def _g (dir_ , * args ):
3526 return subprocess .run (["git" , "-C" , str (dir_ ), * args ], check = True ,
@@ -65,21 +56,30 @@ def _fake_stack(tmpdir):
6556 return clone
6657
6758
68- def _patch_release (clone , tmpdir , with_mike = False ):
69- env = {"LPB_DOCS_PREVIEW" : str (tmpdir / "preview" )}
70- if with_mike :
71- binr = tmpdir / "bin"
72- binr .mkdir (exist_ok = True )
73- mike = binr / "mike"
74- mike .write_text (_FAKE_MIKE )
75- mike .chmod (0o755 )
76- env ["PATH" ] = f"{ binr } { os .pathsep } { os .environ ['PATH' ]} "
77- return (mock .patch .multiple (
78- rel ,
79- repo_path = lambda name : clone ,
80- get_version = lambda : (clone / "VERSION" ).read_text ().strip (),
81- ),
82- mock .patch .dict (os .environ , env ))
59+ def _patch_release (clone , tmpdir ):
60+ return mock .patch .multiple (
61+ rel ,
62+ repo_path = lambda name : clone ,
63+ get_version = lambda : (clone / "VERSION" ).read_text ().strip (),
64+ ), mock .patch .dict (os .environ , {"LPB_DOCS_PREVIEW" : str (tmpdir / "preview" )})
65+
66+
67+ def _patch_build ():
68+ """Intercept the mkdocs build call (keeps tests hermetic — CI has no
69+ mkdocs). Emulates writing site/ *relative to the cwd kwarg*, so a wrong
70+ cwd is caught by the marker assertions."""
71+ import pathlib
72+ real = rel .run_cmd
73+
74+ def fake (args , ** kw ):
75+ if any ("mkdocs" in a for a in args ):
76+ site = pathlib .Path (kw .get ("cwd" ) or "." ) / "site"
77+ site .mkdir (parents = True , exist_ok = True )
78+ (site / ".marker" ).write_text ("built\n " )
79+ return "ok\n " , "" , 0
80+ return real (args , ** kw )
81+
82+ return mock .patch .object (rel , "run_cmd" , fake )
8383
8484
8585# ─── pure math ────────────────────────────────────────────────────────────
@@ -218,8 +218,8 @@ def test_release_state_real_conflict(tmpdir):
218218
219219def test_docs_ready_flags_and_pushes (tmpdir ):
220220 clone = _fake_stack (tmpdir )
221- p1 , p2 = _patch_release (clone , tmpdir , with_mike = True )
222- with p1 , p2 :
221+ p1 , p2 = _patch_release (clone , tmpdir )
222+ with p1 , p2 , _patch_build () :
223223 code = rel .cmd_release_docs_ready (assume_yes = True , cons = _quiet_console ())
224224 assert code == 0
225225 remote = tmpdir / "remotes" / "devstack.git"
@@ -228,14 +228,14 @@ def test_docs_ready_flags_and_pushes(tmpdir):
228228 # dev content is merged into docs on the remote
229229 doc = _g (remote , "show" , "refs/heads/docs:doc/x.md" ).stdout
230230 assert doc == "content v1\n "
231- # mike/generate ran in the preview worktree, not the caller's cwd
232- assert (tmpdir / "preview" / "docs" / " site" / ".marker" ).is_file ()
231+ # mkdocs build ran in the preview worktree, not the caller's cwd
232+ assert (tmpdir / "preview" / "site" / ".marker" ).is_file ()
233233
234234
235235def test_docs_ready_idempotent (tmpdir ):
236236 clone = _fake_stack (tmpdir )
237- p1 , p2 = _patch_release (clone , tmpdir , with_mike = True )
238- with p1 , p2 :
237+ p1 , p2 = _patch_release (clone , tmpdir )
238+ with p1 , p2 , _patch_build () :
239239 assert rel .cmd_release_docs_ready (assume_yes = True ,
240240 cons = _quiet_console ()) == 0
241241 # second run: already ready → no-op
@@ -245,16 +245,16 @@ def test_docs_ready_idempotent(tmpdir):
245245
246246def test_docs_ready_reflag_after_drift (tmpdir ):
247247 clone = _fake_stack (tmpdir )
248- p1 , p2 = _patch_release (clone , tmpdir , with_mike = True )
249- with p1 , p2 :
248+ p1 , p2 = _patch_release (clone , tmpdir )
249+ with p1 , p2 , _patch_build () :
250250 assert rel .cmd_release_docs_ready (assume_yes = True ,
251251 cons = _quiet_console ()) == 0
252252 # doc content changes on dev → stale until re-flagged
253253 _g (clone , "checkout" , "dev" )
254254 (clone / "doc" / "x.md" ).write_text ("content v3\n " )
255255 _g (clone , "commit" , "-qam" , "v3" )
256256 _g (clone , "push" , "-q" , "origin" , "dev" )
257- with p1 , p2 :
257+ with p1 , p2 , _patch_build () :
258258 assert rel ._docs_release_state ()["verdict" ] == "stale"
259259 assert rel .cmd_release_docs_ready (assume_yes = True ,
260260 cons = _quiet_console ()) == 0
0 commit comments