Εισαγωγή

Σκοπός : Να βοηθήσει τον αναγνώστη στην υλοποίηση ενός ελάχιστου αλλά funzionικού pipeline CI/CD για μια εφαρμογή Python, με αυτόματη ανάπτυξη στο PyPI.

Ένας καλά σχεδιασμένος pipeline CI/CD επιτρέπει όχι μόνο την νωρίς ανίχνευση αναλλοίωσης στο κύκλο ανάπτυξης, αλλά και την πλήρης αυτοματοποίηση της διαδικασίας ανάπτυξης.

Σε αυτό το άρθρο, θα εξερευνήσουμε πώς να ρυθμίσουμε ένα πλήρες pipeline με GitHub Actions για μια εφαρμογή Python, από τη συνεχή ενσωμάτωση (CI) έως τη συνεχή ανάπτυξη (CD) στο PyPI.

Αρχιτεκτονική του Pipeline

Το pipeline μας αποτελείται από δύο διαφορετικούς workflows:

  1. διαδικασία CI: Εκτελείται σε κάθε push και pull request

  2. διαδικασία CDΕνεργοποιείται μόνο κατά τις εκδόσεις GitHub

ci cd overview

Διαμόρφωση του Pipeline της Συνεχούς Ενσωμάτωσης (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

Ενεργοποιητές (on)

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

Ο pipeline ενεργοποιείται σε : - Κάθε push στον κλάδο`main` - Κάθε pull request pros`main`

Αυτή η προσέγγιση εγγυάται ότι ο κύριος κώδικας παραμένει σταθερός και ότι κάθε συνεισφορά εγκρίνεται πριν την ενσωμάτωση.

==== 2. Περιβάλλον Εκτέλεσης

----

runs-on: ubuntu-latest

Η Ubuntu Latest προσφέρει μια καλή ισορροπία μεταξύ απόδοσης, κόστους και συμβατότητας για τα περισσότερα έργα Python.

==== 3. Έλεγχος κώδικα

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

Η δράση`checkout@v4`Ανακτά τον πηγαίο κώδικα του αποθετηρίου. Η έκδοση v4 προσφέρει βελτιώσεις στην απόδοση και την ασφάλεια.

==== 4. Ρύθμιση Python

----

- 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 και δοκιμές)

==== 6. Έλεγχος κώδικα με Ruff

----

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

**Ruff**είναι ένας υπερ-γρήγορος linter Python γραμμένος σε 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**Εργαλεία πακέτων Python - **τροχός**: Σύγχρονη μορφή διανομής Python - **σπίγκο**: Ασφαλές εργαλείο για ανέβασμα στο PyPI

==== 3. Ρύθμιση αυθεντικοποίησης

----

env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}

Η έλεγχος ταυτότητας χρησιμοποιεί το token API PyPI που αποθηκεύεται ως secret GitHub, πιο ασφαλές από τα κλασικά διαπιστευτήρια.

==== 4. Κατασκευή και Δημοσίευση

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

- `sdist`: Δημιούργησε μια διανομή πηγής - `bdist_wheel`: Δημιουργεί ένα wheel (δυαδική διανομή) - `twine upload`: Δημοσίευσε τις διανομές στο PyPI

== Διαμόρφωση του πακέτου Python

=== Δομή του 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 Secrets

=== Ρυθμίσεις του Token PyPI

1. **Δημιουργήστε ένα API token στο PyPI**:

- Συνδεθείτε στο PyPI - Πηγαίτε στο Account Settings > API tokens - Δημιουργήστε ένα νέο token με τις κατάλληLES δικαιώματα

1. **Προσθέστε το μυστικό στο GitHub**:

- Ρυθμίσεις αποθετήριου > Μυστικά και μεταβλητές > Actions - Δημιουργήστε ένα νέο κρυφό που ονομάζεται`PYPI_API_TOKEN` - Επικολλήστε το token σας PyPI

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

actor Developer as dev
participant "GitHub αποθήκη" as repo
participant "GitHub Actions" 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
----

