326 lines
9.5 KiB
Python
326 lines
9.5 KiB
Python
import sys
|
|
|
|
import nox
|
|
|
|
# Global configuration
|
|
DEFAULT_PYTHON = "3.13"
|
|
SUPPORTED_PYTHONS = ["3.13"]
|
|
nox.options.reuse_existing_virtualenvs = True
|
|
nox.options.error_on_external_run = True
|
|
|
|
# =============================================================================
|
|
# QUICK DEVELOPMENT SESSIONS (Fast - Run daily)
|
|
# =============================================================================
|
|
|
|
|
|
@nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv")
|
|
def lint(session):
|
|
"""Check code formatting and linting."""
|
|
session.install("ruff")
|
|
session.run("ruff", "check", "src/", "scripts/", "examples/")
|
|
|
|
|
|
@nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv")
|
|
def format(session):
|
|
"""Format code with ruff."""
|
|
session.install("ruff")
|
|
session.run("ruff", "format", ".")
|
|
|
|
|
|
# session.run("ruff", "check", "--fix", ".")
|
|
|
|
|
|
@nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv")
|
|
def typecheck(session):
|
|
"""Check types with pyright."""
|
|
session.install("pyright")
|
|
session.install("-e", ".")
|
|
session.run("pyright", stderr=sys.stdout)
|
|
|
|
|
|
@nox.session(python=SUPPORTED_PYTHONS, reuse_venv=True, venv_backend="uv")
|
|
def unit_tests(session):
|
|
"""Run BDD tests with Behave."""
|
|
session.install("-e", ".[tests]")
|
|
session.install("behave")
|
|
|
|
# Run Behave BDD tests (excluding discovery tests)
|
|
python_executable = session.bin + "/python"
|
|
|
|
# Check if a specific feature file is passed
|
|
args = []
|
|
if session.posargs and session.posargs[0].endswith(".feature"):
|
|
# If a specific feature file is passed, run only that file
|
|
args = [
|
|
python_executable,
|
|
"-m",
|
|
"behave",
|
|
"-q",
|
|
"--tags=not @discovery",
|
|
*session.posargs,
|
|
]
|
|
else:
|
|
# Default: run all features with posargs appended
|
|
args = [
|
|
python_executable,
|
|
"-m",
|
|
"behave",
|
|
"-q",
|
|
"--tags=not @discovery",
|
|
"features/",
|
|
*session.posargs,
|
|
]
|
|
|
|
session.run(*args)
|
|
|
|
|
|
@nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv")
|
|
def docs(session):
|
|
"""Build documentation with MkDocs."""
|
|
session.install("-e", ".[docs]")
|
|
session.run("mkdocs", "build")
|
|
|
|
|
|
@nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv")
|
|
def serve_docs(session):
|
|
"""Serve docs locally for development."""
|
|
session.install("-e", ".[docs]")
|
|
session.run("mkdocs", "serve", "--dev-addr", "0.0.0.0:8000")
|
|
|
|
|
|
@nox.session(python=SUPPORTED_PYTHONS, reuse_venv=True, venv_backend="uv")
|
|
def build(session):
|
|
"""Build the wheel distribution."""
|
|
session.install("build")
|
|
session.run("python", "-m", "build", "--wheel")
|
|
|
|
|
|
@nox.session(python=SUPPORTED_PYTHONS, reuse_venv=True, venv_backend="uv")
|
|
def integration_tests(session):
|
|
"""Run Robot Framework integration tests (excluding discovery tests)."""
|
|
session.install("-e", ".[tests]")
|
|
|
|
# If posargs provided, run only those specific files/suites
|
|
if session.posargs:
|
|
session.run(
|
|
"robot",
|
|
"--outputdir",
|
|
"build/reports/robot",
|
|
"--loglevel",
|
|
"INFO",
|
|
"--report",
|
|
"report.html",
|
|
"--log",
|
|
"log.html",
|
|
"--xunit",
|
|
"xunit.xml",
|
|
"--exclude",
|
|
"slow",
|
|
"--exclude",
|
|
"discovery", # Exclude discovery tests
|
|
"--exitonfailure", # Exit immediately on test failure
|
|
*session.posargs,
|
|
external=False, # Ensure exit code is checked
|
|
success_codes=[0], # Only code 0 is success
|
|
)
|
|
else:
|
|
# Default: run all tests in robot/ directory
|
|
session.run(
|
|
"robot",
|
|
"--outputdir",
|
|
"build/reports/robot",
|
|
"--loglevel",
|
|
"INFO",
|
|
"--report",
|
|
"report.html",
|
|
"--log",
|
|
"log.html",
|
|
"--xunit",
|
|
"xunit.xml",
|
|
"--exclude",
|
|
"slow",
|
|
"--exclude",
|
|
"discovery", # Exclude discovery tests
|
|
# "--exitonfailure", # Exit immediately on test failure
|
|
"robot/",
|
|
external=False, # Ensure exit code is checked
|
|
success_codes=[0], # Only code 0 is success
|
|
)
|
|
|
|
|
|
@nox.session(python=SUPPORTED_PYTHONS, reuse_venv=True, venv_backend="uv")
|
|
def slow_integration_tests(session):
|
|
"""Run Robot Framework integration tests."""
|
|
session.install("-e", ".[tests]")
|
|
session.run(
|
|
"robot",
|
|
"--outputdir",
|
|
"build/reports/robot",
|
|
"--loglevel",
|
|
"INFO",
|
|
"--report",
|
|
"report.html",
|
|
"--log",
|
|
"log.html",
|
|
"--xunit",
|
|
"xunit.xml",
|
|
"robot/",
|
|
*session.posargs,
|
|
)
|
|
|
|
|
|
@nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv")
|
|
def coverage_report(session):
|
|
"""Generate coverage report from Behave tests."""
|
|
session.install("-e", ".[tests]")
|
|
|
|
# Clean up any existing coverage data
|
|
session.run("coverage", "erase")
|
|
|
|
# Run Behave tests with coverage
|
|
session.run(
|
|
"coverage",
|
|
"run",
|
|
"--source=src",
|
|
"--omit=src/cleveragents/discovery/*",
|
|
"-m",
|
|
"behave",
|
|
"features/",
|
|
"-q",
|
|
"--tags=not @discovery",
|
|
)
|
|
|
|
# Combine parallel coverage data (required when parallel=true in config)
|
|
try:
|
|
session.run("coverage", "combine")
|
|
except Exception:
|
|
# No parallel data to combine
|
|
pass
|
|
|
|
# Generate and display coverage reports
|
|
session.run("coverage", "report", "--show-missing", "--fail-under=85")
|
|
session.run("coverage", "html")
|
|
session.run("coverage", "xml")
|
|
|
|
|
|
@nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv")
|
|
def discovery_tests(session):
|
|
"""Run Phase 0 discovery tests (tagged with @discovery)."""
|
|
session.install("-e", ".[tests]")
|
|
session.install("behave")
|
|
python_executable = session.bin + "/python"
|
|
# Run only tests tagged with @discovery
|
|
session.run(
|
|
python_executable,
|
|
"-m",
|
|
"behave",
|
|
"-q",
|
|
"--tags=@discovery",
|
|
"features/",
|
|
*session.posargs,
|
|
)
|
|
|
|
|
|
@nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv")
|
|
def discovery_coverage(session):
|
|
"""Generate coverage report for discovery tests."""
|
|
session.install("-e", ".[tests]")
|
|
|
|
# Clean up any existing coverage data
|
|
session.run("coverage", "erase")
|
|
|
|
# Run only discovery tests with coverage
|
|
session.run(
|
|
"coverage",
|
|
"run",
|
|
"--source=src/cleveragents/discovery",
|
|
"-m",
|
|
"behave",
|
|
"features/",
|
|
"-q",
|
|
"--tags=@discovery",
|
|
)
|
|
|
|
# Combine parallel coverage data (required when parallel=true in config)
|
|
try:
|
|
session.run("coverage", "combine")
|
|
except Exception:
|
|
# No parallel data to combine
|
|
pass
|
|
|
|
# Generate and display coverage reports
|
|
session.run("coverage", "report", "--show-missing")
|
|
session.run("coverage", "html")
|
|
session.run("coverage", "xml")
|
|
|
|
|
|
@nox.session(python=SUPPORTED_PYTHONS, reuse_venv=True, venv_backend="uv")
|
|
def discovery_integration(session):
|
|
"""Run Robot Framework integration tests tagged with 'discovery'."""
|
|
session.install("-e", ".[tests]")
|
|
|
|
# If posargs provided, run only those specific files/suites with discovery tag
|
|
if session.posargs:
|
|
session.run(
|
|
"robot",
|
|
"--outputdir",
|
|
"build/reports/robot_discovery",
|
|
"--loglevel",
|
|
"INFO",
|
|
"--report",
|
|
"discovery_report.html",
|
|
"--log",
|
|
"discovery_log.html",
|
|
"--xunit",
|
|
"discovery_xunit.xml",
|
|
"--include",
|
|
"discovery", # Include only discovery tests
|
|
"--exitonfailure", # Exit immediately on test failure
|
|
*session.posargs,
|
|
external=False, # Ensure exit code is checked
|
|
success_codes=[0], # Only code 0 is success
|
|
)
|
|
else:
|
|
# Default: run all discovery tests in robot/ directory
|
|
session.run(
|
|
"robot",
|
|
"--outputdir",
|
|
"build/reports/robot_discovery",
|
|
"--loglevel",
|
|
"INFO",
|
|
"--report",
|
|
"discovery_report.html",
|
|
"--log",
|
|
"discovery_log.html",
|
|
"--xunit",
|
|
"discovery_xunit.xml",
|
|
"--include",
|
|
"discovery", # Include only discovery tests
|
|
"robot/",
|
|
external=False, # Ensure exit code is checked
|
|
success_codes=[0], # Only code 0 is success
|
|
)
|
|
|
|
|
|
@nox.session(python=DEFAULT_PYTHON, reuse_venv=True, venv_backend="uv")
|
|
def benchmark(session):
|
|
"""Run Airspeed Velocity benchmarks and publish results."""
|
|
session.install("-e", ".[tests]")
|
|
config_path = "asv.conf.json"
|
|
session.run("asv", "run", "--show-stderr", "--verbose", f"--config={config_path}")
|
|
session.run("asv", "publish", f"--config={config_path}")
|
|
|
|
|
|
# Sessions to run by default when running `nox` without arguments
|
|
nox.options.sessions = [
|
|
"lint", # ~5-10 seconds
|
|
"format", # ~5-10 seconds (auto-fixes issues)
|
|
"typecheck", # ~10-20 seconds
|
|
"unit_tests", # ~30-60 seconds (without ML deps)
|
|
"integration_tests",
|
|
"docs", # ~10-30 seconds
|
|
"build", # ~5-10 seconds
|
|
"benchmark", # ASV benchmarks for performance tracking
|
|
"coverage_report", # ~30-60 seconds (without ML deps)
|
|
]
|