perf(ci): optimize e2e_tests push job to reduce execution time #3043
@@ -315,6 +315,10 @@ jobs:
|
||||
nox -s e2e_tests 2>&1 | tee build/nox-e2e-tests-output.log
|
||||
env:
|
||||
NOX_DEFAULT_VENV_BACKEND: uv
|
||||
# Run E2E suites in parallel via pabot. 4 workers keeps
|
||||
# wall-clock time well under the 45-minute timeout while
|
||||
# staying within the memory budget of the docker runner.
|
||||
TEST_PROCESSES: "4"
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
|
||||
|
||||
+32
-4
@@ -413,6 +413,10 @@ def e2e_tests(session: nox.Session):
|
||||
|
||||
Tests that require LLM API keys will skip gracefully when the keys
|
||||
are not present in the environment.
|
||||
|
||||
Parallelism is controlled by the ``TEST_PROCESSES`` environment variable
|
||||
(default: min(cpu_count, 2)). Override via ``TEST_PROCESSES=N nox -s
|
||||
e2e_tests`` or by passing ``--processes N`` as a session argument.
|
||||
"""
|
||||
session.install("-e", ".[tests]")
|
||||
session.env["CLEVERAGENTS_AUTO_APPLY_MIGRATIONS"] = "true"
|
||||
@@ -428,12 +432,18 @@ def e2e_tests(session: nox.Session):
|
||||
# Ensure output directory exists
|
||||
os.makedirs("build/reports/robot-e2e", exist_ok=True)
|
||||
|
||||
# Pre-compile bytecode to avoid cold-compilation overhead.
|
||||
# Pre-compile bytecode so that parallel pabot workers (and the
|
||||
# Python sub-processes they spawn via ``Run Process``) can read
|
||||
# cached .pyc files instead of each cold-compiling every module
|
||||
# from source simultaneously — avoids a thundering-herd race on
|
||||
# CI runners with high core counts.
|
||||
session.run("python", "-m", "compileall", "-q", "src/")
|
||||
|
||||
# Build a pre-migrated template DB so helper scripts that call
|
||||
# setup_workspace() can copy it instead of running 25+ Alembic
|
||||
# migrations per test — reduces per-test setup from ~1-3 s to ~1 ms.
|
||||
# Critical for parallel pabot execution where many suites start
|
||||
# simultaneously and would otherwise all race to run migrations.
|
||||
template_path = _create_template_db(session)
|
||||
session.env["CLEVERAGENTS_TEMPLATE_DB"] = template_path
|
||||
|
||||
@@ -449,8 +459,26 @@ def e2e_tests(session: nox.Session):
|
||||
if value:
|
||||
session.env[key] = value
|
||||
|
||||
# Split posargs into pabot-specific args (--processes) and robot args.
|
||||
pabot_args, robot_args = _split_pabot_args(session.posargs)
|
||||
parallel_args = _pabot_parallel_args(pabot_args)
|
||||
|
||||
# TDD expected-fail listener — inverts results for @tdd_expected_fail
|
||||
# tagged tests and validates TDD tag combinations.
|
||||
# See CONTRIBUTING.md > TDD Issue Test Tags.
|
||||
tdd_listener = str(
|
||||
Path(__file__).parent / "robot" / "tdd_expected_fail_listener.py"
|
||||
)
|
||||
|
||||
# Use pabot (parallel Robot Framework runner) instead of the sequential
|
||||
# ``robot`` runner. Each E2E suite file runs in its own pabot worker
|
||||
# process, so independent suites execute concurrently rather than
|
||||
# serially. Suite-level isolation (separate CLEVERAGENTS_HOME per
|
||||
# suite) ensures workers do not share database state.
|
||||
session.run(
|
||||
"robot",
|
||||
"pabot",
|
||||
*parallel_args,
|
||||
*pabot_args,
|
||||
"--outputdir",
|
||||
"build/reports/robot-e2e",
|
||||
"--loglevel",
|
||||
@@ -466,8 +494,8 @@ def e2e_tests(session: nox.Session):
|
||||
"--include",
|
||||
"E2E",
|
||||
"--listener",
|
||||
str(Path(__file__).parent / "robot" / "tdd_expected_fail_listener.py"),
|
||||
*session.posargs,
|
||||
tdd_listener,
|
||||
*robot_args,
|
||||
"robot/e2e/",
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user