هذا الالتزام موجود في:
2026-07-27 00:05:12 +03:00
التزام 80980bbf16
19 ملفات معدلة مع 1912 إضافات و0 حذوفات

108
q3-cicd/README.md Normal file
عرض الملف

@@ -0,0 +1,108 @@
# بناء CI/CD Pipeline على غيمة (GitHub Actions + Ghaymah Container Registry)
## محتويات
```
.github/workflows/workflow.yml # الـ workflow الكامل
README.md # هذا التوثيق
```
---
## 1) نظرة عامة على الـ Pipeline
3 مراحل متسلسلة (jobs)، كل مرحلة تعتمد على نجاح ما قبلها:
```
build-and-push ──▶ deploy-staging ──▶ deploy-production
(بناء + فحص (نشر تلقائي، (⏸ موافقة يدوية
+ رفع للسجل) بدون موافقة) مطلوبة قبل التنفيذ)
```
- **build-and-push**: يبني صورة Docker، يشغّلها محليًا داخل الـ runner ويتحقق من `/health` (بوابة جودة أساسية) قبل رفعها فعليًا إلى **Ghaymah Container Registry**.
- **deploy-staging**: ينشر الصورة تلقائيًا على بيئة `staging` فور نجاح البناء — بدون تدخل بشري، لأن الهدف من staging هو تحقق سريع ومستمر.
- **deploy-production**: نفس صورة staging (بدون إعادة بناء) تُنشر على `production`، لكن **الوظيفة لا تبدأ التنفيذ إلا بعد موافقة يدوية** (تفاصيل القسم التالي).
---
## 2) الموافقة اليدوية (Manual Approval) قبل الإنتاج
الطريقة المعتمدة في الـ workflow هي **GitHub Environments** — وهي الآلية الرسمية والموصى بها من GitHub لهذا الغرض (وليس كودًا مخصصًا يفتح "تذكرة" أو ينتظر تعليقًا).
### كيفية الإعداد (مرة واحدة فقط، من واجهة المستودع):
1. اذهب إلى **Settings → Environments** في مستودع GitHub.
2. أنشئ بيئة باسم `production` (يجب أن يطابق الاسم بالضبط ما هو مكتوب في `environment: name: production` داخل الـ workflow).
3. فعّل **Required reviewers** وأضف الأشخاص أو الفريق المخوّل بالموافقة على نشر الإنتاج (مثال: قائد الفريق التقني أو مسؤول SRE).
4. (اختياري لكن موصى به) فعّل **Wait timer** (مثلاً 0-5 دقائق) كطبقة أمان إضافية، و**Deployment branches** لتقييد النشر على فرع `main` فقط.
5. أضف أسرار الإنتاج (Secrets) الخاصة بهذه البيئة تحديدًا (`GHAYMAH_API_TOKEN` لبيئة production منفصل عن نفس المتغير في staging) — هذا يمنع تسريب صلاحيات الإنتاج حتى لو تم تشغيل job آخر بالخطأ.
### كيف يعمل عمليًا
عندما يصل تنفيذ الـ workflow إلى job **deploy-production**، يتوقف تلقائيًا في حالة **"Waiting"** ولا تُنفَّذ أي خطوة داخله (بما فيها تسجيل الدخول لـ Ghaymah CLI) حتى يوافق أحد المراجعين المخوّلين من تبويب **Actions** في GitHub. هذا يضمن أن الكود الذي وصل فعليًا إلى staging وتحقق من صحته هو نفسه الذي يُنشر للإنتاج — دون إعادة بناء، ودون فجوة زمنية تسمح بتغييرات غير مراجعة.
---
## 3) الفرق بين بيئة Staging وبيئة Production
| الجانب | Staging | Production |
|---|---|---|
| **الغرض** | تحقق نهائي قبل الإنتاج: هل يعمل الكود على بنية تحتية شبيهة بالإنتاج؟ | خدمة المستخدمين الفعليين مباشرة |
| **آلية النشر** | تلقائي بالكامل فور نجاح البناء (CD حقيقي) | يدوي الموافقة، تلقائي التنفيذ بعدها |
| **حجم الموارد** | أصغر (نسخة واحدة أو نسختان، موارد أقل) لتقليل التكلفة | مطابق للحمل الحقيقي المتوقع، مع auto-scaling فعّال |
| **البيانات** | بيانات وهمية/مقنّعة (synthetic/masked data)، لا تُستخدم بيانات مستخدمين حقيقية أبدًا | بيانات حقيقية حساسة، تخضع لسياسات الخصوصية والنسخ الاحتياطي |
| **حساسية الأسرار (Secrets)** | مفاتيح API تجريبية/محدودة الصلاحية | مفاتيح إنتاج كاملة الصلاحية، معزولة تمامًا في GitHub Environment منفصل |
| **المراقبة والتنبيهات** | مراقبة أساسية (health checks) دون تنبيهات استدعاء (paging) | مراقبة كاملة + تنبيهات فورية (Slack/Page) عند أي شذوذ، حسب سياسات الحادثة الموثقة سابقًا |
| **النطاق (Domain)** | `*-staging.ghaymah.systems` أو نطاق فرعي داخلي | النطاق العام الفعلي للخدمة |
| **قابلية إعادة الإنشاء** | يمكن إعادة تدميرها وإنشاؤها في أي وقت دون قلق | تغييرات البنية تمر عبر مراجعة/موافقة، أي تعديل مباشر عليها له أثر تشغيلي |
| **من يوافق على النشر إليها** | لا أحد — تلقائي بالكامل | مراجع مخوّل محدد مسبقًا (Required Reviewer) |
**الخلاصة العملية:** staging هي "بروفة" مطابقة قدر الإمكان للإنتاج تُستخدم لاكتشاف الأخطاء قبل وصولها للمستخدمين، بينما production هي البيئة الوحيدة التي يُسمح فيها بموافقة بشرية صريحة كحاجز أخير قبل التأثير على المستخدمين الحقيقيين.
---
## 4) الربط مع Ghaymah CLI
### أ) التثبيت (داخل الـ workflow أو محليًا)
```bash
curl -fsSL https://cli.ghaymah.systems/install.sh | sh
ghaymah --version
```
> ملاحظة: عنوان التثبيت وأسماء الأوامر أعلاه مبنية على النمط القياسي لأدوات CLI الخاصة بمنصات الحاويات (deploy/login/logs). يُرجى التأكد من الأمر الدقيق ورابط التثبيت من `docs.ghaymah.cloud` أو console الحساب، حيث إن تفاصيل الواجهة قد تختلف عن الأمثلة هنا.
### ب) المصادقة (Authentication)
لا تُستخدم بيانات اعتماد شخصية داخل الـ pipeline أبدًا. بدلًا من ذلك:
1. يُنشأ **API Token** مخصص لبيئة CI/CD من لوحة تحكم غيمة (Settings → API Tokens أو ما يعادلها)، بصلاحيات محدودة (نشر/سحب صور فقط، وليس صلاحيات إدارية كاملة).
2. يُخزَّن هذا التوكن كسر (Secret) في GitHub:
- `GHAYMAH_REGISTRY_TOKEN` — لتسجيل الدخول لسجل الحاويات (`docker/login-action`).
- `GHAYMAH_API_TOKEN` — لتنفيذ أوامر `ghaymah deploy` عبر الـ CLI.
3. تسجيل الدخول داخل الـ workflow:
```bash
ghaymah auth login --token "$GHAYMAH_API_TOKEN"
```
### ج) الربط مع سجل الحاويات (Container Registry)
تسجيل الدخول لسجل الحاويات يتم عبر الأمر القياسي لـ Docker (متوافق مع أي سجل OCI، بما فيه سجل غيمة):
```bash
echo "$GHAYMAH_REGISTRY_TOKEN" | docker login registry.ghaymah.systems \
--username "$GHAYMAH_REGISTRY_USER" --password-stdin
```
وهذا بالضبط ما يقوم به `docker/login-action@v3` المستخدم في الـ workflow، مع الاستفادة من إدارة GitHub الآمنة للأسرار بدل كتابتها في نص الأوامر.
### د) أوامر النشر الأساسية
```bash
# نشر صورة على خدمة معيّنة (staging أو production حسب --env)
ghaymah deploy --service <service-name> --image <registry>/<namespace>/<image>:<tag> --env <staging|production> --wait
# متابعة سجلات الخدمة بعد النشر
ghaymah logs --service <service-name> --follow
# التحقق من حالة الخدمة والنسخ الحالية
ghaymah status --service <service-name>
# التراجع عن نشر فاشل (Rollback) إلى آخر نسخة مستقرة
ghaymah rollback --service <service-name>
```
### هـ) أفضل الممارسات المطبّقة في هذا الـ Pipeline
- **صورة واحدة تنتقل عبر كل البيئات**: تُبنى مرة واحدة في `build-and-push` وتُنشر بنفس الوسم (tag) على staging ثم production — لا إعادة بناء بين البيئتين، لضمان أن ما يُختبر هو نفسه ما يُنشر.
- **فصل الأسرار حسب البيئة**: أسرار `staging` منفصلة تمامًا عن أسرار `production` عبر GitHub Environments، فحتى لو تم اختراق بيئة staging لا يتأثر الإنتاج.
- **بوابة جودة قبل الرفع**: فحص `/health` يتم داخل الـ runner *قبل* دفع الصورة فعليًا إلى السجل، لتفادي رفع صور معطوبة.
- **موافقة يدوية = حاجز بشري واحد واضح**: بدل انتشار موافقات متفرقة في أدوات متعددة، الموافقة مركزية في نفس واجهة GitHub Actions التي يراقبها الفريق أصلًا.

