Giriş

Amaç : Okuyucuya, bir Python uygulaması için minimalist ancak işlevsel bir CI/CD hattının kurulumunu göstererek ve aynı zamanda PyPI’ye otomatik dağıtım yaparak eşlik eder.

Geliştirme süreçlerinin otomasyonu modern projelerde kaçınılmaz hale gelmiştir. İyi tasarlanmış bir CI/CD borusu, sadece geliştirme döngüsünün erken aşamasında regresyonları tespit etmekle kalmaz, aynı zamanda dağıtım sürecinin tamamen otomatize edilmesini de sağlar.

Bu makalede, bir Python uygulaması için GitHub Actions kullanarak tam bir CI/CD pipeline oluşturma sürecini, sürekli entegrasyondan (CI) PyPI üzerindeki sürekli dağıtıma (CD) kadar inceleyeceğiz.

Pipeline Mimarisi

Pipeline’ımız iki ayrı workflow’tan oluşur :

  1. CI Hattı: Her push ve pull request’te çalıştırılır

  2. CD Pipeline: Sadece GitHub yayınları sırasında tetiklenir.

@startuml
!theme plain

package "GitHub Depo" {
  [Source Code] as source
  [GitHub Actions] as actions
}

package "CI İşlem Hattı" {
  [Checkout] as checkout_ci
  [Setup Python] as python_ci
  [Install Dependencies] as deps_ci
  [Linting (Ruff)] as lint
  [Unit Tests] as tests
}

