MoonStack — إزاي الريليس والأبديت بيشتغلوا فعلًا + اقتراحات الاستقرار

موثّق من الكود · 2026-06-17 · شرح + اقتراحات

الخلاصة في سطر: الأبديت مش بيسحب من GitHub. الباكدج بيتبني على سيرفر البِلد (moonui) من الفيلات الموجودة فعليًا (base_path() للـ BE + مجلد الفرونت المبني)، بيتوقّع، وبيتنشر في versions.json. العميل بينزّل الباكدج الموقّع ويطبّقه.
للعمل بكذا ديفلوبر: الأنضف نبني الريليس من main (شوف قسم 2.5) — بس انتبه: main فيه السورس بس (مفيش vendor ولا الفرونت المبني public/app)، فبيحتاج خطوة بناء (composer + ng build) — وده بيخلّيه قابل لإعادة الإنتاج.

1) جهة البِلد/الريليس (الديفلوبر) — منين بتتاخد الفيلات

moonstack:buildPackageBuilder::build() بياخد المصدر من $source = base_path() ويحزم: moonstack:release / ship → بينشر الباكدج في مجلد الريليس + بيحدّث versions.json (المانيفست اللي العميل بيـpoll عليه). ship = build + publish في خطوة، وكمان بينشر ملف الـ updater نفسه موقّع (للـ self-heal).
دِفلوبر → git push (GitHub) ← تعاون/باك أب فقط، مش في مسار الأبديت │ ▼ (لازم تنشر على moonui) moonui: git pull + local-deploy.sh → base_path() (BE) ng build --base-href /app/ → MOONSTACK_FRONTEND_DIST (FE) │ ▼ moonstack:build / ship = لقطة (snapshot) للفيلات دي الآن [ <name>-v<ver>.zip + sha256 + signature ] → release dir + versions.json
⚠️ الـ push لـ GitHub لوحده مايحطّش حاجة في الأبديت — اللي بيتشحن = اللي على moonui وقت الـ build.

2) جهة العميل (الأبديت) — إزاي بيتطبّق بأمان

moonstack-update.php (ملف مستقل) بيعمل بالترتيب:
0
Self-heal: لو فيه نسخة updater أحدث موقّعة → يستبدل نفسه ويطلب إعادة المحاولة (يمنع updater باظ من تعطيل الأسطول).
1
يقرا versions.json ويختار أصغر تنزيل: delta (الملفات المتغيّرة بس) لو متاح، وإلا full.
2
Pre-flight (متطلبات: PHP، صلاحيات…).
3
تنزيل + تحقق: sha256 لازم يطابق، والتوقيع يتأكد بالمفتاح العام.
4
Backup (DB + .env + الملفات المتأثرة) + كتابة lock فيه نقطة الرجوع.
5
Maintenance down.
6
Apply: delta = نسخ المتغيّر بس · full = تبديل الكود مع الحفاظ على الـ DATA (الفرونت delete-then-copy فمفيش chunks قديمة).
7
Composer — بس لو composer.lock اتغيّر (تجنّب نسخ 15k ملف vendor).
8
migrate (timeout-guarded) → جديد 8b sync-reference (يزرع تعريفات الإعدادات، best-effort/non-fatal) → caches.
9
up + finalize (ختم النسخة).

شبكات الأمان الموجودة دلوقتي قوية

2.5) الريليس من GitHub main مباشرة — للعمل بكذا ديفلوبر موصى به

بدل ما تجمّع شغل كل الديفلوبرز يدويًا على moonui وتبلد، الأنضف إن الريليس يتبني من main (اللي كله بيعمله merge عليه أصلًا).
تصحيح مهم (متأكد منه من الريموت): main في الريبوهين فيه السورس بس — مفيش vendor ومفيش الفرونت المبني (public/app = 0 ملفات). الفرونت المبني موجود حاليًا في public_html اللي ملوش remote — يعني مش متبوش على GitHub. فالبِلد-من-git لازم يعمل خطوة بناء (composer + ng build)، وده ميزة: ريليس قابل لإعادة الإنتاج 100%.

الـ pipeline المقترح