158
q3-cicd/workflow.yml Normal file
عرض الملف

@@ -0,0 +1,158 @@
name: CI/CD - Build, Push, Deploy (Ghaymah)
# يعمل تلقائيًا عند الدفع لفرع main، أو يدويًا لأي فرع/بيئة عبر workflow_dispatch
on:
push:
branches: ["main"]
workflow_dispatch:
inputs:
image_tag:
description: "وسم اختياري إضافي للصورة (افتراضيًا: git SHA)"
required: false
default: ""
# صلاحيات أقل ما يمكن (least privilege)
permissions:
contents: read
packages: write
env:
# عنوان سجل الحاويات الخاص بغيمة - عدّله حسب مشروعك
GHAYMAH_REGISTRY: registry.ghaymah.systems
GHAYMAH_NAMESPACE: my-team
IMAGE_NAME: sample-api
jobs:
# ---------------------------------------------------------------------
# 1) بناء الصورة واختبارها ورفعها إلى Ghaymah Container Registry
# ---------------------------------------------------------------------
build-and-push:
name: Build & Push Image
runs-on: ubuntu-latest
outputs:
image_ref: ${{ steps.vars.outputs.image_ref }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set image tag variables
id: vars
run: |
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-7)
TAG="${{ github.event.inputs.image_tag }}"
if [ -z "$TAG" ]; then TAG="$SHORT_SHA"; fi
IMAGE_REF="${GHAYMAH_REGISTRY}/${GHAYMAH_NAMESPACE}/${IMAGE_NAME}:${TAG}"
echo "image_ref=${IMAGE_REF}" >> "$GITHUB_OUTPUT"
echo "Building: ${IMAGE_REF}"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# تسجيل الدخول إلى سجل حاويات غيمة عبر بيانات اعتماد مخزّنة كـ GitHub Secrets
- name: Log in to Ghaymah Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.GHAYMAH_REGISTRY }}
username: ${{ secrets.GHAYMAH_REGISTRY_USER }}
password: ${{ secrets.GHAYMAH_REGISTRY_TOKEN }}
- name: Build image
uses: docker/build-push-action@v6
with:
context: .
push: false
load: true
tags: |
${{ steps.vars.outputs.image_ref }}
${{ env.GHAYMAH_REGISTRY }}/${{ env.GHAYMAH_NAMESPACE }}/${{ env.IMAGE_NAME }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
# اختبار سريع للتأكد أن /health يستجيب قبل الرفع للسجل (بوابة جودة أساسية)
- name: Smoke test the built image
run: |
docker run -d --name smoke -p 8080:8080 ${{ steps.vars.outputs.image_ref }}
for i in $(seq 1 10); do
if curl -sf http://localhost:8080/health; then echo "Health check passed"; break; fi
echo "Waiting for app to start... ($i/10)"; sleep 2
done
curl -sf http://localhost:8080/health || (docker logs smoke && exit 1)
docker stop smoke
- name: Push image to Ghaymah Registry
uses: docker/build-push-action@v6
with:
context: .
push: true
tags: |
${{ steps.vars.outputs.image_ref }}
${{ env.GHAYMAH_REGISTRY }}/${{ env.GHAYMAH_NAMESPACE }}/${{ env.IMAGE_NAME }}:latest
# ---------------------------------------------------------------------
# 2) نشر تلقائي على STAGING فور نجاح البناء - بدون موافقة يدوية
# ---------------------------------------------------------------------
deploy-staging:
name: Deploy to Staging
needs: build-and-push
runs-on: ubuntu-latest
environment:
name: staging
url: https://sample-api-staging.ghaymah.systems
steps:
- name: Install Ghaymah CLI
run: |
curl -fsSL https://cli.ghaymah.systems/install.sh | sh
ghaymah --version
- name: Authenticate Ghaymah CLI
run: ghaymah auth login --token "${{ secrets.GHAYMAH_API_TOKEN }}"
- name: Deploy image to staging service
run: |
ghaymah deploy \
--service sample-api-staging \
--image "${{ needs.build-and-push.outputs.image_ref }}" \
--env staging \
--wait
- name: Verify staging health
run: |
curl -sf https://sample-api-staging.ghaymah.systems/health
# ---------------------------------------------------------------------
# 3) نشر على PRODUCTION - يتطلب موافقة يدوية (Manual Approval)
# الموافقة تُنفَّذ عبر GitHub Environment "production" المحمي بمراجعين
# مطلوبين (Required Reviewers) من إعدادات المستودع، وليس بكود مخصص.
# ---------------------------------------------------------------------
deploy-production:
name: Deploy to Production (Manual Approval Required)
needs: [build-and-push, deploy-staging]
runs-on: ubuntu-latest
environment:
name: production # <-- هذا السطر يفعّل بوابة الموافقة اليدوية المضبوطة في إعدادات المستودع
url: https://sample-api.ghaymah.systems
steps:
- name: Install Ghaymah CLI
run: |
curl -fsSL https://cli.ghaymah.systems/install.sh | sh
ghaymah --version
- name: Authenticate Ghaymah CLI
run: ghaymah auth login --token "${{ secrets.GHAYMAH_API_TOKEN }}"
- name: Deploy image to production service
run: |
ghaymah deploy \
--service sample-api-production \
--image "${{ needs.build-and-push.outputs.image_ref }}" \
--env production \
--strategy rolling \
--wait
- name: Verify production health
run: |
curl -sf https://sample-api.ghaymah.systems/health
- name: Post-deploy smoke check on /metrics
run: |
curl -sf https://sample-api.ghaymah.systems/metrics