test(integration): run the cost shard with xdist workers

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
kerry 2026-09-19 00:50:29 +00:00
parent e52eea84e6
commit 6eb67a8423
3 changed files with 32 additions and 12 deletions

View file

@ -2987,7 +2987,7 @@ jobs:
- run:
name: Run owned integration contracts
command: bash .circleci/scripts/run_integration.sh << parameters.suite >>
no_output_timeout: 25m
no_output_timeout: 15m
- run:
name: Stop owned database and Redis
when: always

View file

@ -1,10 +1,11 @@
from __future__ import annotations
import json
import os
import hashlib
import os
from collections.abc import Sequence
from collections.abc import Iterator
from importlib.metadata import version
from collections.abc import Generator, Iterator
from pathlib import Path
from typing import Final
@ -28,6 +29,26 @@ def pytest_configure(config: pytest.Config) -> None:
config.addinivalue_line("markers", "integration: owned real-service integration contracts")
config.addinivalue_line("markers", "covers(*ids): independently asserted behavior contracts")
config.stash[REPORTS] = []
config.pluginmanager.register(IntegrationReportPlugin(config))
class IntegrationReportPlugin:
def __init__(self, config: pytest.Config) -> None:
self.config = config
def pytest_runtest_logreport(self, report: pytest.TestReport) -> None:
self.config.stash[REPORTS].append(report)
@pytest.hookimpl(optionalhook=True)
def pytest_xdist_node_collection_finished(self, node: object, ids: Sequence[str]) -> None:
owned_prefix: Final = "tests/integration/"
self.config.stash[COLLECTED] = tuple(
nodeid
for nodeid in ids
if nodeid.split("::", 1)[0].startswith(owned_prefix)
and len(Path(nodeid.split("::", 1)[0]).parts) > 2
and Path(nodeid.split("::", 1)[0]).parts[2] in OWNED_DIRECTORIES
)
def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item]) -> None:
@ -54,16 +75,9 @@ def pytest_collection_modifyitems(config: pytest.Config, items: list[pytest.Item
config.stash[COLLECTED] = tuple(item.nodeid for item in owned)
@pytest.hookimpl(wrapper=True)
def pytest_runtest_makereport(
item: pytest.Item, call: pytest.CallInfo[None]
) -> Generator[None, pytest.TestReport, pytest.TestReport]:
report: Final = yield
item.config.stash[REPORTS].append(report)
return report
def pytest_sessionfinish(session: pytest.Session, exitstatus: int) -> None:
if hasattr(session.config, "workerinput"):
return
destination: Final = os.environ.get("INTEGRATION_RESULTS_DIR")
if destination is None:
return

View file

@ -18,6 +18,7 @@ def main() -> int:
parser.add_argument("--results", type=Path, default=Path("test-results/integration"))
parser.add_argument("--seed", type=int, default=int(os.environ.get("INTEGRATION_SEED", "4106601")))
parser.add_argument("--order-seed", type=int, default=int(os.environ.get("INTEGRATION_ORDER_SEED", "0")))
parser.add_argument("--workers", type=int, default=int(os.environ.get("INTEGRATION_WORKERS", "1")))
options: Final = parser.parse_args()
root: Final = Path(__file__).resolve().parents[2]
selected: Final = tuple(
@ -56,6 +57,11 @@ def main() -> int:
f"--hypothesis-seed={options.seed}",
f"--integration-order-seed={options.order_seed}",
f"--junitxml={output / 'junit.xml'}",
*(
("-n", str(options.workers))
if options.workers > 1
else ()
),
],
cwd=root,
env=environment,