about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--conftest.py35
1 files changed, 32 insertions, 3 deletions
diff --git a/conftest.py b/conftest.py
index 5b5eb87..c4a51dc 100644
--- a/conftest.py
+++ b/conftest.py
@@ -16,6 +16,7 @@ For auth-flow tests also set:
 """
 
 import os
+import time
 import pytest
 import requests
 
@@ -25,19 +26,47 @@ _GN3_DEFAULT = "https://cd.genenetwork.org/api3"
 _GN_AUTH_DEFAULT = "https://auth-cd.genenetwork.org"
 
 
+def _wait_for(url: str, timeout: int = 120, interval: int = 2) -> None:
+    """Poll url until the upstream service is up or timeout elapses.
+
+    Retries on ConnectionError (process not yet bound) and on 502/503
+    (Nginx upstream-not-ready responses).  Any other HTTP response is
+    treated as "service is up".
+    """
+    deadline = time.monotonic() + timeout
+    last_exc = None
+    while time.monotonic() < deadline:
+        try:
+            resp = requests.get(url, timeout=5, allow_redirects=True)
+            if resp.status_code not in (502, 503):
+                return
+        except requests.exceptions.ConnectionError as exc:
+            last_exc = exc
+        time.sleep(interval)
+    raise RuntimeError(
+        f"Service at {url} did not become available within {timeout}s"
+    ) from last_exc
+
+
 @pytest.fixture(scope="session")
 def gn2_url() -> str:
-    return os.environ.get("GN2_BASE_URL", _GN2_DEFAULT).rstrip("/")
+    url = os.environ.get("GN2_BASE_URL", _GN2_DEFAULT).rstrip("/")
+    _wait_for(url)
+    return url
 
 
 @pytest.fixture(scope="session")
 def gn3_url() -> str:
-    return os.environ.get("GN3_BASE_URL", _GN3_DEFAULT).rstrip("/")
+    url = os.environ.get("GN3_BASE_URL", _GN3_DEFAULT).rstrip("/")
+    _wait_for(url)
+    return url
 
 
 @pytest.fixture(scope="session")
 def gn_auth_url() -> str:
-    return os.environ.get("GN_AUTH_BASE_URL", _GN_AUTH_DEFAULT).rstrip("/")
+    url = os.environ.get("GN_AUTH_BASE_URL", _GN_AUTH_DEFAULT).rstrip("/")
+    _wait_for(url)
+    return url
 
 
 @pytest.fixture(scope="session")