Stop background git from racing test_docs_mirror temp cleanup

test_staged_root_sourced_doc_with_stale_mirror_fails errored in the
"Script smoke tests & backend build" job on PR #1857 (run 33609703555)
with OSError [Errno 39] Directory not empty: '.git' raised from
TemporaryDirectory cleanup. The test body passed; a background git
process spawned by init/add/commit (auto-gc, fsmonitor, or maintenance)
was still writing under .git when shutil.rmtree ran. The suite passes on
main most of the time and locally, so this is a race, not a logic bug.

Disable gc.auto, core.fsmonitor and maintenance.auto for the throwaway
repos, and point GIT_CONFIG_GLOBAL/GIT_CONFIG_SYSTEM at os.devnull so a
runner's host config cannot re-enable them. Construct both temp
directories with ignore_cleanup_errors=True as a belt-and-braces fallback
so a straggler can never fail a test whose assertions already passed.
This commit is contained in:
rcourtman
2026-09-02 09:55:47 +01:00
parent facee87bb4
commit d227cfcb10
+21 -2
View File
@@ -4,6 +4,7 @@
from __future__ import annotations
import importlib.util
import os
from pathlib import Path
import subprocess
import sys
@@ -20,6 +21,17 @@ sys.modules[SPEC.name] = docs_mirror
SPEC.loader.exec_module(docs_mirror)
# Background git processes (auto-gc, fsmonitor, maintenance) can still be
# writing under .git when TemporaryDirectory cleanup runs, which makes rmtree
# fail with "Directory not empty". Disable them for the throwaway repos and
# ignore host config so it cannot re-enable them.
GIT_ENV = {
**os.environ,
"GIT_CONFIG_GLOBAL": os.devnull,
"GIT_CONFIG_SYSTEM": os.devnull,
}
def run_git(root: Path, *args: str) -> None:
subprocess.run(
[
@@ -30,10 +42,17 @@ def run_git(root: Path, *args: str) -> None:
"user.email=test@example.invalid",
"-c",
"user.name=test",
"-c",
"gc.auto=0",
"-c",
"core.fsmonitor=false",
"-c",
"maintenance.auto=false",
*args,
],
check=True,
capture_output=True,
env=GIT_ENV,
)
@@ -59,7 +78,7 @@ class DocsMirrorMappingTest(unittest.TestCase):
class DocsMirrorStagedTest(unittest.TestCase):
def setUp(self) -> None:
self._temporary = tempfile.TemporaryDirectory()
self._temporary = tempfile.TemporaryDirectory(ignore_cleanup_errors=True)
self.addCleanup(self._temporary.cleanup)
self.root = Path(self._temporary.name)
run_git(self.root, "init", "-q")
@@ -139,7 +158,7 @@ class DocsMirrorStagedTest(unittest.TestCase):
class DocsMirrorWorktreeTest(unittest.TestCase):
def test_worktree_drift_and_sync(self) -> None:
with tempfile.TemporaryDirectory() as temporary:
with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as temporary:
root = Path(temporary)
write(root, "docs/GUIDE.md", "# Guide v2\n")
write(root, "frontend-modern/public/docs/GUIDE.md", "# Guide v1\n")