AILIXIR Bot commited on
Commit
ab17055
·
1 Parent(s): f987f0b

Auto-sync: 9ec47ffa7894617d757f0d327196ac187860d921

Browse files
.github/workflows/integration-test-hf.yml CHANGED
@@ -12,108 +12,110 @@ concurrency:
12
  cancel-in-progress: true
13
 
14
  jobs:
15
- core-ai-proxy:
16
  runs-on: ubuntu-latest
17
- timeout-minutes: 30
18
-
19
  steps:
20
- - name: Checkout
21
- uses: actions/checkout@v4
22
-
23
  - name: Warm up ailixir-api Space
24
  run: |
25
  echo "Waiting for ailixir-api HF Space..."
26
  for i in $(seq 1 60); do
27
- if curl -sf https://Ailixir-AI-Team-ailixir-api.hf.space/ > /dev/null 2>&1; then
28
- echo "ailixir-api is up"
29
- sleep 5
30
- exit 0
31
  fi
32
  echo "Attempt $i/60..."
33
  sleep 5
34
  done
35
- exit 1
36
 
37
  - name: Warm up ailixir-drug-repurposing Space
38
  run: |
39
  echo "Waiting for ailixir-drug-repurposing HF Space..."
40
  for i in $(seq 1 60); do
41
  if curl -sf https://RottenShadow-ailixir-drug-repurposing.hf.space/health > /dev/null 2>&1; then
42
- echo "ailixir-drug-repurposing is up"
43
- sleep 3
44
- exit 0
45
  fi
46
  echo "Attempt $i/60..."
47
  sleep 5
48
  done
49
- exit 1
50
 
51
  - name: Warm up ailixir-admet Space
52
  run: |
53
  echo "Waiting for ailixir-admet HF Space..."
54
  for i in $(seq 1 60); do
55
  if curl -sf https://shdwRow-ailixir-admet.hf.space/health > /dev/null 2>&1; then
56
- echo "ailixir-admet is up"
57
- sleep 3
58
- exit 0
59
  fi
60
  echo "Attempt $i/60..."
61
  sleep 5
62
  done
63
- exit 1
64
 
65
  - name: Warm up ailixir-chemical-rag Space
66
  run: |
67
  echo "Waiting for ailixir-chemical-rag HF Space..."
68
  for i in $(seq 1 60); do
69
  if curl -sf https://RottenShadow-ailixir-chemical-rag.hf.space/health > /dev/null 2>&1; then
70
- echo "ailixir-chemical-rag is up"
71
- sleep 3
72
- exit 0
73
  fi
74
  echo "Attempt $i/60..."
75
  sleep 5
76
  done
77
- exit 1
 
 
 
 
 
 
 
 
78
 
79
  - name: Login and get Bearer token
80
  run: |
81
  echo "POST /api/user/login"
82
- HTTP_CODE=$(curl -s -o login.json -w "%{http_code}" -X POST https://Ailixir-AI-Team-ailixir-api.hf.space/api/user/login \
83
- -H "Content-Type: application/json" \
84
- -d '{"email":"salehyasmeen080@gmail.com","password":"123456789"}')
85
- echo "HTTP Status: $HTTP_CODE"
86
- cat login.json
87
- echo ""
88
-
89
- if [ "$HTTP_CODE" != "200" ]; then
90
- echo "Login failed with HTTP $HTTP_CODE"
91
- exit 1
92
- fi
93
-
94
- python3 - <<'PY'
95
- import json, sys
96
- try:
97
- data = json.load(open("login.json"))
98
- except json.JSONDecodeError as e:
99
- print("Invalid JSON response:", e)
100
- with open("login.json") as f:
101
- print("Raw response:", f.read())
102
- sys.exit(1)
103
-
104
- if not data.get("success"):
105
- print("Login failed:", json.dumps(data, indent=2))
106
- sys.exit(1)
107
-
108
- token = data.get("data", {}).get("token")
109
- if not token:
110
- print("No token in response:", json.dumps(data, indent=2))
111
- sys.exit(1)
112
-
113
- with open("token.txt", "w") as f:
114
- f.write(token)
115
- print("Login OK - token saved")
116
- PY
 
 
 
 
 
