بخش ۱: راهاندازی یک پایپلاین CI/CD ساده برای Python و PyPI
منتشر شده در 17 July 2025
Sommaire
مقدمه
Objectif : همراه کردن خواننده در راهاندازی یک پایپلاین CI/CD Minimalist ولی کارآمد برای یک برنامه پایتون، با استقرار خودکار روی PyPI.
اتوماسیون فرآیندهای توسعه در پروژههای مدرن ضروری شده است. یک لولهخط CI/CD بهتر طراحیشده نه تنها به تشخیص زودهنگام رگرسیونها در چرخه توسعه کمک میکند، بلکه بهطور کامل فرآیند استقرار را اتوماتیک میکند.
در این مقاله، ما میخواهیم بررسی کنیم که چگونه یک خط لوله کامل با GitHub Actions برای یک برنامه Python تنظیم شود، از ادغام مداوم (CI) تا استقرار مداوم (CD) روی PyPI.
معماری پایپ لاین
پایپ لاین ما از دو workflow متمایز تشکیل میشود :
-
خط لوله CI: انجام شده در هر push و pull request
-
خط لوله CD: فقط در رleases GitHubtrigger
@startuml
!theme plain
package "گیتهاب مخزن" {
[Source Code] as source
[GitHub Actions] as actions
}
package "پایپلاین CI" {
[Checkout] as checkout_ci
[Setup Python] as python_ci
[Install Dependencies] as deps_ci
[Linting (Ruff)] as lint
[Unit Tests] as tests
}
package "خط لوله CD" {
[Checkout] as checkout_cd
[Setup Python] as python_cd
[Build Package] as build
[Publish to PyPI] as pypi
}
source --> actions : Push/PR
actions --> checkout_ci
checkout_ci --> python_ci
python_ci --> deps_ci
deps_ci --> lint
lint --> tests
source --> actions : Release
actions --> checkout_cd : On Release
checkout_cd --> python_cd
python_cd --> build
build --> pypi
@enduml
پیکربندی خط لوله یکپارچگی مستمر (CI)
ساختار Workflow CI
Workflow 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
1. тригер (on)
----
----
on:
push:
branches:
- main
pull_request:
branches:
- main
----
پالاین بر حسب : - هر push روی شاخه`main` - هر pull request به`main`
این رویکرد تضمین میکند که کد اصلی پایدار بماند و هر گونه مشارکت قبل از ادغام تأیید شود.
==== 2. محیط اجرا
----
runs-on: ubuntu-latest
Ubuntu Latest یک توازن مناسب بین عملکرد، هزینه و سازگاری برای اکثر پروژههای پایتون ارائه میدهد.
==== 3. checkout کد
```yaml
----
----
- name: Checkout code
uses: actions/checkout@v4
----
عمل`checkout@v4`کد منبع/repository را دریافت میکند. نسخه v4 بهبودهای عملکرد و امنیت را به ارمغان میآورد.
==== 4. پیکربندی پایتون
----
- name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.x'
استفاده از`'3.x'`اجازه میدهد بهطور خودکار از آخرین نسخه پایدار Python 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 را به آخرین نسخه بهروزرسانی کنید - وابستگیهای پروژه را نصب کنید - ابزارهای توسعه (linting و tests) را اضافه کن
==== 6. بررسی با Ruff
----
- name: Run Linting (Ruff) run: ruff check .
**Ruff**یک linter پایتون فوقالعاده سریع است که به زبان Rust نوشته شده؛ این ابزار ویژگیهای چندین ابزار (Flake8, Black, isort) را در یک ابزار کارآمد ترکیب میکند.
==== 7. اجرای تستها
```yaml
----
----
- name: Run Tests (Pytest)
run: pytest
----
Pytest کل مجموعة تستها را اجرا میکند، تا اطمینان حاصل شود که تغییرات هیچ نوع ریگرسیون (بازگشت)ی وارد نکنند.
== پیکربندی پایپلاین استقرار (CD)
=== ساختار workflow CD
Workflow CD فقط هنگام ریلیزهای GitHub اجرا میشود و انتشار را روی 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 تنها هنگام انتشار یک رلیز GitHub فعال میشود. این رویکرد کنترل دقیق بر استقرارها را تضمین میکند.
==== 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`: ایجاد یک wheel (توزیع باینری) - `twine upload`: منتشر کردن توزیعها روی PyPI
== تنظیم پیکج پایتون
=== ساختار setup.py
برای اینکه پایپلاین کار کند، پروژه شما باید شامل یک فایل باشد.`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 Secrets
=== تنظیم توکن PyPI
1. **ایجاد توکن API در PyPI**:
- به PyPI وارد شوید - به Account Settings > API tokens بروید - ایجاد یک توکن جدید با مجوزهای مناسب
1. **افزودن رمز در GitHub**:
- تنظیمات مخزن > رازها و متغیرها > عملیات - یک رمز جدید با نام`PYPI_API_TOKEN` - توکن PyPI خود را جایگذاری کنید
[plantuml, secrets-flow, svg]
----
@startuml
!theme plain
actor Developer as dev
participant "مخزن گیتهاب" as repo
participant "عملیات گیتهاب" as actions
participant PyPI
dev -> repo : Configure PYPI_API_TOKEN secret
repo -> actions : Trigger CD pipeline on release
actions -> actions : Access secret securely
actions -> PyPI : Authenticate with token
PyPI -> PyPI : Validate and publish package
note over actions, PyPI
Token never exposed in logs
Automatic rotation possible
end note
@enduml
----
== فرآیند کامل استقرار
=== روند استقرار
[plantuml, deployment-sequence, svg]
----
@startuml
!theme plain
actor Developer as dev
participant "گیت محلی" as git
participant "گیتهاب" as github
participant "GitHub Actions" as actions
participant PyPI
participant "کاربران نهایی" as users
dev -> git : git tag v1.0.0
dev -> git : git push origin v1.0.0
git -> github : Push tag
dev -> github : Create release from tag
github -> actions : Trigger CD pipeline
actions -> actions : Checkout code
actions -> actions : Setup Python environment
actions -> actions : Install build tools
actions -> actions : Build distributions (sdist + wheel)
actions -> PyPI : Upload to PyPI with token
PyPI -> PyPI : Validate and publish
users -> PyPI : pip install playlist-downloader
note over dev, github
Release creation can be automated
or done manually through GitHub UI
end note
@enduml
----
=== وضعیت پایپلاین
[plantuml, pipeline-states, svg]
----
@startuml
!theme plain
[*] --> Idle
Idle --> CI_Running : Push/PR created
CI_Running --> CI_Success : All checks pass
CI_Running --> CI_Failed : Linting/Tests fail
CI_Success --> Idle : Merge completed
CI_Failed --> Idle : Fix and retry
Idle --> CD_Running : Release published
CD_Running --> CD_Success : Package published
CD_Running --> CD_Failed : Build/Upload error
CD_Success --> Idle : Package available on PyPI
CD_Failed --> Idle : Fix and retry release
note on link #red : Blocks merge
note on link #green : Allows deployment
@enduml
----
== بهترین روشها و بهینهسازیها
=== 1. مدیریت نسخهها
برچسبهای Git معنادار را استفاده کنید :
----
git tag -a v1.2.3 -m "Release version 1.2.3" git push origin v1.2.3
=== 2. تستهای ماتریس
برای تست روی چندین نسخه پایتون :
```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') }}
=== 4. محیطهای استقرار
از محیطهای 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 "Linting را اجرا کن" as lint
usecase "اجرای تستها" as test
usecase "بسته ساخت" as build
usecase "منتشر کنید در PyPI" as publish
usecase "ایجاد انتشار" as release
}
dev --> lint : Pushes code
dev --> test : Pushes code
dev --> release : Creates release
ga --> build : On release trigger
ga --> publish : After successful build
user --> publish : Downloads package
lint .> test : triggers
test .> build : on success
build .> publish : on success
@enduml
----
=== معمارای استقرار
[plantuml, deployment-architecture, svg]
----
@startuml
!theme plain
cloud "گیتهاب" {
[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
Secure token-based
authentication
end note
[Secrets Store] .. N1
@enduml
----
== نظارت و اشکالزدایی
=== لاگها و مانیتورینگ
GitHub Actions لاگهای تفصیلی برای هر مرحله ارائه میدهد. برای دیباگ:
1. **لاگها را بررسی کنید**هر مرحله
2. **debug را فعال کنید**با`ACTIONS_STEP_DEBUG`
3. **از artifacts استفاده کنید**برای ذخیره کردن فایلهای بیلد
----
- 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، تجربه توسعه را بهطور اساسی تغییر میدهد. با خودکارسازی لنتینگ، تستها و استقرار، شما :
- **خطاها را کاهش دهید**در تولید - **دورها را شتاب دهید**توسعه - **اعتماد را بهبود بخشید**در ریلیزهای شما - **همکاری را تسهیل کنید**به صورت تیم
این پایپلین میتواند برای انواع مختلف پروژههای پایتون با تنظیم ابزارهای لنتینگ، چارچوبهای تست یا مقصدهای استقرار، تنظیم شود.
سرمایهگذاری اولیه در تنظیم این گردشهای کار به سرعت از طریق صرفهجویی در زمان و کاهش خطاهای دستی در حین استقرارها بازگردانده میشود.
== منابع تکمیلی
- 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/[مستندات Twine]
✅ لاینپایین عملکردی دست یافت ! اکنون شما یک pipeline CI/CD ساده دارید که امکان خودکارسازی تستها و انتشار بسته Python شما در PyPI مستقیماً از GitHub Actions را فراهم میکند.
با این حال، این pipeline بهطور عمدی به حداقل حد ممکن باقی مانده است. هنوز برخی از جنبههای ضروری در یک بافت حرفهای را پوشش نمیدهد :
تستهای چند نسخه پایتون،
تحلیل خودکار امنیتی،
استقرار تدریجی از طریق Test PyPI,
نظارت و متریکهای لوله،
اتوماسیون نسخهبندی و ادغام روشهای خوب مدرن (pyproject.toml).
در بخش بعدی، به سطح بالاتر خواهیم رفت. شما یاد خواهید گرفت تا این پایپلاین پایه را به یک زنجیره استقرار صنعتی واقعی، قوی و ایمن، آماده برای پروژههای Python تولیدی تبدیل کنید.
----