-
Notifications
You must be signed in to change notification settings - Fork 1.3k
245 lines (220 loc) · 9.36 KB
/
Copy pathopenresponses-conformance.yml
File metadata and controls
245 lines (220 loc) · 9.36 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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
name: OpenResponses Conformance Tests
run-name: Run OpenResponses conformance tests against ogx Responses API
# This job is REQUIRED — it enforces conformance with the OpenResponses spec
# (https://openresponses.org). Any failing conformance test fails the job.
# See: https://github.com/ogx-ai/ogx/issues/4818
#
# Inference calls are replayed from checked-in recordings under
# tests/integration/openresponses/recordings/. To add or update recordings,
# run the server locally with OGX_TEST_INFERENCE_MODE=record-if-missing
# pointed at that directory, run the compliance tests, and commit the results.
on:
push:
branches:
- main
- 'release-[0-9]+.[0-9]+.x'
paths:
- 'src/ogx/providers/inline/responses/**'
- 'src/ogx_api/responses/**'
- 'src/ogx_api/openai_responses.py'
- 'src/ogx/core/server/auth.py'
- 'tests/integration/openresponses/**'
- '.github/workflows/openresponses-conformance.yml'
pull_request:
branches:
- main
- 'release-[0-9]+.[0-9]+.x'
paths:
- 'src/ogx/providers/inline/responses/**'
- 'src/ogx_api/responses/**'
- 'src/ogx_api/openai_responses.py'
- 'src/ogx/core/server/auth.py'
- 'tests/integration/openresponses/**'
- '.github/workflows/openresponses-conformance.yml'
merge_group:
branches:
- main
- 'release-[0-9]+.[0-9]+.x'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref == 'refs/heads/main' && github.run_id || github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
openresponses-conformance:
name: OpenResponses Conformance
runs-on: ubuntu-latest
env:
# Dummy key satisfies config parsing; actual inference is replayed from recordings
OPENAI_API_KEY: "dummy-key-for-replay-mode"
INFERENCE_MODEL: "openai/gpt-4o-mini"
OGX_PORT: 8321
OGX_TEST_INFERENCE_MODE: "replay"
OGX_TEST_RECORDING_DIR: ${{ github.workspace }}/tests/integration/openresponses
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Check for recordings
id: check-recordings
run: |
RECORDINGS_DIR="${{ github.workspace }}/tests/integration/openresponses/recordings"
COUNT=$(find "$RECORDINGS_DIR" -name "*.json" 2>/dev/null | wc -l)
echo "recordings_count=$COUNT" >> "$GITHUB_OUTPUT"
if [ "$COUNT" -eq 0 ]; then
echo "::warning::No recordings found in tests/integration/openresponses/recordings/."
echo "::warning::Run the server locally with OGX_TEST_INFERENCE_MODE=record-if-missing"
echo "::warning::and commit the resulting recordings to enable conformance testing in CI."
else
echo "Found $COUNT recording(s)"
fi
- name: Install dependencies
uses: ./.github/actions/setup-runner
with:
python-version: '3.12'
- name: Install ci-tests distro provider dependencies
run: uv run ogx stack list-deps ci-tests --format uv | sh
- name: Start OGX server
run: |
mkdir -p /tmp/ogx-conformance
export OGX_LOG_WIDTH=200
nohup uv run ogx stack run ci-tests --port "$OGX_PORT" --insecure \
> /tmp/ogx-conformance/server.log 2>&1 &
echo "Server PID: $!"
- name: Wait for OGX server to be ready
run: |
echo "Waiting for OGX server..."
for _ in {1..60}; do
if curl -s "http://localhost:$OGX_PORT/v1/health" | grep -q "OK"; then
echo "OGX server is ready!"
exit 0
fi
sleep 2
done
echo "OGX server failed to start in 120 seconds"
cat /tmp/ogx-conformance/server.log
exit 1
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 #v2.0.0
- name: Clone OpenResponses repository
run: |
git clone --depth=1 https://github.com/openresponses/openresponses.git /tmp/openresponses
- name: Install OpenResponses dependencies
working-directory: /tmp/openresponses
run: bun install
- name: Run OpenResponses conformance tests
id: run-tests
run: |
cd /tmp/openresponses
bun run bin/compliance-test.ts \
--base-url "http://localhost:$OGX_PORT/v1" \
--api-key "ogx" \
--model "$INFERENCE_MODEL" \
--json > /tmp/openresponses-results.json 2>/dev/null || true
echo "=== OpenResponses Conformance Test Output ==="
bun run bin/compliance-test.ts \
--base-url "http://localhost:$OGX_PORT/v1" \
--api-key "ogx" \
--model "$INFERENCE_MODEL" \
--verbose 2>&1 | tee /tmp/openresponses-output.txt || true
- name: Generate conformance report
if: always()
run: |
{
echo "## OpenResponses Conformance Test Results"
echo ""
echo "> These tests enforce [OpenResponses](https://www.openresponses.org) API"
echo "> conformance. Any failing test fails this job."
echo "> See [#4818](https://github.com/ogx-ai/ogx/issues/4818)."
echo ""
echo "**Model:** \`$INFERENCE_MODEL\`"
echo "**Recordings:** ${{ steps.check-recordings.outputs.recordings_count }} file(s) in \`tests/integration/openresponses/recordings/\`"
echo ""
} >> "$GITHUB_STEP_SUMMARY"
if [ "${{ steps.check-recordings.outputs.recordings_count }}" = "0" ]; then
{
echo "### No Recordings Found"
echo ""
echo "To enable conformance testing, generate recordings locally:"
echo '```bash'
echo "OPENAI_API_KEY=\$YOUR_KEY bash scripts/record-openresponses-conformance.sh"
echo ""
echo "# Then commit the recordings"
echo "git add tests/integration/openresponses/recordings/"
echo "git commit -m 'chore: add OpenResponses conformance recordings'"
echo '```'
echo "Commit the resulting \`tests/integration/openresponses/recordings/*.json\` files."
} >> "$GITHUB_STEP_SUMMARY"
elif [ -f /tmp/openresponses-results.json ] && jq -e '.summary' /tmp/openresponses-results.json > /dev/null 2>&1; then
PASSED=$(jq -r '.summary.passed' /tmp/openresponses-results.json)
FAILED=$(jq -r '.summary.failed' /tmp/openresponses-results.json)
TOTAL=$(jq -r '.summary.total' /tmp/openresponses-results.json)
{
echo "### Summary"
echo ""
echo "| Metric | Count |"
echo "|--------|-------|"
echo "| ✅ Passed | $PASSED |"
echo "| ❌ Failed | $FAILED |"
echo "| **Total** | **$TOTAL** |"
echo ""
echo "### Test Details"
echo ""
echo "| Test | Status | Duration |"
echo "|------|--------|----------|"
jq -r '.results[] | "| \(.name) | \(if .status == "passed" then "✅ Pass" else "❌ Fail" end) | \(.duration // "—")ms |"' \
/tmp/openresponses-results.json
echo ""
} >> "$GITHUB_STEP_SUMMARY"
if [ "$FAILED" -gt 0 ]; then
{
echo "### Failure Details"
echo ""
jq -r '.results[] | select(.status == "failed") | "**\(.name)**\n" + ((.errors // []) | map("- \(.)") | join("\n")) + "\n"' \
/tmp/openresponses-results.json
} >> "$GITHUB_STEP_SUMMARY"
fi
else
{
echo "### Results"
echo ""
echo "Could not parse structured results."
if [ -f /tmp/openresponses-output.txt ]; then
echo ""
echo "<details><summary>Raw output</summary>"
echo ""
echo '```'
cat /tmp/openresponses-output.txt
echo '```'
echo ""
echo "</details>"
fi
} >> "$GITHUB_STEP_SUMMARY"
fi
- name: Enforce conformance
run: |
if [ ! -f /tmp/openresponses-results.json ] || ! jq -e '.summary' /tmp/openresponses-results.json > /dev/null 2>&1; then
echo "::error::No parseable OpenResponses conformance results were produced."
exit 1
fi
FAILED=$(jq -r '.summary.failed' /tmp/openresponses-results.json)
if [ "$FAILED" -gt 0 ]; then
echo "::error::$FAILED OpenResponses conformance test(s) failed."
exit 1
fi
echo "All OpenResponses conformance tests passed."
- name: Upload conformance test results
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: openresponses-conformance-results-${{ github.run_id }}
path: |
/tmp/openresponses-results.json
/tmp/openresponses-output.txt
retention-days: 30
if-no-files-found: warn
- name: Print server log on failure
if: failure()
run: |
echo "=== OGX server log (last 200 lines) ==="
tail -200 /tmp/ogx-conformance/server.log || true