النشر من GitHub عبر OIDC
اضبط التفويض من البوابة، وانسخ سير عمل GitHub Actions الجاهز، ثم ارفع. يبني حزمة Docker، ويرفعها إلى مستودعك الخاص، وينشرها على تطبيقك بلا أسرار دائمة.
كيف تجري عملية النشر
كل عملية رفع إلى الفرع المسموح به تُشغّل سير عمل واحداً يقوم بثلاثة أمور، تجري مصادقتها جميعاً برموز OIDC قصيرة العمر من GitHub، بلا كلمات مرور ثابتة ولا مفاتيح API مُخزَّنة في أيّ مكان من هذا المسار:
- الرفع إلى المستودع. يسجّل GitHub Actions الدخول إلى
registry.alawadi.cloudعبرdocker login -u oidc(برمز يُنشأ وقت التشغيل)، ثم يبني حزمة تطبيقك ويرفعها موسومة بقيمة SHA الخاص بالالتزام. - النشر. يستبدل التشغيل نفسه رمز OIDC آخر برمز نشر قصير العمر يُستخدم لمرّة واحدة، ثم ينشر تلك الحزمة بالذات على تطبيق واحد.
يحكم هذا تفويضان منفصلان: تفويض الرفع إلى المستودع (أيّ مستودع GitHub يحقّ له رفع الحزم)، وتفويض النشر على التطبيق (أيّ مستودع GitHub يحقّ له النشر على تطبيق محدّد). رفع الحزمة وحده لا ينشر: تحتاج الاثنين معاً. تُجهّز لك البوابة كليهما عبر نماذج، وتسلّمك سير عمل جاهزاً، فلا تكتب YAML بيدك ولا تبحث عن المعرّفات.
اضبطه من البوابة
تولّد لك البوابة سير العمل بالكامل، معبّأً مسبقاً بعنوان مستودعك، والـ audiences، ومعرّف التطبيق، وقيمة deploy audience. كل ما عليك نسخه وتعديل ما يخصّ بناء مشروعك فقط.
افتح المستودعات، وأنشئ مستودعك الخاص أو اختره، ثم افتح صفحة تفاصيله. بطاقة Push setup (GitHub Actions OIDC) تضمّ نموذج تفويض المستودع.
في Push setup، املأ GitHub repository (owner/repo)، وBranch ref
(معبّأ مسبقاً بـ refs/heads/main)، وEnvironment اختيارياً، ثم انقر
Configure trust. تعرض البطاقة قيمة OIDC Audience التي خصّصها المستودع
للقراءة فقط. لن تكتبها بنفسك.
انزل إلى بطاقة CI workflow templates واختر تبويب بيئة التشغيل (Node ·
Express، أو Next.js · React، أو Python · FastAPI، أو Python · Django، أو Go،
أو PHP · Laravel، أو Java · Spring Boot، أو Rust، أو Static · Vite). تعرض
البطاقة App port (دائماً 8080)، وHealth endpoint، وEnv vars التي
تتوقّعها تلك البيئة.
من قائمة Deploy target المنسدلة، اختر التطبيق الذي سينشر عليه سير العمل. القائمة مُرشّحة على مشروع المستودع. إن ظهرت شارة Deploy trust required، فانقر Configure deploy trust. نقرة واحدة تعيد استخدام مستودع GitHub والفرع والبيئة من تفويض المستودع، فلا تعيد إدخال شيء. تتحوّل الشارة إلى Deploy trust configured.
انقر Copy workflow لنسخ ملف .github/workflows/deploy.yml المُولَّد. يحتوي
أصلاً على قيم IMAGE وPUSH_AUDIENCE وCONTAINER_ID وDEPLOY_AUDIENCE
الحقيقية. ضَعه في مستودعك، وعدّل فقط متغيّرات البناء الخاصة بكل بيئة والمكتوبة
كتعليقات داخل الملف (وDOCKERFILE إن لم يكن في جذر المستودع). وإن لم يكن لدى
مستودعك ملف Dockerfile، فوسّع Supporting Dockerfile وانسخ الملف الجاهز
للإنتاج الخاص ببيئتك.
التزم بتغييراتك وارفعها إلى الفرع المسموح به. تابع عملية النشر من صفحة تفاصيل التطبيق (الخط الزمني والسجلّات). وفي صفحة تفاصيل المستودع، تظهر الأوسمة المرفوعة في بطاقة Images.
سير العمل مُولَّد لا مكتوب يدوياً
بمجرّد اختيارك هدف النشر، تُملأ قيم CONTAINER_ID وDEPLOY_AUDIENCE وIMAGE
وPUSH_AUDIENCE كلّها في الملف المنسوخ. لا تبحث عن المعرّفات ولا تركّب سلسلة
الـ audience بيدك. التعديلات الوحيدة هي متغيّرات البناء الخاصة بالبيئة المكتوبة
كتعليقات داخل الملف.
ما داخل سير العمل المُولَّد
ملف .github/workflows/deploy.yml المنسوخ مكتمل. والقيم التي يعبّئها مسبقاً:
| المتغيّر | القيمة التي تحقنها البوابة |
|---|---|
IMAGE | مستودع حزم تطبيقك، مثل registry.alawadi.cloud/<tenant>/<slug>. |
PUSH_AUDIENCE | قيمة OIDC audience للمستودع، الظاهرة للقراءة فقط في Push setup. |
CONTAINER_ID | معرّف هدف النشر المختار. |
DEPLOY_AUDIENCE | alawadi-deploy:container:<CONTAINER_ID>، محسوبة لك (وتظهر أيضاً مع زرّ نسخ). |
DOCKERFILE | Dockerfile افتراضياً. غيّره فقط إن كان ملفك في مكان آخر. |
يسجّل سير العمل الدخول عبر OIDC (docker login registry.alawadi.cloud -u oidc --password-stdin)، ويضبط BUILDX_NO_DEFAULT_ATTESTATIONS=1 (لأنّ المستودع يرفض
وسم الـ attestation الافتراضي عند البناء)، ويطلب permissions: id-token: write.
كل بيئة تستمع على المنفذ 8080 كمستخدم غير جذر (non-root)، جاهزة لسياسة الأمان
المقيّدة في المنصّة.
إن كان تفويض مستودعك يضمّ قيمة Environment، فإنّ سير العمل المُولَّد يضيف أيضاً
environment: <name> إلى المهمّة كي يطابق ادّعاء OIDC.
للمستوى المتقدّم: ضبط تفويض النشر من صفحة التطبيق
لكل تطبيق بطاقته الخاصة Continuous deployment (GitHub Actions) في صفحة تفاصيل
التطبيق (/dashboard/projects/<project-id>/containers/<container-id>). وهي
التفويض نفسه الذي يضبطه زرّ Configure deploy trust، مع نموذج يمكنك تحريره
مباشرة:
- GitHub repository (
owner/repo، مطلوب) - Branch ref (معبّأ مسبقاً بـ
refs/heads/main، مطلوب، يجب أن يبدأ بـrefs/) - Environment (ادّعاء بيئة GitHub اختياري)
انقر Configure trust، فتعرض البطاقة قيمة Deploy audience
(alawadi-deploy:container:<container-id>) مع مقطع نشر جاهز. وتتحدّث قائمة
Recent deployments في البطاقة نفسها تلقائياً مع تنفيذ كل عملية رفع
(queued → rolling_out → succeeded). وأيّ عملية نشر لا تصل إلى succeeded
تنتهي بإحدى الحالات failed أو rolled_back أو superseded أو stranded.
استطلاع حالة النشر من CI الخاص بك
يعيد طلب النشر عنوان status_url تستطلعه، فاعتمد في حلقتك على هذه القيم
بالضبط. الحالة أثناء النشر هي rolling_out؛ أمّا running فهو الاسم القديم
الذي كانت عمليات النشر الأقدم تصدره ولم تعد الجديدة تستخدمه. اعتبر succeeded
نجاحاً، واعتبر failed وrolled_back وsuperseded وstranded حالات نهائية
غير ناجحة (superseded ليست خطأً؛ فقد حلّت عملية رفع أحدث محلّ هذه العملية،
لكن عليك مع ذلك أن تتوقّف عن الاستطلاع). وأيّ قيمة أخرى تعني أن تواصل
الاستطلاع. ومقطع النشر الذي تولّده لك البوابة يتّبع هذه القواعد أصلاً، فالأفضل
أن تنسخه بدل كتابة الحلقة بيدك.
للمستوى المتقدّم: التشغيل من CI بلا البوابة
إن كنت تؤتمت ضبط التفويض نفسه (في سكربتات التهيئة الخاصة بك مثلاً)، فيمكنك استدعاء الـ API مباشرة. وهذا هو المسار الثانوي: نماذج البوابة أعلاه هي المسار الأساسي الموصى به.
اضبط تفويض النشر على التطبيق برمز Bearer من البوابة (وهو JWT تحصل عليه بعد تسجيل الدخول بحساب Google، لا رمز OIDC من GitHub):
# PROJECT_ID و CONTAINER_ID من صفحة تفاصيل التطبيق.
curl -sS -X PUT \
"https://api.alawadi.cloud/v1/projects/$PROJECT_ID/containers/$CONTAINER_ID/deploy/github-oidc-trust" \
-H "Authorization: Bearer $PORTAL_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"repository":"owner/repo","ref":"refs/heads/main","environment":"production"}'للاطّلاع عليه أو حذفه:
curl -sS \
"https://api.alawadi.cloud/v1/projects/$PROJECT_ID/containers/$CONTAINER_ID/deploy/github-oidc-trust" \
-H "Authorization: Bearer $PORTAL_ACCESS_TOKEN"
curl -sS -X DELETE \
"https://api.alawadi.cloud/v1/projects/$PROJECT_ID/containers/$CONTAINER_ID/deploy/github-oidc-trust" \
-H "Authorization: Bearer $PORTAL_ACCESS_TOKEN"أمّا النشر نفسه (أي ما يشغّله سير العمل المُولَّد مع كل عملية رفع) فهو استبدال عبر نداءين. أولاً تستبدل رمز GitHub OIDC (المطلوب بقيمة deploy audience) برمز نشر قصير العمر يُستخدم لمرّة واحدة، ثم ترسل الحزمة:
name: Deploy
on:
push:
branches: [main]
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to container (OIDC -> short-lived deploy token)
env:
IMAGE: registry.alawadi.cloud/acme/web
CONTAINER_ID: 8f31c2a0-1b2c-4d5e-8f9a-0123456789ab
DEPLOY_AUDIENCE: alawadi-deploy:container:8f31c2a0-1b2c-4d5e-8f9a-0123456789ab
run: |
OIDC="$(curl -sSf \
-H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=$DEPLOY_AUDIENCE" | jq -r .value)"
DEPLOY_TOKEN="$(curl -sSf -X POST \
-H "Authorization: Bearer $OIDC" \
"https://api.alawadi.cloud/v1/containers/$CONTAINER_ID/deploy-token" | jq -r .token)"
curl -sSf -X POST \
-H "Authorization: Bearer $DEPLOY_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"image\":\"$IMAGE:${{ github.sha }}\"}" \
"https://api.alawadi.cloud/v1/containers/$CONTAINER_ID/deploy"# 1. استبدل رمز GitHub OIDC برمز نشر قصير العمر.
DEPLOY_TOKEN=$(curl -sSf -X POST \
-H "Authorization: Bearer $OIDC_TOKEN" \
"https://api.alawadi.cloud/v1/containers/$CONTAINER_ID/deploy-token" | jq -r .token)
# 2. انشر الحزمة (وسم ثابت، never :latest).
curl -sSf -X POST \
"https://api.alawadi.cloud/v1/containers/$CONTAINER_ID/deploy" \
-H "Authorization: Bearer $DEPLOY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"image":"registry.alawadi.cloud/acme/web:sha-8f31c2a"}'{
"image": "registry.alawadi.cloud/acme/web:sha-8f31c2a"
}لا أسرار دائمة
رموز النشر والرفع قصيرة العمر ومحدودة الصلاحية. ورمز النشر يُستخدم لمرّة واحدة
ومربوط بتطبيق واحد؛ لن تخزّن مفتاح API دائماً في GitHub. ويجب أن تستخدم الحزم
المنشورة وسماً ثابتاً (مثل sha-8f31c2a) لا :latest، وأن تأتي من مستودع
تملكه.
ذو صلة: ربط مستودع Docker خاص للسماح بالرفع وتسمية الحزم.