Skip to content

Commit 196f2b6

Browse files
Add regression tests for --base-dir workspace path override
1 parent 45c36ac commit 196f2b6

2 files changed

Lines changed: 81 additions & 1 deletion

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"""Regression tests for issue #4 — --base-dir must not mutate WORKSPACE_PATH."""
2+
3+
from __future__ import annotations
4+
5+
import os
6+
import sys
7+
import unittest
8+
from unittest.mock import patch
9+
10+
REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
11+
if REPO_ROOT not in sys.path:
12+
sys.path.insert(0, REPO_ROOT)
13+
14+
from scripts import export as export_script # noqa: E402
15+
16+
17+
class TestExportBaseDirOverride(unittest.TestCase):
18+
def test_main_passes_base_dir_as_resolve_override(self):
19+
opts = {
20+
"since": "all",
21+
"out_dir": ".",
22+
"include_composer": False,
23+
"zip": True,
24+
"exclusion_rules_path": None,
25+
"base_dir": "/custom/workspace",
26+
}
27+
with patch.object(export_script, "parse_args", return_value=opts):
28+
with patch.object(
29+
export_script,
30+
"collect_export_entries",
31+
return_value=[],
32+
) as mock_collect:
33+
with patch.object(
34+
export_script,
35+
"resolve_workspace_path",
36+
return_value="/resolved/workspace",
37+
) as mock_resolve:
38+
with self.assertRaises(SystemExit) as ctx:
39+
export_script.main()
40+
self.assertEqual(ctx.exception.code, 0)
41+
mock_resolve.assert_called_once_with(override="/custom/workspace")
42+
mock_collect.assert_called_once()
43+
self.assertEqual(
44+
mock_collect.call_args.kwargs["workspace_path"],
45+
"/resolved/workspace",
46+
)
47+
48+
def test_base_dir_does_not_mutate_workspace_path_env(self):
49+
opts = {
50+
"since": "all",
51+
"out_dir": ".",
52+
"include_composer": False,
53+
"zip": True,
54+
"exclusion_rules_path": None,
55+
"base_dir": "/custom/workspace",
56+
}
57+
sentinel = "/original/env/workspace"
58+
prior = os.environ.get("WORKSPACE_PATH")
59+
os.environ["WORKSPACE_PATH"] = sentinel
60+
try:
61+
with patch.object(export_script, "parse_args", return_value=opts):
62+
with patch.object(export_script, "collect_export_entries", return_value=[]):
63+
with patch.object(
64+
export_script,
65+
"resolve_workspace_path",
66+
return_value="/resolved/workspace",
67+
):
68+
with self.assertRaises(SystemExit):
69+
export_script.main()
70+
self.assertEqual(os.environ.get("WORKSPACE_PATH"), sentinel)
71+
finally:
72+
if prior is None:
73+
os.environ.pop("WORKSPACE_PATH", None)
74+
else:
75+
os.environ["WORKSPACE_PATH"] = prior
76+
77+
78+
if __name__ == "__main__":
79+
unittest.main()

utils/workspace_path.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99

1010
from .path_helpers import expand_tilde_path
1111

12-
# Module-level override set via POST /api/set-workspace (or --base-dir).
12+
# Module-level override set via POST /api/set-workspace.
13+
# CLI ``--base-dir`` passes resolve_workspace_path(override=...) instead.
1314
# Reads and writes are serialized by _workspace_path_lock so threaded WSGI
1415
# workers (gunicorn --threads, waitress, etc.) always see the latest override
1516
# from another thread and resolve_workspace_path's snapshot+expand stays consistent.

0 commit comments

Comments
 (0)