Часть 1: Создание простого CI/CD конвейера для Python и PyPI
Опубликовано 17 July 2025
Введение
Автоматизация процессов разработки стала неизбежной в современных проектах. Хорошо спроектированный CI/CD‑pipeline позволяет не только выявлять регрессии на ранних этапах цикла разработки, но и полностью автоматизировать процесс развёртывания.
В этой статье мы рассмотрим, как настроить полный пайплайн с GitHub Actions для приложения Python: от непрерывной интеграции (CI) до непрерывного развертывания (CD) на PyPI.
Архитектура конвейера
Наш конвейер состоит из двух отдельных рабочих процессов:
-
конвейер CI: Выполняется при каждом push и pull request
-
Конвейер CD: Срабатывает только во время релизов GitHub
@startuml
!theme plain
package "Репозиторий GitHub" {
[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)
Структура 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
----
Конвейер запускается при: - Каждый push в ветку`main` - Каждый pull request к`main`
Этот подход гарантирует, что основной код остаётся стабильным и что любой вклад одобрен перед интеграцией.
==== 2. Среда выполнения
----
runs-on: ubuntu-latest
Ubuntu Latest предлагает хороший компромисс между производительностью, стоимостью и совместимостью для большинства проектов на Python.
==== 3. Выдача кода
----
- 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. Установка зависимостей
----
- name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install ruff pytest pytest-mock
Этап: - Обновить pip до последней версии - Установите зависимости проекта - Добавьте инструменты разработки (линтинг и тесты)
==== 6. Линтинг с Ruff
- name: Run Linting (Ruff) run: ruff check .
**Ruff**является сверхбыстрым линтером Python, написанным на Rust. Он объединяет функции нескольких инструментов (Flake8, Black, isort) в один мощный инструмент.
==== 7. Выполнение тестов
- name: Run Tests (Pytest) run: pytest
Pytest запускает весь набор тестов, гарантируя, что изменения не вызывают регрессий.
== Конфигурация пайплайна развертывания (CD)
=== Структура рабочего процесса CD
CD workflow запускается только при релизах 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
==== 1. Срабатывание Release
on: release: types: - published
Pipeline CD срабатывает только при публикации релиза GitHub. Такой подход обеспечивает точный контроль над развертываниями.
==== 2. Установка средств сборки
```yaml
----
----
----
----
pip install setuptools wheel twine
----
- **setuptools**: Инструменты упаковки Python - **колесо**: Формат дистрибутива современного Питона - **шпагат**: Безопасный инструмент для загрузки в PyPI
==== 3. Настройка аутентификации
----
env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
Аутентификация использует токен API PyPI, хранящийся как секрет GitHub, который более безопасен, чем классические учётные данные.
==== 4. Сборка и публикация
----
run: | python setup.py sdist bdist_wheel twine upload dist/*
- `sdist`Создаёт исходный дистрибутив - `bdist_wheel`: Создаёт wheel (бинарное распределение) - `twine upload`Опубликуй дистрибутивы на PyPI
== Настройка пакета Python
=== Структура 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
=== Настройка токена 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 "Репозиторий 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
----
== Воркфлоу полного развертывания
=== Последовательность развёртывания
[plantuml, deployment-sequence, svg]
----
@startuml
!theme plain
actor Developer as dev
participant "Локальный Git" as git
participant "GitHub" as github
participant "GitHub Действия" 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
----
== Хорошие практики и оптимизации
=== Управление версиями
Используйте семантические теги Git :
git tag -a v1.2.3 -m "Release version 1.2.3" git push origin v1.2.3
=== 2. Тесты матрицы
Для тестирования на нескольких версиях Python :
----
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 для контролируемых развертываний:
jobs: deploy: environment: production runs-on: ubuntu-latest
1. **Добавить секрет в GitHub** :
=== Диаграмма вариантов использования
[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 "Запустить линтинг" 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. **Активируйте отладку**с`ACTIONS_STEP_DEBUG`
3. **Используйте артефакты**для сохранения файлов сборки
- 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 }}
----
== Заключение
Внедрение надёжного CI/CD-пайплайна с использованием GitHub Actions кардинально преобразует опыт разработки. Автоматизируя линтинг, тесты и развёртывание, вы :
- **Сократите ошибки**в производстве - **Ускорьте циклы**разработки - **Улучшите доверие**в ваших релизах - **Упростите сотрудничество**в команде
Этот пайплайн можно адаптировать к различным типам проектов Python, настраивая инструменты линтинга, фреймворки тестирования или места развертывания.
Первоначальные инвестиции в настройку этих рабочих процессов быстро окупаются за счёт экономии времени и снижения количества ручных ошибок при развертывании.
== Дополнительные ресурсы
- 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]
✅ Функциональный конвейер достигнут! Теперь у вас есть простой конвейер CI/CD, который позволяет автоматизировать ваши тесты и публиковать ваш пакет Python на PyPI напрямую из GitHub Actions.
Однако этот конвейер сознательно остаётся минималистичным. Он ещё не покрывает некоторые необходимые аспекты в профессиональном контексте :
Тесты нескольких версий Python,
Автоматический анализ безопасности,
Постепенное развертывание через Test PyPI,
Мониторинг и метрики конвейера,
Автоматизация версионирования и интеграция современных лучших практик (pyproject.toml).
В следующей части мы перейдём на следующий уровень. Вы научитесь превращать этот базовый пайплайн в настоящую промышленную цепочку развёртывания, надёжную и безопасную, готовую для производственных проектов на Python.
----
----
Для тестирования на нескольких версиях Python:
----
strategy: matrix: python-version: [3.8, 3.9, "3.10", "3.11"]
=== 3. Кэширование зависимостей
Ускорьте сборку с помощью кэша:
```yaml
----
----
- name: Cache pip dependencies
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
----
=== 4. Среды развертывания
Используйте среды GitHub для контролируемого развертывания:
----
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 "Запуск линтинга" 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
----
=== Архитектура развертывания
1. **Добавить секрет в GitHub**Пожалуйста, предоставьте текст для перевода.
== Мониторинг и отладка
=== Логи и мониторинг
GitHub Actions предоставляет подробные логи для каждого шага. Для отладки:
1. **Изучите логи**каждого шага
2. **Активируйте режим отладки**с`ACTIONS_STEP_DEBUG`
3. **Используйте артефакты**для сохранения файлов сборки
```yaml
----
----
- name: Upload build artifacts
uses: actions/upload-artifact@v3
if: failure()
with:
name: build-logs
path: build/
----
=== Уведомления
Добавьте уведомления в Slack или по электронной почте:
----
- name: Notify on failure if: failure() uses: 8398a7/action-slack@v3 with: status: ${{ job.status }} webhook_url: ${{ secrets.SLACK_WEBHOOK }}
== Заключение
Внедрение надежного CI/CD-конвейера с помощью GitHub Actions радикально меняет процесс разработки. Автоматизируя линтинг, тестирование и развертывание, вы:
- **Сократите количество ошибок**в продакшене - **Ускорьте циклы**разработки - **Повысьте доверие**в ваших релизах - **Облегчите сотрудничество**в команде
Этот конвейер может быть адаптирован к различным типам Python-проектов путем настройки инструментов линтинга, фреймворков для тестирования или целей развертывания.
Первоначальные инвестиции в настройку этих рабочих процессов быстро окупаются за счет экономии времени и сокращения количества ручных ошибок при развертывании.
== Дополнительные ресурсы
- 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]
✅ Функциональный конвейер достигнут! Теперь у вас есть простой CI/CD-конвейер, который позволяет автоматизировать тестирование и публиковать ваш Python-пакет в PyPI напрямую из GitHub Actions.
Однако этот пайплайн намеренно остается минималистичным. Он пока не охватывает некоторые аспекты, необходимые в профессиональном контексте:
Тесты для нескольких версий Python,
Автоматический анализ безопасности,
Поэтапное развертывание через Test PyPI,
Мониторинг и метрики конвейера,
Автоматизация версионирования и внедрение современных лучших практик (`pyproject.toml`).
В следующей части мы перейдем на новый уровень. Вы научитесь превращать этот базовый конвейер в полноценную промышленную цепочку развертывания — надежную и безопасную, готовую к производственным проектам на Python.
=== Диаграмма вариантов использования
[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 "Запустить линтинг" 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
Безопасная аутентификация на основе токенов
end note
[Secrets Store] .. N1
@enduml
----
== Мониторинг и отладка
=== Логи и мониторинг
GitHub Actions предоставляет подробные логи для каждого шага. Для отладки:
1. **Изучите логи**каждого step
2. **Активируйте debug**с`ACTIONS_STEP_DEBUG`
3. **Используйте артефакты**для сохранения файлов сборки
```yaml
----
- 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 радикально меняет процесс разработки. Автоматизируя линтинг, тестирование и развертывание, вы:
- **Сократите количество ошибок**в продакшене - **Ускорьте циклы**разработки - **Повысьте уровень доверия**в ваших релизах - **Облегчите сотрудничество**в команде
Этот конвейер может быть адаптирован к различным типам Python-проектов путем настройки инструментов линтинга, тестовых фреймворков или целей развертывания.
Первоначальные инвестиции в настройку этих рабочих процессов быстро окупаются за счет экономии времени и сокращения количества ручных ошибок при развертывании.
== Дополнительные ресурсы
- 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]
✅ Функциональный конвейер достигнут! Теперь у вас есть простой CI/CD-конвейер, который позволяет автоматизировать тестирование и публиковать ваш Python-пакет в PyPI напрямую через GitHub Actions.
Тем не менее, этот конвейер намеренно остается минималистичным. Он пока не охватывает некоторые аспекты, необходимые в профессиональном контексте:
Тестирование нескольких версий Python,
Автоматический анализ безопасности,
Постепенное развертывание через Test PyPI,
Мониторинг и метрики конвейера,
Автоматизация версионирования и внедрение современных лучших практик (`pyproject.toml`).
В следующей части мы перейдем на следующий уровень. Вы научитесь превращать этот базовый пайплайн в полноценную промышленную цепочку развертывания, надежную и безопасную, готовую для продакшн-проектов на Python.