Автоматизация выпусков инструментов командной строки Swift с помощью GitHub Actions

14 апреля 2023

Недавно мною был открыт исходный код инструмента командной строки Swift под названием chatty, который дает вам возможность использовать ChatGPT от Open AI прямо из терминала.

Помимо возможности выпустить проект с открытым исходным кодом, я потратил некоторое время на то, чтобы автоматизировать процесс выпуска моего нового инструмента командной строки с помощью GitHub Actions.

 

Процесс выпуска

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

По этой причине я решил распространять мой инструмент командной строки через два различных канала:

  1. Homebrew - популярный менеджер пакетов для macOS, широко используемый для установки приложений командной строки.
  2. GitHub релизы, где пользователи могут загружать артефакты напрямую. Homebrew использует этот метод для установки исполняемых инструментов.

Обратите внимание, что приложение chatty доступно только для macOS (Intel и Apple Silicon), но в будущих версиях я планирую добавить поддержку для Linux и Windows 👀.

Поскольку проект с открытым исходным кодом, а GitHub предлагает неограниченное количество бесплатных минут для публичных репозиториев, я решил использовать GitHub Actions в качестве провайдера CI/CD, что, в свою очередь, позволило мне воспользоваться широкой экосистемой действий, управляемых сообществом, для упрощения процесса.

 

Создание рабочего процесса выпуска

Первый шаг к настройке рабочего процесса GitHub Actions - это создание нового файла в каталоге .github/workflows вашего репозитория. Имя файла может быть любым, я решил назвать свой release.yml.

 

Вызов при каждом нажатии тега

Как только я поместил файл рабочего процесса в нужную директорию, я добавил событие push с фильтром, чтобы рабочий процесс срабатывал только тогда, когда тег релиза (v*.*.*.*) будет помещен в хранилище:

release.yml
name: Release

on:
  push:
    tags:
      - v*.*.*

 

 

Сборка исполняемого файла для выпуска

Чтобы разместить приложение, сначала мне нужно было собрать его для архитектур, которые я хотел поддерживать (macOS arm64 и x86_64).

Для этого мне нужно было указать рабочему процессу запускаться на последней версии macOS, проверить репозиторий и собрать исполняемый продукт с двумя архитектурными срезами с помощью swift build:

release.yml
name: Release

on:
  push:
    tags:
      - v*.*.*

jobs:
  release:
    runs-on: macos-latest

    steps:
      - uses: actions/checkout@v3
      - name: Build executable for release
        run: swift build -c release --arch a

 

 

Создание релиза на GitHub

Затем мне нужно было создать релиз на GitHub с тегом ref в качестве имени и прикрепленным из предыдущего шага сжатым архивом артефакта:

ame: Release

on:
  push:
    tags:
      - v*.*.*

jobs:
  release:
    runs-on: macos-latest

    steps:
      - uses: actions/checkout@v3
      - name: Build executable for release
        run: swift build -c release --arch arm64 --arch x86_64 --product chatty
      - name: Compress archive
        run: tar -czf ${{ github.ref_name }}.tar.gz -C .build/apple/Products/Release chatty
      - name: Release
        uses: softprops/action-gh-release@v1
        with:
          files: ${{ github.ref_name }}.tar.gz
          token: ${{ secrets.GITHUB_TOKEN }}

Наименование тарбол архива важно, так как в следующем разделе оно используется для определения URL-адреса исполняемого файла формулы Homebrew.

Как видно в рабочем процессе выше, я обнаружил, что использование softprops' action-gh-release action было самым простым способом создания и настройки релиза для GitHub.

 

Создание новой версии формулы Homebrew

Как я уже упоминал в статье, мне хотелось сделать chatty доступным в Homebrew, так как это самый популярный способ установки инструментов командной строки на macOS.

Чтобы распространять мой инструмент в Homebrew, мне сначала нужно было опубликовать формулу. Я использовал существующий отвод Homebrew, который я создал для другого проекта, и добавил совершенно новую формулу, указывающую на существующий исполняемый файл chatty:

Formula/chatty-cli.rb

class ChattyCli < Formula
  desc "A command line application to interact with ChatGPT directly from the terminal"
  homepage ""
  url "https://github.com/polpielladev/chatty-cli/archive/v1.0.2.tar.gz"
  sha256 "a258e0d6d96488bbcb01b51a97e2370185c0207aea7a31565f48716060eabf56"
  license ""
  version "1.0.2"

  def install
    bin.install "chatty"
  end
end

Формула имеет описание и URL-адрес к архиву релиза с соответствующей контрольной суммой SHA256. Также у неё есть метод install, который сообщает Homebrew установить исполняемый файл под названием 'chatty' (найденный в корне тарбол) в директорию двоичных файлов Homebrew пользователя.

Не смотря на то, что все работало отлично, я хотел автоматизировать данный процесс и максимально его упростить. Исследуя возможности для этого, я наткнулся на великолепный GitHub экшн от Mislav Marohnić, который, в частности, используется Fastlane для автоматического обновления их формулы Homebrew при каждом релизе.

Затем я выполнил данный экшн непосредственно после создания релиза GitHub в моем рабочем процессе:

release.yml
name: Release

on:
  push:
    tags:
      - v*.*.*

jobs:
  release:
    runs-on: macos-latest

    steps:
      - uses: actions/checkout@v3
      - name: Build executable for release
        run: swift build -c release --arch arm64 --arch x86_64 --product chatty
      - name: Compress archive
        run: tar -czf ${{ github.ref_name }}.tar.gz -C .build/apple/Products/Release chatty
      - name: Release
        uses: softprops/action-gh-release@v1
        with:
          files: ${{ github.ref_name }}.tar.gz
          token: ${{ secrets.GITHUB_TOKEN }}
      - uses: mislav/bump-homebrew-formula-action@v2
        with:
          formula-name: chatty-cli
          homebrew-tap: polpielladev/homebrew-tap
          base-branch: main
          download-url: https://github.com/polpielladev/chatty-cli/releases/download/${{ github.ref_name }}/${{ github.ref_name }}.tar.gz
        env:
          COMMITTER_TOKEN: ${{ secrets.CHATTY_COMMITTER_TOKEN }}


Мне пришлось указать в действии homebrew имя формулы (formula-name), имя моего персонального Homebrew-тапа (polpielladev/homebrew-tap), поскольку по умолчанию он использует Homebrew/homebrew-core, имя ветки для коммита новой формулы в репозиторий тапа (main) и URL-адрес загрузки исполняемого архива.

Поскольку действию необходимо создавать коммит в отдельный репозиторий, мне пришлось создать новый токен доступа к персональным данным с областью public_repo (вам может потребоваться создать его с областью repo, если ваш тап размещен в частном репозитории), добавить его в секреты репозитория как CHATTY_COMMITTER_TOKEN и передать его экшену через переменную окружения с именем COMMITTER_TOKEN.

Теперь каждый раз, когда я пушу новый тег в репозиторий, рабочий процесс будет создавать релиз GitHub, собирать исполняемый файл для macOS arm64 и x86_64, сжимать его в тарбол-архив, загружать его в релиз и создавать новую версию формулы Homebrew.

 

Куда идти дальше

Как я уже упоминал ранее, chatty - полностью с открытым исходным кодом, поэтому вы можете посмотреть полный рабочий процесс в репозитории GitHub.

Также, если у вас есть какие-либо предложения по улучшению данного процесса релиза, не стесняйтесь создавать issue или pull request, или пишите мне в Twitter.
 

Оригинал статьи

Содержание