117
 
118
  - name: Test aggregated AI health via Laravel
119
  run: |
@@ -125,13 +127,13 @@ jobs:
125
  cat health.json
126
  echo ""
127
  python3 - <<'PY'
128
- import json, sys
129
- data = json.load(open("health.json"))
130
- if not data.get("success"):
131
- print("AI services health check failed:", json.dumps(data, indent=2))
132
- sys.exit(1)
133
- print("All AI services healthy via Laravel proxy")
134
- PY
135
 
136
  - name: Test ADMET prediction via Laravel proxy
137
  run: |
@@ -151,26 +153,26 @@ jobs:
151
  fi
152
 
153
  python3 - <<'PY'
154
- import json, sys
155
- try:
156
- data = json.load(open("admet.json"))
157
- except json.JSONDecodeError as e:
158
- print("Invalid JSON response:", e)
159
- with open("admet.json") as f:
160
- print("Raw response:", f.read())
161
- sys.exit(1)
162
-
163
- if not data.get("success"):
164
- print("ADMET prediction test failed:", json.dumps(data, indent=2))
165
- sys.exit(1)
166
-
167
- results = data.get("data", {}).get("results", [])
168
- if len(results) < 3:
169
- print(f"Expected at least 3 results, got {len(results)}")
170
- sys.exit(1)
171
-
172
- print(f"ADMET prediction OK - {len(results)} compounds processed")
173
- PY
174
 
175
  - name: Test Chemical RAG proxy via Laravel
176
  run: |
@@ -184,13 +186,13 @@ jobs:
184
  cat chemical.json
185
  echo ""
186
  python3 - <<'PY'
187
- import json, sys
188
- data = json.load(open("chemical.json"))
189
- if not data.get("success"):
190
- print("Chemical RAG proxy test failed:", json.dumps(data, indent=2))
191
- sys.exit(1)
192
- print("Chemical RAG proxy OK")
193
- PY
194
 
195
  - name: Test Drug Repurposing proxy via Laravel
196
  run: |
@@ -202,15 +204,16 @@ jobs:
202
  cat drug.json
203
  echo ""
204
  python3 - <<'PY'
205
- import json, sys
206
- data = json.load(open("drug.json"))
207
- if not data.get("success"):
208
- print("Drug Repurposing proxy test failed:", json.dumps(data, indent=2))
209
- sys.exit(1)
210
- print("Drug Repurposing proxy OK")
211
- PY
212
 
213
  chemical-search:
 
214
  runs-on: ubuntu-latest
215
  timeout-minutes: 15
216
 
@@ -218,34 +221,42 @@ jobs:
218
  - name: Checkout
219
  uses: actions/checkout@v4
220
 
221
- - name: Warm up ailixir-api Space
222
  run: |
223
- for i in $(seq 1 60); do
224
- if curl -sf https://Ailixir-AI-Team-ailixir-api.hf.space/ > /dev/null 2>&1; then
225
- echo "ailixir-api is up"
226
- sleep 5
227
- exit 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  fi
229
- echo "Waiting ($i/60)..."
230
- sleep 5
231
  done
232
  exit 1
233
 
234
- - name: Login and get Bearer token
235
- run: |
236
- HTTP_CODE=$(curl -s -o login.json -w "%{http_code}" -X POST https://Ailixir-AI-Team-ailixir-api.hf.space/api/user/login \
237
- -H "Content-Type: application/json" \
238
- -d '{"email":"salehyasmeen080@gmail.com","password":"123456789"}')
239
- if [ "$HTTP_CODE" != "200" ]; then exit 1; fi
240
- python3 - <<'PY'
241
- import json
242
- with open('login.json') as f: data = json.load(f)
243
- token = data.get('data', {}).get('token')
244
- if not token: exit(1)
245
- with open('token.txt','w') as f: f.write(token)
246
- print('Login OK')
247
- PY
248
-
249
  - name: Test retrieval-only chemical search
250
  run: |
