5a558eb09e
TypeScript SDK Compatibility V1.x E2E Tests / Select Node version matrix (push) Has been cancelled
TypeScript SDK Compatibility V1.x E2E Tests / TypeScript SDK Compatibility V1.x E2E Tests Node ${{matrix.node_version}} (push) Has been cancelled
TypeScript SDK E2E Tests / TypeScript SDK E2E Tests Node ${{matrix.node_version}} (push) Has been cancelled
Opik Optimizer - E2E Tests / build-opik (push) Has been cancelled
TypeScript SDK Compatibility V1.x E2E Tests / build-opik (push) Has been cancelled
Python SDK E2E Tests / Select Python version matrix (push) Has been cancelled
Python SDK E2E Tests / Python SDK E2E Tests ${{matrix.python_version}} (push) Has been cancelled
Python SDK E2E Tests / build-opik (push) Has been cancelled
Python SDK Compatibility V1.x E2E Tests / Select Python version matrix (push) Has been cancelled
Python SDK Compatibility V1.x E2E Tests / Python SDK Compatibility V1.x E2E Tests ${{matrix.python_version}} (push) Has been cancelled
Python SDK Compatibility V1.x E2E Tests / build-opik (push) Has been cancelled
TypeScript SDK E2E Tests / Select Node version matrix (push) Has been cancelled
TypeScript SDK E2E Tests / build-opik (push) Has been cancelled
Opik Optimizer - E2E Tests / Opik Optimizer E2E Tests Python ${{matrix.python_version}} (push) Has been cancelled
Opik Optimizer - E2E Tests / Opik Optimizer Integration Smoke Tests (push) Has been cancelled
🐙 Code Quality / detect (push) Has been cancelled
🐙 Code Quality / lint (${{ matrix.leg.name }}) (push) Has been cancelled
🐙 Code Quality / summary (push) Has been cancelled
TypeScript SDK Library Integration Tests / Check Secrets (push) Has been cancelled
TypeScript SDK Library Integration Tests / opik-vercel (Vercel AI SDK / eve) (push) Has been cancelled
SDK Library Integration Tests Runner / Check Secrets (push) Has been cancelled
SDK Library Integration Tests Runner / Missed OpenAI API Key Warning (push) Has been cancelled
SDK Library Integration Tests Runner / Build (push) Has been cancelled
SDK Library Integration Tests Runner / openai_tests (push) Has been cancelled
SDK Library Integration Tests Runner / langchain_tests (push) Has been cancelled
SDK Library Integration Tests Runner / langchain_legacy_tests (push) Has been cancelled
SDK Library Integration Tests Runner / llama_index_tests (push) Has been cancelled
SDK Library Integration Tests Runner / anthropic_tests (push) Has been cancelled
SDK Library Integration Tests Runner / mistral_tests (push) Has been cancelled
SDK Library Integration Tests Runner / groq_tests (push) Has been cancelled
SDK Library Integration Tests Runner / aisuite_tests (push) Has been cancelled
SDK Library Integration Tests Runner / haystack_tests (push) Has been cancelled
SDK Library Integration Tests Runner / dspy_tests (push) Has been cancelled
SDK Library Integration Tests Runner / crewai_v0_tests (push) Has been cancelled
SDK Library Integration Tests Runner / crewai_v1_tests (push) Has been cancelled
SDK Library Integration Tests Runner / genai_tests (push) Has been cancelled
SDK Library Integration Tests Runner / adk_tests (push) Has been cancelled
SDK Library Integration Tests Runner / adk_legacy_1_3_0_tests (push) Has been cancelled
SDK Library Integration Tests Runner / evaluation_metrics_tests (push) Has been cancelled
SDK Library Integration Tests Runner / bedrock_tests (push) Has been cancelled
SDK Library Integration Tests Runner / litellm_tests (push) Has been cancelled
SDK Library Integration Tests Runner / harbor_tests (push) Has been cancelled
SDK Library Integration Tests Runner / Slack Notification (push) Has been cancelled
Lint Opik Helm Chart / render-equality (push) Has been cancelled
Opik Optimizer - Unit Tests / Opik Optimizer Unit Tests Python ${{matrix.python_version}} (push) Has been cancelled
Python BE E2E Tests / Python BE E2E (push) Has been cancelled
Python Backend Tests / run-python-backend-tests (push) Has been cancelled
Python SDK Unit Tests / Python SDK Unit Tests ${{matrix.python_version}} (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
SDK E2E Libraries Integration Tests / Check Secrets (push) Has been cancelled
SDK E2E Libraries Integration Tests / Missed OpenAI API Key Warning (push) Has been cancelled
SDK E2E Libraries Integration Tests / build-opik (push) Has been cancelled
SDK E2E Libraries Integration Tests / E2E Lib Integration Python ${{matrix.python_version}} (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-gemini) (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-langchain) (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-openai) (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-otel) (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-vercel) (push) Has been cancelled
TypeScript SDK Build & Publish / build-and-publish (push) Has been cancelled
TypeScript SDK Unit Tests / Test on Node ${{ matrix.node-version }} (push) Has been cancelled
Backend Tests / discover-tests (push) Has been cancelled
Backend Tests / ${{ matrix.name }} (push) Has been cancelled
Build and Publish SDK / build-and-publish (push) Has been cancelled
Build Opik Docker Images / set-version (push) Has been cancelled
Build Opik Docker Images / build-backend (push) Has been cancelled
Build Opik Docker Images / build-sandbox-executor-python (push) Has been cancelled
Build Opik Docker Images / build-python-backend (push) Has been cancelled
Build Opik Docker Images / build-frontend (push) Has been cancelled
Build Opik Docker Images / create-git-tag (push) Has been cancelled
ClickHouse Migration Cluster Check / validate-clickhouse-migrations (push) Has been cancelled
Docs - Publish / run (push) Has been cancelled
E2E Tests - Post Merge (v2) / 🧪 E2E v2 Tests (${{ github.event.inputs.tier || 't1' }}) (push) Has been cancelled
E2E Tests - Post Merge (v2) / 📢 Slack Notification (push) Has been cancelled
Frontend Unit Tests / Test on Node 20 (push) Has been cancelled
Guardrails E2E Tests / Select Python version matrix (push) Has been cancelled
Guardrails E2E Tests / Guardrails E2E Tests ${{matrix.python_version}} (push) Has been cancelled
Guardrails E2E Tests / 📢 Slack Notification (push) Has been cancelled
Guardrails Backend Unit Tests / Guardrails Backend Unit Tests (push) Has been cancelled
Guardrails Backend Unit Tests / 📢 Slack Notification (push) Has been cancelled
Lint Opik Helm Chart / lint-helm-chart (Helm v3.21.0) (push) Has been cancelled
Lint Opik Helm Chart / lint-helm-chart (Helm v4.2.0) (push) Has been cancelled
Lint Opik Helm Chart / unittest-helm-chart (push) Has been cancelled
192 lines
6.1 KiB
Python
192 lines
6.1 KiB
Python
"""Happy-path e2e tests for the local runner.
|
|
|
|
Test 1 (basic): register echo agent, create job, verify trace output.
|
|
Test 2 (mask): register echo_config agent, create mask, create job with
|
|
mask_id, verify the mask value appears in the trace output.
|
|
"""
|
|
|
|
import time
|
|
from typing import Optional
|
|
|
|
|
|
import opik
|
|
import opik.rest_api.client as rest_api_client
|
|
from opik.api_objects.agent_config.config import ConfigManager
|
|
from .conftest import RunnerInfo
|
|
|
|
|
|
JOB_COMPLETION_TIMEOUT = 30
|
|
TRACE_PROPAGATION_TIMEOUT = 30
|
|
AGENT_REGISTRATION_TIMEOUT = 10
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Helpers
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def submit_job(
|
|
api: rest_api_client.OpikApi,
|
|
agent_name: str,
|
|
message: str,
|
|
project_id: str,
|
|
mask_id: Optional[str] = None,
|
|
) -> None:
|
|
"""Create a job for the given agent."""
|
|
api.runners.create_job(
|
|
agent_name=agent_name,
|
|
inputs={"message": message},
|
|
project_id=project_id,
|
|
mask_id=mask_id,
|
|
)
|
|
|
|
|
|
def wait_for_completed_job(
|
|
api: rest_api_client.OpikApi, runner_id: str, match_text: str
|
|
):
|
|
"""Poll list_jobs until a completed job whose inputs contain *match_text* appears."""
|
|
result = []
|
|
|
|
def _find():
|
|
page = api.runners.list_jobs(runner_id=runner_id, size=20)
|
|
if page.content:
|
|
for j in page.content:
|
|
if j.status == "completed" and j.inputs and match_text in str(j.inputs):
|
|
result.clear()
|
|
result.append(j)
|
|
return True
|
|
return False
|
|
|
|
assert opik.synchronization.until(
|
|
_find,
|
|
max_try_seconds=JOB_COMPLETION_TIMEOUT,
|
|
allow_errors=True,
|
|
), f"No completed job with '{match_text}' found within {JOB_COMPLETION_TIMEOUT}s"
|
|
|
|
return result[0]
|
|
|
|
|
|
def find_trace_by_input(
|
|
api: rest_api_client.OpikApi, project_name: str, match_text: str
|
|
):
|
|
"""Poll until a trace whose input contains *match_text* appears and has output."""
|
|
result = []
|
|
|
|
def _find():
|
|
page = api.traces.get_traces_by_project(
|
|
project_name=project_name,
|
|
size=20,
|
|
)
|
|
if page.content:
|
|
for t in page.content:
|
|
if t.input and match_text in str(t.input) and t.output:
|
|
result.clear()
|
|
result.append(t)
|
|
return True
|
|
return False
|
|
|
|
assert opik.synchronization.until(
|
|
_find,
|
|
max_try_seconds=TRACE_PROPAGATION_TIMEOUT,
|
|
allow_errors=True,
|
|
), f"No trace with '{match_text}' found within {TRACE_PROPAGATION_TIMEOUT}s"
|
|
|
|
return result[0]
|
|
|
|
|
|
def wait_for_agent_registration(
|
|
api: rest_api_client.OpikApi, agent_name: str, project_id: str
|
|
) -> None:
|
|
"""Poll until the agent is registered with any runner in the project."""
|
|
|
|
def _is_agent_registered():
|
|
runners_page = api.runners.list_runners(project_id=project_id, size=50)
|
|
if runners_page.content:
|
|
for runner in runners_page.content:
|
|
if runner.agents:
|
|
for agent in runner.agents:
|
|
if agent.name == agent_name:
|
|
return True
|
|
return False
|
|
|
|
if not opik.synchronization.until(
|
|
_is_agent_registered,
|
|
max_try_seconds=AGENT_REGISTRATION_TIMEOUT,
|
|
allow_errors=True,
|
|
):
|
|
raise AssertionError(
|
|
f"Agent '{agent_name}' was not registered within {AGENT_REGISTRATION_TIMEOUT}s"
|
|
)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Tests
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
def test_runner_happy_path(api_client, runner_process: RunnerInfo, project):
|
|
"""Basic: register echo agent, run job, verify job result, trace output, and job logs."""
|
|
message = f"hello-e2e-{int(time.time())}"
|
|
|
|
wait_for_agent_registration(api_client, "echo", project.id)
|
|
|
|
submit_job(api_client, "echo", message, project.id)
|
|
|
|
job = wait_for_completed_job(api_client, runner_process.runner_id, message)
|
|
assert job.result is not None, "Completed job should have a result"
|
|
assert f"echo: {message}" in str(job.result)
|
|
assert job.trace_id is not None, "Completed job should have a trace_id"
|
|
|
|
trace = find_trace_by_input(api_client, project.name, message)
|
|
assert f"echo: {message}" in str(trace.output)
|
|
|
|
logs_result = []
|
|
|
|
def _find_logs():
|
|
logs = api_client.runners.get_job_logs(job.id)
|
|
if logs:
|
|
logs_result.clear()
|
|
logs_result.extend(logs)
|
|
return True
|
|
return False
|
|
|
|
assert opik.synchronization.until(
|
|
_find_logs,
|
|
max_try_seconds=5,
|
|
allow_errors=True,
|
|
), f"Expected job logs for job {job.id}, got none"
|
|
|
|
log_text = " ".join(entry.text for entry in logs_result)
|
|
assert message in log_text, f"Expected '{message}' in job logs, got: {log_text}"
|
|
|
|
|
|
def test_runner_with_mask(opik_client, api_client, runner_process: RunnerInfo, project):
|
|
"""Mask: register echo_config agent, create mask, verify mask value in job result and trace."""
|
|
message = f"mask-e2e-{int(time.time())}"
|
|
custom_greeting = f"custom-greeting-{int(time.time())}"
|
|
|
|
wait_for_agent_registration(api_client, "echo_config", project.id)
|
|
|
|
manager = ConfigManager(
|
|
project_name=project.name,
|
|
rest_client_=opik_client.rest_client,
|
|
)
|
|
manager.create_blueprint(
|
|
parameters={"greeting": "default-greeting"},
|
|
)
|
|
mask_id = manager.create_mask(
|
|
parameters={"greeting": custom_greeting},
|
|
)
|
|
|
|
submit_job(api_client, "echo_config", message, project.id, mask_id=mask_id)
|
|
|
|
job = wait_for_completed_job(api_client, runner_process.runner_id, message)
|
|
assert job.result is not None, "Completed job should have a result"
|
|
assert custom_greeting in str(job.result)
|
|
assert job.trace_id is not None, "Completed job should have a trace_id"
|
|
|
|
trace = find_trace_by_input(api_client, project.name, message)
|
|
assert custom_greeting in str(trace.output), (
|
|
f"Expected '{custom_greeting}' in trace output, got: {trace.output}"
|
|
)
|