Python Programming

إدارة التبعيات الجاهزة للإنتاج: حل تعارضات ملفات القفل باستخدام pip-tools و Poetry

إدارة التبعيات الجاهزة للإنتاج: حل تعارضات ملفات القفل باستخدام pip-tools و Poetry

في عالم تطوير بايثون، تكون الرحلة من البيئة المحلية إلى النشر في الإنتاج مليئة بليالي الكوابيس المتعلقة بعبارة "يعمل على جهازي". ورغم أن نظام بايثون البيئي قد تحسن بشكل كبير، إلا أن التحدي الأكثر استمرارية لا يزال يتمثل في حل التبعيات واتساق ملفات القفل (lockfiles). عند بناء خطوط أنابيب CI/CD، فإن الاعتماد فقط على ملف requirements.txt الذي يتم إنشاؤه بواسطة pip freeze هو وصفة للكوارث. في هذه المقالة، سنستكشف كيفية تحقيق عمليات بناء حتمية (deterministic) من خلال الاستفادة من pip-tools و Poetry لحل تعارضات ملفات القفل وضمان أن بيئة الإنتاج قابلة للتكرار تمامًا مثل إعدادات التطوير المحلية.

مشكلة ملف القفل في CI/CD

غالبًا ما تتضمن إدارة التبعيات التقليدية أمر "تجميد" (freeze) يلتقط الحالة الدقيقة للحزم المثبتة. ومع ذلك، فإن هذه الملفات قابلة للتعديل. إذا قام مطور بتحديث حزمة محليًا، فإن ملف requirements.txt يتغير، مما قد يؤدي إلى إدخال أخطاء خفية في خط الأنابيب. والأكثر أهمية، أن أمر pip install يقوم بحل التبعيات بشكل ديناميكي أثناء عملية التثبيت. في بيئة CI، هذا يعني أن الكود المتطابق يمكن أن ينتج عنه حزم ثنائية أو أشجار تبعيات مختلفة إذا تغيرت ظروف الشبكة أو حالة مستودعات الحزم قليلاً بين عمليات البناء.

لحل هذه المشكلة، نحتاج إلى فصل الاهتمامات: أداة لكتابة التبعيات (القيود) وأخرى لتثبيتها. هنا تبرز أدوات pip-tools و Poetry، حيث تعملان كبوابات تضمن أن البيئة في مرحلة الاختبار (staging) تعكس بيئة الإنتاج بدقة.

الاستراتيجية أ: pip-tools للنهج العملي

يُعد pip-tools حلاً خفيف الوزن مصمم خصيصًا لفصل ملف الإدخال عن ملف القفل المُركب. فهو يستخدم نهجًا إعلانيًا (declarative) حيث تحدد تبعياتك في ملف requirements.in (المصدر القابل للتعديل) وتقوم بتجميعها في ملف requirements.txt (ملف القفل غير القابل للتعديل). هذا يضمن أن خطوة التجميع تكون حتمية.

يتضمن سير العمل تشغيل أمر pip-compile لتوليد ملف القفل. يقوم هذا الملف بتثبيت كل من التبعات المباشرة وغير المباشرة على إصدار معين وقيمة تحقق (checksum). في خط أنابيب CI الخاص بك، تقوم بالتثبيت فقط من هذا ملف القفل، متجاوزةً تمامًا محرك حل التبعيات.

# requirements.in
django>=4.2
psycopg2-binary==2.9.6

# تشغيل التجميع محليًا لتوليد requirements.txt
pip-compile requirements.in

# في CI/CD، قم بالتثبيت بدقة من ملف القفل
pip-sync requirements.txt

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

الاستراتيجية ب: Poetry لعمليات سير العمل المرتكزة على المشروع

يقدم Poetry تجربة أكثر حداثة ودمجًا. فهو يعامل المشروع نفسه كوحدة توزيع، ويدير كلًا من التبعيات والبيئات الافتراضية. يعمل ملف pyproject.toml الخاص بـ Poetry كمصدر للحقيقة، حيث يجمع بين البيانات الوصفية وإعدادات البناء وتعريفات التبعيات.

على عكس pip-tools، يحل Poetry التبعيات باستخدام محلل تبعيات متطور يحاول تقليل تعارضات الإصدارات قبل توليد ملف poetry.lock. هذا ملف القفل بنفس أهمية ملف القفل الخاص بـ pip-tools لموثوقية CI/CD.

# pyproject.toml
[tool.poetry.dependencies]
python = "^3.11"
requests = "^2.31.0"
django = "^4.2.5"

[tool.poetry.group.dev.dependencies]
pytest = "^7.4.0"

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

# CI Pipeline Script (Bash)
# تثبيت Poetry
curl -sSL https://install.python-poetry.org | python3 -

# التأكد من استخدام ملف القفل
poetry install --no-root --no-interaction

# التحقق من سلامة ملف القفل
poetry check

سد الفجوة: التعامل مع تعارضات ملفات القفل

رغم نقاط قوتها، فإن تعارضات ملفات القفل تحدث. يحدث هذا عادةً عندما تتطلب تبعيتان إصدارات غير متوافقة من تابعة ثالثة غير مباشرة. في العالم الحقيقي، يتجلى هذا غالبًا كخطأ "عدم تطابق الإصدار" أثناء بناء CI.

عند استخدام pip-tools، يمكنك حل ذلك عن طريق إضافة قيود إصدار محددة إلى ملف requirements.in لفرض إصدار متوافق، ثم إعادة التجميع. بالنسبة لـ Poetry، يجب عليك استخدام أمر poetry update --no-interaction package_name لتحديث تابعة معينة أو شجرتها بشكل انتقائي، أو استخدام علامة poetry lock --no-update للتأكد من أن ملف القفل يطابق ملف pyproject.toml تمامًا دون محاولة حل إصدارات جديدة.

بالنسبة لبيئات الإنتاج عالية المخاطر، فإن أفضل ممارسة هي معاملة ملف القفل ككود. لا يجب أن تقوم طلبات الدمج (merge requests) بتحديث ملف المصدر (requirements.in أو pyproject.toml) فحسب، بل يجب أن تتضمن أيضًا ملف القفل الناتج. هذا يضمن أن قرار الحل يتم مراجعته من قبل الزملاء قبل دمجه في الفرع الرئيسي.

الخلاصة

تحقيق نشر جاهز للإنتاج في بايثون يتطلب أكثر من مجرد سرد التبعيات. فهو يتطلب عملية صارمة يتم فيها فصل حل التبعيات عن التثبيت. سواء اخترت التحكم الصريح والخفيف لـ pip-tools أو إدارة المشاريع الشاملة لـ Poetry، فإن الهدف يبقى واحدًا: عمليات بناء حتمية وقابلة للتكرار.

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

Share: