39354-vm/docs/flatlogic-cicd-backend.md
2026-03-28 04:47:13 +00:00

185 lines
5.4 KiB
Markdown

# Flatlogic CI/CD + External DB + Ingestion API
هذا الإعداد يجعل المشروع يعمل بهذه الصورة:
- **GitHub** هو مصدر الحقيقة للكود.
- **Bolt / Replit** يدفعان التعديلات إلى نفس المستودع أو يرسلان `repository_dispatch`.
- **GitHub Actions** تبني المشروع وتتحقق منه ثم تنشره إلى VM الخاص بـ Flatlogic.
- **Flatlogic / API Server** يدير بيانات المنتجات القادمة من أدوات السحب وويبهوكات شي إن.
- **Supabase / PostgreSQL** هو مخزن البيانات الخارجي للمنتجات والفئات وسجل أحداث التكامل.
## ما تمت إضافته
- `.github/workflows/ci.yml`
- Typecheck + Build لكل Push / Pull Request.
- `.github/workflows/deploy-flatlogic.yml`
- ينشر تلقائيًا إلى VM عند التحديث على `main` أو `master`.
- يدعم `repository_dispatch` لأنواع:
- `bolt_sync`
- `replit_sync`
- `flatlogic_deploy`
- `scripts/flatlogic-deploy.sh`
- يسحب آخر نسخة من GitHub.
- يثبت الحزم.
- يشغل `typecheck` و `build`.
- يطبق schema قاعدة البيانات عبر Drizzle.
- يعيد تشغيل `extra-store` و `flatlogic-api` عبر PM2.
- `.env.example`
- كل متغيرات البيئة المطلوبة للـ DB والـ API والأمان.
- API endpoints جديدة داخل `artifacts/api-server`.
## الأسرار المطلوبة في GitHub Actions
أضف هذه القيم في **GitHub → Settings → Secrets and variables → Actions**:
### أسرار النشر إلى Flatlogic VM
- `FLATLOGIC_HOST`
- `FLATLOGIC_USER`
- `FLATLOGIC_SSH_KEY`
- `FLATLOGIC_PROJECT_DIR`
- `FLATLOGIC_DEPLOY_BRANCH` (اختياري)
### أسرار الـ backend
- `DATABASE_URL`
- `DB_SSL` = `require`
- `DB_POOL_MAX` = `20`
- `DB_QUERY_TIMEOUT_MS` = `15000`
- `DB_STATEMENT_TIMEOUT_MS` = `15000`
- `ADMIN_TOKEN`
- `API_INGEST_KEY`
- `WEBHOOK_SECRET`
- `SHEIN_WEBHOOK_SECRET`
- `API_PORT` = `8080`
- `STORE_PORT` = `3001`
## إعداد قاعدة البيانات الخارجية (Supabase / PostgreSQL)
الحد الأدنى المقترح لاستيعاب 2000 منتج من Extra + Shein:
- استخدم **Postgres خارجي** أو **Supabase**.
- يفضل في Supabase استخدام **transaction pooler** داخل `DATABASE_URL`.
- الإعدادات الافتراضية المضافة في الكود:
- `DB_POOL_MAX=20`
- `DB_QUERY_TIMEOUT_MS=15000`
- `DB_STATEMENT_TIMEOUT_MS=15000`
- `keepAlive=true`
- أضف الـ schema بالأمر:
```bash
pnpm --filter @workspace/db run push
```
> ملاحظة: الجدول `products` صار يدعم الآن `source`, `external_id`, `source_url`, `currency`, `availability`, `metadata`, `last_synced_at` مع فهارس مخصصة للبحث والتزامن.
## API Endpoints الجديدة
### 1) Bulk ingestion للمنتجات
`POST /api/ingest/products/bulk`
Headers:
```text
x-api-key: <API_INGEST_KEY>
content-type: application/json
```
Body مثال:
```json
{
"source": "shein",
"webhook_id": "apify-run-123",
"products": [
{
"external_id": "shein-10001",
"sku": "SKU-10001",
"name": "فستان صيفي",
"brand": "SHEIN",
"price": 149,
"original_price": 199,
"stock": 25,
"availability": "in_stock",
"sizes": ["S", "M", "L"],
"colors": ["Black", "Pink"],
"images": ["https://example.com/1.jpg"],
"category": {
"slug": "dresses",
"name": "فساتين"
},
"source_url": "https://example.com/product/10001"
}
]
}
```
### 2) Upsert منتج مفرد
`POST /api/ingest/products/upsert`
نفس الحماية عبر `x-api-key`.
### 3) Webhook تحديثات شي إن
`POST /api/webhooks/shein/products`
Headers:
```text
x-api-key: <API_INGEST_KEY>
x-webhook-signature: sha256=<hmac_sha256_of_raw_body>
content-type: application/json
```
Body مثال:
```json
{
"webhook_id": "shein-webhook-987",
"event": "price.updated",
"products": [
{
"external_id": "shein-10001",
"price": 139,
"stock": 12,
"availability": "low_stock",
"sizes": ["S", "M"]
}
]
}
```
### 4) Pipeline status
`GET /api/integrations/pipeline/status`
- محمي بـ `Authorization: Bearer <ADMIN_TOKEN>`
- يعرض:
- حالة إعداد الأمان
- حالة الـ DB
- عدد المنتجات حسب المصدر
- آخر أحداث التكامل
## ربط Bolt / Replit مع GitHub
أفضل سيناريو:
1. اجعل **Bolt** أو **Replit** يدفعان إلى نفس مستودع GitHub.
2. كل Push إلى `main` يشغل:
- `ci.yml`
- ثم `deploy-flatlogic.yml`
3. النتيجة: يتم تحديث الموقع والـ backend تلقائيًا.
إذا كانت الأداة لا تدفع مباشرة إلى GitHub، استخدم `repository_dispatch` من GitHub API بنوع:
- `bolt_sync`
- `replit_sync`
## ملاحظات تشغيلية
- الواجهة الأمامية الآن تدعم `VITE_API_BASE_URL` إذا أردت backend مختلفًا عن نفس الدومين.
- في وضع التطوير، Vite يمرر `/api` إلى `http://127.0.0.1:8080` عبر proxy.
- إذا لم تكن أسرار الـ backend موجودة، فسيستمر المتجر الأمامي بالعمل، لكن تشغيل خدمة الـ API سيتم تخطيه أثناء النشر.