بالنسبة لأي مطور بايثون جاد في البرمجيات مفتوحة المصدر أو توزيع المكتبات الداخلية، فإن العملية اليدوية لتعبئة الملفات ورفعها إلى PyPI تمثل عنق زجاجة كبير. إنها عرضة للأخطاء، ومملة، وتُدخل احتكاكاً في سير العمل التطويري. من خلال أتمتة هذه العملية باستخدام GitHub Actions و Twine والإصدار الدلالي الصارم، يمكنك ضمان أن كل إصدار يكون قابلاً للتكرار، آمناً، وفورياً.
خط أنابيب الإصدار الحديث
لا يقتصر خط أنابيب الإصدار القوي على رفع الملفات فحسب؛ بل يقوم أيضاً بمراجعة الكود الخاص بك، وإدارة أرقام الإصدارات تلقائياً، والتعامل مع الأسرار بشكل آمن. تتكون المكونات الأساسية لهذه الأتمتة مما يلي:
- GitHub Actions: المحرك الذي يشغل سير العمل عند أحداث محددة، مثل دفع علامة (tag) جديدة.
- Setuptools / Poetry / Hatch: الأدوات التي تبني ملفات التوزيع الخاصة بك (sdist و bdist_wheel).
- Twine: الأداة الموثوقة لرفع الحزم إلى PyPI.
- الإصدار الدلالي (SemVer): المعيار الذي يضمن أن أرقام الإصدارات تعكس طبيعة التغييرات (رئيسي.فرعي.تصحيحي).
الخطوة 1: فرض الإصدار الدلالي
قبل الأتمتة، يجب عليك تحديد كيفية زيادة الإصدارات. نوصي باستخدام نمط versioneer أو الاعتماد على علامات Git. سيتم تشغيل سير العمل فقط عند دفع علامة تتطابق مع النمط v*. يضمن ذلك عدم إنشاء أرقام الإصدارات تلقائياً بواسطة تشغيل CI، بل يتم الإعلان عنها صراحةً من قبل المطور.
الخطوة 2: تكوين سير عمل GitHub Actions
أنشئ ملفاً في المسار .github/workflows/publish.yml. يحدد هذا الملف YAML خط الأنابيب. سيعمل سير العمل عند حدث create، وتحديداً عند تصفية العلامات.
name: Publish Python Distribution to PyPI
on:
release:
types: [published]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write # Use OIDC authentication
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Build and publish
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: |
python -m build
twine upload dist/*
أفضل ممارسات الأمان: استخدام OIDC
يستخدم المثال أعلاه id-token: write والمتغيرات البيئية للتعامل القديم مع الرموز. ومع ذلك، فإن أفضل ممارسة حديثة هي استخدام الاتصال المفتوح (OIDC) مع PyPI. يسمح هذا لـ GitHub Actions بافتراض هوية موثوقة دون تخزين رموز API طويلة الأمد في أسرار المستودع الخاص بك. لتمكين ذلك، يجب عليك تكوين مزود OIDC في إعدادات مشروعك على PyPI.
قم بتحديث خطوة publish كما يلي لأقصى درجات الأمان:
- name: Publish distribution to PyPI
run: twine upload dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
ملاحظة: عند استخدام OIDC، عادةً لا تحتاج إلى تخزين كلمة المرور في الأسرار. بدلاً من ذلك، تتولى خطوة actions/setup-python أو إجراء OIDC محدد المصادقة بشكل ديناميكي.
الخطوة 3: بناء التوزيع
في سير العمل، نستخدم python -m build. هذا هو البديل الحديث لـ setup.py sdist bdist_wheel. يضمن ذلك استخدامك لـ build معزولاً عن بيئتك المحلية، مما يضمن بناء ملفات wheel تماماً كما سيتم بناؤها في حاوية نظيفة. تنتج هذه الخطوة مجلد dist/ الذي يحتوي على كل من توزيع المصدر و wheel الثنائي.
الخاتمة
تحويل إصدارات حزم بايثون الخاصة بك من مهمة يدوية إلى عملية موثوقة وقابلة للتدقيق. من خلال الاستفادة من GitHub Actions، تفصل منطق الإصدار عن جهازك المحلي. من خلال استخدام Twine و OIDC، تحافظ على معايير أمان عالية. وأخيراً، من خلال الالتزام بالإصدار الدلالي عبر علامات Git، توفر وضوحاً لمستخدميك حول استقرار برمجياتك.
ابدأ بتنفيذ هذا سير العمل على مشروع غير حرج. اختبره بإنشاء حزمة اختبار على TestPyPI قبل الدفع إلى المستودع الرئيسي. بمجرد أن يصبح خط الأنابيب الخاص بك مستقراً، ستجد أن إصدار الميزات الجديدة يصبح بسيطاً مثل وضع علامة على التزام (commit)، مما يتيح لك التركيز على كتابة الكود بدلاً من إدارة عمليات النشر.