251
  TOKEN=$(cat token.txt)
@@ -258,19 +269,19 @@ jobs:
258
  cat search.json
259
  echo ""
260
  python3 - <<'PY'
261
- import json, sys
262
- data = json.load(open("search.json"))
263
- if not data.get("success"):
264
- print("Chemical search (retrieval-only) failed:", json.dumps(data, indent=2))
265
- sys.exit(1)
266
- if not isinstance(data.get("compounds"), list):
267
- print("Missing 'compounds' array in response")
268
- sys.exit(1)
269
- if data.get("metadata", {}).get("source") != "retrieval":
270
- print("Expected source='retrieval', got:", data.get("metadata", {}).get("source"))
271
- sys.exit(1)
272
- print("Chemical search (retrieval-only) OK - found", len(data["compounds"]), "compounds")
273
- PY
274
 
275
  - name: Test full RAG chemical search
276
  run: |
@@ -284,25 +295,26 @@ jobs:
284
  cat rag.json
285
  echo ""
286
  python3 - <<'PY'
287
- import json, sys
288
- data = json.load(open("rag.json"))
289
- if not data.get("success"):
290
- print("Chemical search (full RAG) failed:", json.dumps(data, indent=2))
291
- sys.exit(1)
292
- if not isinstance(data.get("compounds"), list):
293
- print("Missing 'compounds' array in response")
294
- sys.exit(1)
295
- if data.get("metadata", {}).get("source") != "full_rag":
296
- print("Expected source='full_rag', got:", data.get("metadata", {}).get("source"))
297
- sys.exit(1)
298
- for compound in data["compounds"]:
299
- if not compound.get("explanation"):
300
- print("Missing explanation for compound:", compound.get("name"))
301
- sys.exit(1)
302
- print("Chemical search (full RAG) OK - found", len(data["compounds"]), "compounds with explanations")
303
- PY
304
 
305
  drug-repurposing-integration:
 
306
  runs-on: ubuntu-latest
307
  timeout-minutes: 30
308
 
@@ -310,34 +322,42 @@ jobs:
310
  - name: Checkout
311
  uses: actions/checkout@v4
312
 
313
- - name: Warm up ailixir-api Space
314
  run: |
315
- for i in $(seq 1 60); do
316
- if curl -sf https://Ailixir-AI-Team-ailixir-api.hf.space/ > /dev/null 2>&1; then
317
- echo "ailixir-api is up"
318
- sleep 5
319
- exit 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
320
  fi
321
- echo "Waiting ($i/60)..."
322
- sleep 5
323
  done
324
  exit 1
325
 
326
- - name: Login and get Bearer token
327
- run: |
328
- HTTP_CODE=$(curl -s -o login.json -w "%{http_code}" -X POST https://Ailixir-AI-Team-ailixir-api.hf.space/api/user/login \
329
- -H "Content-Type: application/json" \
330
- -d '{"email":"salehyasmeen080@gmail.com","password":"123456789"}')
331
- if [ "$HTTP_CODE" != "200" ]; then exit 1; fi
332
- python3 - <<'PY'
333
- import json
334
- with open('login.json') as f: data = json.load(f)
335
- token = data.get('data', {}).get('token')
336
- if not token: exit(1)
337
- with open('token.txt','w') as f: f.write(token)
338
- print('Login OK')
339
- PY
340
-
341
  - name: Test unauthenticated DR request is rejected
342
  run: |
343
  echo "POST /api/drug-repurposing/targets (no auth)"
@@ -349,11 +369,11 @@ jobs:
349
  exit 1
350
  fi
351
  python3 - <<'PY'
352
- import json
353
- with open('dr_unauth.json') as f: data = json.load(f)
354
- assert not data.get('success', True), 'Expected success=false'
355
- print('Unauthenticated DR request correctly rejected')
356
- PY
357
 
358
  - name: Test DR target lookup requires disease_name
359
  run: |
@@ -367,7 +387,7 @@ jobs:
367
  echo "Expected 422, got $HTTP_CODE"
368
  exit 1
369
  fi
370
- echo "Missing disease_name correctly rejected"
371
 
