كلاود
development

انشر تطبيقك بالـ Git على السيرفر: نشر نظيف قابل للتراجع في ثوانٍ

كلاود|١٣ سبتمبر ٢٠٢٦|7 دقائق قراءة|١٥٢ مشاهدة
انشر تطبيقك بالـ Git على السيرفر: نشر نظيف قابل للتراجع في ثوانٍ

دليل هندسي لنشر تطبيقك عبر Git بطريقة ذرّية: webhook أو pull، خطوات نشر مرتّبة، ورجوع لأي إصدار سابق في أقل من 5 ثوانٍ عبر تبديل رابط رمزي.

الإجابة المباشرة: كيف تنشر بالـ Git بنظافة وقابلية تراجع

النشر النظيف عبر Git يقوم على مبدأ واحد: لا تعدّل الكود مباشرة على السيرفر، بل اجعل السيرفر يسحب نسخة محددة من مستودعك ويبنيها في مجلد جديد، ثم يبدّل رابطاً رمزياً واحداً ليصبح هو النسخة الحيّة. بهذا الشكل يصبح كل نشر عملية ذرّية إما أن تنجح كلها أو لا شيء، والرجوع لأي إصدار سابق هو مجرد إعادة توجيه الرابط الرمزي مرة أخرى في أقل من 5 ثوانٍ.

لديك مسارّان لتشغيل النشر: إما webhook يرسله مستودعك (GitHub أو GitLab) لحظة الدفع فيشغّل سكربت النشر تلقائياً خلال ثانية أو ثانيتين، أو pull يدوي تنفّذه بنفسك عبر SSH أو أمر مجدول. المبدأ الهندسي واحد في الحالتين: السيرفر يستقبل commit محدد بهويته الكاملة (SHA بطول 40 خانة)، يبني عليه الاعتماديات والأصول، يشغّل الترحيلات، ثم يبدّل النسخة الحيّة دفعة واحدة.

القاعدة الذهبية التي تحمي إنتاجك: احتفظ بآخر 5 إصدارات على الأقل في مجلدات منفصلة على القرص. مجلد التطبيق النموذجي يزن من 150 إلى 400 ميغابايت، فخمس نسخ لا تكلّفك سوى ملّي واحد من مساحة SSD، مقابل قدرة على العودة الفورية لأي منها إذا انفجر النشر الأخير. هذا الفرق بين توقّف يمتد 30 دقيقة وأنت تصلح على السيرفر مباشرة، وبين رجوع يستغرق ثوانٍ.

webhook أم pull: أيهما تختار

الطريقتان تحلّان نفس المشكلة بأسلوبين. اختر بناءً على حجم فريقك ووتيرة نشرك.

النشر بالـ webhook (تلقائي)

عند كل دفع إلى الفرع المخصص للإنتاج، يرسل GitHub طلب POST إلى نقطة استقبال على سيرفرك تحمل تفاصيل الـ commit. السيرفر يتحقق من التوقيع ثم يشغّل سكربت النشر. هذا الأنسب للفرق التي تنشر عدة مرات يومياً، لأن زمن الرحلة من الدفع إلى الإنتاج ينزل تحت 30 ثانية بلا تدخّل بشري.

  • الميزة: صفر خطوات يدوية، النشر يبدأ خلال جزء من الثانية بعد الدفع.
  • العيب: يحتاج نقطة استقبال عامة ومؤمّنة، وأي خلل في السكربت ينفّذ تلقائياً بلا مراجعة.

النشر بالـ pull (يدوي أو مجدول)

هنا تتصل بالسيرفر عبر SSH وتشغّل سكربت النشر بنفسك، أو تجدوله عبر مهمة دورية. هذا المسار أبسط أمنياً لأنه لا يفتح أي نقطة استقبال عامة، ويعطيك لحظة مراجعة أخيرة قبل الضغط على الزر. أغلب الشركات ذات النظام المخصص التي تنشر مرة أو مرتين أسبوعياً تكتفي بهذا المسار، وهو الأكثر شيوعاً على خوادم VPS المُدارة.

القاعدة العملية: إن كنت تنشر أكثر من 5 مرات أسبوعياً فالـ webhook يوفّر عليك وقتاً حقيقياً، وإن كان نشرك أهدأ فالـ pull اليدوي أوضح وأأمن. كثير من الفرق تبدأ بالـ pull ثم تنتقل للـ webhook حين تنضج عملية النشر.

خطوات النشر كاملة بالترتيب

