forked from stacklok/codegate
-
Notifications
You must be signed in to change notification settings - Fork 0
332 lines (288 loc) · 12.1 KB
/
integration-tests.yml
File metadata and controls
332 lines (288 loc) · 12.1 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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
# This workflow will run the integration tests for the project
name: Tests - Integration
on:
workflow_call:
inputs:
artifact-name:
description: 'The name of the artifact to download'
required: true
type: string
secrets:
copilot-key:
description: 'The Copilot key to use for integration tests'
required: true
anthropic-key:
description: 'The Anthropic key to use for integration tests'
required: true
openrouter-key:
description: 'The Openrouter key to use for integration tests'
required: true
jobs:
integration-tests:
name: Test
runs-on: ubuntu-latest
strategy:
fail-fast: false # Continue running other tests if one fails
matrix:
python-version: [ "3.12" ]
test-provider: [ "copilot", "openai", "anthropic", "ollama", "vllm", "llamacpp", "openrouter" ]
env:
ENV_COPILOT_KEY: ${{ secrets.copilot-key }}
ENV_OPENAI_KEY: ${{ secrets.copilot-key }} # We use the same key for OpenAI as the Copilot tests
ENV_ANTHROPIC_KEY: ${{ secrets.anthropic-key }}
ENV_OPENROUTER_KEY: ${{ secrets.openrouter-key }}
CA_CERT_FILE: "/home/runner/work/codegate/codegate/codegate_volume/certs/ca.crt"
CODEGATE_CONTAINER_NAME: "codegate"
CODEGATE_MOUNT_PATH_CERT_FILE: "/app/codegate_volume/certs/ca.crt"
CODEGATE_LOG_LEVEL: "DEBUG"
LOCAL_OLLAMA_URL: "http://localhost:11434"
LOCAL_VLLM_URL: "http://localhost:8000"
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
lfs: true
- name: Checkout LFS objects
run: git lfs pull
- name: Ensure file permissions for mounted volume
run: |
mkdir -p ./codegate_volume/certs ./codegate_volume/models ./codegate_volume/db
chmod -R 777 ./codegate_volume
- name: Download the CodeGate container image
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
name: ${{ inputs.artifact-name }}
- name: Load the CodeGate container image
run: |
docker load -i image.tar
echo "Loaded image:"
docker images
- name: Download the Qwen2.5-Coder-0.5B-Instruct-GGUF model (llamacpp only)
if: ${{ matrix.test-provider == 'llamacpp' }} # This is only needed for llamacpp
run: |
wget -P ./codegate_volume/models https://huggingface.co/Qwen/Qwen2.5-Coder-0.5B-Instruct-GGUF/resolve/main/qwen2.5-coder-0.5b-instruct-q5_k_m.gguf
- name: Start the CodeGate container
run: |
# Get the image name
DOCKER_IMAGE=$(docker images --format "{{.Repository}}:{{.Tag}}" | head -n 1)
echo "Running container from image: $DOCKER_IMAGE"
# Run the container
docker run --name $CODEGATE_CONTAINER_NAME -d --network host \
-v "$(pwd)"/codegate_volume:/app/codegate_volume \
-e CODEGATE_APP_LOG_LEVEL=$CODEGATE_LOG_LEVEL \
-e CODEGATE_OLLAMA_URL=$LOCAL_OLLAMA_URL \
-e CODEGATE_VLLM_URL=$LOCAL_VLLM_URL \
-e CODEGATE_DEV_ENV=true \
--restart unless-stopped $DOCKER_IMAGE
# Confirm the container started
echo "Container started:"
docker ps
# Verify container is running with correct ports
docker ps -f name=$CODEGATE_CONTAINER_NAME
# Check mount configuration
docker inspect $CODEGATE_CONTAINER_NAME -f '{{ json .Mounts }}' | jq
- name: Test the healthcheck endpoint
timeout-minutes: 4
run: |
# Check the healthcheck endpoint is available
while true; do
echo "Checking for healthcheck endpoint in CodeGate..."
if curl --silent --fail --get "http://localhost:8989/health" >/dev/null; then
echo "Healthcheck endpoint is available"
break
else
echo "Healthcheck endpoint not available. Retrying in 5 seconds..."
sleep 5
fi
done
curl "http://localhost:8989/health"
- name: Ensure certificates are available in the container
timeout-minutes: 4
run: |
# Wait for the cert file to be available in the container
while true; do
echo "Checking for $CODEGATE_MOUNT_PATH_CERT_FILE in container $CODEGATE_CONTAINER_NAME..."
if docker exec "$CODEGATE_CONTAINER_NAME" test -f "$CODEGATE_MOUNT_PATH_CERT_FILE"; then
echo "Cert file found: $CODEGATE_MOUNT_PATH_CERT_FILE"
break
else
echo "Cert file not found. Retrying in 5 seconds..."
sleep 5
fi
done
# Verify volume contents are accessible
docker exec $CODEGATE_CONTAINER_NAME ls -la /app/codegate_volume
- name: Copy and install the CodeGate certificate
run: |
docker cp codegate:/app/codegate_volume/certs/ca.crt ./codegate.crt
sudo cp ./codegate.crt /usr/local/share/ca-certificates/codegate.crt
sudo update-ca-certificates
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5
with:
python-version: ${{ matrix.python-version }}
- name: Install Poetry
uses: snok/install-poetry@76e04a911780d5b312d89783f7b1cd627778900a # v1
with:
version: 2.0.1
virtualenvs-create: true
virtualenvs-in-project: true
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
with:
path: .venv
key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }}
- name: Install dependencies
run: poetry install --with dev
- name: Run the Ollama container (ollama-only)
if: ${{ matrix.test-provider == 'ollama' }} # This is only needed for Ollama
timeout-minutes: 15
env:
MAX_RETRIES: 3
run: |
function check_model_ready() {
response=$(curl -s http://localhost:11434/api/generate -d '{
"model": "qwen2.5-coder:1.5b",
"prompt": "Hello",
"stream": false
}' 2>&1)
if ! echo "$response" | grep -q "error"; then
return 0 # Success
fi
return 1 # Not ready/error
}
function cleanup_container() {
docker stop ollama >/dev/null 2>&1 || true
docker rm ollama >/dev/null 2>&1 || true
sleep 2
}
retry_count=0
while [ $retry_count -lt $MAX_RETRIES ]; do
# Cleanup any existing container
cleanup_container
echo "Starting Ollama container (Attempt $(($retry_count + 1))/$MAX_RETRIES)"
docker run -d -v ollama:/root/.ollama --network host --name ollama -e OLLAMA_LOG_LEVEL=DEBUG ollama/ollama
# Wait for endpoint to be available
endpoint_wait=0
while [ $endpoint_wait -lt 30 ]; do
if curl --silent --fail --get "http://localhost:11434" >/dev/null; then
echo "Ollama endpoint is available"
break
fi
sleep 2
endpoint_wait=$((endpoint_wait + 1))
done
if [ $endpoint_wait -eq 30 ]; then
echo "Endpoint never became available, retrying..."
retry_count=$((retry_count + 1))
continue
fi
echo "Starting model download/initialization..."
docker exec -d ollama ollama run qwen2.5-coder:1.5b
# Monitor container and model status
monitor_count=0
while [ $monitor_count -lt 90 ]; do # 7.5 minutes
# Check if container is still running
if ! docker ps | grep -q ollama; then
echo "Container crashed, logs:"
docker logs ollama
retry_count=$((retry_count + 1))
break
fi
# Check if model is ready
if check_model_ready; then
echo "Model is ready!"
exit 0 # Success!
fi
echo "Model not ready yet. Waiting... ($(($monitor_count + 1))/90)"
sleep 5
monitor_count=$((monitor_count + 1))
done
if [ $monitor_count -eq 90 ]; then
echo "Timeout waiting for model, container logs:"
docker logs ollama
retry_count=$((retry_count + 1))
fi
done
echo "Failed after $MAX_RETRIES attempts"
exit 1
- name: Build and run the vllm container (vllm-only)
if: ${{ matrix.test-provider == 'vllm' }} # This is only needed for VLLM
timeout-minutes: 10
run: |
# We clone the VLLM repo and build the container because the CPU-mode container is not published
git clone https://github.com/vllm-project/vllm.git
cd vllm
docker build -f Dockerfile.cpu -t vllm-cpu-env --shm-size=4g .
docker run -d --name vllm \
--network="host" \
vllm-cpu-env --model Qwen/Qwen2.5-Coder-0.5B-Instruct
echo -e "\nVerify the vllm container is serving\n"
docker ps -f name=vllm
echo "Loop until the endpoint responds successfully"
while ! curl --silent --fail --get "http://localhost:8000/ping" >/dev/null; do
echo "Ping not available yet. Retrying in 2 seconds..."
sleep 2
done
echo -e "\nPing is now available!\n"
echo -e "\nVerify the completions endpoint works\n"
curl http://localhost:8000/v1/completions -H "Content-Type: application/json" -d '{
"model": "Qwen/Qwen2.5-Coder-0.5B-Instruct",
"prompt": ["Hello"],
"max_tokens": 100,
"temperature": 0
}'
echo -e "\nVerify the chat/completions endpoint works\n"
curl -X POST http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen2.5-Coder-0.5B-Instruct",
"messages": [
{"role": "system", "content": "You are a coding assistant."},
{"role": "user", "content": "Hello"}
],
"temperature": 0,
"max_tokens": 4096,
"extra_body": {}
}'
echo -e "\nPrint the vllm container logs\n"
docker logs vllm
- name: Tests - ${{ matrix.test-provider }}
timeout-minutes: 15
env:
CODEGATE_PROVIDERS: ${{ matrix.test-provider }}
run: |
poetry run --ansi python tests/integration/integration_tests.py
- name: Logs - CodeGate container
if: always()
continue-on-error: true
run: |
docker logs $CODEGATE_CONTAINER_NAME
echo "Models contents:"
ls -la codegate_volume/models
docker exec $CODEGATE_CONTAINER_NAME ls -la /app/codegate_volume/models
echo "Certs contents:"
ls -la codegate_volume/certs
docker exec $CODEGATE_CONTAINER_NAME ls -la /app/codegate_volume/certs
echo "DB contents:"
ls -la codegate_volume/db
docker exec $CODEGATE_CONTAINER_NAME ls -la /app/codegate_volume/db
- name: Logs - vllm container (vllm-only)
if: always()
continue-on-error: true
run: |
if ${{ matrix.test-provider == 'vllm' }}; then
docker logs vllm
else
echo "Skipping vllm logs, as this is not a VLLM test"
fi
- name: Logs - Ollama container (ollama-only)
if: always()
continue-on-error: true
run: |
if ${{ matrix.test-provider == 'ollama' }}; then
docker logs ollama
else
echo "Skipping Ollama logs, as this is not an Ollama test"
fi