Рубрики
Без рубрики

Python Package CI / CD с Действиями и поэзией GitHub

Вы также можете прочитать это в моем блоге здесь. В предыдущем посте я ссылался на чистый CI / CD, проверяет … Помечено с Python, Github, поэзией, дежопами.

Вы также можете прочитать это в моем блоге здесь Отказ

В оформлении Предыдущий пост Я ссылался на чистые проверки CI/CD и авторелизацию для моей программы «Случайную программу». Я хотел, чтобы:

  1. Каждое изменение, которое я делаю в мою программу, не сломает существующую функциональность (непрерывная интеграция), а также
  2. Публикация нового выпуска на PYPI автоматически (непрерывная доставка/развертывание).

GitHub предоставляет функцию автоматизации рабочего процесса Действия GitHub Отказ По сути, вы пишете настройки рабочих процессов в файле yaml в Your-Repo/.Github/Workflows/ И они будут выполнены на определенных событиях репозитория.

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

  1. Испытательный синтаксис, запустив пробелов для форматирования (N.B. Синтаксис правильности представляет собой подмножество корректности форматирования).
  2. Тестовая функциональность через различные операционные системы и версий Python Бег автоматизированные тесты во всей программе. Для этой программы я включал только один базовый тест черного ящика, который более демонстрирует, чем полезным (он проверяет матч Regex с выходом программы). Набор узловных испытаний будет более подходящим для более сложной программы.
  3. Устойчивость к созданию теста, пытаясь построить программу (но отбрасывать артефакт сборки) по теми же комбинациям операционных систем и версий Python от шага 2.

Вот …| полный рабочий процесс .

Каждый коммит к багажнику

Триггер для этого объявлен в верхней части файла рабочего процесса:

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

Испытательный синтаксис путем проверки форматирования

Во-первых, мы должны оформить репозиторий в Действия GitHub, используя Собственный Оформить заказ действие . Тогда мы должны настроить версию Python, используя Github’s Setup-Python Действие Отказ Наконец, мы можем использовать Блэк предоставил действие GitHub Для проверки форматирования – он работает Black --check --дифф На клону рабочего процесса Runner’s клон REPO и выводит код ошибки, если какой-либо файл Python в REPO не удается правила форматирования Black. Обратите внимание, что черный не удается, если AST Не может быть проанализирован (то есть, если есть какие-либо синтаксические ошибки), поэтому его также можно использовать для проверки правильности синтаксиса, которая сама является хорошим прокси для проверки конфликтных строк слияния.

jobs:
  black-formatting-check:
    name: Check formatting
    runs-on: 'ubuntu-latest'
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-python@v2
      - uses: psf/black@stable

Запуск работы в разных средах сборки

Действия GitHub предоставляют функциональные возможности сборки матрицы, где вы предоставляете опцию, установленную для каждой переменной, и она запускает зависимые шаги с N-ARY Dartesian Product Из этих n Переменные наборы опции:

  build:
    runs-on: ${{ matrix.os }}
    needs: black-formatting-check
    strategy:
      matrix:
        os:
          - 'ubuntu-latest'
          - 'macos-latest'
          - 'windows-latest'
        python-version:
          - '3.7'
          - '3.8'
          - '3.9'

Это определено в рабочие места. .strategy.matrix директива . Я добавил 2 переменных: один для ОС (с Ubuntu, MacOS и Windows в качестве опций) и один для версии Python (с 3,7, 3,8 и 3.9 в качестве опций). Это означает, что все в построить Работа будет работать на каждом комбинации ОС и вариантов версии Python:

  • Ubuntu, Python 3.7
  • Ubuntu, Python 3.8
  • Ubuntu, Python 3.9
  • MacOS, Python 3.7
  • MacOS, Python 3.8
  • так далее

Обратите внимание, что бежит на Директива определяется как $ {{matrix.os}} какие указывает на значение ОС Переменная в нынешнем бегунке. Внутренне шаги несколько нравятся:

  1. Действия GitHub разрабатывает директивы для работы и видит, что есть матричная стратегия.
  2. Он вращает отдельный бегун для каждой матричной комбинации и определяет переменные Matrix.os и Matrix.python-версия как значения для этой комбинации. Например, в бегуне Ubuntu/Python 3.7 Matrix.os и Matrix.python-версия Отказ
  3. Он запускает шаги работы в каждом бегунке, он повернул на шаге 2.

