الجزء 1: إعداد خط أنابيب CI/CD بسيط لـ Python وPyPI
نُشر في 17 July 2025
جدول المحتويات
مقدمة
الهدف : مرافقة القارئ في إعداد مسار CI/CD بسيط لكن وظيفي لتطبيق بايثون، مع نشر تلقائي على PyPI.
أصبحت أتمتة عمليات التطوير لا غنى عنها في المشاريع الحديثة. يتيح خط أنابيب CI/CD مصمم جيدًا ليس فقط اكتشاف التراجعات مبكرًا في دورة التطوير، بل أيضًا أتمتة عملية النشر بالكامل.
في هذه المقالة، سنستكشف كيفية إعداد مسار كامل باستخدام GitHub Actions لتطبيق بايثون، من التكامل المستمر (CI) إلى النشر المستمر (CD) على PyPI.
بنية الـPipeline
يتألف خط الأنابيب الخاص بنا من سيرتي عمل مختلفتين :
-
سلسلة CIيتم التنفيذ في كل push وpull request
-
خط أنابيب CD: يتم تشغيله فقط في إصدارات GitHub
@startuml
!theme plain
package "GitHub مستودع" {
[Source Code] as source
[GitHub Actions] as actions
}
package "خط أنابيب التكامل المستمر" {
[Checkout] as checkout_ci
[Setup Python] as python_ci
[Install Dependencies] as deps_ci
[Linting (Ruff)] as lint
[Unit Tests] as tests
}
package "خط أنابيب التسليم المستمر" {
[Checkout] as checkout_cd
[Setup Python] as python_cd
[Build Package] as build
[Publish to PyPI] as pypi
}
source --> actions : ادفع/PR
actions --> checkout_ci
checkout_ci --> python_ci
python_ci --> deps_ci
deps_ci --> lint
lint --> tests
source --> actions : إصدار
actions --> checkout_cd : عند الإصدار
checkout_cd --> python_cd
python_cd --> build
build --> pypi
@enduml
إعداد خط أنابيب التكامل المستمر (CI)
هيكل سير عمل التكامل المستمر
تم تصميم سير عمل CI لتحقق كل مساهمة في الكود. إليك إعداده الكامل :
name: CI/CD Pipeline
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
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 -r requirements.txt
pip install ruff pytest pytest-mock
- name: Run Linting (Ruff)
run: ruff check .
- name: Run Tests (Pytest)
run: pytest
تحليل مراحل CI
المُحفِّزات (on)
----
----
on:
push:
branches:
- main
pull_request:
branches:
- main
----
يُشغَّل الـpipeline عند : - كل دفع على الفرع`main` - كل طلب سحب نحو`main`
هذه المنهجية تضمن أن يظل الكود الرئيسي مستقرًا وأن يتم التحقق من أي مساهمة قبل دمجهما.
==== بيئة التنفيذ
----
runs-on: ubuntu-latest
أوبنتو لايتس يقدم توازنًا جيدًا بين الأداء، التكلفة، والتوافق لمعظم مشروعات بايثون
==== 3. سحب الكود
```yaml
----
----
- name: Checkout code
uses: actions/checkout@v4
----
الإجراء`checkout@v4`يسترجع كود المصدر من المستودع. الإصدار v4 يجلب تحسينات في الأداء والأمان.
==== 4. التكوين بايثون
----
- name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.x'
استخدام`'3.x'`permet باستخدام التحديث التلقائي لأحدث نسخة مستقرة من بايثون 3، مما يبسط الصيانة.
==== 5. تثبيت التبعيات
```yaml
----
----
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install ruff pytest pytest-mock
----
هذه الخطوة : - تحديث pip إلى أحدث نسخة - قم بتثبيت تبعيات المشروع - أضف أدوات التطوير (التدقيق والاختبارات)
==== 6. فحص الكود مع Ruff
----
- name: Run Linting (Ruff) run: ruff check .
**Ruff**هو مدقق Python سريع للغاية مكتوب بلغة Rust. يجمع ميزات عدة أدوات (Flake8, Black, isort) في أداة واحدة عالية الأداء.
==== 7. تنفيذ الاختبارات
```yaml
----
----
- name: Run Tests (Pytest)
run: pytest
----
يقوم Pytest بتنفيذ مجموعة الاختبار بالكامل، مما يضمن أن التعديلات لا تسبب تراجعات.
== إعداد مسار النشر (CD)
=== هيكل سير عمل CD
يتم تشغيل سير العمل CD فقط عند الإصدارات في جيت هاب، ويؤتمت عملية النشر إلى PyPI :
[source,yaml]
----
name: Publish to PyPI
on:
release:
types:
- published
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
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 setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
----
=== تحليل المراحل CD
==== مشغل الإصدار
----
on: release: types: - published
لا يتم تشغيل خط أنابيب التسليم المستمر (CD) إلا عند نشر إصدار جيت هب. يضمن هذا النهج تحكمًا دقيقًا في عمليات النشر.
==== 2. تثبيت أدوات البناء
```yaml
----
----
pip install setuptools wheel twine
----
- **setuptools**أدوات حزم بايثون - **عجلة**: تنسيق توزيع بايثون حديث - **خيط**أداة آمنة لتحميل إلى PyPI
==== 3. تكوين المصادقة
----
env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
المصادقة تستخدم توكن API PyPI مخزّنًا كسِرٍّ في GitHub، وهو أكثر أمانًا من بيانات الاعتماد التقليدية.
==== 4. البناء والنشر
```yaml
----
----
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
----
- `sdist`: أنشئ توزيعًا مصدريًا - `bdist_wheel`أنشئ عجلة (توزيع ثنائي) - `twine upload`: ينشر التوزيعات على PyPI
== إعداد حزمة بايثون
=== بنية setup.py
لكي يعمل الـpipeline، يجب أن يحتوي مشروعك على ملفًا`setup.py`:
[source,python]
----
from setuptools import setup, find_packages
with open("README.adoc", "r", encoding="utf-8") as fh:
long_description = fh.read()
setup(
name="playlist-downloader",
version="1.0.0",
author="Votre Nom",
author_email="[email protected]",
description="CLI tool for managing YouTube playlists",
long_description=long_description,
long_description_content_type="text/plain",
url="https://github.com/cheroliv/playlist-downloader",
packages=find_packages(),
classifiers=[
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
],
python_requires=">=3.8",
install_requires=[
"typer>=0.9.0",
"yt-dlp>=2023.1.6",
"google-api-python-client>=2.70.0",
"google-auth-oauthlib>=0.7.1",
"pymonad>=2.4.0",
"pyyaml>=6.0",
],
entry_points={
"console_scripts": [
"playlist-downloader=cli:app",
],
},
)
----
=== النقاط الأساسية لملف setup.py
1. **بيانات تعريفية**الاسم, الإصدار, المؤلف, الوصف
2. **الاعتماديات**قائمة الحزم المطلوبة
3. **نقاط الدخول**الأوامر CLI المعروضة
4. **المصنفات**: بيانات تعريفية لـ PyPI
== التأمين باستخدام أسرار GitHub
=== إعداد توكن PyPI
1. **إنشاء رمز API على PyPI** :
- قم بتسجيل الدخول إلى PyPI انتقل إلى إعدادات الحساب > رموز API - أنشئ رمزًا جديدًا مع الأذونات المناسبة
1. **إضافة السر في GitHub**:
- إعدادات المستودع > الأسرار والمتغيرات > إجراءات - أنشئ سرًا جديدًا باسم`PYPI_API_TOKEN` لصق رمز PyPI الخاص بك
[plantuml, secrets-flow, svg]
----
@startuml
!theme plain
actor Developer as dev
participant "GitHub مستودع" as repo
participant "GitHub إجراءات" as actions
participant PyPI
dev -> repo : ضبط السر PYPI_API_TOKEN
repo -> actions : تشغيل CD pipeline عند الإصدار
actions -> actions : الوصول إلى السر بأمان
actions -> PyPI : مصادقة باستخدام الرمز
PyPI -> PyPI : تحقق من الحزمة وانشرها
note over actions, PyPI
الرمز لا يُكشف أبداً في السجلات
التدوير التلقائي ممكن
end note
@enduml
----
== سير عمل النشر الكامل
=== سلسلة النشر
[plantuml, deployment-sequence, svg]
----
@startuml
!theme plain
actor Developer as dev
participant "Git محلي" as git
participant "GitHub" as github
participant "GitHub الإجراءات" as actions
participant PyPI
participant "المستخدمون النهائيون" as users
dev -> git : git tag v1.0.0
dev -> git : git push origin v1.0.0
git -> github : دفع العلامة
dev -> github : إنشاء إصدار من الوسم
github -> actions : تشغيل خط أنابيب CD
actions -> actions : كود الدفع
actions -> actions : إعداد بيئة بايثون
actions -> actions : تثبيت أدوات البناء
actions -> actions : بناء التوزيعات (sdist + wheel)
actions -> PyPI : ارفع إلى PyPI مع الرمز
PyPI -> PyPI : تحقق ونشر
users -> PyPI : pip تثبيت playlist-downloader
note over dev, github
يمكن أتمتة إنشاء الإصدارات
أو يتم إجراؤه يدويًا عبر واجهة GitHub
end note
@enduml
----
=== États du Pipeline
[plantuml, pipeline-states, svg]
----
@startuml
!theme plain
[*] --> Idle
Idle --> CI_Running : Push/PR تم الإنشاء
CI_Running --> CI_Success : كل الاختبارات ناجحة
CI_Running --> CI_Failed : Linting/Tests فشل
CI_Success --> Idle : الدمج مكتمل
CI_Failed --> Idle : أصلح وأعد المحاولة
Idle --> CD_Running : الإصدار المنشور
CD_Running --> CD_Success : تم نشر الحزمة
CD_Running --> CD_Failed : بناء/Upload خطأ
CD_Success --> Idle : الحزمة متوفرة على PyPI
CD_Failed --> Idle : إصلاح وإعادة المحاولة للإصدار
note on link #red : تندمج الكتل
note on link #green : يسمح بالنشر
@enduml
----
== الممارسات الجيدة والتحسينات
=== إدارة الإصدارات
استخدم وسوم Git دلالية :
----
git tag -a v1.2.3 -m "Release version 1.2.3" git push origin v1.2.3
=== اختبارات المصفوفة
لاختبار على عدة إصدارات بايثون:
```yaml
----
----
strategy:
matrix:
python-version: [3.8, 3.9, "3.10", "3.11"]
----
=== 3. ذاكرة التخزين المؤقت للاعتماديات
سرّع عمليات البناء باستخدام التخزين المؤقت:
----
- name: Cache pip dependencies uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
=== بيئات النشر
استخدم بيئات GitHub للنشر المتحكم فيه:
```yaml
----
----
jobs:
deploy:
environment: production
runs-on: ubuntu-latest
----
== حالة الاستخدام والهندسة المعمارية
=== مخطط حالة الاستخدام
[plantuml, use-cases, svg]
----
@startuml
!theme plain
left to right direction
actor "مطور" as dev
actor "GitHub الإجراءات" as ga
actor "مستخدم نهائي" as user
package "CI/CD نظام" {
usecase "تشغيل الفحص" as lint
usecase "تنفيذ الاختبارات" as test
usecase "بناء الحزمة" as build
usecase "نشر إلى PyPI" as publish
usecase "إنشاء إصدار" as release
}
dev --> lint : يدفع الكود
dev --> test : يدفع الكود
dev --> release : يُنشر إصدار
ga --> build : عند تحرير الزناد
ga --> publish : بعد بناء ناجح
user --> publish : تنزيل الحزمة
lint .> test : triggers
test .> build : on success
build .> publish : on success
@enduml
----
=== معمارية النشر
[plantuml, deployment-architecture, svg]
----
@startuml
!theme plain
cloud "GitHub" {
[Source Repository]
[GitHub Actions]
[Secrets Store]
}
cloud "PyPI" {
[Package Registry]
[Distribution Files]
}
node "CI/CD خط أنابيب" {
[Linting]
[Testing]
[Building]
[Publishing]
}
[Source Repository] --> [GitHub Actions] : Triggers
[GitHub Actions] --> [Linting]
[Linting] --> [Testing]
[Testing] --> [Building]
[Building] --> [Publishing]
[Publishing] --> [Package Registry] : Uploads
[Secrets Store] --> [Publishing] : Provides token
note as N1
مصادقة آمنة تعتمد على الرموز
end note
[Secrets Store] .. N1
@enduml
----
== المراقبة والتصحيح
=== السجلات والرصد
يوفر GitHub Actions سجلات مفصلة لكل خطوة. للتصحيح :
1. **افحص السجلات**من كل خطوة
2. **فعّل التصحيح**مع`ACTIONS_STEP_DEBUG`
3. **استخدم القطع الأثرية**لحفظ ملفات البناء
----
- name: Upload build artifacts uses: actions/upload-artifact@v3 if: failure() with: name: build-logs path: build/
=== إشعارات
أضف إشعارات Slack أو بريد إلكتروني :
```yaml
----
----
- name: Notify on failure
if: failure()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
----
== الاستنتاج
إعداد خط أنابيب CI/CD قوي باستخدام GitHub Actions يغير تجربة التطوير بشكل جذري. من خلال أتمتة الفحص الثابت، والاختبارات والنشر، أنت :
- **قلل الأخطاء**قيد الإنتاج - **سرّعوا الدورات**من التطوير - **حسّنوا الثقة**في إصداراتكم - **سَهّلو التعاون**في فريق
يمكن تعديل هذا pipeline ليتوافق مع مختلف أنواع مشروعات بايثون عن طريق تعديل أدوات اللينط، أطر عمل الاختبار، أو وجهات النشر.
الاستثمار الأولي في إعداد هذه العمليات يتم استرداده بسرعة بفضل توفير الوقت وتقليل الأخطاء اليدوية أثناء النشر.
== مصادر إضافية
- https://docs.github.com/en/actions[توثيق GitHub Actions] - https://packaging.python.org/[دليل تغليف بايثون] - https://docs.pytest.org/[توثيق Pytest] - https://docs.astral.sh/ruff/[توثيق Ruff] - https://twine.readthedocs.io/[توثيق تاوين]
تم الوصول إلى خط أنابيب وظيفي ! الآن لديك خط أنابيب CI/CD بسيط يسمح لك بأتمتة اختباراتك ونشر حزمة Python الخاصة بك على PyPI مباشرةً من GitHub Actions.
ومع ذلك، يظل هذا الخط الأنبوبي مقصودًا أن يكون بسيطًا. لا يغطي بعد بعض الجوانب الأساسية في سياق احترافي:
اختبارات الإصدارات المتعددة من بايثون،
تحليل الأمان التلقائي،
النشر التدريجي عبر اختبار PyPI،
مراقبة ومقاييس خط الأنابيب
أتمتة الإصدار ودمج الممارسات الجيدة الحديثة (pyproject.toml).
في الجزء التالي، سننتقل إلى المستوى الأعلى. ستتعلم تحويل هذا الخط الأساسي إلى سلسلة توزيع صناعية حقيقية، قوية وآمنة، جاهزة لمشاريع بايثون للإنتاج.
----