سكربت النشر الجيد ينفّذ خطوات محددة بترتيب صارم، وأي خطأ في أي خطوة يوقف العملية قبل تبديل النسخة الحيّة. الترتيب الصحيح يمنع حالة نصف منشورة تخدم للعميل صفحة مكسورة.

الترتيب القياسي

  • 1. جلب النسخة: استنساخ أو سحب الـ commit المحدد إلى مجلد إصدار جديد باسم يحمل الطابع الزمني أو الـ SHA، مثل releases/20260814-143000.
  • 2. تثبيت الاعتماديات: تشغيل composer install بوضع الإنتاج بلا حزم التطوير، وينزّل هذا حجم node_modules بنسبة تصل إلى 60% مقارنة ببيئة التطوير.
  • 3. بناء الأصول: بناء ملفات CSS وJavaScript النهائية المضغوطة، وهذه الخطوة وحدها قد تستغرق من 20 إلى 90 ثانية حسب حجم المشروع.
  • 4. ربط الملفات المشتركة: ربط رمزي لملف البيئة والمجلدات التي يجب أن تبقى ثابتة بين الإصدارات مثل مجلد الرفوعات والسجلات.
  • 5. تشغيل الترحيلات: تنفيذ ترحيلات قاعدة البيانات، ويفضّل أن تكون متوافقة للأمام حتى يعمل الإصدار القديم والجديد على نفس المخطط لحظة التبديل.
  • 6. تسخين الكاش: بناء كاش الإعدادات والمسارات والقوالب مسبقاً، فهذا يقصّ زمن أول طلب بعد النشر من ثوانٍ إلى أجزاء من الثانية.
  • 7. التبديل الذرّي: إعادة توجيه الرابط الرمزي current إلى مجلد الإصدار الجديد دفعة واحدة.
  • 8. إعادة تحميل العمليات: إعادة تحميل مشغّل PHP وأي عمّال طوابير حتى يلتقطوا الكود الجديد.

لاحظ أن الخطوات من 1 إلى 6 كلها تجري في مجلد جانبي بينما العميل لا يزال يُخدَم من النسخة القديمة، فلا يشعر بأي انقطاع. التبديل في الخطوة 7 هو اللحظة الوحيدة الحسّاسة، وهو أسرع من أن يُلاحَظ لأنه لا يتعدّى إعادة كتابة رابط رمزي واحد.

النشر الذرّي بمجلدات الإصدارات والرابط الرمزي

القلب التقني لكل ما سبق هو بنية المجلدات. بدل أن يكون تطبيقك في مجلد واحد ثابت، تنظّمه هكذا: مجلد releases يحوي كل إصدار في مجلد فرعي مستقل، ومجلد shared للملفات التي تعبر الإصدارات، ورابط رمزي اسمه current يشير دائماً إلى الإصدار الحيّ. سيرفر الويب يوجَّه إلى current وليس إلى مجلد محدد.

عند النشر، تُبنى النسخة الجديدة كاملة في releases، وحين تنجح كل الخطوات يُعاد توجيه current إليها في عملية واحدة غير قابلة للانقطاع. هذه هي الفكرة التي جعلت أدوات مثل Capistrano وDeployer وEnvoyer معياراً في النشر منذ أكثر من 10 سنوات. الفائدة المقاسة: زمن التبديل الفعلي أقل من 50 ميلي ثانية، وهو أقصر من زمن استجابة أي طلب حقيقي.

الملفات المشتركة مهمة هنا لأنها تمنع فقدان البيانات. ملف البيئة الذي يحمل أسرارك، ومجلد رفوعات المستخدمين، وملفات السجلات، كلها تعيش في shared وتُربَط رمزياً داخل كل إصدار، فلا تُستنسخ ولا تُمحى عند حذف إصدار قديم.

الرجوع لإصدار سابق في ثوانٍ

هنا تظهر القيمة الحقيقية للبنية. حين يكشف نشر عن خلل في الإنتاج، لا تفتح محرراً على السيرفر ولا تسحب commit إصلاح على عجل، بل تعيد توجيه current إلى مجلد الإصدار السابق الذي ما زال موجوداً كما هو، فيعود موقعك سليماً خلال ثوانٍ.

