Део 1 : Поставити једноставни CI/CD pipeline за Python и PyPI
Објављено 17 July 2025
Sommaire
Uvod
Циљ : Pomoći čitaču u postavljanju minimalističkog, ali funkcionalnog CI/CD pipelinea za Python aplikaciju, sa automatskim deploy-om na PyPI.
Automatizacija procesa razvoja postala je neophodna u modernim projektima. Dobro dizajniran CI/CD pipeline ne samo što otkriva regresije ranije u ciklusu razvoja, već i potpuno automatizuje proces raspoređivanja.
У овом чланку ћемо испитати како подешати потпуни са GitHub Actions за Python апликацију, од континуиране интеграције (CI) до континуиране доставе (CD) на PyPI.
Архитектура пиплайна
Naš pipeline se sastoji od dvaju različitih workflow:
-
CI PipelineIzvršen na svakom push-u i pull request-u
-
CD Pipeline: Pokreće se samo tokom GitHub release-ova
@startuml
!theme plain
package "Repozitorijum GitHub" {
[Source Code] as source
[GitHub Actions] as actions
}
package "CI cevovod" {
[Checkout] as checkout_ci
[Setup Python] as python_ci
[Install Dependencies] as deps_ci
[Linting (Ruff)] as lint
[Unit Tests] as tests
}
package "CD Pipeline" {
[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
Konfiguracija CI pipeline-a
Struktura CI radnog toka
CI radni tok je dizajniran da validira svaki doprinos kodu. Evo njene potpune konfiguracije:
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
Analiza koraka CI
Pokretači (on)
----
----
on:
push:
branches:
- main
pull_request:
branches:
- main
----
Pajplajn se pokreće na: - Svaki push na granu`main` - svaki pull request ka`main`
Ovaj pristup garantuje da glavni kod ostane stabilan i da svaki doprinos bude proveren pre integracije.
==== 2. Izvršno okruženje
----
runs-on: ubuntu-latest
Ubuntu Latest nudi dobar kompromis između performansi, cene i kompatibilnosti za većinu Python projekata.
==== 3. Check‑out koda
```yaml
----
----
- name: Checkout code
uses: actions/checkout@v4
----
Akcija`checkout@v4`Преузима изворни код из репозиторија. Верзија v4 донесе надоградње у области перформанси и безбедности.
==== 4. Конфигурација Python
----
- name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.x'
Коришћење`'3.x'`omogućuje automatsko korišćenje najnovije stabilne verzije Python 3, pojednostavljajući održavanje.
==== 5. Инсталација зависности
```yaml
----
----
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install ruff pytest pytest-mock
----
Овај чекор : - Ažuriraj pip na najnoviju verziju - Instaliraj zavisnosti projekta - Dodaj alate za razvoj (linting i testovi)
==== 6. Lintiranje sa Ruff
----
- name: Run Linting (Ruff) run: ruff check .
**Ruff**Ултра-брз Python линтер написан на Rust. Он комбинује функционалности неколико алата (Flake8, Black, isort) у један ефикасан алат.
==== 7. Izvršavanje testova
```yaml
----
----
- name: Run Tests (Pytest)
run: pytest
----
Pytest izvršava celi skup testova, osiguravajući da promene ne uvedu regresije.
== Конфигурација ЦИД пайплайна
=== Struktura CD workflow-a
CD workflow se pokreće samo tokom GitHub release-ova i automatizuje objavu na 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/*
----
=== Analiza koraka CD
==== Pokretač Release
----
on: release: types: - published
CD pipeline se pokreće samo prilikom objavljivanja GitHub release-a. Ovaj pristup osigurava preciznu kontrolu nad deploy-ovanjem.
==== 2. Instalacija alata za gradnju
```yaml
----
----
pip install setuptools wheel twine
----
- **setuptools**: Alati za pakiranje Python - **wheel**: Moderni format distribucije Pythona - **konopac**: Осигурен алат за аплоадинг ка PyPI
==== 3. Конфигурација аутентификације
----
env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
Аутентификација користи PyPI API токен складиштењен као GitHub тајна, који је безбеднији од традиционалних учредња.
==== 4. Izgradnja i objava
```yaml
----
----
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
----
- `sdist`: Kreiraj izvornu distribuciju - `bdist_wheel`Kreiraj wheel (binarna distribucija) - `twine upload`Objavljuje distribucije na PyPI
== Конфигурација пајтон пакета
=== Struktura fajla setup.py
Da bi pipeline funkcionisao, vaš projekat mora da uključuje fajl.`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",
],
},
)
----
=== Kljucne tačke setup.py
1. **Metapodaci**: Ime, verzija, autor, opis
2. **зависност**: Списак потребних пакета
3. **Улазне тачке**: Izložene CLI komande
4. **Klasifikatori**Metapodaci za PyPI
== Заштита преко GitHub secretова
=== Конфигурација Token PyPI
1. **Kreirati API token na PyPI**:
- Prijavite se na PyPI - Idite na Account Settings > API tokens - Креирајте нови токен са одговарајућим овозбедицама
1. **Додај секрет у GitHub**:
- Podešavanja repozitorija > Tajne i varijable > Akcije - Kreirajte novu tajnu nazvanu`PYPI_API_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
----
== Radni tok potpunog raspoređivanja
=== sekvenca implementacije
[plantuml, deployment-sequence, svg]
----
@startuml
!theme plain
actor Developer as dev
participant "Lokalni Git" as git
participant "GitHub" as github
participant "GitHub akcije" as actions
participant PyPI
participant "Krajnji korisnici" 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
----
=== Stanja pipeline-a
[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
----
== Dobre prakse i optimizacije
=== Upravljanje verzijama
Koristite semantičke Git tagove:
----
git tag -a v1.2.3 -m "Release version 1.2.3" git push origin v1.2.3
=== 2. Testovi matrice
Za testiranje na verzijama Pythona:
```yaml
----
----
strategy:
matrix:
python-version: [3.8, 3.9, "3.10", "3.11"]
----
=== 3. Keš zavisnosti
Ubrzajte gradnje sa kešom:
----
- name: Cache pip dependencies uses: actions/cache@v3 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
=== 4. Okruženja za deploy
Koristite GitHub okruženja za kontrolisana objavljivanja:
```yaml
----
----
jobs:
deploy:
environment: production
runs-on: ubuntu-latest
----
== Случај употребе и архитектура
=== Дијаграм случајева коришћења
[plantuml, use-cases, svg]
----
@startuml
!theme plain
left to right direction
actor "razvijalac" as dev
actor "GitHub Actions" as ga
actor "Krajnji korisnik" as user
package "CI/CD Sistem" {
usecase "Pokreni lintanje" as lint
usecase "Izvrši testove" as test
usecase "Izgradite paket" as build
usecase "Objavi na PyPI" as publish
usecase "Kreiraj izdanje" 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 cijevovod" {
[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
=== logovi i monitoring
GitHub Actions nudi detaljne zapise za svaki korak. Za debugiranje:
1. **Ispitajte logove**svake korak
2. **Uključite debug**sa`ACTIONS_STEP_DEBUG`
3. **Koristi artefakte**Да сачувате fajlove za build
----
- name: Upload build artifacts uses: actions/upload-artifact@v3 if: failure() with: name: build-logs path: build/
=== Obaveštenja
Dodajte Slack ili e‑mail obaveštenja:
```yaml
----
----
- name: Notify on failure
if: failure()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
----
== Zaključak
Postavljanje jakog CI/CD pipelinea sa GitHub Actions radikalno menja iskustvo razvoja. Automatizovanjem lintovanja, testova i deploy-a, vi :
- **Смањите грешке**у производњу - **Ubržajte ciklusi**od razvoja - **Poboljšajte poverenje**u vašim releasima - **Olakšajte saradnju**у тим
Ovaj pipeline se može prilagoditi različitim vrstama Python projekata prilagođavanjem alata za lintiranje, okvira za testiranje ili destinacija za implementaciju.
Početni ulaganje u podešavanje ovih radnih tokova se brzo vraća zbog uštede vremena i smanjivanja ručnih grešaka tokom implementacija.
== Dodatni resursi
- https://docs.github.com/en/actions[Документација GitHub Actions] - https://packaging.python.org/[Python vodič za pakovanje] - https://docs.pytest.org/[Dokumentacija Pytest] - https://docs.astral.sh/ruff/[Документација Ruff] - https://twine.readthedocs.io/[Документация Twine]
✅ Funkcionalni pipeline postignut ! Sada imate jednostavni CI/CD pipeline koji vam omogućava da automatizujete svoje testove i da objavite svoj Python paket na PyPI izravno iz GitHub Actions.
Ovakav pipeline ostaje svestrano minimalistički. Još ne pokriva neke neophodne aspekte u profesionalnom kontekstu :
Тестови више верзија Питона,
Automatska analiza bezbednosti,
Postupno raspoređivanje putem Test PyPI,
Набљудање и метрике конвејера,
Automatizacija verzioniranja i uvođenje modernih dobrih praksi (pyproject.toml).
U sledećem delu, prelazimo na viši nivo. Naučit ćete da preobrazite ovaj osnovni pipeline u stvarni industrijski lanac implementacije, čvrst i siguran, spreman za Python projekte u proizvodnji.
----