# Ghyma CI/CD Demo 
رابط المشروع : https://mywebapp-prod-13c5436cf063.hosted.ghaymah.systems/

> ⚠️ تحديث مهم: النسخة دي معدّلة بناءً على توثيق رسمي حقيقي من Ghaymah. المنصة **لسه معندهاش CLI** ("coming soon, inshallah") **ولا auto-trigger** عند push. النشر الفعلي **يدوي بالكامل** من لوحة التحكم.

---

## إيه اللي الـ pipeline بيعمله فعليًا (وإيه اللي لسه يدوي)

| المرحلة | مؤتمتة؟ |
|---|---|
| بناء صورة Docker | ✅ أوتوماتيك (GitHub Actions) |
| فحص سريع (smoke test) على `/health` | ✅ أوتوماتيك |
| موافقة يدوية قبل production | ✅ أوتوماتيك (عن طريق GitHub Environments) |
| **النشر الفعلي على Ghaymah** | ❌ **يدوي** — تدخل لوحة التحكم وتحط Commit SHA بنفسك |

يعني الـ workflow مش هينشر لوحده — هو هيبني الصورة، يتأكد إنها شغالة، ويطبعلك بالظبط "انسخ الـ SHA ده وحطه في تطبيق كذا". لما Ghaymah تطلق الـ CLI بتاعها، هنضيف خطوة أخيرة تلقائية بدل النسخ اليدوي.

---

## الخطوة 0: المتطلبات
- Docker Desktop
- حساب GitHub
- حساب Docker Hub
- حساب على Ghaymah Cloud

---

## الخطوة 1: التجربة المحلية
```
npm install
npm start
```
افتح `http://localhost:3000/` و `/health` و `/version`.

## الخطوة 2: التجربة بالـ Docker
```
docker build -t ghyma-cicd-demo:local .
docker run -d -p 3000:3000 --name ghyma-demo ghyma-cicd-demo:local
curl http://localhost:3000/health
docker stop ghyma-demo && docker rm ghyma-demo
```

## الخطوة 3: رفع المشروع على GitHub
```
git init
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin https://github.com/Moetaz-Alfy/ghyma-cicd-demo.git
git push -u origin main
git checkout -b develop
git push -u origin develop
```

## الخطوة 4: أضف Secrets للـ Registry في GitHub

> هذه الخطوة تحقق شرط "الرفع لـ Registry" في متطلبات المهمة حرفيًا. Docker Hub هنا بيشتغل كبديل مؤقت لحد ما Ghaymah تطلق Container Registry خاص بيها — التفاصيل في قسم "ملاحظة عن خطوة الـ Registry" آخر الملف.

```
Settings → Secrets and variables → Actions → New repository secret
```
| الاسم | القيمة |
|---|---|
| `DOCKERHUB_USERNAME` | اسم مستخدمك على Docker Hub |
| `DOCKERHUB_TOKEN` | Access Token من Docker Hub (Account Settings → Security → New Access Token) |

## الخطوة 5: فعّل بيئة production بموافقة يدوية
```
Settings → Environments → New environment → production
```
فعّل **Required reviewers** واختار نفسك.

### شرح آلية عمل الموافقة اليدوية بالتفصيل

الـ job اسمه `notify-production` في `ci-cd.yml` مربوط بالسطر ده:
```yaml
environment:
  name: production
```
لما GitHub تلاقي job مربوط بـ Environment اسمه `production` وعليه Required reviewers مفعّلة، بيحصل الآتي تلقائيًا:

1. الـ job **بيوصل لكل الخطوات اللي قبله عادي** (بناء الصورة، الـ smoke test، الرفع للـ Registry) — دي مش متأثرة بالموافقة خالص
2. لما الدور يجي على `notify-production` نفسه، GitHub **بيوقفه فورًا** قبل أول خطوة جواه، وبيحطه في حالة **"Waiting"**
3. المراجع (Reviewer) المحدد بياخد إشعار على GitHub (وبالإيميل لو مفعّل)، ويشوف في تاب Actions زرار **"Review deployments"**
4. المراجع بيقدر يشوف تفاصيل الـ commit والـ diff قبل ما يوافق
5. لو ضغط **Approve and deploy** → الخطوات جوه الـ job تشتغل فعليًا
6. لو ضغط **Reject** → الـ job بيتوقف نهائيًا وميطبعش أي تعليمات نشر

**ليه الميزة دي مهمة تحديدًا هنا؟** لأن Ghaymah نفسها معندهاش نظام موافقات داخلي (النشر عندها مجرد حقل تكتب فيه SHA وتضغط Save، من غير أي حماية). فالموافقة اليدوية دي بتتم بالكامل على مستوى GitHub **قبل** ما تصل أصلاً لمرحلة "انسخ الـ SHA والصقه في Ghaymah" — يعني حتى لو حد عنده وصول للوحة تحكم Ghaymah، هو مش هياخد SHA صحيح للنشر إلا بعد ما تتم الموافقة على GitHub الأول.

