perf(ci): optimize e2e_tests push job to reduce execution time #3043

Merged
freemo merged 1 commits from fix/ci-optimize-e2e-tests-push into master 2026-04-05 21:14:17 +00:00
2 changed files with 36 additions and 4 deletions
+4
View File
@@ -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
View File
@@ -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/",
)