НейроАгент

Сборка Homebrew Bottle из локальной формулы в GitHub Actions

Узнайте, как собирать Homebrew bottle из локальных файлов формул в GitHub Actions. Решите ошибку 'requires formulae to be in a tap' с проверенными решениями и полными примерами рабочих процессов.

Как создать Homebrew-бутылку из локального файла формулы в GitHub Actions?

Я хочу использовать GitHub Actions для создания бутылки для формулы Homebrew, которая находится в том же репозитории. Мой текущий подход:

yaml
- 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

Система 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.

  1. Создайте структуру каталогов tap:

    ваш-репозиторий/
    ├── .github/
    │   └── workflows/
    │       └── build.yml
    ├── Formula/
    │   └── mypackage.rb
    └── Homebrew/
        └── tap.rb
    
  2. Создайте простой файл tap.rb:

    ruby
    # Homebrew/tap.rb
    require "tap"
    
    class YourTap < Tap
      url "https://github.com/ваше-имя/ваш-репозиторий"
      sha256 "ваша_контрольная_сумма" # Вы можете сгенерировать ее после первой сборки
    end
    
  3. Обновите ваш 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:

yaml
- 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 с локальным путем:

yaml
- 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:

yaml
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, вам может потребоваться установить их сначала:

yaml
- name: Install dependencies
  run: |
    brew install dependency1 dependency2

Проблемы с Cellar: Bottle должны собираться в правильном расположении cellar. Если вы используете пользовательскую установку Homebrew:

yaml
- 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 обрабатывает это автоматически.

Лучшие практики

  1. Используйте несколько версий ОС: Собирайте bottle для разных версий macOS для обеспечения совместимости
  2. Тестируйте перед сборкой: Всегда тестируйте вашу formula с помощью brew install --dry-run перед сборкой bottle
  3. Обновляйте bottle DSL: После сборки обновляйте вашу formula сгенерированным DSL bottle
  4. Используйте GitHub Releases: Загружайте bottle как релизы GitHub для легкой дистрибуции
  5. Управляйте зависимостями: Убедитесь, что все зависимости правильно указаны и доступны

Согласно руководству Джонатана Чанга, “Когда библиотека, от которой зависит ваша formula, имеет критические изменения (например, Boost), вам нужно будет увеличить номер ревизии; если он еще не присутствует в вашей formula, просто добавьте revision 1.”

Источники

  1. Build Homebrew bottle in GitHub Actions - Stack Overflow
  2. Homebrew tap with bottles uploaded to GitHub Releases — Homebrew
  3. Create bottle from local Formula · Homebrew · Discussion #4468
  4. Maintain your own Homebrew repository, with binary bottles · Jonathan Chang
  5. Automate build workflow for Homebrew tap bottles (Linux and macOS) · GitHub Gist
  6. Bottles.md - Homebrew Documentation

Заключение

Сборка Homebrew bottle из локальных formulae в GitHub Actions требует понимания архитектуры tap Homebrew. Ключевые решения:

  1. Создайте правильную структуру tap - Это наиболее надежный подход, который отражает официальные практики Homebrew
  2. Используйте brew tap-new - Создает временный контекст tap для вашей локальной formula
  3. Используйте флаг --formula - Позволяет собирать из локальных путей с правильными флагами
  4. Генерируйте bottle DSL - Обновляет вашу formula с метаданными bottle после сборки

Реализовав одно из этих решений, вы сможете успешно собирать bottle из ваших локальных файлов formula, сохраняя совместимость с системой bottle Homebrew. Рекомендуемый подход - создание правильной структуры tap, так как он предоставляет наиболее надежное и поддерживаемое решение для workflow непрерывной интеграции.