372
  - name: Test DR target lookup via Laravel proxy
373
  run: |
@@ -387,40 +407,41 @@ jobs:
387
  fi
388
 
389
  python3 - <<'PY'
390
- import json, sys
391
- data = json.load(open("dr_targets.json"))
392
- if not data.get("success"):
393
- print("DR target lookup failed:", json.dumps(data, indent=2))
394
- sys.exit(1)
395
- job_id = data.get("data", {}).get("job_id")
396
- status = data.get("data", {}).get("status")
397
- print(f"DR target lookup OK - job_id={job_id}, status={status}")
398
-
399
- # Poll for completion
400
- import time, urllib.request
401
- base = "https://Ailixir-AI-Team-ailixir-api.hf.space/api/drug-repurposing/targets"
402
- with open("token.txt") as f: token = f.read().strip()
403
- for i in range(30):
404
- req = urllib.request.Request(f"{base}/{job_id}")
405
- req.add_header("Authorization", f"Bearer {token}")
406
- resp = urllib.request.urlopen(req)
407
- status_data = json.loads(resp.read())
408
- s = status_data.get("data", {}).get("status")
409
- if s == "completed":
410
- output = status_data.get("data", {}).get("output", {})
411
- assert len(output.get("targets", [])) > 0, "No targets found"
412
- print(f"DR targets completed - {len(output['targets'])} targets found")
413
- sys.exit(0)
414
- elif s == "failed":
415
- print("DR target lookup failed:", json.dumps(status_data, indent=2))
416
- sys.exit(1)
417
- print(f" Polling... attempt {i+1}/30, status={s}")
418
- time.sleep(5)
419
- print("DR target lookup did not complete in time")
420
- sys.exit(1)
421
- PY
422
 
423
  docking-integration:
 
424
  runs-on: ubuntu-latest
425
  timeout-minutes: 15
426
 
@@ -428,34 +449,42 @@ jobs:
428
  - name: Checkout
429
  uses: actions/checkout@v4
430
 
431
- - name: Warm up ailixir-api Space
432
  run: |
433
- for i in $(seq 1 60); do
434
- if curl -sf https://Ailixir-AI-Team-ailixir-api.hf.space/ > /dev/null 2>&1; then
435
- echo "ailixir-api is up"
436
- sleep 5
437
- exit 0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
438
  fi
439
- echo "Waiting ($i/60)..."
440
- sleep 5
441
  done
442
  exit 1
443
 
444
- - name: Login and get Bearer token
445
- run: |
446
- HTTP_CODE=$(curl -s -o login.json -w "%{http_code}" -X POST https://Ailixir-AI-Team-ailixir-api.hf.space/api/user/login \
447
- -H "Content-Type: application/json" \
448
- -d '{"email":"salehyasmeen080@gmail.com","password":"123456789"}')
449
- if [ "$HTTP_CODE" != "200" ]; then exit 1; fi
450
- python3 - <<'PY'
451
- import json
452
- with open('login.json') as f: data = json.load(f)
453
- token = data.get('data', {}).get('token')
454
- if not token: exit(1)
455
- with open('token.txt','w') as f: f.write(token)
456
- print('Login OK')
457
- PY
458
-
459
  - name: Test docking submit
460
  run: |
461
  TOKEN=$(cat token.txt)
@@ -483,10 +512,10 @@ jobs:
483
  fi
484
 
485
  python3 - <<'PY'
486
- import json, sys
487
- data = json.load(open("docking.json"))
488
- if not data.get("success"):
489
- print("Docking submit failed:", json.dumps(data, indent=2))
490
- sys.exit(1)
491
- print("Docking submit OK - job created")
492
- PY
 
12
  cancel-in-progress: true
13
 
14
  jobs:
15
+ warmup-spaces:
16
  runs-on: ubuntu-latest
17
+ timeout-minutes: 15
 
18
  steps:
 
 
 
19
  - name: Warm up ailixir-api Space
20
  run: |
21
  echo "Waiting for ailixir-api HF Space..."
22
  for i in $(seq 1 60); do