1
الديفلوبرز merge لـ main (BE + FE) → نعمل tag للنسخة (v2.3.0) على الاتنين.
2
build runner (moonui أو CI) ينضّف ويبني من الـ tag:
• BE: git checkout v2.3.0composer install --no-dev --optimize-autoloader (ينتج vendor).
• FE: git checkout v2.3.0npm ci && ng build --base-href /app/ (ينتج dist).
3
php artisan moonstack:build v2.3.0 --source=<be-checkout> --frontend=<fe-dist> --sign → باكدج موقّع.
4
moonstack:release / ship → versions.json → العملاء ينزّلوا.

التغيير الوحيد المطلوب في الكود

PackageBuilder::build() بيقبل opts['source'] أصلًا، لكن أمر moonstack:build مفيهوش --source دلوقتي. نضيف اختيار --source (تعديل بسيط) → نقدر نبني من أي checkout نظيف من غير ما نلمس moonui. (بديل من غير تعديل: نشغّل الأمر من جوه الـ checkout نفسه بعد composer install + .env مؤقت.)

ليه ده أحسن

التكلفة (مقبولة، مش بتخل بالسرعة/الدقة)

ملاحظة: الخطة إننا نعمل merge لـ main بعد ما نخلّص شغل MoonStack — وده بالظبط نقطة بداية الريليس في الـ pipeline ده.

3) اقتراحاتي للتحسين مقترحات — مش منفّذة

كلها بتزوّد الاستقرار من غير ما تخل بالسرعة ولا الدقة — التأثير موضّح في الجدول.

#التحسينالمكسب (استقرار)السرعةالدقةالجهد
1Health-check بعد الأبديت + rollback تلقائي
بعد up وقبل فك الـ lock: نضرب endpoint صحة (مثلًا /up + لوجين/داشبورد). لو رجع خطأ → rollback تلقائي للـ backup.
عالي — بيمسك "migrate نجح بس الأبليكيشن باظ" (اللي دلوقتي بيعدّي)+ريكوست واحد (مهمل)محايدصغير
2Canary / إطلاق متدرّج (channels)
الريليس يروح لعميل تجربة (moontest) الأول؛ بعد ما يثبت سليم نرقّيه لـ stable لباقي الأسطول.
عالي — ريليس باظ مايضربش كل العملاء مرة واحدةمحايد (تحديث كل عميل زيه زيه)محايدمتوسط
3بِلد قابل لإعادة الإنتاج (من tag نظيف) أو حارس "dirty tree"
نبني من git archive <tag> في مجلد مؤقت، أو على الأقل نحذّر/نمنع الـ build لو base_path فيه تعديلات غير متكوميتة مقابل تاج الريليس.
دقة عالية — مستحيل نشحن ملفات قديمة/غير متكوميتة بالغلطمحايد على العميل (جهة البِلد فقط)+++صغير (حارس) / متوسط (archive)
4تنظيف الـ backups (retention)
نحتفظ بآخر N باك أب ونمسح الأقدم — القرص المليان نفسه ممكن يفشّل تحديث.
متوسط — يمنع فشل بسبب امتلاء القرصمحايدمحايدصغير
5تحقق سلامة بعد الـ apply
بعد النسخ، نطابق checksums الملفات المشحونة من الـ manifest — نكتشف apply ناقص/تالف ونعمل rollback.
متوسط — يمسك تطبيق جزئي/تالف+هاش للملفات المتغيّرة (بسيط)+صغير
6اختبار idempotency لـ updater.seeders
اختبار CI يتأكد إن كل seeder في القايمة updateOrCreate ومن غير side-effects (يحمي خطوة الـ seed الجديدة وهي بتكبر).
متوسط — يحافظ على أمان خطوة 8bمحايد (CI بس)+صغير

4) الترتيب المقترح للتنفيذ

1
Health-check + rollback تلقائي — أعلى مكسب أمان بأقل تكلفة. (يكمّل شبكات الأمان الموجودة بإنه يمسك الأعطال اللي بعد نجاح الـ migrate.)
2
Canary channel (moontest أولًا) — يحمي الأسطول من ريليس باظ.
3
حارس dirty-tree في الـ build — يضمن إننا بنشحن بالظبط اللي اتكوميت.
4
الباقي (retention · تحقق ما بعد apply · اختبار idempotency) — تحسينات تدريجية.
ملاحظة: مفيش حاجة فيهم بتبطّأ تحديث العميل — أغلبها جهة البِلد أو ريكوست/هاش بسيط، والـ canary مابيغيّرش سرعة التحديث الفردي.

السياق الكامل في الـ KB: knowledge-base/topics/moonstack-update.md · مرتبط بـ middleware.md.