Как настроить действия GitHub и интеграцию PyPI для проектов Python
5 сентября 2024 г.Как использовать действия GitHub и создать интеграцию с pypi для проектов Python
Введение
Когда я создавал свой первый пакет Python,dataclass-sqlalchemy-mixins (гитхабилиpypi), я столкнулся с интересной проблемой:
как настроитьCI/CDна GitHub, чтобы гарантировать, что ничего не сломается, когда я публикую новые изменения, и автоматически публиковать кодPyPI. Я обсуждал, как опубликовать свой собственный пакет, используяpoetryв этомстатья.
Обычно для проверки любого коммита, сделанного в главной ветке посредством запроса на извлечение, необходимо запустить тесты.
Кроме того, полезно использовать линтеры для проверки стиля кода, особенно когда над проектом работают несколько разработчиков.
*CI (непрерывная интеграция) — практика автоматического создания и тестирования изменений кода после их слияния в репозиторий.*
*CD (непрерывная доставка) — автоматизированная доставка кода в среду разработки или производства*
Создание рабочих процессов
GitHub поддерживает действия, которые представляют собой автоматизированные процессы, способные выполнять одну или несколько задач, включаяCI/CDтрубопроводы.
Подробнее о них можно прочитать вДокументация GitHub.
Рабочие процессы — это то, что GitHub будет запускать в соответствии с вашей конфигурацией. Они должны быть расположены в.github/workflowsкаталог и быть.yamlфайлы.
Например, если мы хотим запускать тесты после каждого коммита, нам нужно создать файл с именемtest.yml.
Я выбрал имяtestдля удобства и для указания того, что этот конкретный рабочий процесс отвечает за тесты, но это может быть что угодно.
name: "Test"
on:
pull_request:
types:
- "opened"
- "synchronize"
- "reopened"
push:
branches:
- '*'
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.12
id: setup-python
uses: actions/setup-python@v5
with:
python-version: 3.12
- name: Cache poetry install
uses: actions/cache@v4
with:
path: ~/.local
key: poetry-${{ steps.setup-python.outputs.python-version }}-1.7.1-0
- uses: snok/install-poetry@v1
with:
version: 1.7.1
virtualenvs-create: true
virtualenvs-in-project: true
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v4
with:
path: .venv
key: venv-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
- name: Install dependencies
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction
- name: Run tests
run: poetry run pytest --cov-report=xml
Позвольте мне объяснить ключевые элементы файла:
name- Это название рабочего процесса.pull request- Указывает типы запросов на извлечение, которые запускают рабочий процесс. Рекомендуемые значения по умолчанию:opened,synchronize, иreopened.Подробнее об этих типах вы можете прочитатьздесь.
push- Указывает ветви, запускающие рабочий процесс.jobs- Рабочий процесс может состоять из одного или нескольких заданий, которые по умолчанию выполняются параллельно, но также могут быть настроены на последовательное выполнение.
Я хотел бы обсудить, что происходит во время выполнения заданий с этим кодом.
Во-первых, имя задания может использоваться для настройки наборов правил для репозитория или определенных ветвей. В этом случае единственное задание, которое будет запущено, — это test. Подробности наборов правил будут рассмотрены позже.
Theruns-onключ указывает, в какой операционной системе будут выполняться задания.
Стратегия настройки:fail-fast: falseозначает, что GitHub не будет отменять все текущие и поставленные в очередь задания вmatrixесли какая-либо работа в матрице не выполняется.
Thematrixпараметр будет рассмотрен позже.
Как вы можете видеть, в коде много похожих кодов.usesвведите шаги. Например:
actions/setup-python@v5actions/cache@v4snok/install-poetry@v1
На первый взгляд названия действий могут показаться запутанными, но на самом деле это пути к репозиториям GitHub для этих действий,
исключая@vчасть.
Например, вы можете просмотреть исходный код первого действия, посетивhttps://github.com/actions/setup-python.
То же самое можно сделать и для других действий.@vиспользуется для указания того, какую версию действия следует использовать.
Ключ with используется для передачи параметров действию.
Например, если мы хотим установитьPython 3.12, мы проходимpython-version: 3.12вSet up Python 3.12шаг. Тот же подход применим и к другим шагам.
Короче говоря, тестовое задание выполняет следующие шаги:
- Устанавливает
Pythonс требуемой версией. - Устанавливает
Poetry1.7.1 зависимость с использованием кэша GitHub. - Создает Python .venv в корневом каталоге, если кэш не найден. Кэш виртуальной среды зависит от
Pythonверсия иpoetry.lock. - Если кэшированная виртуальная среда не найдена, устанавливаются зависимости проекта.
- Проводит тесты.
Использование служб в рабочих процессах
Созданный рабочий процесс довольно прост и может не подойти для тестирования более сложных приложений или проектов.
Это связано с тем, что такие проекты часто требуют, чтобы такие сервисы, как базы данных или кэширование, функционировали правильно. Хотя можно писать тесты, которые имитируют запросы к этим сервисам, я бы не рекомендовал этого делать, так как это может снизить эффективность тестового покрытия.
Я продемонстрирую, как включить услугу в рабочий процесс, используяPostgreSQLв качестве примера.
jobs:
test:
services:
postgres:
image: postgres:latest
env:
POSTGRES_PASSWORD: postgres
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
Добавлениеservicesключ с требуемым именем сервиса позволяет настроить его во время работы.
Более того, вы можете передавать ему настройки аналогично при использованииdocker.
Использование нескольких параметров во время выполнения задания
И последнее, но не менее важное — ситуация, когда вам необходимо выполнить задание с использованием других параметров.
Например, вам может потребоваться выполнить задание с несколькими конкретнымиPythonверсии, а не только последние, или с различными зависимостями.
Это может быть особенно полезно, когда вам необходимо обеспечить обратную совместимость со старыми зависимостями.GitHubдает стратегический ключ для решения этой проблемы.matrixпараметр позволяет запустить задание с несколькими значениями.
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12"]
sqlalchemy-version: ["1.4.52", "2.0.31"]
Задание с матрицей, настроенной таким образом, будет сравнивать каждое значение списка параметров с каждым другим значением.
В результате будет четыре запуска задания со следующими комбинациямиPythonиSQLAlchemyверсии соответственно:
3.11,1.4.523.11,2.0.313.12,1.4.523.12,2.0.31
Вы можете получить доступ к параметрам в ходе выполнения задания, используя${{ matrix.python-version }}или${{ matrix.sqlalchemy-version }}.
- name: Set up Python ${{ matrix.python-version }}
id: setup-python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install sqlalchemy ${{ matrix.sqlalchemy-version }}
run: pip install sqlalchemy==${{ matrix.sqlalchemy-version }}
Использование наборов правил GitHub
Но иногда простого выполнения заданий по вашему проекту недостаточно.
Бывают ситуации, когда вам может потребоваться ограничить слияние коммитов в ветке master. Хотя это может быть необязательно, когда вы работаете над проектом в одиночку, это настоятельно рекомендуется, когда несколько человек работают над одной и той же кодовой базой. Это помогает предотвратить ситуации, когда кто-то случайно объединяет коммит, который нарушает код, даже если конвейеры выходят из строя.
GitHub предоставляет для этого полезный инструмент, называемый наборами правил.
Доступ к нему можно получить из меню настроек репозитория по адресуhttps://github.com/{Author}/{Repository}/settings/rules.
После создания нового набора правил прокрутите вниз доRequire status checks to pass, включите его и укажите, какие задания необходимо сдать.
Чтобы найти проверку, введите название нужной работы, и GitHub предоставит предложения.
Обратите внимание, что каждая работа в матрице будет иметь свое собственное название, что позволит вам выбирать их по отдельности.

Публикация в pypi
В последней части я хотел бы рассказать о том, как создать интеграцию с pypi и публиковать новые версии с релизом.
Для этого необходимо создать новый файл Yaml с рабочими процессами публикации.
name: Upload Python Package to PyPi on release
on:
release:
types: [published]
permissions:
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/project/dataclass-sqlalchemy-mixins/
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: '3.x'
- uses: snok/install-poetry@v1
with:
version: 1.7.1
virtualenvs-create: true
virtualenvs-in-project: true
- name: Build package
run: poetry build
- name: Publish package
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
Этот рабочий процесс:
- Устанавливает
Python. - Устанавливает
Poetry1.7.1 зависимость с использованием кэша GitHub. - Создайте исходный код и архивы колес.
- Публикует пакет в pypi
Да, это так просто, как кажется.
Вам просто нужно добавитьPYPI_API_TOKENв хранилище секретов(https://github.com/{Author}/{Repository}/settings/secrets/actions).
Наконец, создайте новый релиз (https://github.com/{Author}/{Repository}/releases), и пакет будет загружен.
Оригинал