23
+ if curl -sf https://Ailixir-AI-Team-ailixir-api.hf.space/health > /dev/null 2>&1; then
24
+ echo "✓ ailixir-api is up"
25
+ break
 
26
  fi
27
  echo "Attempt $i/60..."
28
  sleep 5
29
  done
 
30
 
31
  - name: Warm up ailixir-drug-repurposing Space
32
  run: |
33
  echo "Waiting for ailixir-drug-repurposing HF Space..."
34
  for i in $(seq 1 60); do
35
  if curl -sf https://RottenShadow-ailixir-drug-repurposing.hf.space/health > /dev/null 2>&1; then
36
+ echo "✓ ailixir-drug-repurposing is up"
37
+ break
 
38
  fi
39
  echo "Attempt $i/60..."
40
  sleep 5
41
  done
 
42
 
43
  - name: Warm up ailixir-admet Space
44
  run: |
45
  echo "Waiting for ailixir-admet HF Space..."
46
  for i in $(seq 1 60); do
47
  if curl -sf https://shdwRow-ailixir-admet.hf.space/health > /dev/null 2>&1; then
48
+ echo "✓ ailixir-admet is up"
49
+ break
 
50
  fi
51
  echo "Attempt $i/60..."
52
  sleep 5
53
  done
 
54
 
55
  - name: Warm up ailixir-chemical-rag Space
56
  run: |
57
  echo "Waiting for ailixir-chemical-rag HF Space..."
58
  for i in $(seq 1 60); do
59
  if curl -sf https://RottenShadow-ailixir-chemical-rag.hf.space/health > /dev/null 2>&1; then
60
+ echo "✓ ailixir-chemical-rag is up"
61
+ break
 
62
  fi
63
  echo "Attempt $i/60..."
64
  sleep 5
65
  done
66
+
67
+ core-ai-proxy:
68
+ needs: warmup-spaces
69
+ runs-on: ubuntu-latest
70
+ timeout-minutes: 30
71
+
72
+ steps:
73
+ - name: Checkout
74
+ uses: actions/checkout@v4
75
 
76
  - name: Login and get Bearer token
77
  run: |
78
  echo "POST /api/user/login"
79
+ for attempt in {1..3}; do
80
+ HTTP_CODE=$(curl -s -o login.json -w "%{http_code}" -X POST https://Ailixir-AI-Team-ailixir-api.hf.space/api/user/login \
81
+ -H "Content-Type: application/json" \
82
+ -d '{"email":"salehyasmeen080@gmail.com","password":"123456789"}')
83
+ echo "HTTP Status: $HTTP_CODE (attempt $attempt/3)"
84
+
85
+ if [ "$HTTP_CODE" = "200" ]; then
86
+ python3 - <<'PY'
87
+ import json, sys
88
+ try:
89
+ data = json.load(open("login.json"))
90
+ except json.JSONDecodeError as e:
91
+ print("Invalid JSON response:", e)
92
+ with open("login.json") as f:
93
+ print("Raw response:", f.read())
94
+ sys.exit(1)
95
+
96
+ if not data.get("success"):
97
+ print("Login failed:", json.dumps(data, indent=2))
98
+ sys.exit(1)
99
+
100
+ token = data.get("data", {}).get("token")
101
+ if not token:
102
+ print("No token in response:", json.dumps(data, indent=2))
103
+ sys.exit(1)
104
+
105
+ with open("token.txt", "w") as f:
106
+ f.write(token)
107
+ print("✓ Login OK - token saved")
108
+ PY
109
+ if [ $? -eq 0 ]; then exit 0; fi
110
+ fi
111
+
112
+ if [ $attempt -lt 3 ]; then
113
+ echo "Login attempt $attempt failed, retrying in 10s..."
114
+ sleep 10
115
+ fi
116
+ done
117
+ echo "Login failed after 3 attempts"
118
+ exit 1
119
 
120
  - name: Test aggregated AI health via Laravel
121
  run: |
 
127
  cat health.json
128
  echo ""
129
  python3 - <<'PY'
