مقدمه

Objectif : همراه کردن خواننده در راه‌اندازی یک پایپ‌لاین CI/CD Minimalist ولی کارآمد برای یک برنامه پایتون، با استقرار خودکار روی PyPI.

اتوماسیون فرآیندهای توسعه در پروژه‌های مدرن ضروری شده است. یک لوله‌خط CI/CD بهتر طراحی‌شده نه تنها به تشخیص زودهنگام رگرسیون‌ها در چرخه توسعه کمک می‌کند، بلکه به‌طور کامل فرآیند استقرار را اتوماتیک می‌کند.

در این مقاله، ما می‌خواهیم بررسی کنیم که چگونه یک خط لوله کامل با GitHub Actions برای یک برنامه Python تنظیم شود، از ادغام مداوم (CI) تا استقرار مداوم (CD) روی PyPI.

معماری پایپ لاین

پایپ لاین ما از دو workflow متمایز تشکیل می‌شود :

  1. خط لوله CI: انجام شده در هر push و pull request

  2. خط لوله 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 تولیدی تبدیل کنید.
----

مقالات مرتبط