Вы можете увидеть пример того, как выглядит этот матричный запуск в консоли Действия GitHub здесь (См. Все комбинации OS/Python в левой боковой панели). Эти параметры матрицы выполняются параллельно по умолчанию, поэтому выполнение задания, определенной самой медленной опцией Matrix. Обратите внимание, что если ваш репозиторий является частным, вы будете взимаются минуты действий для каждой отдельной комбинации сборки, с некоторыми Гефты множители для Macos и Windows (1 MacOS Minute – это 10 минут акций Credit, 1 Windows Minute составляет 2 минуты акций кредит на 2021 мая).

Тестовая функциональность

Опять же, нам нужно проверить репо для этой работы и настроить версию Python. Ключевое различие с настройкой версии Python здесь по сравнению с работой черного форматирования состоит в том, что версия Python указывается и указывает на опцию Matrix для Python-версия :

    steps:
      - name: Checkout code
        uses: actions/checkout@v2
      - name: Setup Python
        uses: actions/setup-python@v2
        with:
          python-version: ${{matrix.python-version}}

Затем нам нужно настроить зависимости для программы, чтобы убедиться, что она может работать. Я использовал поэзию для зависимости и виртуального управления окружающей средой, и она не включена в любой бегун среда Итак, мы должны установить его на шаг рабочего процесса. Установка требуется некоторое время, хотя, чтобы ускорить время выполнения рабочего процесса, я «постоянно» кэш-стихов, используя GitHub предоставляется кэш действие . Я запускаю этап установки только в том случае, если кэш пропускается, что не произойдет, поскольку ключ постоянна для каждой комбинации версий OS/Python.

      # Perma-cache Poetry since we only need it for checking pyproject version
      - name: Cache Poetry
        id: cache-poetry
        uses: actions/cache@v2.1.5
        with:
          path: ~/.poetry
          key: ${{ matrix.os }}-poetry
      # Only runs when key from caching step changes
      - name: Install latest version of Poetry
        if: steps.cache-poetry.outputs.cache-hit != 'true'
        run: |
          curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
      # Poetry still needs to be re-prepended to the PATH on each run, since
      # PATH does not persist between runs.
      - name: Add Poetry to $PATH
        run: |
          echo "$HOME/.poetry/bin" >> $GITHUB_PATH
      - name: Get Poetry version
        run: poetry --version

Затем я делаю еще один шаг кэширования для зависимостей и установить их, если Поэзия. Блок изменилось:

      - name: Check pyproject.toml validity
        run: poetry check --no-interaction
      - name: Cache dependencies
        id: cache-deps
        uses: actions/cache@v2.1.5
        with:
          path: ${{github.workspace}}/.venv
          key: ${{ matrix.os }}-${{ hashFiles('**/poetry.lock') }}
          restore-keys: ${{ matrix.os }}-
      - name: Install deps
        if: steps.cache-deps.cache-hit != 'true'
        run: |
          poetry config virtualenvs.in-project true
          poetry install --no-interaction

Наконец, однажды выполняется зависимость и виртуальная настройка среды, я бегаю Pteest:

      - name: Run tests
        run: poetry run pytest -v

Стабильность тестирования сборки

Для тестирования стабильности постройки мы просто бегаем поэзии построить Подкоманда, которая создает артефакты сборки:

      - name: Build artifacts
        run: poetry build

Автоматическое слияние

GitHub также позволяет запрограммировать запросы на тягу автоматически, если настраиваются правила защиты от ответственности, и если запрос на тягу проходит все необходимые отзывы и проверки состояния. В настройках репо> Филиалы> Правила защиты от ответственности у меня есть правило, определенное для Главная требуя всех рабочих мест в build.yml Рабочий процесс, чтобы пройти до того, как ветвь может быть объединена в Главная Отказ

Есть 2 части до автоматизации выпуска GitHub:

  1. Создайте релиз GitHub, используя Git Tags и добавьте его артефакты сборки ( Workflow ).
  2. Опубликовать пакет на PYPI ( Workflow ).

Создать выпуск GitHub

Мы настроили рабочий процесс, чтобы вызвать нажимать на тег, начиная с V :

on:
  push:
    # Sequence of patterns matched against refs/tags
    tags:
      - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10

Тогда мы определяем нашу Автокресла Работа, работающая на Ubuntu (самый дешевый и самый быстрый github Действия бегун):

name: Create Release

jobs:
  autorelease:
    name: Create Release
    runs-on: 'ubuntu-latest'

Наши первые 2 этапа почти такие же, как наш рабочий процесс для толкающих и PRS на основной : Мы оформием оформление репо и настроив поэтиров. Наш шаг заказа немного отличается, хотя: мы предоставляем 0 к Глубина извлечения Ввод, поэтому мы составляем глубокий клон со всеми коммитами, а не мелким клоном с только недавним фиксацией.

    steps:
      - name: Checkout code
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

Шаги настроек поэзии идентичны, поэтому я не буду включать их здесь.

