|
11 | 11 |
|
12 | 12 | from __future__ import annotations |
13 | 13 |
|
14 | | -import fcntl |
15 | 14 | import time |
16 | 15 | from contextlib import contextmanager |
17 | 16 | from typing import TYPE_CHECKING |
@@ -103,69 +102,63 @@ def _delete_provider(stub: object, name: str) -> None: |
103 | 102 | @pytest.fixture |
104 | 103 | def providers_v2_enabled( |
105 | 104 | sandbox_client: SandboxClient, |
106 | | - tmp_path_factory: pytest.TempPathFactory, |
| 105 | + _gateway_config_guard: None, |
107 | 106 | ) -> Iterator[None]: |
108 | 107 | """Enable the gateway-global ``providers_v2_enabled`` opt-in for one test. |
109 | 108 |
|
110 | 109 | Composing a provider's network policy onto a sandbox is gated behind this |
111 | 110 | setting, which defaults off; the built-in github profile's git-transport |
112 | 111 | rules only reach the sandbox with it enabled. |
113 | 112 |
|
114 | | - The setting is gateway-global, so this mutates shared state. To keep it safe |
115 | | - on an existing or shared gateway and under parallel workers: |
116 | | -
|
117 | | - - The mutation is serialized across xdist workers with an exclusive file lock |
118 | | - on the run's shared base temp dir (``getbasetemp().parent``), held for the |
119 | | - whole test so the read-modify-restore cannot interleave. |
120 | | - - The exact prior value (or absence) is captured via ``GetGatewayConfig`` and |
121 | | - restored in ``finally``, leaving the gateway as it was found. |
122 | | -
|
123 | | - ``global`` is a Python keyword, so it is passed through a dict expansion. |
| 113 | + The setting is gateway-global. Exclusivity against other xdist workers is |
| 114 | + provided by the ``exclusive_gateway_config`` marker plus the autouse |
| 115 | + ``_gateway_config_guard`` guard (see conftest): no concurrent worker is |
| 116 | + mid-test while this fixture mutates and restores the setting, so none can |
| 117 | + observe the transient value. Depending on the guard here also orders the |
| 118 | + exclusive lock acquisition before the mutation. |
| 119 | +
|
| 120 | + ``GetGatewayConfig`` returns known keys even when unset, with an empty |
| 121 | + ``SettingValue`` (no populated oneof), so the setting is treated as present |
| 122 | + only when its value oneof is set; otherwise restore is a delete. ``global`` |
| 123 | + is a Python keyword, so it is passed through a dict expansion. |
124 | 124 | """ |
125 | 125 | stub = sandbox_client._stub |
126 | 126 | key = "providers_v2_enabled" |
127 | | - lock_path = tmp_path_factory.getbasetemp().parent / "providers-v2-setting.lock" |
128 | | - with lock_path.open("w") as lock_file: |
129 | | - fcntl.flock(lock_file, fcntl.LOCK_EX) |
130 | | - |
131 | | - # GetGatewayConfig returns known keys even when unset, with an empty |
132 | | - # SettingValue (no populated oneof). Only treat the setting as explicitly |
133 | | - # present when its value oneof is actually set; otherwise restore = delete. |
134 | | - config = stub.GetGatewayConfig(sandbox_pb2.GetGatewayConfigRequest()) |
135 | | - prior_value = sandbox_pb2.SettingValue() |
136 | | - had_prior = ( |
137 | | - key in config.settings |
138 | | - and config.settings[key].WhichOneof("value") is not None |
| 127 | + config = stub.GetGatewayConfig(sandbox_pb2.GetGatewayConfigRequest()) |
| 128 | + prior_value = sandbox_pb2.SettingValue() |
| 129 | + had_prior = ( |
| 130 | + key in config.settings |
| 131 | + and config.settings[key].WhichOneof("value") is not None |
| 132 | + ) |
| 133 | + if had_prior: |
| 134 | + prior_value.CopyFrom(config.settings[key]) |
| 135 | + |
| 136 | + stub.UpdateConfig( |
| 137 | + openshell_pb2.UpdateConfigRequest( |
| 138 | + setting_key=key, |
| 139 | + setting_value=sandbox_pb2.SettingValue(bool_value=True), |
| 140 | + **{"global": True}, |
139 | 141 | ) |
| 142 | + ) |
| 143 | + try: |
| 144 | + yield |
| 145 | + finally: |
140 | 146 | if had_prior: |
141 | | - prior_value.CopyFrom(config.settings[key]) |
142 | | - |
143 | | - stub.UpdateConfig( |
144 | | - openshell_pb2.UpdateConfigRequest( |
145 | | - setting_key=key, |
146 | | - setting_value=sandbox_pb2.SettingValue(bool_value=True), |
147 | | - **{"global": True}, |
148 | | - ) |
149 | | - ) |
150 | | - try: |
151 | | - yield |
152 | | - finally: |
153 | | - if had_prior: |
154 | | - stub.UpdateConfig( |
155 | | - openshell_pb2.UpdateConfigRequest( |
156 | | - setting_key=key, |
157 | | - setting_value=prior_value, |
158 | | - **{"global": True}, |
159 | | - ) |
| 147 | + stub.UpdateConfig( |
| 148 | + openshell_pb2.UpdateConfigRequest( |
| 149 | + setting_key=key, |
| 150 | + setting_value=prior_value, |
| 151 | + **{"global": True}, |
160 | 152 | ) |
161 | | - else: |
162 | | - stub.UpdateConfig( |
163 | | - openshell_pb2.UpdateConfigRequest( |
164 | | - setting_key=key, |
165 | | - delete_setting=True, |
166 | | - **{"global": True}, |
167 | | - ) |
| 153 | + ) |
| 154 | + else: |
| 155 | + stub.UpdateConfig( |
| 156 | + openshell_pb2.UpdateConfigRequest( |
| 157 | + setting_key=key, |
| 158 | + delete_setting=True, |
| 159 | + **{"global": True}, |
168 | 160 | ) |
| 161 | + ) |
169 | 162 |
|
170 | 163 |
|
171 | 164 | # =========================================================================== |
@@ -560,6 +553,7 @@ def test_update_provider_rejects_type_change( |
560 | 553 | # =========================================================================== |
561 | 554 |
|
562 | 555 |
|
| 556 | +@pytest.mark.exclusive_gateway_config |
563 | 557 | @pytest.mark.usefixtures("providers_v2_enabled") |
564 | 558 | def test_github_provider_allows_https_git_clone( |
565 | 559 | sandbox: Callable[..., Sandbox], |
|
0 commit comments