From da3d0dfd06ace32f208329c0803791823b8bfdbe Mon Sep 17 00:00:00 2001 From: Brent Edwards Date: Fri, 13 Feb 2026 04:32:45 +0000 Subject: [PATCH] chore(ci): re-enable pabot, add discovery resource stub - Restore pabot-based integration_tests with conservative parallelism (<=2 processes by default) and support PABOT_PROCESSES/--processes - Remove the temporary CI debug dump from noxfile.py - Add robot/discovery_common.resource to silence non-fatal warning - Document the change in implementation_plan.md --- implementation_plan.md | 10 ++++ noxfile.py | 85 ++++++++++++++++----------------- robot/discovery_common.resource | 2 + 3 files changed, 54 insertions(+), 43 deletions(-) create mode 100644 robot/discovery_common.resource diff --git a/implementation_plan.md b/implementation_plan.md index 1e8c366a..3018e85e 100644 --- a/implementation_plan.md +++ b/implementation_plan.md @@ -477,6 +477,16 @@ The following work from the previous implementation has been completed and will - **Fix** (`robot/scientific_paper_basic.robot`): Initialize `${CONTEXT_DIR}` to `${TEMPDIR}/paper_basic_contexts` in the Variables table, and guard cleanup with `Run Keyword If '${CONTEXT_DIR}' != '${EMPTY}'` before removing the directory. This prevents accidental deletion of the workspace when the suite is skipped. - **Verification**: Not re-run on CI yet; local `nox -s integration_tests` should continue to pass (204/204) with `OPENAI_API_KEY` unset. +**2026-02-13**: Enhancement - Restore parallel Robot runs + silence discovery resource warning + +- **Change 1 — Reintroduce `pabot` for `integration_tests`**: + - **Reason**: Sequential `robot` runs were reliable but slow (~7 minutes on CI). With the teardown bug fixed, we can safely return to parallel execution. + - **Implementation** (`noxfile.py`): `integration_tests` now runs `pabot` with conservative default parallelism (max 2 processes). Overrides supported via `PABOT_PROCESSES` or `--processes` in nox args. Existing `--variable PYTHON:` injection remains to ensure `Run Process` uses the venv interpreter. +- **Change 2 — Add `robot/discovery_common.resource` stub**: + - **Reason**: `robot/core_cli_commands.robot` imports `discovery_common.resource`, which does not exist. This emits a non-fatal warning every run even though discovery-tagged tests are excluded. + - **Fix**: Add a minimal placeholder resource file to silence the warning. +- **Cleanup**: Remove the temporary CI debug dump in `integration_tests` now that the failure mode has been addressed. + **2026-02-06**: CRITICAL ARCHITECTURAL DECISION - Tool-Based Resource Modification - **REPLACED**: OutputParser/code fence parsing approach - **WITH**: Tool-based change tracking (modern approach used by Claude Code, Cursor, Aider) diff --git a/noxfile.py b/noxfile.py index f429ebaf..bb49497d 100644 --- a/noxfile.py +++ b/noxfile.py @@ -36,6 +36,37 @@ def _behave_parallel_args(posargs: list[str]) -> list[str]: return ["--processes", str(_default_processes())] +def _pabot_parallel_args(posargs: list[str]) -> list[str]: + has_custom_processes = any( + arg in {"--processes"} or arg.startswith("--processes=") for arg in posargs + ) + if has_custom_processes: + return [] + env_override = os.environ.get("PABOT_PROCESSES") + if env_override: + return ["--processes", env_override] + return ["--processes", str(min(_default_processes(), 2))] + + +def _split_pabot_args(posargs: list[str]) -> tuple[list[str], list[str]]: + pabot_args: list[str] = [] + robot_args: list[str] = [] + i = 0 + while i < len(posargs): + arg = posargs[i] + if arg == "--processes" and i + 1 < len(posargs): + pabot_args.extend([arg, posargs[i + 1]]) + i += 2 + continue + if arg.startswith("--processes="): + pabot_args.append(arg) + i += 1 + continue + robot_args.append(arg) + i += 1 + return pabot_args, robot_args + + def _install_behave_parallel(session: nox.Session) -> None: """Install behave-parallel with a custom CLI wrapper.""" @@ -352,12 +383,11 @@ def build(session: nox.Session): @nox.session(python=SUPPORTED_PYTHONS, reuse_venv=True, venv_backend="uv") def integration_tests(session: nox.Session): - """Run Robot Framework integration tests (sequential via robot). + """Run Robot Framework integration tests (parallel via pabot). - Uses ``robot`` directly instead of ``pabot`` for reliable execution - in constrained CI containers. pabot spawns a new ``robot`` - subprocess per suite which exhausts process/FD limits on CI after - ~24 suites, causing ``FileNotFoundError: 'robot'``. + Defaults to conservative parallelism (<=2 processes) to avoid + resource pressure in CI. Override via PABOT_PROCESSES or by passing + --processes/--processes=N in session arguments. """ session.install("-e", ".[tests]") session.env["CLEVERAGENTS_AUTO_APPLY_MIGRATIONS"] = "true" @@ -367,42 +397,6 @@ def integration_tests(session: nox.Session): venv_bin = os.path.join(session.virtualenv.location, "bin") session.env["PATH"] = venv_bin + os.pathsep + os.environ.get("PATH", "") - # Debug: confirm robot is discoverable and show working directory - session.run( - "python", - "-c", - "import shutil, os, sys, stat\n" - "print('=== CI Debug ===')\n" - "print('python:', sys.executable)\n" - "print('robot at:', shutil.which('robot'))\n" - "print('which python:', shutil.which('python'))\n" - "print('PATH:', os.environ.get('PATH', '(unset)'))\n" - "print('cwd:', os.getcwd())\n" - "print('robot/ contents:', sorted(os.listdir('robot')))\n" - "# Check resource files in detail\n" - "for name in ['v2_paths.resource', 'common.resource']:\n" - " p = os.path.join('robot', name)\n" - " ap = os.path.abspath(p)\n" - " e, f2, lnk = os.path.exists(ap), os.path.isfile(ap), os.path.islink(ap)\n" - " print(f'{name}: exists={e}, isfile={f2}, islink={lnk}, abspath={ap}')\n" - " if os.path.exists(ap):\n" - " st = os.stat(ap)\n" - " r = os.access(ap, os.R_OK)\n" - " print(f' size={st.st_size}, mode={oct(st.st_mode)}, readable={r}')\n" - " with open(ap, 'rb') as f:\n" - " data = f.read(100)\n" - " print(f' first_100_bytes={data!r}')\n" - "# Check fixture dirs referenced by v2_paths.resource\n" - "fix_dirs = ['features/fixtures/v2', 'features/fixtures/v2/configs'," - " 'features/fixtures/v2/contexts', 'features/fixtures/v2/examples'," - " 'features/fixtures/v2/paper_contexts']\n" - "for d in fix_dirs:\n" - " print(f'{d}: exists={os.path.isdir(d)}')\n" - "# Robot Framework version\n" - "import robot; print('RF version:', robot.version.VERSION)\n" - "print('=== End CI Debug ===')\n", - ) - # Ensure output directory exists (CI starts with a clean checkout) os.makedirs("build/reports/robot", exist_ok=True) @@ -410,8 +404,13 @@ def integration_tests(session: nox.Session): # instead of relying on PATH (which may not propagate to subprocesses). venv_python = os.path.join(venv_bin, "python") + pabot_args, robot_args = _split_pabot_args(session.posargs) + parallel_args = _pabot_parallel_args(pabot_args) + session.run( - "robot", + "pabot", + *parallel_args, + *pabot_args, "--outputdir", "build/reports/robot", "--loglevel", @@ -428,7 +427,7 @@ def integration_tests(session: nox.Session): "slow", "--exclude", "discovery", - *session.posargs, + *robot_args, "robot/", ) diff --git a/robot/discovery_common.resource b/robot/discovery_common.resource new file mode 100644 index 00000000..209492c5 --- /dev/null +++ b/robot/discovery_common.resource @@ -0,0 +1,2 @@ +*** Settings *** +Documentation Placeholder resource for discovery-tagged tests.