package "CD İşlem Hattı" {
  [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 : Yayın
actions --> checkout_cd : Yayımda
checkout_cd --> python_cd
python_cd --> build
build --> pypi

@enduml

(CI) Sürekli Entegrasyon İşlem Hattı Yapılandırması

CI İş Akışı Yapısı

CI iş akışı, kod üzerindeki her katkısıyı doğrulamak için tasarlanmıştır. İşte tam konfigürasyonu:

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 Aşamaları Analizi

Tetikleyiciler (on)

----
on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
----

Boruhattı tetiklenir : Dal üzerindeki her push`main` - Her bir pull request doğrultusunda`main`

Bu yaklaşım, ana kodun stabil kalmasını sağlar ve tüm katkılar entegrasyon öncesi onaylanır.

==== Çalıştırma Ortamı

```yaml
----
runs-on: ubuntu-latest
----

Ubuntu Latest, çoğu Python projesi için performans, maliyet ve uyumluluk arasında iyi bir denge sunar.

==== Kodun Checkoutu

```yaml
----
- name: Checkout code
  uses: actions/checkout@v4
----

Eylem`checkout@v4`depo kaynak kodunu alır. v4 sürümü performans ve güvenlik iyileştirmeleri getirir.

==== 4. Python yapılandırması

```yaml
----
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: '3.x'
----

Kullanımı`'3.x'`Python 3'in en güncel kararlı sürümünü otomatik olarak kullanmasını sağlayarak bakımı basitleştirir.

==== 5. Bağımlılıkların Yüklenmesi

```yaml
----
- name: Install dependencies
  run: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt
    pip install ruff pytest pytest-mock
----

Bu adım: - Pip'i son sürüme güncellendi Proje bağımlılıklarını yükle - Geliştirme araçlarını ekle (linting ve testler)

==== 6. Ruff ile linting

```yaml
----
- name: Run Linting (Ruff)
  run: ruff check .
----

**Ruff**Python için ultra hızlı bir Rust tabanlı linterdır. Birden fazla araç (Flake8, Black, isort)'ün işlevselliğini tek performanslı bir araçta birleştirir.

==== 7. Testlerin yürütülmesi

```yaml
----
- name: Run Tests (Pytest)
  run: pytest
----

Pytest tüm test paketini çalıştırarak, değişikliklerin regresyon oluşturmayacağını garanti eder.

== Dağıtım iş hattı yapılandırması (CD)

=== CD İş Akışı Yapısı

CD iş akışı yalnızca GitHub sürümleri sırasında tetiklenir ve PyPI'de yayınlamayı otomatikleştirir :

[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 Aşamaları Analizi

==== 1. Serbest bırakma tetikleyicisi

```yaml
----
on:
  release:
    types:
      - published
----

CD ardışık hattı, yalnızca bir GitHub Yayını yayınlandığında tetiklenir. Bu yaklaşım dağıtımlar üzerinde hassas kontrol sağlar.

==== 2. Derleme Araçlarının Kurulumu

```yaml
----
pip install setuptools wheel twine
----

- **setuptools**Python paketleme araçları - **wheel**Modern Python dağıtım formatı - **iplik**PyPI'ye güvenli yükleme aracı

==== 3. Kimlik Doğrulama Yapılandırması

```yaml
----
env:
  TWINE_USERNAME: __token__
  TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
----

Kimlik doğrulama, bir GitHub gizli olarak saklanan PyPI API belirteci kullanır ve klasik kimlik bilgilerinden daha güvenlidir.

==== 4. Derleme ve Yayın

```yaml
----
run: |
  python setup.py sdist bdist_wheel
  twine upload dist/*
----

- `sdist`Kaynak dağılımı oluşturur - `bdist_wheel`Bir wheel (ikili dağıtım) oluştur - `twine upload`Dağıtımları PyPI'de yayınla

== Python Paketi Yapılandırması

=== setup.py'nin yapısı

Pipeline'ın çalışması için projeniz bir dosya içermelidir.`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'nin Önemli Noktaları

1. **Metadata**İsim, sürüm, yazar, açıklama
2. **Bağımlılıklar**Gerekli paketler listesi
3. **giriş noktaları**: Gösterilen CLI komutları
4. **sınıflandırıcılar**PyPI için meta veri

== GitHub Secret'leriyle güvenli bir yöntem

=== PyPI Belirteci Yapılandırması

1. **PyPI'de bir API jetonu oluştur** :

PyPI'ye giriş yapın - Hesap Ayarları > API belirteçlerine gidin - Uygun izinlere sahip yeni bir jeton oluşturun

1. **GitHub'da gizli bilgiyi ekleyin**:

- Depo Ayarları > Gizli bilgiler ve değişkenler > Actions Bir ad verilmiş yeni bir secret oluşturun`PYPI_API_TOKEN` - PyPI jetonunuzu yapıştır

[plantuml, secrets-flow, svg]
----
@startuml
!theme plain

actor Developer as dev
participant "GitHub Depo" as repo
participant "GitHub İşlemler" as actions
participant PyPI

dev -> repo : PYPI_API_TOKEN gizliyi yapılandır
repo -> actions : Yayın sırasında CD pipeline'ını tetiklemek
actions -> actions : Gizli bilgiye güvenli erişim
actions -> PyPI : Belirteçle kimlik doğrulama yap
PyPI -> PyPI : Paketi doğrula ve yayınla

note over actions, PyPI
Asla günlüklerde gösterilmez
Otomatik döndürme mümkün
end note

@enduml
----

== Tam Dağıtım İş Akışı

=== Dağıtım Sırası

[plantuml, deployment-sequence, svg]
----
@startuml
!theme plain

actor Developer as dev
participant "Yerel Git" as git
participant "GitHub" as github
participant "GitHub Eylemler" as actions
participant PyPI
participant "Son Kullanıcılar" as users

dev -> git : git tag v1.0.0
dev -> git : git push origin v1.0.0
git -> github : Push tag
dev -> github : Tag'den yayın oluştur
github -> actions : CD pipeline'ini tetikle
actions -> actions : Ödeme kodu
actions -> actions : Python ortamını kurun
actions -> actions : Derleme araçlarını kur
actions -> actions : Dağıtımları oluşturun (sdist + wheel)
actions -> PyPI : Jeton kullanarak PyPI'e yükleyin
PyPI -> PyPI : Doğrula ve Yayınla
users -> PyPI : pip install playlist-downloader

note over dev, github
Yayın oluşturma otomatize edilebilir
veya GitHub kullanıcı arayüzü üzerinden manuel olarak yapılabilir
end note

@enduml
----

=== Pipeline Durumları

[plantuml, pipeline-states, svg]
----
@startuml
!theme plain

[*] --> Idle

Idle --> CI_Running : Push/PR oluşturuldu
CI_Running --> CI_Success : Tüm kontroller başarılı olur
CI_Running --> CI_Failed : Linting/Tests başarısız
CI_Success --> Idle : Birleştirme tamamlandı
CI_Failed --> Idle : Düzelt ve yeniden dene

Idle --> CD_Running : Yayınlanmış sürüm
CD_Running --> CD_Success : Paket yayınlandı
CD_Running --> CD_Failed : Build/Upload hata
CD_Success --> Idle : PyPI üzerindeki paket
CD_Failed --> Idle : Düzelt, yeniden deneyin ve yayınlayın

note on link #red : Bloklar birleşir
note on link #green : Dağıtım izni verir

@enduml
----

== İyi Uygulamalar ve Optimizasyonlar

=== 1. Version Yönetimi

Semantik Git etiketlerini kullanın

```bash
----
git tag -a v1.2.3 -m "Release version 1.2.3"
git push origin v1.2.3
----

=== 2. Matris testleri

Birden fazla Python sürümünde test yapmak için :

```yaml
----
strategy:
  matrix:
    python-version: [3.8, 3.9, "3.10", "3.11"]
----

=== 3. Bağımlılık Önbelleği

Belleği kullanarak derlemeleri hızlandırın :

```yaml
----
- name: Cache pip dependencies
  uses: actions/cache@v3
  with:
    path: ~/.cache/pip
    key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
----

=== 4. Dağıtım Ortamları

Kontrollü dağıtımlar için GitHub ortamlarını kullanın :

```yaml
----
jobs:
  deploy:
    environment: production
    runs-on: ubuntu-latest
----

== Kullanım Durumları ve Mimari

=== Kullanım Durumu Diyagramı

[plantuml, use-cases, svg]
----
@startuml
!theme plain

left to right direction

actor "Developer" as dev
actor "GitHub Actions" as ga
actor "End User" as user

package "CI/CD System" {
  usecase "Run Linting" as lint
  usecase "Execute Tests" as test
  usecase "Build Package" as build
  usecase "Publish to PyPI" as publish
  usecase "Create Release" as release
}

dev --> lint : Kod gönderir
dev --> test : Kod gönderir
dev --> release : Bir sürüm oluşturur
ga --> build : Tetiği serbest bıraktığınızda
ga --> publish : Başarılı derleme sonrası
user --> publish : İndirme paketi

lint .> test : triggers
test .> build : on success
build .> publish : on success

@enduml
----

=== Dağıtım Mimarisi

[plantuml, deployment-architecture, svg]
----
@startuml
!theme plain

cloud "GitHub" {
  [Source Repository]
  [GitHub Actions]
  [Secrets Store]
}

cloud "PyPI" {
  [Package Registry]
  [Distribution Files]
}

node "CI/CD Boru hattı" {
  [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
Güvenli jeton tabanlı kimlik doğrulama
end note

[Secrets Store] .. N1

@enduml
----

== İzleme ve Hata Ayıklama

=== Loglar ve İzleme

GitHub Actions her adım için ayrıntılı loglar sağlar. Hata ayıklama için:

1. **Logları inceleyin**her adımın
2. **Debug modunu etkinleştirin**ile`ACTIONS_STEP_DEBUG`
3. **Artifact'leri kullanın**derinleme dosyalarını yedeklemek için

```yaml
----
- name: Upload build artifacts
  uses: actions/upload-artifact@v3
  if: failure()
  with:
    name: build-logs
    path: build/
----

=== Bildirimler

Slack veya e-posta bildirimleri ekleyin

```yaml
----
- name: Notify on failure
  if: failure()
  uses: 8398a7/action-slack@v3
  with:
    status: ${{ job.status }}
    webhook_url: ${{ secrets.SLACK_WEBHOOK }}
----

== Sonuç

GitHub Actions ile sağlam bir CI/CD işlem hattı oluşturmak, geliştirme deneyiminizi kökten değiştirir. Linting, testleri ve dağıtımı otomatikleştirdiğinizde, siz:

- **Hataları azaltın**Üretimde - **Döngüleri hızlandırın**gelişim - **Güveni artırın**sürümlerinizde - **İşbirliğini kolaylaştırın**ekip olarak

Bu ardışık düzen, linting araçları, test çerçeveleri veya dağıtım hedeflerini ayarlayarak çeşitli tipteki Python projelerine uyarlanabilir.

Bu iş akışlarının yapılandırmasındaki başlangıç yatırımı, zaman tasarrufu ve dağıtımlar sırasında manuel hataların azalması sayesinde hızla geri döner.

== Ek Kaynaklar

- https://docs.github.com/en/actions[GitHub Actions Belgeleri] - https://packaging.python.org/[Python Paketleme Kılavuzu] - https://docs.pytest.org/[Pytest Dokümantasyonu] - https://docs.astral.sh/ruff/[Ruff Dokümantasyonu] - https://twine.readthedocs.io/[Twine Belgeleri]

Bir işlevsel pipeline başarıyla ulaşıldı ! Şimdi, testlerinizi otomatikleştirebileceğiniz ve Python paketinizi PyPI'de doğrudan GitHub Actions üzerinden yayınlayabilmenize olanak tanıyan basit bir CI/CD pipeline'a sahipsiniz.

Ancak, bu pipeline istenerek minimalist tutulmaktadır. Henüz profesyonel bir bağlamda gerekli olan bazı yönleri hâlâ kapsamıyor:

Python'un çoklu sürüm testleri,

Otomatik güvenlik analizi,

Test PyPI üzerinden aşamalı dağıtım,

İşlem hattı izleme ve ölçümleri,

Versiyonlama otomasyonu ve modern iyi uygulamaların entegrasyonu (pyproject.toml).

Bir sonraki bölümde, seviyeyi bir yukarı taşıyacağız. Bu temel pipeline'ı, üretim için hazır, sağlam ve güvenli gerçek bir endüstriyel dağıtım zincirine dönüştürmeyi öğreneceksiniz.

İlgili Makaleler