130
+ import json, sys
131
+ data = json.load(open("health.json"))
132
+ if not data.get("success"):
133
+ print("AI services health check failed:", json.dumps(data, indent=2))
134
+ sys.exit(1)
135
+ print("✓ All AI services healthy via Laravel proxy")
136
+ PY
137
 
138
  - name: Test ADMET prediction via Laravel proxy
139
  run: |
 
153
  fi
154
 
155
  python3 - <<'PY'
156
+ import json, sys
157
+ try:
158
+ data = json.load(open("admet.json"))
159
+ except json.JSONDecodeError as e:
160
+ print("Invalid JSON response:", e)
161
+ with open("admet.json") as f:
162
+ print("Raw response:", f.read())
163
+ sys.exit(1)
164
+
165
+ if not data.get("success"):
166
+ print("ADMET prediction test failed:", json.dumps(data, indent=2))
167
+ sys.exit(1)
168
+
169
+ results = data.get("data", {}).get("results", [])
170
+ if len(results) < 3:
171
+ print(f"Expected at least 3 results, got {len(results)}")
172
+ sys.exit(1)
173
+
174
+ print(f"✓ ADMET prediction OK - {len(results)} compounds processed")
175
+ PY
176
 
177
  - name: Test Chemical RAG proxy via Laravel
178
  run: |
 
186
  cat chemical.json
187
  echo ""
188
  python3 - <<'PY'
189
+ import json, sys
190
+ data = json.load(open("chemical.json"))
191
+ if not data.get("success"):
192
+ print("Chemical RAG proxy test failed:", json.dumps(data, indent=2))
193
+ sys.exit(1)
194
+ print("✓ Chemical RAG proxy OK")
195
+ PY
196
 
197
  - name: Test Drug Repurposing proxy via Laravel
198
  run: |
 
204
  cat drug.json
205
  echo ""
206
  python3 - <<'PY'
207
+ import json, sys
208
+ data = json.load(open("drug.json"))
209
+ if not data.get("success"):
210
+ print("Drug Repurposing proxy test failed:", json.dumps(data, indent=2))
211
+ sys.exit(1)
212
+ print("✓ Drug Repurposing proxy OK")
213
+ PY
214
 
215
  chemical-search:
216
+ needs: warmup-spaces
217
  runs-on: ubuntu-latest
218
  timeout-minutes: 15
219
 
 
221
  - name: Checkout
222
  uses: actions/checkout@v4
223
 
224
+ - name: Login and get Bearer token
225
  run: |
226
+ for attempt in {1..3}; do
227
+ HTTP_CODE=$(curl -s -o login.json -w "%{http_code}" -X POST https://Ailixir-AI-Team-ailixir-api.hf.space/api/user/login \
228
+ -H "Content-Type: application/json" \
229
+ -d '{"email":"salehyasmeen080@gmail.com","password":"123456789"}')
230
+ if [ "$HTTP_CODE" = "200" ]; then
231
+ python3 - <<'PY'
232
+ import json, sys
233
+ try:
234
+ data = json.load(open("login.json"))
235
+ except json.JSONDecodeError as e:
236
+ print("Invalid JSON response:", e)
237
+ with open("login.json") as f:
238
+ print("Raw response:", f.read())
239
+ sys.exit(1)
240
+
241
+ if not data.get("success"):
242
+ print("Login failed:", json.dumps(data, indent=2))
243
+ sys.exit(1)
244
+
245
+ token = data.get("data", {}).get("token")
246
+ if not token:
247
+ print("No token in response:", json.dumps(data, indent=2))
248
+ sys.exit(1)
249
+
250
+ with open("token.txt", "w") as f:
251
+ f.write(token)
252
+ print("✓ Login OK - token saved")
253
+ PY
254
+ if [ $? -eq 0 ]; then exit 0; fi
255
  fi
256
+ [ $attempt -lt 3 ] && sleep 10
 
257
  done
258
  exit 1
259
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  - name: Test retrieval-only chemical search
261
  run: |
262
  TOKEN=$(cat token.txt)
 
269
  cat search.json
270
  echo ""
271
  python3 - <<'PY'
