Как создать Homebrew-бутылку из локального файла формулы в GitHub Actions?
Я хочу использовать GitHub Actions для создания бутылки для формулы Homebrew, которая находится в том же репозитории. Мой текущий подход:
- name: build package
run: |
brew install --build-bottle ./Formula/mypackage.rb
brew bottle mypackage
Однако это приводит к ошибке:
Error: Homebrew requires formulae to be in a tap, rejecting:
./Formula/mypackage.rb (/Users/runner/work/homebrew-test/homebrew-test/Formula/mypackage.rb)
Если я использую brew tap owner/mytap и brew install --build-bottle mypackage, это работает, но использует основную ветку вместо ветки разработки, где я вношу изменения.
Как заставить Homebrew создавать бутылку из локального файла mypackage.rb в GitHub Actions?
Сборка Homebrew bottle из локального файла formula в GitHub Actions
Для сборки Homebrew bottle из локального файла formula в GitHub Actions необходимо создать правильную структуру tap или использовать команды создания tap в Homebrew. Homebrew требует, чтобы formulae находились в контексте tap, а не в виде путей к файлам, поэтому ваш текущий подход завершается ошибкой “requires formulae to be in a tap”.
Содержание
- Понимание требования к tap
- Решение 1: Создание локальной структуры tap
- Решение 2: Использование brew tap-new
- Решение 3: Использование brew bottle с путем к Formula
- Полный workflow GitHub Actions
- Устранение распространенных проблем
- Лучшие практики
Понимание требования к tap
Система bottle Homebrew разработана вокруг tap, которые по сути являются репозиториями Git, содержащими formulae. Эта структура позволяет Homebrew более эффективно управлять зависимостями, версиями и бинарными пакетами. Когда вы пытаетесь установить из локального пути к файлу, такого как ./Formula/mypackage.rb, Homebrew отклоняет его, потому что:
- Bottle должны быть связаны с определенным tap для правильного управления версиями
- Структура tap предоставляет метаданные о зависимостях и совместимости
- Bottle хранятся в каталогах, специфичных для tap, со стандартными соглашениями об именовании
Как объясняется в обсуждениях Homebrew, “Убедитесь, что Formula/my_formular.rb находится в Homebrew tap (например, созданном с помощью brew tap-new), и ссылайтесь на него по имени, а не с использованием относительного пути”.
Решение 1: Создание локальной структуры tap
Наиболее надежным решением является создание правильной структуры tap внутри вашего репозитория. Этот подход имитирует организацию официальных tap Homebrew.
-
Создайте структуру каталогов tap:
ваш-репозиторий/ ├── .github/ │ └── workflows/ │ └── build.yml ├── Formula/ │ └── mypackage.rb └── Homebrew/ └── tap.rb -
Создайте простой файл tap.rb:
ruby# Homebrew/tap.rb require "tap" class YourTap < Tap url "https://github.com/ваше-имя/ваш-репозиторий" sha256 "ваша_контрольная_сумма" # Вы можете сгенерировать ее после первой сборки end -
Обновите ваш workflow GitHub Actions:
yaml- name: build package run: | brew tap-new ваше-имя/ваш-репозиторий brew install --build-bottle --formula ./Formula/mypackage.rb brew bottle mypackage
Этот подход позволяет собирать из вашей локальной formula, сохраняя правильный контекст tap.
Решение 2: Использование brew tap-new
Вы можете создать временный tap в среде GitHub Actions с помощью brew tap-new:
- name: build package
run: |
brew tap-new ваше-имя/ваш-репозиторий
brew install --build-bottle --formula ./Formula/mypackage.rb
brew bottle mypackage
Эта команда создает tap, с которым может быть ассоциирована ваша локальная formula. Formula будет ссылаться по ее полному имени tap (ваше-имя/ваш-репозиторий/mypackage), а не по пути к файлу.
Решение 3: Использование brew bottle с путем к Formula
Согласно решению на Stack Overflow, вы можете использовать флаг --formula с локальным путем:
- name: build package
run: |
brew install --build-bottle --formula ./Formula/mypackage.rb
brew bottle --json --write ./Formula/mypackage.rb
Опции --json --write генерируют DSL bottle, который может быть вставлен в ваш файл formula. Этот подход напрямую решает вашу первоначальную попытку, добавляя необходимые флаги.
Полный workflow GitHub Actions
Вот комплексный workflow, который охватывает все аспекты сборки bottle:
name: Build Homebrew Bottle
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, macos-13, macos-12]
steps:
- uses: actions/checkout@v3
- name: Set up Homebrew
uses: Homebrew/actions/setup-homebrew@master
- name: Build bottle
run: |
# Создаем временный tap
brew tap-new ваше-имя/ваш-репозиторий
# Собираем из локальной formula
brew install --build-bottle --formula ./Formula/mypackage.rb
# Генерируем bottle
brew bottle mypackage
# Загружаем артефакты
find . -name "*.bottle.tar.gz" -exec sh -c 'echo "::set-output name=artifact::$(basename "$0")"' {} \ |
while read artifact; do
echo "::upload-artifact::${artifact}"
done
- name: Generate bottle DSL
run: |
brew bottle --json --write ./Formula/mypackage.rb
git add ./Formula/mypackage.rb
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git commit -m "Update bottle DSL" || true
git push
Этот workflow:
- Поддерживает несколько версий macOS
- Создает правильный контекст tap
- Собирает bottle из вашей локальной formula
- Загружает артефакты как релизы GitHub
- Обновляет formula с метаданными bottle
Устранение распространенных проблем
Проблемы с зависимостями: Если ваша formula имеет зависимости, недоступные в стандартном репозитории Homebrew, вам может потребоваться установить их сначала:
- name: Install dependencies
run: |
brew install dependency1 dependency2
Проблемы с Cellar: Bottle должны собираться в правильном расположении cellar. Если вы используете пользовательскую установку Homebrew:
- name: Set up custom Homebrew
run: |
echo '/usr/local/opt/python/libexec/bin' >> $GITHUB_PATH
Именование bottle: Bottle должны следовать соглашению об именовании {formula}-{version}-{os}-{arch}.bottle.tar.gz. Команда brew bottle обрабатывает это автоматически.
Лучшие практики
- Используйте несколько версий ОС: Собирайте bottle для разных версий macOS для обеспечения совместимости
- Тестируйте перед сборкой: Всегда тестируйте вашу formula с помощью
brew install --dry-runперед сборкой bottle - Обновляйте bottle DSL: После сборки обновляйте вашу formula сгенерированным DSL bottle
- Используйте GitHub Releases: Загружайте bottle как релизы GitHub для легкой дистрибуции
- Управляйте зависимостями: Убедитесь, что все зависимости правильно указаны и доступны
Согласно руководству Джонатана Чанга, “Когда библиотека, от которой зависит ваша formula, имеет критические изменения (например, Boost), вам нужно будет увеличить номер ревизии; если он еще не присутствует в вашей formula, просто добавьте revision 1.”
Источники
- Build Homebrew bottle in GitHub Actions - Stack Overflow
- Homebrew tap with bottles uploaded to GitHub Releases — Homebrew
- Create bottle from local Formula · Homebrew · Discussion #4468
- Maintain your own Homebrew repository, with binary bottles · Jonathan Chang
- Automate build workflow for Homebrew tap bottles (Linux and macOS) · GitHub Gist
- Bottles.md - Homebrew Documentation
Заключение
Сборка Homebrew bottle из локальных formulae в GitHub Actions требует понимания архитектуры tap Homebrew. Ключевые решения:
- Создайте правильную структуру tap - Это наиболее надежный подход, который отражает официальные практики Homebrew
- Используйте
brew tap-new- Создает временный контекст tap для вашей локальной formula - Используйте флаг
--formula- Позволяет собирать из локальных путей с правильными флагами - Генерируйте bottle DSL - Обновляет вашу formula с метаданными bottle после сборки
Реализовав одно из этих решений, вы сможете успешно собирать bottle из ваших локальных файлов formula, сохраняя совместимость с системой bottle Homebrew. Рекомендуемый подход - создание правильной структуры tap, так как он предоставляет наиболее надежное и поддерживаемое решение для workflow непрерывной интеграции.