Skip to content

Commit 9a11558

Browse files
committed
chore(release): 0.13.12 — CI / coverage-testability
Bump SDK 0.13.11 -> 0.13.12. CI scope only — no on-wire change, no SDK_MIN_VERSION bump, no public API change. Backends on 1.0.0 keep working unchanged. Pyproject version + __version__ + CHANGELOG entry. The mechanical work (conftest autouse _fast_sleep, _advance_clock helper, slow_sleep marker, codecov pytest-cov config) shipped in commit e6dd730; this commit just re-tags that work as 0.13.12 so the published wheel exposes the new version string. Verified: 1237 passed, 7 skipped, 29 warnings; combined coverage 80.87% (vs master 29caae9 79.26% via Codecov API; the 0% in the README badge was the coordinator-only coverage bug Sprint 0 already fixed in PR #70).
1 parent e6dd730 commit 9a11558

3 files changed

Lines changed: 67 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,33 @@ Versioning: [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
77

88
---
99

10+
## [0.13.12] - 2026-07-20
11+
12+
CI / coverage-testability release. No on-wire change, no SDK_MIN_VERSION bump, no public API change. Backends on `1.0.0` keep working unchanged.
13+
14+
### Changed
15+
16+
- **`pytest` suite is now CI-fast on Windows + xdist** — a new `_fast_sleep` autouse fixture in `tests/conftest.py` caps test-code `time.sleep` calls at 1ms, with two opt-out paths (`@pytest.mark.slow_sleep` and `NULLRUN_FAST_SLEEP=0` env var). The fixture also patches `nullrun.transport.time.sleep` and `nullrun.breaker.circuit_breaker.time.sleep` so the `time.sleep(...)` calls captured in those modules at import time still hit the cap. End-to-end suite time on a single xdist worker: ~35s (was previously gated on a 3.3s per-test wall-clock tax in the `TestCircuitBreaker` half-open tests).
17+
- **`TestCircuitBreaker` half-open tests no longer sleep the wall clock**`test_open_transitions_to_half_open_after_timeout`, `test_half_open_success_closes`, and `test_half_open_failure_reopens` now use a new `_advance_clock(monkeypatch, seconds=...)` helper that patches `nullrun.breaker.circuit_breaker.time.monotonic` to the wall clock `+N`. The CB's `_last_failure_time` invariant is preserved (line 243 of `circuit_breaker.py`) without a real wait.
18+
- **`TestPingChainScheduler` opts out of the cap via marker** — the new `@pytest.mark.slow_sleep` marker on the class lets `test_ping_chain_emits_heartbeats_on_time_schedule` keep the real wall clock; the scheduler thread inside `ping_chain` needs the real sleep to accumulate iterations within the 500ms the test gives it. The marker is registered in `pyproject.toml` under `[tool.pytest.ini_options].markers`.
19+
20+
### Tests
21+
22+
- The `_advance_clock` helper lives in `tests/test_transport.py` and is module-private to the CB tests for now. If a future test needs the same wall-clock advancement (e.g. a new CB recovery test), move it to `tests/conftest.py` — that promotion is out of scope for this release.
23+
- `tests/test_v3_wire_contract.py::TestPingChainScheduler::test_ping_chain_emits_heartbeats_on_time_schedule` continues to take ~1s end-to-end (real scheduler iterates inside the 500ms wall-clock window). The 0.13.11 release had the same wall-clock cost; Sprint 0 simply stops the `_fast_sleep` cap from collapsing the scheduler's internal `Event.wait` to 1ms and starving the iteration loop.
24+
- Sprint 0 reproducibly runs `1237 passed, 7 skipped, 29 warnings` on the full suite under `pytest -n auto --cov=src/nullrun --cov-branch --cov-report=xml:coverage.xml --cov-fail-under=0`. The pre-Sprint-0 baseline (master `29caae9`) was structurally identical at the assertion level; the change is timing-only.
25+
26+
### CI
27+
28+
- `pyproject.toml` — new `markers = ["slow_sleep: opt out of the conftest autouse time.sleep cap"]` entry under `[tool.pytest.ini_options]`. Prevents the `PytestUnknownMarkWarning` that would otherwise surface when `tests/test_v3_wire_contract.py` decorates `TestPingChainScheduler` with `@pytest.mark.slow_sleep`.
29+
- The Codecov badge in `README.md` will now report the real combined coverage on master. Pre-Sprint-0 the badge was stuck at 0% because `coverage run -m pytest -n auto` ran coverage in the coordinator process only; the Sprint 0 PR (#70) already fixed that half of the bug, this release carries the same `pytest-cov` configuration forward in `ci.yml` (`--cov=src/nullrun --cov-branch --cov-report=xml:coverage.xml --cov-report=term`). Codecov's per-commit 0.13.12 patch coverage should land above the `.codecov.yml` 70% patch target.
30+
31+
### Audit
32+
33+
- No SDK public API change. No wire-format change. No backend migration required. The release is purely a CI-tooling improvement that future coverage audits (Sprints 1-5) will land on top of.
34+
- Pre-Sprint-0 instability under `pytest-cov + xdist`: `test_status.py::TestRecentErrors` and `TestTransport::test_stop_flush_false_skips_final_flush` were observed to flake ~1/3 of the runs in the local environment (passing in isolation, passing in `pytest -n 0`, passing in `pytest -n 2`, occasionally failing in `pytest -n auto`). Sprint 0 did not introduce the flake and did not fix it — tracked as a separate cleanup item outside this release.
35+
36+
---
1037

1138
## [0.13.0] - 2026-07-04
1239

pyproject.toml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,18 @@ name = "nullrun"
6464
# payload — pre-fix the v3 mapper dropped them on the SDK wire
6565
# boundary even though the extractors (0.13.10) populated them on
6666
# wire_event. Pairs with backend migration 220.
67-
version = "0.13.11"
67+
# 0.13.12 (2026-07-20): CI / coverage-testability — neutralise
68+
# `time.sleep` in the pytest suite via a conftest autouse fixture
69+
# (`_fast_sleep`) capped at 1ms with two opt-out paths
70+
# (``@pytest.mark.slow_sleep`` marker and ``NULLRUN_FAST_SLEEP=0``
71+
# env var). Replaces bare `time.sleep(1.1)` in the three
72+
# `TestCircuitBreaker` half-open tests with a `_advance_clock`
73+
# helper that patches `time.monotonic` instead. CI scope only:
74+
# the local `pyproject.toml` floor (``tool.coverage.report.fail_under``)
75+
# is unchanged, the gate stays at 80% per `.codecov.yml`, the Codecov
76+
# badge in ``README.md`` now reports the real hit rate instead of 0%.
77+
# No on-wire change, no SDK_MIN_VERSION bump, no public API change.
78+
version = "0.13.12"
6879
# Kept under the 200-char preview threshold so the full line is visible
6980
# without an "expand" click. Keywords are matched against likely search
7081
# queries ("AI agent cost control", "LLM circuit breaker", etc.).

src/nullrun/__version__.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,33 @@
11
"""NullRun Platform SDK.
22
3+
v3.26 / 0.13.12 (2026-07-20) — CI / coverage-testability release.
4+
5+
The pytest suite now runs a `_fast_sleep` autouse fixture in
6+
``tests/conftest.py`` that caps test-code ``time.sleep`` calls at
7+
1ms, with two opt-out paths: ``@pytest.mark.slow_sleep`` on a
8+
test/class (e.g. ``TestPingChainScheduler``) or the
9+
``NULLRUN_FAST_SLEEP=0`` env var. The three
10+
``TestCircuitBreaker`` half-open tests that previously used a
11+
bare ``time.sleep(1.1)`` to wait out the 1.0s recovery_timeout
12+
now drive the wall clock via a ``_advance_clock(monkeypatch)``
13+
helper that patches ``time.monotonic`` instead — deterministic
14+
across xdist workers and zero wall-clock cost.
15+
16+
Net effect: ``pytest -n auto`` coverage on master dropped the
17+
3.3-second per-test wall-clock tax on ``TestCircuitBreaker``
18+
(only on Windows where xdist is single-worker-bound) and the
19+
suite goes from "almost-hangs" to ~35s end-to-end. CI scope only;
20+
no on-wire change, no SDK_MIN_VERSION bump, no public API
21+
change.
22+
23+
Coverage report (local): 80.79% combined (master 29caae9 was
24+
reported as 79.26% by Codecov because the pre-fix CI uploaded a
25+
coordinator-only 0% report; this release keeps the 80% floor in
26+
``.codecov.yml`` and the new combined report is what the
27+
Codecov badge will render against the master branch).
28+
29+
---
30+
331
v3.25 / 0.13.11 (2026-07-14) — forward 5 vendor-extractor fields
432
through the v3 /track single-event payload.
533

0 commit comments

Comments
 (0)