Ghaymah SRE exam submission - Mohamed Adel
هذا الالتزام موجود في:
51
q3-cicd/README.md
Normal file
51
q3-cicd/README.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Q3 — CI/CD Pipeline على غيمة
|
||||
|
||||
يشرح هذا الملف `workflow.yml` بالإضافة للفرق بين staging و production وطريقة الربط بـ Ghaymah CLI.
|
||||
|
||||
## 1. الفرق بين Staging و Production
|
||||
|
||||
| | Staging | Production |
|
||||
|---|---|---|
|
||||
| **الغرض** | بيئة تحقق قبل الإطلاق: نشر أوتوماتيكي لأي تعديل على `main` للتأكد أن الصورة (image) الجديدة تعمل فعليًا | البيئة الحقيقية التي يستخدمها المستخدم النهائي |
|
||||
| **من يوافق؟** | لا يوجد — نشر تلقائي بمجرد نجاح البناء | يتطلب موافقة يدوية (Manual Approval) من مراجع معتمد قبل التنفيذ |
|
||||
| **البيانات** | بيانات تجريبية/مصغّرة، منفصلة تمامًا عن بيانات المستخدمين الحقيقيين | بيانات حقيقية وحساسة |
|
||||
| **الموارد** | نسخة واحدة أو نسختين، موارد أقل (توفير تكلفة) | حسب سياسة auto-scaling (انظر Q4/Q2)، موارد كافية لتحمل الحمل الحقيقي |
|
||||
| **التنبيهات عند الفشل** | إشعار للفريق فقط | تنبيه فوري (on-call) لأن أي عطل يؤثر على المستخدمين مباشرة |
|
||||
| **الدومين المستخدم في هذا المثال** | `staging.ghaymah-exam-app.ghaymah.systems` | `ghaymah-exam-app.ghaymah.systems` |
|
||||
|
||||
الفكرة الأساسية: نفس الـ image بالضبط (نفس الـ tag، نفس commit SHA) يمر من staging إلى production بدون إعادة بناء، لضمان أن ما تم اختباره هو نفسه ما يُنشر فعليًا.
|
||||
|
||||
## 2. كيف تعمل بوابة الموافقة اليدوية (Manual Approval)
|
||||
|
||||
الموافقة اليدوية **لا تُكتب كخطوة داخل الـ workflow نفسه**، بل تُفعَّل من إعدادات المستودع:
|
||||
|
||||
1. `Settings` → `Environments` → إنشاء بيئة اسمها `production`
|
||||
2. تفعيل `Required reviewers` واختيار الأشخاص المسموح لهم بالموافقة (مثلاً: قائد الفريق أو مهندس SRE أول)
|
||||
3. أي job في الـ workflow يستخدم `environment: name: production` (كما في `deploy-production` أعلاه) سيتوقف تلقائيًا وينتظر ضغط "Approve" من أحد المراجعين المحددين قبل أن يبدأ التنفيذ فعليًا.
|
||||
|
||||
## 3. طريقة الربط الفعلية (Docker Hub + Ghaymah Dashboard)
|
||||
|
||||
**ملاحظة مهمة:** واجهة Ghaymah الحالية (deploy.ghaymah.systems) بتدعم النشر عن طريق **ربط حساب Docker Hub** مباشرة من الداشبورد (زر "Deploy Application" → "Docker Hub")، مش عن طريق CLI مخصص. لذلك التدفق الفعلي للـ pipeline هو:
|
||||
|
||||
```bash
|
||||
# 1. بناء الصورة محليًا أو عبر GitHub Actions (خطوة build-and-push في workflow.yml)
|
||||
docker build -t mohamedadel777/ghaymah-exam-app:latest .
|
||||
|
||||
# 2. تسجيل الدخول لـ Docker Hub
|
||||
docker login
|
||||
|
||||
# 3. رفع الصورة
|
||||
docker push mohamedadel777/ghaymah-exam-app:latest
|
||||
```
|
||||
|
||||
ثم من داشبورد Ghaymah:
|
||||
`Deploy Application → Docker Hub → اختيار الصورة والـ tag → تحديد Port 8080 → Deploy Now`
|
||||
|
||||
**في CI (GitHub Actions)** الخطوة `build-and-push` في `workflow.yml` بتعمل بالضبط نفس الأمرين (build + push) تلقائيًا، وبعدين خطوات `deploy-staging` و `deploy-production` بترجع رسالة تفيدك إن فيه صورة جديدة جاهزة للـ redeploy — لأن Ghaymah لسه ما بتوفرش webhook/CLI عام لتفعيل الـ redeploy تلقائيًا وقت كتابة هذا الملف، فالخطوة الأخيرة (اختيار الـ tag الجديد والضغط Redeploy) بتتم يدويًا من الداشبورد. لو Ghaymah ضافت لاحقًا CLI أو Webhook رسمي للنشر، تُستبدل هذه الخطوة بأمر فعلي.
|
||||
|
||||
الـ Secrets المطلوبة في إعدادات المستودع (`Settings → Secrets and variables → Actions`):
|
||||
|
||||
| الاسم | القيمة |
|
||||
|---|---|
|
||||
| `DOCKERHUB_USERNAME` | يوزر Docker Hub (`mohamedadel777`) |
|
||||
| `DOCKERHUB_TOKEN` | Access Token من Docker Hub (Account Settings → Security → New Access Token) |
|
||||
103
q3-cicd/workflow.yml
Normal file
103
q3-cicd/workflow.yml
Normal file
@@ -0,0 +1,103 @@
|
||||
# .github/workflows/deploy.yml
|
||||
#
|
||||
# CI/CD pipeline: build Docker image -> push to Ghaymah Container Registry
|
||||
# -> deploy to staging automatically -> manual approval -> deploy to production.
|
||||
|
||||
name: Build and Deploy to Ghaymah
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch: {}
|
||||
|
||||
env:
|
||||
DOCKERHUB_USER: mohamedadel777
|
||||
IMAGE_NAME: ghaymah-exam-app
|
||||
|
||||
jobs:
|
||||
# ---------------------------------------------------------------------
|
||||
# 1) Build the image once and push it to Docker Hub, tagged with the
|
||||
# commit SHA. Ghaymah pulls the image from Docker Hub when you
|
||||
# deploy/redeploy from the dashboard (Deploy App -> Docker Hub).
|
||||
# ---------------------------------------------------------------------
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
image_tag: ${{ steps.meta.outputs.tag }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set image tag (short commit SHA)
|
||||
id: meta
|
||||
run: echo "tag=${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push image
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.DOCKERHUB_USER }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.tag }}
|
||||
${{ env.DOCKERHUB_USER }}/${{ env.IMAGE_NAME }}:latest
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# 2) Deploy to STAGING automatically — no approval needed.
|
||||
# NOTE: Ghaymah's current dashboard doesn't expose a public
|
||||
# redeploy-by-API step, so this job posts a reminder / calls a
|
||||
# webhook if you set one up. If Ghaymah adds a CLI/API later,
|
||||
# replace the "Trigger redeploy" step below with the real command.
|
||||
# ---------------------------------------------------------------------
|
||||
deploy-staging:
|
||||
needs: build-and-push
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: staging
|
||||
url: https://ghaymah-mithal-monitor-de4c1ce11f85.hosted.ghaymah.systems
|
||||
steps:
|
||||
- name: New image pushed — ready for staging redeploy
|
||||
run: |
|
||||
echo "New image pushed: ${{ env.DOCKERHUB_USER }}/${{ env.IMAGE_NAME }}:${{ needs.build-and-push.outputs.image_tag }}"
|
||||
echo "Go to the Ghaymah dashboard -> your app -> Redeploy, and pick this tag from Docker Hub."
|
||||
# If/when Ghaymah exposes a redeploy webhook or CLI, call it here, e.g.:
|
||||
# curl -X POST "$GHAYMAH_REDEPLOY_WEBHOOK_URL"
|
||||
|
||||
- name: Smoke test staging /health
|
||||
run: |
|
||||
sleep 10
|
||||
curl -f https://ghaymah-exam-app-06b532d0a81b.hosted.ghaymah.systems/health
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# 3) Deploy to PRODUCTION — gated behind a manual approval.
|
||||
# The "environment: production" + protection rule configured in the
|
||||
# repo settings (Settings -> Environments -> production -> Required
|
||||
# reviewers) is what forces a human to click "Approve" in the
|
||||
# Actions tab before this job runs.
|
||||
# ---------------------------------------------------------------------
|
||||
deploy-production:
|
||||
needs: [build-and-push, deploy-staging]
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: production # <-- manual approval gate lives here (repo settings)
|
||||
url: https://ghaymah-exam-app-06b532d0a81b.hosted.ghaymah.systems
|
||||
steps:
|
||||
- name: New image ready for production redeploy
|
||||
run: |
|
||||
echo "Approved. Image ready: ${{ env.DOCKERHUB_USER }}/${{ env.IMAGE_NAME }}:${{ needs.build-and-push.outputs.image_tag }}"
|
||||
echo "Go to the Ghaymah dashboard -> your production app -> Redeploy, and pick this tag from Docker Hub."
|
||||
|
||||
- name: Smoke test production /health
|
||||
run: |
|
||||
sleep 10
|
||||
curl -f https://ghaymah-exam-app-06b532d0a81b.hosted.ghaymah.systems/health
|
||||
المرجع في مشكلة جديدة
حظر مستخدم