مستويات التراجع

  • تراجع فوري: تبديل current إلى الإصدار السابق. لا بناء ولا سحب، مجرد إعادة توجيه رابط، ويكتمل في أقل من 5 ثوانٍ. هذا خط دفاعك الأول.
  • تراجع بالكود: إن كان الخلل في الكود نفسه وتريده مسجّلاً في تاريخ المستودع، استخدم git revert على الـ commit المعطوب لإنشاء commit عكسي، ثم انشر عادة. هذا يبقي التاريخ نظيفاً بلا إعادة كتابة.
  • تراجع بالوسم: إن كنت توسم كل إصدار إنتاجي بوسم مثل v1.4.2، تنشر الوسم السابق مباشرة بأمر واحد، وهذا أوضح للفرق التي تتبع إصدارات رقمية.

الفخ الوحيد في التراجع هو قاعدة البيانات. إعادة توجيه الرابط الرمزي ترجع الكود فوراً لكنها لا تلغي ترحيلاً حذف عموداً أو غيّر نوع بيانات. لهذا القاعدة الذهبية: اجعل ترحيلاتك متوافقة للأمام والخلف، ولا تحذف عموداً في نفس النشر الذي يوقف استخدامه. احذف الاستخدام في نشر، ثم احذف العمود في نشر لاحق بعد أيام. هذا يجعل أي تراجع في الكود آمناً بلا لمس البيانات.

تأمين الـ webhook والوصول

إن اخترت مسار الـ webhook فأنت تفتح باباً على سيرفرك، ويجب أن يكون هذا الباب محكماً. أكثر من 80% من ثغرات النشر الآلي تأتي من نقطة استقبال بلا تحقق توقيع.

  • تحقق التوقيع: يرسل GitHub رأس توقيع محسوباً بمفتاح سرّي مشترك، ويجب أن يحسب سيرفرك نفس التوقيع للحمولة ويرفض أي طلب لا يطابق، فلا يشغّل النشر أحد سواك.
  • مفاتيح النشر: استخدم deploy key بصلاحية قراءة فقط لسحب المستودع، فحتى لو تسرّب المفتاح من السيرفر لا يستطيع أحد الدفع لمستودعك.
  • حصر الفرع: اجعل السكربت يتجاهل أي دفع لغير فرع الإنتاج، فدفعك لفرع تجريبي لا يلمس الموقع الحيّ.
  • عزل الأسرار: ملف البيئة يبقى خارج المستودع تماماً وخارج أي مسار يقرؤه الويب، ويُربَط من shared فقط.

على خوادم كلاود السعودية، نقطة الاستقبال والمستودع والقاعدة كلها داخل المملكة، فرحلة الـ webhook من GitHub إلى سيرفرك في الرياض تكتمل بزمن استجابة قريب من 8 ميلي ثانية للطلبات المحلية، مقابل 100 إلى 120 ميلي ثانية لو كان سيرفرك خارجياً. القرب يعني أيضاً أن بيانات نشرك وأسرارك لا تغادر الحدود، وهو شرط أساسي للأنظمة المرتبطة بالنفاذ الوطني أو التكامل الحكومي.

أخطاء شائعة تجنّبها

معظم كوارث النشر تتكرر بأنماط معروفة، وتجنّبها يرفع نسبة نشرك الناجح فوق 99%.

  • التعديل المباشر على السيرفر: أي تعديل يدوي على النسخة الحيّة يضيع في النشر التالي ويكسر التطابق مع المستودع. القاعدة: السيرفر يقرأ من Git فقط، لا يُكتب فيه بيدك.
  • نشر بلا اختبار مسبق: شغّل الاختبارات في بيئة التكامل قبل النشر لا بعده. اكتشاف خلل في الاختبار أرخص 100 مرة من اكتشافه في الإنتاج.
  • ترحيلات هدّامة في نشر واحد: فصل حذف الأعمدة عن حذف استخدامها كما شرحنا يحمي قابلية التراجع.
  • حذف كل الإصدارات القديمة فوراً: أبقِ 5 إصدارات على الأقل، فبلا نسخة سابقة على القرص يتحوّل تراجعك من ثوانٍ إلى عملية بناء كاملة.
  • عدم تسخين الكاش: نشر بلا بناء كاش مسبق يعني أن أول عشرات المستخدمين يدفعون ثمن البطء.

النشر النظيف ليس أداة واحدة، بل انضباط في بنية المجلدات وترتيب الخطوات وسياسة التراجع. حين تركّب هذه الثلاثة على خادم سحابي سعودي قريب من مستخدميك ومتوافق مع متطلبات السيادة الرقمية، تصبح كل عملية نشر حدثاً هادئاً لا مغامرة، ويصبح التراجع خياراً بضغطة زر لا كابوس ليلة.

مشاركة