Затем мы используем поэзию, чтобы получить версию проекта от pyproject.toml , Храните его в переменной окружающей среде, затем проверьте, соответствует ли версия тегов в версии проекта:

      - name: Add version to environment vars
        run: |
          PROJECT_VERSION=$(poetry version --short)
          echo "PROJECT_VERSION=$PROJECT_VERSION" >> $GITHUB_ENV
      - name: Check if tag version matches project version
        run: |
          TAG=$(git describe HEAD --tags --abbrev=0)
          echo $TAG
          echo $PROJECT_VERSION
          if [[ "$TAG" != "v$PROJECT_VERSION" ]]; then exit 1; fi

Это немного ограждения из-за того, как я вызываю авторелез. Я обновляю pyproject.toml Версия на моем локальном клоне, используя Версия поэзии <Версия> , совершите его на Главная Затем пометите его с тем же <Версия> и протолкните коммит и тег, который затем начинает этот рабочий процесс. Нам нужно убедиться, что тег версии и pyproject.toml Версии совпадают (в случае, если мы забываем правильно поднять версии).

Затем мы делаем ту же зависимость и настройку Virtualenv, как в моем рабочем процессе по сборке, используя поэтиграфию, а затем запустить Pteest и Поэзия построить Отказ Артефакты сборки будут использоваться, когда мы создаем выпуск на последнем этапе этого рабочего процесса.

Следующим шагом является создание некоторых заметок выпуска. Я держу шаблон релиза в ..gitub Папка и добавьте немного вывода Gitlog к нему:

 - name: Release Notes
        run: git log $(git describe HEAD~ --tags --abbrev=0)..HEAD --pretty='format:* %h %s%n  * %an <%ae>' --no-merges >> ".github/RELEASE-TEMPLATE.md"

Эта команда Gnarly Gitlog проверяет все коммиты с момента последнего тега на голову. Для каждого Commit, он добавляет HASH HASH, субъекту сообщения Commit Commun, имя автора и автор электронной почты на шаблон выпуска.

Наконец, мы используем 3-й партийный выпуск Создание действий Для создания проекта выпуска с заметками выпуска и артефактам мы только что создали:

      - name: Create Release Draft
        uses: softprops/action-gh-release@v1
        with:
          body_path: ".github/RELEASE-TEMPLATE.md"
          draft: true
          files: |
            dist/random_standup-${{env.PROJECT_VERSION}}-py3-none-any.whl
            dist/random-standup-${{env.PROJECT_VERSION}}.tar.gz
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GITHUB_REPOSITORY: jidicula/random-standup

Это создает черновик, видимый на https://github.com/jidicula/random-standup-py/reluses Отказ Я изменяю объявления об освобождении по мере необходимости и опубликовать выпуск.

Публикация на Pypi

Последний шаг процесса выпуска состоит в том, чтобы опубликовать отпуск пакета в индекс пакета Python вместе с активами выпуска. Вот полный рабочий процесс Отказ

На этот раз мы запускаем рабочий процесс, чтобы запустить публикуемый релиза (последний шаг предыдущего рабочего процесса вручную публикует проект выпуска):

on:
  release:
    types:
      - published

Мы делаем ту же оформление оформления касса и поэзированную настройку, что и раньше. Тогда мы просто бегаем Поэзия публикует --build Использование токена Pypi в качестве переменной среды Secrets GitHub для аутентификации:

      - name: Publish to PyPI
        env:
          PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
        run: |
          poetry config pypi-token.pypi $PYPI_TOKEN
          poetry publish --build

Так что в целом, работа над этим проектом будет включать:

  1. Сделайте PR за мои изменения.
  2. Подтвердите авто-слияние.
  3. Повторите шаги 1 и 2, пока не готов выпустить.
  4. Поднять pyproject.toml Версия на моем локальном клоне, используя Версия поэзии Отказ Совершить изменения.
  5. Создайте тег на Главная Указывая на версию Bump Commit.
  6. Нажмите как тег, так и версия BYM для GitHub.
  7. Ждать Создать релиз бежать до конца.
  8. Перейти к https://github.com/jidicula/random-standup-py/reluses и изменить анонсы для проекта только созданного релиза.
  9. Опубликовать выпуск.
  10. Ждать Pypi публикует бежать до конца.
  11. Проверьте Pypi Для обновленной версии пакета.

Если у вас есть какие-либо вопросы или комментарии, напишите мне на johanan+blog@forcepush.tech или опубликуете комментарий ниже.

Вы нашли этот пост полезным? Купите мне напиток или спонсировать мне здесь Действительно

Оригинал: “https://dev.to/jidicula/python-ci-cd-with-github-actions-2e26”