272
+ import json, sys
273
+ data = json.load(open("search.json"))
274
+ if not data.get("success"):
275
+ print("Chemical search (retrieval-only) failed:", json.dumps(data, indent=2))
276
+ sys.exit(1)
277
+ if not isinstance(data.get("compounds"), list):
278
+ print("Missing 'compounds' array in response")
279
+ sys.exit(1)
280
+ if data.get("metadata", {}).get("source") != "retrieval":
281
+ print("Expected source='retrieval', got:", data.get("metadata", {}).get("source"))
282
+ sys.exit(1)
283
+ print("✓ Chemical search (retrieval-only) OK - found", len(data["compounds"]), "compounds")
284
+ PY
285
 
286
  - name: Test full RAG chemical search
287
  run: |
 
295
  cat rag.json
296
  echo ""
297
  python3 - <<'PY'
298
+ import json, sys
299
+ data = json.load(open("rag.json"))
300
+ if not data.get("success"):
301
+ print("Chemical search (full RAG) failed:", json.dumps(data, indent=2))
302
+ sys.exit(1)
303
+ if not isinstance(data.get("compounds"), list):
304
+ print("Missing 'compounds' array in response")
305
+ sys.exit(1)
306
+ if data.get("metadata", {}).get("source") != "full_rag":
307
+ print("Expected source='full_rag', got:", data.get("metadata", {}).get("source"))
308
+ sys.exit(1)
309
+ for compound in data["compounds"]:
310
+ if not compound.get("explanation"):
311
+ print("Missing explanation for compound:", compound.get("name"))
312
+ sys.exit(1)
313
+ print("✓ Chemical search (full RAG) OK - found", len(data["compounds"]), "compounds with explanations")
314
+ PY
315
 
316
  drug-repurposing-integration:
317
+ needs: warmup-spaces
318
  runs-on: ubuntu-latest
319
  timeout-minutes: 30
320
 
 
322
  - name: Checkout
323
  uses: actions/checkout@v4
324
 
325
+ - name: Login and get Bearer token
326
  run: |
327
+ for attempt in {1..3}; do
328
+ HTTP_CODE=$(curl -s -o login.json -w "%{http_code}" -X POST https://Ailixir-AI-Team-ailixir-api.hf.space/api/user/login \
329
+ -H "Content-Type: application/json" \
330
+ -d '{"email":"salehyasmeen080@gmail.com","password":"123456789"}')
331
+ if [ "$HTTP_CODE" = "200" ]; then
332
+ python3 - <<'PY'
333
+ import json, sys
334
+ try:
335
+ data = json.load(open("login.json"))
336
+ except json.JSONDecodeError as e:
337
+ print("Invalid JSON response:", e)
338
+ with open("login.json") as f:
339
+ print("Raw response:", f.read())
340
+ sys.exit(1)
341
+
342
+ if not data.get("success"):
343
+ print("Login failed:", json.dumps(data, indent=2))
344
+ sys.exit(1)
345
+
346
+ token = data.get("data", {}).get("token")
347
+ if not token:
348
+ print("No token in response:", json.dumps(data, indent=2))
349
+ sys.exit(1)
350
+
351
+ with open("token.txt", "w") as f:
352
+ f.write(token)
353
+ print("✓ Login OK - token saved")
354
+ PY
355
+ if [ $? -eq 0 ]; then exit 0; fi
356
  fi
357
+ [ $attempt -lt 3 ] && sleep 10
 
358
  done
359
  exit 1
360
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
  - name: Test unauthenticated DR request is rejected
362
  run: |
363
  echo "POST /api/drug-repurposing/targets (no auth)"
 
369
  exit 1
370
  fi
371
  python3 - <<'PY'
372
+ import json
373
+ with open('dr_unauth.json') as f: data = json.load(f)
374
+ assert not data.get('success', True), 'Expected success=false'
375
+ print('✓ Unauthenticated DR request correctly rejected')
376
+ PY
377
 
378
  - name: Test DR target lookup requires disease_name
379
  run: |
 
387
  echo "Expected 422, got $HTTP_CODE"