**فرق مهم عن staging:** لاحظ إن job الـ `notify-staging` **مالهوش** سطر `environment: name`، فهو بيشتغل فورًا من غير أي وقفة — ده الفرق الجوهري بين البيئتين في نظام الأتمتة نفسه.

## الخطوة 6: أنشئ المشروع والتطبيقين على Ghaymah (مرة واحدة فقط)

1. سجّل دخول على لوحة تحكم Ghaymah
2. أنشئ **Project** جديد (مثلاً `ghyma-cicd-demo`)
3. جوه المشروع، اعمل **Deploy Application** الأول:
   - Deployment method: **Git-Based Deployment → Deploying from Public GitHub**
   - Application Name: `ghyma-demo-prod`
   - Repository URL: رابط الريبو بتاعك
   - Branch/Commit SHA: أول commit على `main`
   - Port: `3000`
   - Environment Variables: `APP_ENV=production`
4. اعمل **Deploy Application** ثاني بنفس الريبو:
   - Application Name: `ghyma-demo-staging`
   - Repository URL: نفس الريبو
   - Branch/Commit SHA: أول commit على `develop`
   - Port: `3000`
   - Environment Variables: `APP_ENV=staging`

الآن عندك تطبيقين منفصلين تمامًا (نفس الكود، بيانات وبيئة مختلفة).

## الخطوة 7: التجربة الكاملة للـ pipeline
```
git checkout develop
git commit --allow-empty -m "test staging pipeline"
git push
```
روح لتاب **Actions** → هتلاقي `build-and-push` ثم `notify-staging` بيطبع الـ commit SHA.

انسخ الـ SHA ده، روح للوحة تحكم Ghaymah → طبّق التطبيق `ghyma-demo-staging` → الصق الـ SHA في حقل Branch/Commit → Save.

## الخطوة 8: نشر production (بالموافقة)
```
git checkout main
git merge develop
git push
```
في تاب Actions، `notify-production` هيقف وينتظر موافقتك (**Review deployments → Approve and deploy**). بعد الموافقة، هيطبعلك الـ SHA.

انسخه، وحطه في تطبيق `ghyma-demo-prod` على لوحة تحكم Ghaymah → Save.

---

## الفرق بين staging و production على Ghaymah تحديدًا

| المحور | Staging | Production |
|---|---|---|
| اسم التطبيق في Ghaymah | `ghyma-demo-staging` | `ghyma-demo-prod` |
| الفرع المتابَع | `develop` | `main` |
| موافقة قبل تحديث الـ SHA | لا (الأمر يطبع فورًا) | نعم (GitHub Environment) |
| متغير `APP_ENV` | `staging` | `production` |
| من يحدّث SHA فعليًا | إنت، يدويًا، بعد كل push على develop | إنت، يدويًا، بعد الموافقة فقط |

### ليه فصلناهم كتطبيقين منفصلين تمامًا بدل بيئة واحدة بمتغيرات مختلفة؟

في منصات تانية (زي Heroku أو AWS) ممكن "البيئة" تكون مجرد إعداد داخل نفس التطبيق. لكن بما إن Ghaymah بتنشر مباشرة من الكود في GitHub (Git-Based Deployment)، كل "Application" في لوحة تحكمها هي فعليًا:
- نسخة مبنية بشكل مستقل من commit معين
- عندها رابط عام خاص بيها (Public URL) منفصل تمامًا
- عندها Environment Variables خاصة بيها
- بتنشر وتنطفي بشكل مستقل عن أي تطبيق تاني

فبالتالي أنسب طريقة لعمل "بيئتين" على Ghaymah هي إنشاء **تطبيقين منفصلين فعليًا**، مش تطبيق واحد بيتغيّر سلوكه — وده اللي بيضمن إن أي تجربة أو فشل في staging **مستحيل** يأثر على production، لأنهم فعليًا حاويتين مختلفتين تمامًا وليهم رابط مختلف.

### الفرق العملي وقت الاستخدام اليومي
- **تعمل تعديل وعايز تجربه بسرعة؟** ادفع على `develop` → SHA بيتطبع فورًا → تحطه في `ghyma-demo-staging` → تجربه على رابط staging المنفصل من غير أي انتظار
- **متأكد إن التعديل شغال ومستعد ينزل للمستخدمين؟** ادمج (merge) `develop` في `main` → لازم موافقة يدوية قبل ما تاخد الـ SHA أصلاً → تحطه في `ghyma-demo-prod`

القاعدة العامة: **أي كود بيوصل لـ production لازم يكون مر فعليًا من staging الأول بنفس الآلية بالظبط** — نفس الـ Dockerfile، نفس خطوات الـ CI، الفرق الوحيد هو أي بيئة بتستقبل الكود ومين بيوافق قبلها.

