From 35e134ebe654ec209b9061d8af6305b3d1853e86 Mon Sep 17 00:00:00 2001 From: noahpodgurski Date: Thu, 22 Jan 2026 11:23:17 -0500 Subject: [PATCH 1/4] feat: app attest e2e test, ignore dep warnings --- pyproject.toml | 4 + .../app_attest_qa.py} | 0 .../generate_qa_app_attest_certificate.py | 0 src/tests/e2e/test_app_attest_e2e.py | 101 ++++++++++++++++++ 4 files changed, 105 insertions(+) rename scripts/{appattest_qa.py => app_attest_qa/app_attest_qa.py} (100%) rename scripts/{ => app_attest_qa}/generate_qa_app_attest_certificate.py (100%) create mode 100644 src/tests/e2e/test_app_attest_e2e.py diff --git a/pyproject.toml b/pyproject.toml index dc1234a..ed24f74 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -85,6 +85,10 @@ select = ["I"] [tool.pytest.ini_options] asyncio_mode = "auto" +filterwarnings = [ + "ignore:'cgi' is deprecated and slated for removal in Python 3\\.13:DeprecationWarning:webob\\.compat", + "ignore:datetime\\.datetime\\.utcnow\\(\\) is deprecated and scheduled for removal in a future version\\.:DeprecationWarning:pyattest\\.testutils\\.factories\\.attestation\\.apple", +] [tool.pytest_env] APP_ATTEST_QA = "true" diff --git a/scripts/appattest_qa.py b/scripts/app_attest_qa/app_attest_qa.py similarity index 100% rename from scripts/appattest_qa.py rename to scripts/app_attest_qa/app_attest_qa.py diff --git a/scripts/generate_qa_app_attest_certificate.py b/scripts/app_attest_qa/generate_qa_app_attest_certificate.py similarity index 100% rename from scripts/generate_qa_app_attest_certificate.py rename to scripts/app_attest_qa/generate_qa_app_attest_certificate.py diff --git a/src/tests/e2e/test_app_attest_e2e.py b/src/tests/e2e/test_app_attest_e2e.py new file mode 100644 index 0000000..7eb4c15 --- /dev/null +++ b/src/tests/e2e/test_app_attest_e2e.py @@ -0,0 +1,101 @@ +import os +import shutil +import socket +import subprocess +import sys +import time +from pathlib import Path + +import httpx +import pytest + + +def _pick_free_port() -> int: + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + sock.bind(("127.0.0.1", 0)) + return sock.getsockname()[1] + + +def _wait_for_liveness(base_url: str, timeout_s: int = 30) -> None: + deadline = time.time() + timeout_s + url = f"{base_url}/health/liveness" + while time.time() < deadline: + try: + response = httpx.get(url, timeout=2) + if response.status_code == 200: + return + except Exception: + pass + time.sleep(0.5) + raise AssertionError("MLPA did not become live in time.") + + +def test_app_attest_qa_flow_e2e(): + cert_dir = Path("src/tests/certs") + cert_dir_exists = cert_dir.exists() + existing_files = {p.name for p in cert_dir.iterdir()} if cert_dir_exists else set() + cert_dir.mkdir(parents=True, exist_ok=True) + + env = os.environ.copy() + env["APP_ATTEST_QA"] = "true" + env["APP_ATTEST_QA_CERT_DIR"] = str(cert_dir) + env["MLPA_DEBUG"] = "false" + + port = _pick_free_port() + base_url = f"http://127.0.0.1:{port}" + env["PORT"] = str(port) + + server = None + try: + subprocess.run( + [ + sys.executable, + "scripts/app_attest_qa/generate_qa_app_attest_certificate.py", + ], + check=True, + env=env, + ) + + server = subprocess.Popen( + ["mlpa"], + env=env, + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ) + _wait_for_liveness(base_url, timeout_s=60) + + subprocess.run( + [ + sys.executable, + "scripts/app_attest_qa/app_attest_qa.py", + "register", + ], + check=True, + env=env, + ) + + subprocess.run( + [ + sys.executable, + "scripts/app_attest_qa/app_attest_qa.py", + "completion", + ], + check=True, + env=env, + ) + finally: + if server is not None: + server.terminate() + try: + server.wait(timeout=10) + except subprocess.TimeoutExpired: + server.kill() + if cert_dir.exists(): + for path in cert_dir.iterdir(): + if path.name not in existing_files: + if path.is_dir(): + shutil.rmtree(path) + else: + path.unlink() + if not cert_dir_exists: + shutil.rmtree(cert_dir) From f50ac9548bddffc833885a943e988b793fbddc63 Mon Sep 17 00:00:00 2001 From: noahpodgurski Date: Thu, 22 Jan 2026 11:24:58 -0500 Subject: [PATCH 2/4] add e2e tests to linters_and_tests --- .github/workflows/linters_and_tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/linters_and_tests.yml b/.github/workflows/linters_and_tests.yml index 70b2136..b8e2ea5 100644 --- a/.github/workflows/linters_and_tests.yml +++ b/.github/workflows/linters_and_tests.yml @@ -36,3 +36,6 @@ jobs: - name: Run integration tests run: uv run pytest src/tests/integration -v + + - name: Run e2e tests + run: uv run pytest src/tests/e2e -v From bd15191653a75271cc94098fddeb23f56e99f496 Mon Sep 17 00:00:00 2001 From: noahpodgurski Date: Thu, 22 Jan 2026 11:25:33 -0500 Subject: [PATCH 3/4] rename job name --- .github/workflows/linters_and_tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linters_and_tests.yml b/.github/workflows/linters_and_tests.yml index b8e2ea5..513a494 100644 --- a/.github/workflows/linters_and_tests.yml +++ b/.github/workflows/linters_and_tests.yml @@ -1,4 +1,4 @@ -name: linters and unit tests +name: linters and tests on: pull_request: From 5f660c975e5294e6ef04166b8dd443ed6422fc99 Mon Sep 17 00:00:00 2001 From: noahpodgurski Date: Thu, 22 Jan 2026 11:28:50 -0500 Subject: [PATCH 4/4] rm: e2e tests from CI (local only) --- .github/workflows/linters_and_tests.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/linters_and_tests.yml b/.github/workflows/linters_and_tests.yml index 513a494..2c38ff9 100644 --- a/.github/workflows/linters_and_tests.yml +++ b/.github/workflows/linters_and_tests.yml @@ -36,6 +36,3 @@ jobs: - name: Run integration tests run: uv run pytest src/tests/integration -v - - - name: Run e2e tests - run: uv run pytest src/tests/e2e -v