|
| 1 | +#!/usr/bin/env bash |
| 2 | +set -euo pipefail |
| 3 | + |
| 4 | +# ── Package the agent e2e suite as a standalone bundle ─────────────────────── |
| 5 | +# Builds conductor-ai-e2e-python-<version>.tar.gz: a self-contained pytest |
| 6 | +# project carrying the agent e2e test sources (repo-root e2e/), pinned to the |
| 7 | +# published conductor-python[agents]==<version> package from PyPI (no SDK |
| 8 | +# source vendored). |
| 9 | +# |
| 10 | +# Downstream repos (e.g. orkes-io/orkes-conductor) download the bundle from |
| 11 | +# the python-sdk GitHub release and run it against their own server build. |
| 12 | +# This replaces the agentspan-sdk-e2e-python-* bundles formerly cut from |
| 13 | +# agentspan-ai/agentspan — python-sdk is now the canonical home of these |
| 14 | +# suites. Mirrors conductor-oss/java-sdk (conductor-ai-e2e/release/) and |
| 15 | +# conductor-oss/javascript-sdk (scripts/). |
| 16 | +# |
| 17 | +# Usage: |
| 18 | +# ./scripts/package-e2e-bundle.sh --version 2.0.0-rc2 [--out DIR] |
| 19 | +# |
| 20 | +# Packaging is static (no install, no network) — the pinned version does not |
| 21 | +# have to be on PyPI yet, so this can run before the publish job finishes. |
| 22 | +# Note: pip normalizes PEP 440 spellings, so pinning ==2.0.0-rc2 resolves the |
| 23 | +# PyPI artifact 2.0.0rc2. |
| 24 | + |
| 25 | +HERE="$(cd "$(dirname "$0")" && pwd)" |
| 26 | +REPO_ROOT="$(cd "$HERE/.." && pwd)" |
| 27 | + |
| 28 | +VERSION="" |
| 29 | +OUT_DIR="$HERE/e2e-bundle-dist" |
| 30 | + |
| 31 | +while [[ $# -gt 0 ]]; do |
| 32 | + case "$1" in |
| 33 | + --version) VERSION="$2"; shift 2 ;; |
| 34 | + --out) OUT_DIR="$2"; shift 2 ;; |
| 35 | + *) echo "ERROR: unknown arg '$1' (want --version X.Y.Z [--out DIR])" >&2; exit 1 ;; |
| 36 | + esac |
| 37 | +done |
| 38 | + |
| 39 | +[[ -n "$VERSION" ]] || { echo "ERROR: --version is required" >&2; exit 1; } |
| 40 | + |
| 41 | +NAME="conductor-ai-e2e-python-$VERSION" |
| 42 | +STAGE="$OUT_DIR/$NAME" |
| 43 | + |
| 44 | +echo "Packaging agent e2e bundle ($NAME)..." |
| 45 | +rm -rf "$STAGE" |
| 46 | +mkdir -p "$STAGE" |
| 47 | + |
| 48 | +# Suites import the SDK by package (conductor.ai.agents), so the sources copy |
| 49 | +# over verbatim — imports resolve from the installed PyPI package. |
| 50 | +cp -R "$REPO_ROOT/e2e" "$STAGE/e2e" |
| 51 | + |
| 52 | +# Deps mirror the repo's agent-e2e.yml install step, with the editable SDK |
| 53 | +# install swapped for the published pin. |
| 54 | +cat > "$STAGE/requirements.txt" <<'EOF' |
| 55 | +# Pins the published SDK (with the agents extra) to the python-sdk release |
| 56 | +# this bundle was cut from. |
| 57 | +conductor-python[agents]==@VERSION@ |
| 58 | +
|
| 59 | +# Test runner + e2e support deps (mirrors .github/workflows/agent-e2e.yml). |
| 60 | +pytest |
| 61 | +pytest-asyncio |
| 62 | +pytest-xdist |
| 63 | +pytest-rerunfailures |
| 64 | +
|
| 65 | +# Live MCP server used by the MCP tool suites. |
| 66 | +mcp-testkit |
| 67 | +EOF |
| 68 | + |
| 69 | +cat > "$STAGE/run.sh" <<'EOF' |
| 70 | +#!/usr/bin/env bash |
| 71 | +set -euo pipefail |
| 72 | +# Runs the agent e2e suite against a live Conductor server with the agent |
| 73 | +# runtime enabled (conductor-oss >= 3.32.0-rc.8, or orkes-conductor with |
| 74 | +# agentspan.embedded=true). |
| 75 | +# |
| 76 | +# Required services (NOT started by this script): |
| 77 | +# - Conductor server → AGENTSPAN_SERVER_URL (default http://localhost:8080/api) |
| 78 | +# - mcp-testkit → MCP_TESTKIT_URL (default http://localhost:3001) |
| 79 | +# Optional: |
| 80 | +# - AGENTSPAN_LLM_MODEL (default openai/gpt-4o-mini); the provider API key |
| 81 | +# must be configured on the SERVER — the suites never read it. |
| 82 | +# - AGENTSPAN_CLI_PATH (default `agentspan` on PATH) — CLI suites skip if absent. |
| 83 | +# |
| 84 | +# Requires python 3.10–3.13 on PATH as `python` (use a venv; the harness deps |
| 85 | +# may not build on newer interpreters). Usage: ./run.sh [extra pytest args] |
| 86 | +HERE="$(cd "$(dirname "$0")" && pwd)" |
| 87 | +cd "$HERE" |
| 88 | +python -m pip install -r requirements.txt |
| 89 | +mkdir -p results |
| 90 | +python -m pytest e2e/ -v --tb=short -n 3 --dist=loadgroup \ |
| 91 | + --junitxml=results/junit-e2e.xml "$@" |
| 92 | +python e2e/report_generator.py results/junit-e2e.xml results/report.html || true |
| 93 | +echo "Results: $HERE/results/junit-e2e.xml (report.html alongside)" |
| 94 | +EOF |
| 95 | +chmod +x "$STAGE/run.sh" |
| 96 | + |
| 97 | +cat > "$STAGE/README.md" <<'EOF' |
| 98 | +# Conductor Agent SDK (python) — E2E suite @VERSION@ |
| 99 | +
|
| 100 | +Self-contained end-to-end tests for the Conductor Python agent SDK, pinned to |
| 101 | +release **@VERSION@**. Resolves `conductor-python[agents]==@VERSION@` from |
| 102 | +PyPI — no SDK source is vendored. Cut from |
| 103 | +[conductor-oss/python-sdk](https://github.com/conductor-oss/python-sdk) |
| 104 | +(`e2e/`); supersedes the `agentspan-sdk-e2e-python-*` bundles formerly |
| 105 | +released from agentspan-ai/agentspan. |
| 106 | +
|
| 107 | +## Prerequisites (you provide these) |
| 108 | +
|
| 109 | +| Requirement | Env var | Default | |
| 110 | +|-----------------------------------|------------------------|-----------------------------| |
| 111 | +| python 3.10–3.13 (use a venv) | — | — | |
| 112 | +| Conductor server w/ agent runtime | `AGENTSPAN_SERVER_URL` | `http://localhost:8080/api` | |
| 113 | +| LLM model | `AGENTSPAN_LLM_MODEL` | `openai/gpt-4o-mini` | |
| 114 | +| mcp-testkit (MCP suites) | `MCP_TESTKIT_URL` | `http://localhost:3001` | |
| 115 | +| agentspan CLI (CLI suites) | `AGENTSPAN_CLI_PATH` | `agentspan` (on `PATH`) | |
| 116 | +
|
| 117 | +The server needs the agent runtime: conductor-oss `>= 3.32.0-rc.8`, or |
| 118 | +orkes-conductor booted with `agentspan.embedded=true`. LLM provider API keys |
| 119 | +(e.g. `OPENAI_API_KEY`) go to the **server** process, not this suite. |
| 120 | +Suites that need an absent optional service (CLI, LangGraph) skip rather |
| 121 | +than fail. |
| 122 | +
|
| 123 | +## Run |
| 124 | +
|
| 125 | +```bash |
| 126 | +python3.12 -m venv .venv && source .venv/bin/activate |
| 127 | +./run.sh # full suite |
| 128 | +./run.sh -k suite1 # filter, plus any pytest args |
| 129 | +``` |
| 130 | +
|
| 131 | +JUnit XML lands in `results/junit-e2e.xml`, HTML report in |
| 132 | +`results/report.html`. |
| 133 | +
|
| 134 | +## Testing an unreleased SDK |
| 135 | +
|
| 136 | +```bash |
| 137 | +pip install /path/to/conductor_python-X.Y.Z-py3-none-any.whl'[agents]' |
| 138 | +python -m pytest e2e/ -v --tb=short -n 3 --dist=loadgroup |
| 139 | +``` |
| 140 | +EOF |
| 141 | + |
| 142 | +# Stamp the version everywhere (skip binary assets). |
| 143 | +find "$STAGE" -type f ! -name '*.png' ! -name '*.jpg' ! -name '*.jpeg' \ |
| 144 | + ! -name '*.gif' ! -name '*.webp' ! -name '*.pdf' -print0 \ |
| 145 | + | xargs -0 sed -i.bak "s/@VERSION@/$VERSION/g" |
| 146 | +find "$STAGE" -name '*.bak' -delete |
| 147 | + |
| 148 | +mkdir -p "$OUT_DIR" |
| 149 | +tar -czf "$OUT_DIR/$NAME.tar.gz" -C "$OUT_DIR" "$NAME" |
| 150 | +rm -rf "$STAGE" |
| 151 | + |
| 152 | +echo "OK: $OUT_DIR/$NAME.tar.gz" |
0 commit comments