---

## الربط مع Ghaymah CLI — الوضع الحقيقي

Ghaymah **لا توفر CLI في الوقت الحالي**. النص الرسمي:

> "Ghaymah Cloud currently does not have automatic build triggers based on Git commits. Deployments must be manually triggered, or integrated with a CI/CD platform using our CLI (coming soon, inshallah)."

يعني:
- مفيش أوامر `ghaymah login` أو `ghaymah deploy` تقدر تستخدمها دلوقتي
- الطريقة الوحيدة المتاحة حاليًا هي **Git-Based Deployment** من لوحة التحكم مباشرة، مع تحديث يدوي لحقل الـ Commit SHA/Tag لكل تطبيق
- لما الـ CLI يتطلق، هيبقى ممكن نستبدل خطوة `notify-staging`/`notify-production` (اللي بتطبع تعليمات بس) بخطوة فعلية زي `ghaymah deploy --app ghyma-demo-prod --sha <SHA>` تلقائيًا

### إزاي الـ workflow اتصمم عشان "يربط" مع Ghaymah رغم غياب الـ CLI؟

بما إن مفيش API أو CLI نقدر نناديه، الـ workflow بيعمل أقصى حاجة ممكنة أوتوماتيكيًا وبيسيب الجزء المستحيل أتمتته (تحديث حقل الـ SHA في واجهة Ghaymah نفسها) كخطوة يدوية واحدة بس، موثقة بدقة:

```yaml
- name: Print deployment instructions
  run: |
    echo "Ghaymah dashboard -> Application: mywebapp-prod"
    echo "Set Branch/Commit SHA field to: ${{ needs.build-and-push.outputs.commit_sha }}"
```
الخطوة دي مش مجرد رسالة عشوائية — هي **بديل مؤقت** لأمر CLI مستقبلي. لاحظ إن اسم التطبيق والـ SHA بييجوا من متغيرات ديناميكية (`needs.build-and-push.outputs.commit_sha`)، يعني لو غيرت اسم التطبيق أو استخدمت فروع تانية، الرسالة بتتحدث تلقائيًا من غير أي تعديل يدوي في الكود.

### خطة الترقية لما الـ CLI يطلق فعليًا

| دلوقتي (يدوي) | بعد إطلاق CLI (أوتوماتيكي) |
|---|---|
| نسخ الـ SHA من طباعة الـ workflow | استدعاء `ghaymah login --token $TOKEN` |
| فتح لوحة تحكم Ghaymah يدويًا | استدعاء `ghaymah deploy --app <name> --sha <SHA>` مباشرة داخل الـ job |
| الضغط يدويًا على Save | الأمر نفسه بيرجع exit code يوضح نجاح/فشل النشر فورًا داخل GitHub Actions |

التصميم الحالي مبني عمدًا بحيث التحويل يوم ما الـ CLI يتوفر يكون **تغيير بسيط** (استبدال خطوة `Print deployment instructions` بخطوة `ghaymah deploy` فعلية) من غير أي إعادة هيكلة للـ pipeline بالكامل.

## أفضل ممارسات لحد ما الـ CLI يتوفر
- ثابت على تسمية واضحة للتطبيقات (`-prod`, `-staging`) لتفادي الغلط وقت تحديث الـ SHA يدويًا
- استخدم متغيرات بيئة مختلفة تمامًا بين البيئتين (خصوصًا أي مفاتيح API أو روابط قواعد بيانات)
- وثّق كل SHA اتنشر فعليًا على production (تقدر تستخدم GitHub Releases أو Tags لده)

---

## ملاحظة عن خطوة الـ Registry (شفافية كاملة)

متطلبات المهمة الأصلية بتطلب "رفع الصورة إلى ghaymah Container Registry". حاليًا Ghaymah **لا توفر Container Registry عام** — النشر بيتم عن طريق Git-Based Deployment فقط (البند اللي فوق). خطوة الـ `docker push` في الـ workflow بترفع فعليًا على **Docker Hub** كبديل مؤقت، عشان:
1. تستوفي شرط "بناء ورفع الصورة لريجستري" في المهمة حرفيًا
2. تدي نسخة موثقة ومؤرشفة من كل صورة (بالـ commit SHA) تقدر ترجعلها وقت الحاجة
3. تبقى جاهزة تتحول لـ Ghaymah Registry الحقيقي بمجرد ما يتوفر (تغيير قيمة `REGISTRY` في الـ workflow بس)

النشر الفعلي على Ghaymah **مش معتمد على الخطوة دي** — بيعتمد فقط على تحديث الـ Commit SHA في لوحة التحكم زي ما هو موضح في الخطوتين 7 و 8.
