Как настроить действия GitHub и интеграцию PyPI для проектов Python

Как настроить действия 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@v5
  • actions/cache@v4
  • snok/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шаг. Тот же подход применим и к другим шагам.

Короче говоря, тестовое задание выполняет следующие шаги:

  1. УстанавливаетPythonс требуемой версией.
  2. УстанавливаетPoetry1.7.1 зависимость с использованием кэша GitHub.
  3. Создает Python .venv в корневом каталоге, если кэш не найден. Кэш виртуальной среды зависит отPythonверсия иpoetry.lock.
  4. Если кэшированная виртуальная среда не найдена, устанавливаются зависимости проекта.
  5. Проводит тесты.

Использование служб в рабочих процессах

Созданный рабочий процесс довольно прост и может не подойти для тестирования более сложных приложений или проектов.

Это связано с тем, что такие проекты часто требуют, чтобы такие сервисы, как базы данных или кэширование, функционировали правильно. Хотя можно писать тесты, которые имитируют запросы к этим сервисам, я бы не рекомендовал этого делать, так как это может снизить эффективность тестового покрытия.

Я продемонстрирую, как включить услугу в рабочий процесс, используя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.52
  • 3.11, 2.0.31
  • 3.12, 1.4.52
  • 3.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 предоставит предложения.

Обратите внимание, что каждая работа в матрице будет иметь свое собственное название, что позволит вам выбирать их по отдельности.

Set required status checks

Публикация в 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 }}

Этот рабочий процесс:

  1. УстанавливаетPython.
  2. УстанавливаетPoetry1.7.1 зависимость с использованием кэша GitHub.
  3. Создайте исходный код и архивы колес.
  4. Публикует пакет в pypi

Да, это так просто, как кажется.

Вам просто нужно добавитьPYPI_API_TOKENв хранилище секретов(https://github.com/{Author}/{Repository}/settings/secrets/actions).

Наконец, создайте новый релиз (https://github.com/{Author}/{Repository}/releases), и пакет будет загружен.


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE