-
Notifications
You must be signed in to change notification settings - Fork 40
131 lines (112 loc) · 4.19 KB
/
Copy pathagent-e2e.yml
File metadata and controls
131 lines (112 loc) · 4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
name: Agent E2E
# Runs the agent e2e suites (e2e/) against the Conductor OSS server boot
# JAR (Maven Central) — the server this SDK ships against, with the agent
# runtime on by default from 3.32.0-rc.8 onward.
# tests/integration/ai stays manual-only: run it locally against
# a live server with `pytest tests/integration/ai`.
#
# These tests call real LLMs via the OPENAI_API_KEY / ANTHROPIC_API_KEY
# repo secrets. Fork PRs cannot see repo secrets, so for them the run
# fails at the silently-empty guard rather than passing vacuously.
on: [pull_request, workflow_dispatch]
permissions:
contents: read
concurrency:
group: agent-e2e-${{ github.ref }}
cancel-in-progress: true
env:
CONDUCTOR_SERVER_VERSION: "3.32.0-rc18" # pinned server release — bump deliberately
jobs:
agent-e2e:
runs-on: ubuntu-latest
timeout-minutes: 45
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
CONDUCTOR_SERVER_URL: http://localhost:8080/api
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
- name: Cache server JAR
id: jar_cache
uses: actions/cache@v4
with:
path: conductor-server.jar
key: conductor-oss-server-${{ env.CONDUCTOR_SERVER_VERSION }}
- name: Download server JAR from Maven Central
if: steps.jar_cache.outputs.cache-hit != 'true'
run: |
curl -fL --retry 3 -o conductor-server.jar \
"https://repo1.maven.org/maven2/org/conductoross/conductor-server/${CONDUCTOR_SERVER_VERSION}/conductor-server-${CONDUCTOR_SERVER_VERSION}-boot.jar"
- name: Install SDK + test deps
run: |
python -m pip install --upgrade pip
pip install -e '.[agents]'
pip install pytest pytest-asyncio pytest-xdist pytest-rerunfailures mcp-testkit
- name: Start mcp-testkit
run: |
mcp-testkit --transport http --port 3001 &
sleep 2
- name: Start server
run: |
java -jar conductor-server.jar --server.port=8080 > server.log 2>&1 &
- name: Wait for server health
run: |
for i in $(seq 1 45); do
if curl -sf http://localhost:8080/health | grep -q '"healthy"[[:space:]]*:[[:space:]]*true'; then
echo "server healthy after ~$((i*2))s"; exit 0
fi
sleep 2
done
echo "::error::server failed to become healthy within 90s"
tail -100 server.log
exit 1
- name: Run e2e suites
run: |
mkdir -p results
pytest e2e/ -v --tb=short -n 3 --dist=loadgroup \
--junitxml=results/junit-e2e.xml
# e2e/conftest.py pytest.skip()s the whole session when the server is
# unreachable — without this guard a boot failure after the health gate
# (or a future gate regression) would yield a green job that ran nothing.
- name: Guard against silently-empty runs
if: always()
run: |
python - <<'EOF'
import glob
import sys
import xml.etree.ElementTree as ET
total = executed = 0
for path in glob.glob("results/junit-*.xml"):
root = ET.parse(path).getroot()
for suite in root.iter("testsuite"):
t = int(suite.get("tests", 0))
sk = int(suite.get("skipped", 0))
total += t
executed += t - sk
print(f"executed {executed}/{total} tests")
sys.exit(0 if executed > 0 else 1)
EOF
- name: Generate HTML report
if: always()
run: |
python e2e/report_generator.py results/junit-e2e.xml results/report.html || true
- name: Upload results
if: always()
uses: actions/upload-artifact@v4
with:
name: agent-e2e-results
path: |
results/
server.log
retention-days: 14