Loading...

النشر · قراءة 8 دقائق

النشر من Git: ادفع إلى فرعك، وتنطلق النسخة الجديدة

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

قراءة 8 دقائق مبتدئ Updated

النشر من Git: ادفع إلى فرعك، وتنطلق النسخة الجديدة

ما الذي يعنيه "النشر من Git" فعلًا

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

يستبدل النشر عبر Git بتلك السلسلة قاعدة واحدة: الفرع هو مصدر الحقيقة، وما عليه هو ما يعمل. أنت لا ترفع شيئًا. أنت تدفع (push)، وتنفّذ المنصّة البناء ذاته في كل مرة دون اختلاف. القابلية للتكرار هي المقصد — لا الراحة.

ما يحدث بين الـpush والتطبيق الحيّ

السلسلة قصيرة ويستحق أن تعرفها، لأنك حين يقع خلل تريد أن تعرف أي حلقة تفحص.

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

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

ما يحتاج إليه مستودعك

النشر من Git: ادفع إلى فرعك، وتنطلق النسخة الجديدة — ما يحتاج إليه مستودعك
المنصّات المُدارة وحاويات container apps على cdn.com.tr.

شيء واحد أساسًا: **Dockerfile**. هو الوصفة التي تحوّل شيفرتك المصدرية إلى صورة قابلة للتشغيل — الصورة الأساس، والاعتماديات، وخطوة البناء، وأمر البدء. وإن لم يكن لمشروعك ملف كهذا بعد، فكتابته مهمة تُنجز مرة واحدة، والملف نفسه يعمل على حاسوبك أيضًا.

تفصيلان يوفّران على الناس أكبر قدر من الوقت. أولًا، يجب أن ينصت تطبيقك على المنفذ الذي أبلغت المنصّة به، وعلى كل الواجهات (`0.0.0.0`) لا على `localhost` وحده — فالحاوية التي ترتبط بـlocalhost لا يمكن الوصول إليها من خارج نفسها. ثانيًا، كل ما هو سرّي (روابط قواعد البيانات، مفاتيح واجهات البرمجة) مكانه متغيّرات البيئة لا الصورة: فالصور يُعاد بناؤها وتنتقل من مكان إلى آخر، والسرّ المخبوز داخل صورة سرّ لا تستطيع تدويره.

يعمل المشروع متعدّد الخدمات بالطريقة نفسها عبر ملف Docker Compose — فكل خدمة ليست لها صورة جاهزة تحتاج إلى Dockerfile قابل للبناء، وتنهض الحزمة كاملة موصولة ببعضها.

الفروع: أبعِد الإنتاج عن عملك اليومي

هنا تتأذّى الفرق، والعلاج قرار لا ميزة. فإذا كان الإنتاج مرتبطًا بالفرع الذي تطوّر عليه، انطلق كل commit نصف منجَز إلى الهواء. اربط الإنتاج بفرع لا تدمج فيه إلا حين تقصد ذلك — وغالبًا يكون `main` بينما يجري العمل اليومي على فروع الميزات، أو فرع `production` مخصّص إذا كان `main` هو ملعب تكرارك.

الاختبار الذهني المفيد: "لو دفعت الآن، هل أرتاح لأن يرى الزوّار ذلك؟" وإن كان الجواب "لا" ولو مرة واحدة بشأن الفرع المرتبط، فالخطأ في الفرع لا في العملية.

تدفّق إصدار يُبقي الإنتاج مملًّا

# gundelik is: feature dalinda
git checkout -b feature/yeni-fiyatlandirma
git commit -am "pricing page"
git push origin feature/yeni-fiyatlandirma   # deploy TETIKLEMEZ

# yayina hazir oldugunda
git checkout main
git merge feature/yeni-fiyatlandirma
git push origin main                         # deploy BU push ile baslar

حين لا يظهر أثر الـpush

يبدو النشر سحرًا إلى أن يصمت ولا يفعل شيئًا، فشخّص بالترتيب الذي تجري به السلسلة.

ابدأ من الطرف: هل بدأ بناء أصلًا؟ إن لم يظهر أي بناء لِـpush قمت به، فالحلقة المنقطعة هي الربط — إمّا أن المستودع أو الفرع ليس هو المرتبط، أو أن التكامل فقد صلاحية الوصول (تثبيت مسحوب، أو مستودع أُعيدت تسميته أو نُقلت ملكيته). وإن بدأ بناء ثم فشل، فسجلّ البناء يدلّك على الموضع بالضبط؛ وأكثر الأسباب شيوعًا خطوة في Dockerfile تنجح محليًا بفضل ملف يستبعده `.dockerignore` لديك، أو تثبيت اعتمادية يحتاج إلى بيانات اعتماد لا يملكها البناء. وإن نجح البناء ومع ذلك ما زلت ترى النسخة القديمة، فالأرجح كثيرًا أنك تنظر إلى استجابة من الكاش لا إلى تطبيق قديم — اطلب الصفحة بكاسر كاش أو افحص ترويسة حالة الكاش قبل أن تتّهم النشر.

حالة واحدة غير بديهية تستحق المعرفة: إعادة تشغيل نشر لِـcommit فشل من قبل لن تصلحه من تلقاء نفسها. الـcommit هو المُدخَل؛ وما دام المُدخَل لم يتغيّر فلن تتغيّر النتيجة. ادفع إصلاحًا — ولو commit فارغًا — بدلًا من إعادة المحاولة على الـcommit نفسه.

افحص الحالة وأجبر نشرًا من الطرفية

# calisan uygulamanin durumu
cdnctl container apps list --account <uuid>

# son deploy ne yapti
cdnctl container apps logs --account <uuid> --app <app_uuid>

# elle yeniden dagit (ayni commit)
cdnctl container apps deploy --account <uuid> --app <app_uuid>

ما تكسبه حين يصبح النشر مملًّا

المكسب الحقيقي من النشر عبر Git ليس السرعة، بل أن يكفّ النشر عن كونه حدثًا. فحين يصير الإطلاق مجرّد push، تخرج التغييرات الصغيرة وحدها بدل أن تتكدّس في إصدار شهري محفوف بالمخاطر — والتغييرات الصغيرة هي التي تستطيع تنقيحها، لأنك حين ينكسر شيء تعرف بالضبط أيّ commit فعلها.

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

الأسئلة الشائعة

هل أحتاج إلى ملف Dockerfile، أم تستطيع المنصّة تخمين كيفية بناء تطبيقي؟

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

ماذا يحدث للتطبيق العامل بينما تُبنى نسخة جديدة؟

يستمر في الخدمة. لا تحلّ النسخة الجديدة محلّ القديمة إلا بعد بناء الصورة بنجاح؛ وإذا فشل البناء يبقى الإنتاج تمامًا كما كان.

هل أستطيع النشر دون push — لإعادة تشغيل آخر نسخة مثلًا؟

نعم. يمكن إطلاق نشر يدويًا من اللوحة أو عبر cdnctl، باستخدام الـcommit نفسه. وهذا مفيد بعد تغيير متغيّر بيئة، إذ لا ينشئ ذلك commit جديدًا.

كيف أبقي الأسرار خارج المستودع؟

ضعها في متغيّرات بيئة على التطبيق، لا في Dockerfile ولا في الشيفرة. فكل ما يُخبز داخل صورة يسافر معها ولا يمكن تدويره دون إعادة بناء.

دفعت push ولم يحدث شيء. أين أنظر أولًا؟

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