== Ολοκληρό Workflow ανάπτυξης

=== Ακολουθία Ανάπτυξης

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

actor Developer as dev
participant "Τοπικό Git" as git
participant "GitHub" 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
----

=== οι καταστάσεις του pipeline

[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
----

== Καλές πρακτικές και βελτιστοποιήσεις

=== </think>

Διαχείριση Εκδόσεων

Χρησιμοποιείτε σημαντικές ετικέτες Git

----

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

=== 2. Δοκιμές πίνακα

Για να δοκιμάσετε σε πολλές εκδόσεις του Python:

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

=== 3. Cache εξαρτήσεων

Επιταχύστε τις κατασκευές με το caché:

----

- 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 Actions" 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 "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
  Secure token-based
  authentication
end note

[Secrets Store] .. N1

@enduml
----

== Παρακολούθηση και Debugging

=== Καταγραφές και Παρακολούθηση

GitHub Actions παρέχει λεπτομερείς καταγραφές για κάθε βήμα. Για debugging:

1. **Εξετάστε τα logs**κάθε βήμα
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 ή email :

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

== Συμπέρασμα

Η ρύθμιση ενός αξιόπιστου pipeline CI/CD με GitHub Actions μεταμορφώνει ριζικά την εμπειρία ανάπτυξης. Με την αυτοματοποίηση του linting, των τεστ και του ανάπτυξης, εσείς :

- **Μειώστε τα σφάλματα**σε παραγωγή - **Επιταχύνετε τους κύκλους**ανάπτυξης - **Βελτιώστε την εμπιστοσύνη**σε τις εκδόσεις σας - **Ευκολείτε τη συνεργασία**σε ομάδα

Αυτό το pipeline μπορεί να προσαρμοστεί σε διάφορους τύπους Python projects προσαρμόζοντας τα εργαλεία linting, τα frameworks testing ή τους προορισμούς ανάπτυξης.

Η αρχική επένδυση στη ρύθμιση αυτών των ροών εργασίας αποδωθεί γρήγορα από την εξοικονόμηση χρόνου και τη μείωση των χειροκίνητων σφαλμάτων κατά τα αναπτύξεις.

== Πρόσθετοι Πόροι

- https://docs.github.com/en/actions[Τεκμηρίωση GitHub Actions] - https://packaging.python.org/[Οδηγός συσκευασίας Python] - https://docs.pytest.org/[Τεκμηρίωση Pytest] - https://docs.astral.sh/ruff/[Τεκμηρίωση Ruff] - https://twine.readthedocs.io/[Τεκμηρίωση Twine]

Η λειτουργική pipeline έχει επιτευχθεί! Τώρα έχετε ένα απλό pipeline CI/CD που σας επιτρέπει να αυτοματοποιείτε τα τεστ σας και να δημοσιεύετε το πακέτο Python σας στο PyPI άμεσα από τις GitHub Actions.

Ωστόσο, αυτό το pipeline παραμένει εθελοντικά ελαφρύ. Ακόμη δεν καλύπτει ορισμένα βασικά στοιχεία σε επαγγελματικό περιβάλλον :

Δοκιμές πολλαπλών εκδόσεων του Python,

Αυτοματοποιημένη ανάλυση ασφαλείας,

Προοδευτική ανάπτυξη μέσω Test PyPI,

Παρακολούθηση και μετρικά του pipeline,

Αυτοματοποίηση της διαχείρισης εκδόσεων και ενσωμάτωση των σύγχρονων καλών πρακτικών (pyproject.toml).

Στην επόμενη ενότητα, θα προχωρήσουμε στο επόμενο βήμα. Θα μάθετε πώς να μετατρέψετε αυτή τη βασική γραμμή διεργασιών σε μια πραγματική, βιομηχανική, ισχυρή και ασφαλής αλυσίδα ανάπτυξης, έτοιμη για έργα Python παραγωγής.
----

Σχετικά άρθρα