-
Notifications
You must be signed in to change notification settings - Fork 3
266 lines (231 loc) · 7.56 KB
/
integration.yml
File metadata and controls
266 lines (231 loc) · 7.56 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
name: Integration
on:
push:
paths-ignore:
- "**/*.md"
pull_request:
paths-ignore:
- "**/*.md"
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
backend-integration:
name: Backend Integration
runs-on: ubuntu-latest
timeout-minutes: 20
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_USER: querygpt
POSTGRES_PASSWORD: querygpt
POSTGRES_DB: querygpt_test
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U querygpt -d querygpt_test"
--health-interval 5s
--health-timeout 5s
--health-retries 20
mysql:
image: mysql:8.0
env:
MYSQL_DATABASE: querygpt_test
MYSQL_USER: querygpt
MYSQL_PASSWORD: querygpt
MYSQL_ROOT_PASSWORD: root
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping -h 127.0.0.1 -uquerygpt -pquerygpt"
--health-interval=5s
--health-timeout=5s
--health-retries=20
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"
cache-dependency-path: apps/api/pyproject.toml
- name: Install dependencies
working-directory: apps/api
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Start mock LLM gateway
run: |
python scripts/mock_llm_gateway.py > mock-llm.log 2>&1 &
echo $! > /tmp/mock-llm.pid
python - <<'PY'
import time
import urllib.request
for _ in range(30):
try:
with urllib.request.urlopen("http://127.0.0.1:4010/health", timeout=2):
break
except Exception:
time.sleep(1)
else:
raise SystemExit("Mock LLM gateway failed to become healthy")
PY
- name: Run integration tests
working-directory: apps/api
env:
QUERYGPT_TEST_PG_HOST: 127.0.0.1
QUERYGPT_TEST_PG_PORT: "5432"
QUERYGPT_TEST_PG_USER: querygpt
QUERYGPT_TEST_PG_PASSWORD: querygpt
QUERYGPT_TEST_PG_DATABASE: querygpt_test
QUERYGPT_TEST_MYSQL_HOST: 127.0.0.1
QUERYGPT_TEST_MYSQL_PORT: "3306"
QUERYGPT_TEST_MYSQL_USER: querygpt
QUERYGPT_TEST_MYSQL_PASSWORD: querygpt
QUERYGPT_TEST_MYSQL_DATABASE: querygpt_test
QUERYGPT_TEST_MODEL_BASE_URL: http://127.0.0.1:4010/v1
ENCRYPTION_KEY: dGVzdC1lbmNyeXB0aW9uLWtleS0zMmJ5dGVz
run: pytest tests/test_config_integration.py -v
- name: Upload mock gateway log
if: always()
uses: actions/upload-artifact@v4
with:
name: backend-integration-mock-llm-log
path: mock-llm.log
if-no-files-found: ignore
docker-e2e:
name: Docker E2E
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: apps/web/package-lock.json
- name: Install frontend dependencies
working-directory: apps/web
run: npm ci
- name: Build and start Docker stack
run: docker compose -f docker-compose.yml -f docker-compose.ci.yml up -d --build
- name: Wait for frontend and backend
run: |
for url in http://127.0.0.1:8000/health http://127.0.0.1:3000; do
for _ in $(seq 1 60); do
if curl -fsS "$url" >/dev/null; then
break
fi
sleep 2
done
curl -fsS "$url" >/dev/null
done
- name: Install Playwright browser
working-directory: apps/web
run: npx playwright install --with-deps chromium
- name: Run Playwright smoke test
working-directory: apps/web
env:
PLAYWRIGHT_BASE_URL: http://127.0.0.1:3000
run: npm run test:e2e
- name: Collect Docker logs
if: always()
run: |
docker compose -f docker-compose.yml -f docker-compose.ci.yml logs --no-color > docker-compose.integration.log || true
- name: Upload Docker and Playwright artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: docker-e2e-artifacts
path: |
docker-compose.integration.log
apps/web/playwright-report
apps/web/test-results
if-no-files-found: ignore
- name: Shutdown Docker stack
if: always()
run: docker compose -f docker-compose.yml -f docker-compose.ci.yml down -v --remove-orphans
start-sh-smoke:
name: start.sh Smoke (${{ matrix.os }})
runs-on: ${{ matrix.os }}
timeout-minutes: 25
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"
cache-dependency-path: apps/api/pyproject.toml
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
cache: "npm"
cache-dependency-path: apps/web/package-lock.json
- name: Write CI env files
run: |
cat > apps/api/.env <<'EOF'
DATABASE_URL=sqlite+aiosqlite:///./data/querygpt.db
ENCRYPTION_KEY=dGVzdC1lbmNyeXB0aW9uLWtleS0zMmJ5dGVz
EOF
cat > apps/web/.env.local <<'EOF'
NEXT_PUBLIC_API_URL=http://127.0.0.1:8000
INTERNAL_API_URL=http://127.0.0.1:8000
EOF
- name: Setup workspace
run: QUERYGPT_NO_BROWSER=1 ./start.sh setup
- name: Doctor
run: QUERYGPT_NO_BROWSER=1 ./start.sh doctor
- name: Start backend
run: QUERYGPT_NO_BROWSER=1 ./start.sh backend
- name: Start frontend
run: QUERYGPT_NO_BROWSER=1 ./start.sh frontend
- name: Wait for services
run: |
for url in http://127.0.0.1:8000/health http://127.0.0.1:3000; do
for _ in $(seq 1 60); do
if curl -fsS "$url" >/dev/null; then
break
fi
sleep 2
done
curl -fsS "$url" >/dev/null
done
- name: Status
run: ./start.sh status
- name: Upload host smoke logs
if: always()
uses: actions/upload-artifact@v4
with:
name: start-sh-smoke-${{ matrix.os }}
path: |
logs/backend.log
logs/frontend.log
if-no-files-found: ignore
- name: Stop services
if: always()
run: ./start.sh stop
integration-success:
name: Integration Success
needs: [backend-integration, docker-e2e, start-sh-smoke]
if: always()
runs-on: ubuntu-latest
steps:
- name: Verify integration jobs
run: |
if [ "${{ needs.backend-integration.result }}" != "success" ] || \
[ "${{ needs.docker-e2e.result }}" != "success" ] || \
[ "${{ needs.start-sh-smoke.result }}" != "success" ]; then
echo "At least one integration job failed"
exit 1
fi
echo "✅ All integration checks passed!"