388
  exit 1
389
  fi
390
+ echo "✓ Missing disease_name correctly rejected"
391
 
392
  - name: Test DR target lookup via Laravel proxy
393
  run: |
 
407
  fi
408
 
409
  python3 - <<'PY'
410
+ import json, sys
411
+ data = json.load(open("dr_targets.json"))
412
+ if not data.get("success"):
413
+ print("DR target lookup failed:", json.dumps(data, indent=2))
414
+ sys.exit(1)
415
+ job_id = data.get("data", {}).get("job_id")
416
+ status = data.get("data", {}).get("status")
417
+ print(f"✓ DR target lookup OK - job_id={job_id}, status={status}")
418
+
419
+ # Poll for completion
420
+ import time, urllib.request
421
+ base = "https://Ailixir-AI-Team-ailixir-api.hf.space/api/drug-repurposing/targets"
422
+ with open("token.txt") as f: token = f.read().strip()
423
+ for i in range(30):
424
+ req = urllib.request.Request(f"{base}/{job_id}")
425
+ req.add_header("Authorization", f"Bearer {token}")
426
+ resp = urllib.request.urlopen(req)
427
+ status_data = json.loads(resp.read())
428
+ s = status_data.get("data", {}).get("status")
429
+ if s == "completed":
430
+ output = status_data.get("data", {}).get("output", {})
431
+ assert len(output.get("targets", [])) > 0, "No targets found"
432
+ print(f"✓ DR targets completed - {len(output['targets'])} targets found")
433
+ sys.exit(0)
434
+ elif s == "failed":
435
+ print("DR target lookup failed:", json.dumps(status_data, indent=2))
436
+ sys.exit(1)
437
+ print(f" Polling... attempt {i+1}/30, status={s}")
438
+ time.sleep(5)
439
+ print("DR target lookup did not complete in time")
440
+ sys.exit(1)
441
+ PY
442
 
443
  docking-integration:
444
+ needs: warmup-spaces
445
  runs-on: ubuntu-latest
446
  timeout-minutes: 15
447
 
 
449
  - name: Checkout
450
  uses: actions/checkout@v4
451
 
452
+ - name: Login and get Bearer token
453
  run: |
454
+ for attempt in {1..3}; do
455
+ HTTP_CODE=$(curl -s -o login.json -w "%{http_code}" -X POST https://Ailixir-AI-Team-ailixir-api.hf.space/api/user/login \
456
+ -H "Content-Type: application/json" \
457
+ -d '{"email":"salehyasmeen080@gmail.com","password":"123456789"}')
458
+ if [ "$HTTP_CODE" = "200" ]; then
459
+ python3 - <<'PY'
460
+ import json, sys
461
+ try:
462
+ data = json.load(open("login.json"))
463
+ except json.JSONDecodeError as e:
464
+ print("Invalid JSON response:", e)
465
+ with open("login.json") as f:
466
+ print("Raw response:", f.read())
467
+ sys.exit(1)
468
+
469
+ if not data.get("success"):
470
+ print("Login failed:", json.dumps(data, indent=2))
471
+ sys.exit(1)
472
+
473
+ token = data.get("data", {}).get("token")
474
+ if not token:
475
+ print("No token in response:", json.dumps(data, indent=2))
476
+ sys.exit(1)
477
+
478
+ with open("token.txt", "w") as f:
479
+ f.write(token)
480
+ print("✓ Login OK - token saved")
481
+ PY
482
+ if [ $? -eq 0 ]; then exit 0; fi
483
  fi
484
+ [ $attempt -lt 3 ] && sleep 10
 
485
  done
486
  exit 1
487
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
488
  - name: Test docking submit
489
  run: |
490
  TOKEN=$(cat token.txt)
 
512
  fi
513
 
514
  python3 - <<'PY'
515
+ import json, sys
516
+ data = json.load(open("docking.json"))
517
+ if not data.get("success"):
518
+ print("Docking submit failed:", json.dumps(data, indent=2))
519
+ sys.exit(1)
520
+ print("✓ Docking submit OK - job created")
521
+ PY