Skip to content

Commit 0133e8e

Browse files
danielmeppielDaniel MeppielCopilot
authored
fix(tests): set hermetic HOME at conftest import time for Windows xdist workers (#1271)
The previous session-scoped autouse fixture in tests/unit/conftest.py fixed most Windows runner failures, but a single xdist worker (gw2) still hit 53 'RuntimeError: Could not determine home directory' on the windows-2025-vs2026 image -- some test or fixture resolved Path.home() before the autouse fixture's setup ran on that worker. Move the env mutation to module-level import time. Each xdist worker imports tests/unit/conftest.py once, before any fixture or collection runs, so HOME / USERPROFILE / HOMEDRIVE / HOMEPATH are guaranteed to be set before anything in the worker process can call Path.home(). Refs run https://github.com/microsoft/apm/actions/runs/25665840560 Co-authored-by: Daniel Meppiel <copilot-rework@github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 77d1dda commit 0133e8e

2 files changed

Lines changed: 25 additions & 27 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- Pin `Path.home()` under unit tests via a session-scoped autouse conftest fixture, fixing 56 Windows runner failures on the new `windows-2025-vs2026` GitHub-hosted image where `USERPROFILE`/`HOMEDRIVE`+`HOMEPATH` are not seeded for pytest workers; also patch the `_check_and_notify_updates` import binding in the disabled-self-update test so it no longer races on the version-check cache. (#1270)
1313
- `apm install` now works on macOS git 2.53.0 (Homebrew): bare-cache commands switch to `--git-dir` to satisfy the `safe.bareRepository=explicit` default; fetched SHAs are pinned as synthetic refs so `git clone --local --shared` no longer silently omits them. (#1268)
14+
- Set the unit-test hermetic HOME at conftest import time so a single xdist worker on the `windows-2025-vs2026` runner can no longer race fixture setup and re-trigger the 53 `Path.home()` failures the session-scoped autouse fixture was supposed to prevent. (#1271)
1415

1516
## [0.13.0] - 2026-05-11
1617

tests/unit/conftest.py

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,50 @@
11
"""Unit-test conftest: hermetic HOME isolation.
22
3-
The session-scoped autouse fixture below pins ``Path.home()`` to a tmp
4-
directory for the entire unit-test session. Two reasons:
3+
This module sets ``HOME`` (POSIX) / ``USERPROFILE`` + ``HOMEDRIVE`` +
4+
``HOMEPATH`` (Windows) to a process-wide tmp directory **at import
5+
time**, before any fixture or test resolution. Two reasons:
56
67
1. Hermeticity. Unit tests must not read or write the contributor's real
78
``~`` (config files, runtimes, caches). Tests that call
89
``RuntimeManager()`` or ``Path.home()`` directly previously inherited
910
whatever HOME the runner had.
1011
2. Windows runner robustness. On the ``windows-2025-vs2026`` GitHub
1112
Actions image the ``USERPROFILE`` / ``HOMEDRIVE`` + ``HOMEPATH``
12-
triplet is not set under the pytest worker subprocess, so
13+
triplet is not set under the pytest-xdist worker subprocess, so
1314
``Path.home()`` raises ``RuntimeError: Could not determine home
14-
directory.`` This fixture sets the platform-correct trio so
15-
``Path.home()`` always resolves to ``<tmp>`` regardless of runner
16-
image.
15+
directory.``
16+
17+
Why import-time and not a session-scoped autouse fixture: a previous
18+
attempt used ``@pytest.fixture(scope="session", autouse=True)`` and
19+
still failed on a single xdist worker (``gw2`` on Windows). Whatever
20+
the cause (worker scheduling order, a downstream fixture resolving
21+
``Path.home()`` before the autouse fixture's setup completed), running
22+
the env mutation at conftest import time guarantees the env vars are
23+
in place before pytest collects, schedules, or runs anything in this
24+
worker process. Pytest imports each test directory's conftest.py once
25+
per worker, before any fixtures run.
1726
1827
Per-test fixtures that need a different HOME (e.g. tests/unit/integration
1928
that exercise scope resolution) keep using ``monkeypatch.setenv`` and
20-
override this baseline; the function-scoped monkeypatch wins over the
21-
session-scoped baseline for the duration of the test.
29+
override this baseline; monkeypatch's snapshot/restore cycle preserves
30+
this baseline across tests.
2231
"""
2332

2433
from __future__ import annotations
2534

2635
import os
36+
import tempfile
2737
from pathlib import Path
2838

29-
import pytest
30-
3139

3240
def _set_home_env(home: Path) -> None:
3341
"""Set ``HOME`` and the Windows-equivalent vars to ``home``.
3442
3543
``Path.home()`` consults ``HOME`` on POSIX but ``USERPROFILE``
36-
(with ``HOMEDRIVE`` + ``HOMEPATH`` fallback) on Windows.
44+
(with ``HOMEDRIVE`` + ``HOMEPATH`` fallback) on Windows. We
45+
overwrite unconditionally because the Windows runner sometimes
46+
leaves these keys present but empty, which still trips
47+
``Path.home()``.
3748
"""
3849
home_str = str(home)
3950
os.environ["HOME"] = home_str
@@ -45,19 +56,5 @@ def _set_home_env(home: Path) -> None:
4556
os.environ["HOMEPATH"] = tail
4657

4758

48-
@pytest.fixture(scope="session", autouse=True)
49-
def _hermetic_home(tmp_path_factory: pytest.TempPathFactory) -> None:
50-
"""Pin ``Path.home()`` to a per-session tmp dir for all unit tests."""
51-
home = tmp_path_factory.mktemp("apm-unit-home")
52-
previous = {
53-
key: os.environ.get(key) for key in ("HOME", "USERPROFILE", "HOMEDRIVE", "HOMEPATH")
54-
}
55-
_set_home_env(home)
56-
try:
57-
yield
58-
finally:
59-
for key, value in previous.items():
60-
if value is None:
61-
os.environ.pop(key, None)
62-
else:
63-
os.environ[key] = value
59+
_TMP_HOME = Path(tempfile.mkdtemp(prefix="apm-unit-home-"))
60+
_set_home_env(_TMP_HOME)

0 commit comments

Comments
 (0)