Spec-Zone.ru › Homebrew

brew livecheck

Команда brew livecheck находит новейшую версию программного обеспечения формулы или cask, проверяя upstream. Livecheck использует стратегии для определения версий из различных источников, таких как репозитории Git, веб-сайты и т. д.

Поведение

Если для livecheck не заданы инструкции о том, как проверять версии upstream, по умолчанию выполняются следующие действия:

  1. Собирается список URL для проверки.
  • Для формул: используются URL stable, head и homepage в указанном порядке.
  • Для ресурсов формул: используется url.
  • Для cask: используются URL url и homepage в указанном порядке.
  1. Определяется, применимы ли какие-либо стратегии к первому URL. Если нет, проверяется следующий URL.
  2. Если стратегию можно применить, с её помощью проверяются новые версии.
  3. Возвращается новейшая версия (или ошибка, если ни по одному из доступных URL не удалось найти версии).

Иногда необходимо переопределить это поведение по умолчанию, чтобы проверка работала. Если источник не содержит новейшую версию, нужно проверить другой источник. Если livecheck неправильно сопоставляет текст версии, необходимо задать подходящее регулярное выражение или блок strategy.

Это можно сделать, добавив блок livecheck в формулу/cask/ресурс. Дополнительную информацию о доступных методах см. в документации класса Livecheck.

Создание проверки

  1. Изучите отладочный вывод, чтобы понять ситуацию. brew livecheck --debug <formula>|<cask> содержит сведения о том, какие URL проверяет livecheck, какие стратегии применимы, какие версии сопоставлены и т. д.

  2. Изучите доступные источники и выберите URL. Попробуйте удалить имя файла из stable/url и проверьте, откроется ли страница со списком файлов в каталоге. Если это не поможет, попробуйте найти страницу со ссылкой на файл (например, страницу загрузки). Если на веб-сайте невозможно найти новейшую версию, попробуйте проверить другие источники, указанные в формуле/cask. При необходимости поищите другие источники за пределами формулы/cask.

  3. При необходимости создайте регулярное выражение. Если проверка работает без регулярного выражения и оно не принесёт пользы, обычно его можно не указывать. Дополнительную информацию о создании регулярных выражений см. в разделе рекомендации по регулярным выражениям.

Общие рекомендации

  • Используйте strategy только при необходимости. Например, если livecheck уже использует стратегию Git для URL, использовать strategy :git не нужно. Однако если к URL применима Git, но необходимо использовать PageMatch, нужно указать strategy :page_match.

  • Используйте стратегии GithubLatest и GithubReleases только при необходимости и если они подходят. GitHub ограничивает частоту запросов к API, поэтому мы используем эти стратегии, только если Git недостаточна или не подходит. GithubLatest следует использовать только в том случае, если в upstream-репозитории есть подходящий релиз «latest» и формула/cask использует ресурс релиза либо стратегия Git не может правильно определить версию последнего релиза. GithubReleases следует использовать только в том случае, если в upstream-репозитории используются релизы, а стратегии Git и GithubLatest не подходят.

Рекомендации по URL

  • В блоке livecheck обязательно должен быть указан url. Это может быть строка URL (например, "https://www.example.com/downloads/") или символ URL формулы/cask (то есть :stable, :url, :head, :homepage). Исключение из этого правила — блок livecheck, в котором используется только skip.

  • По возможности проверяйте версии в том же месте, где находится стабильный архив.

  • По возможности не проверяйте страницы релизов с постраничной навигацией. Например, мы обычно не проверяем страницу release проекта на GitHub, поскольку предварительные версии могут вытеснить последнюю стабильную версию с первой страницы. В этом случае надёжнее использовать стратегию Git, которая получает все теги репозитория.

Рекомендации по регулярным выражениям

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

  • По возможности регулярные выражения следует делать нечувствительными к регистру, добавляя в конце i (например, /.../i или %r{...}i). Это повышает надёжность: регулярное выражение будет учитывать изменения регистра букв без необходимости вносить правки.

  • В регулярных выражениях следует использовать группу захвата только для текста версии. Например, в /href=.*?example-v?(\d+(?:\.\d+)+)(?:-src)?\.t/i группа захвата используется только для текста версии (сопоставляя версию вроде 1.2, 1.2.3 и т. д.), а в остальных местах используются незахватывающие группы (например, (?:-src)?).

  • Используйте привязки к началу/концу регулярного выражения, чтобы ограничить область поиска. Например, на HTML-страницах мы часто сопоставляем имена файлов или каталоги версий в URL атрибутов href (например, /href=.*?example[._-]v?(\d+(?:\.\d+)+)\.zip/i). В целом ограничение области поиска помогает исключить нежелательные совпадения.

  • Не используйте универсальные шаблоны вроде .* или .+; вместо них выбирайте нежадные и/или подходящие по контексту выражения. Например, для сопоставления символов внутри HTML-атрибута используйте [^"' >]+?.

  • Используйте [._-] вместо точки/подчёркивания/дефиса между названием программы и версией в имени файла. Для файла с именем example-1.2.3.tar.gz выражение example[._-]v?(\d+(?:\.\d+)+)\.t продолжит работать, даже если формат имени файла upstream изменится на example_1.2.3.tar.gz или example.1.2.3.tar.gz.

  • Используйте \.t вместо \.tgz, \.tar\.gz и т. д. Для tar-архивов существует множество расширений (например, .tar.bz2, tbz2, .tar.gz, .tgz, .tar.xz, .txz и т. д.), и со временем upstream-источник может перейти с одного формата сжатия на другой. \.t позволяет избежать этой проблемы: оно сопоставляет текущие и будущие форматы, начинающиеся с t. Для файлов, не являющихся tar-архивами, в регулярном выражении используется полное расширение файла, например \.zip, \.jar и т. д.

Примеры блоков livecheck

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

Если вы сомневаетесь, начните с одного из этих примеров, а не копируйте блок livecheck из случайной формулы/cask.

Имена файлов

При сопоставлении версии по имени файла на HTML-странице мы часто ограничиваем поиск атрибутами href. href=.*? сопоставляет открывающий разделитель (", '), а также любую часть URL перед именем файла.

livecheck do
  url "https://www.example.com/downloads/"
  regex(/href=.*?example[._-]v?(\d+(?:\.\d+)+)\.t/i)
end

Иногда мы делаем выражение более точным, чтобы исключить нежелательные совпадения. Для URL с предшествующим путём можно использовать href=.*?/, а для остальных — href=["']?. Например, это необходимо, если на странице также есть нежелательные файлы с более длинным префиксом (another-example-1.2.tar.gz).

Каталоги версий

При проверке страницы со списком файлов иногда файлы размещаются в отдельных каталогах версий (например, 1.2.3/). В этом случае необходимо определять версии по именам каталогов.

livecheck do
  url "https://www.example.com/releases/example/"
  regex(%r{href=["']?v?(\d+(?:\.\d+)+)/?["' >]}i)
end

Теги Git

Если для URL stable используется стратегия Git, приведённый ниже пример будет сопоставлять только теги вида 1.2/v1.2 и т. д.

livecheck do
  url :stable
  regex(/^v?(\d+(?:\.\d+)+)$/i)
end

Если название программы используется в качестве префикса тегов (например, example-1.2.3), регулярное выражение легко изменить соответствующим образом: /^example[._-]v?(\d+(?:\.\d+)+)$/i

Ссылка на формулу/cask

Формула/cask может использовать ту же проверку, что и другая формула/cask, с помощью formula или cask.

livecheck do
  formula "another-formula"
end

Формула/cask, на которую ссылаются, должна находиться в том же tap, поскольку ссылка на формулу/cask из другого tap приведёт к ошибке, если пользователь ещё не добавил этот tap.

Ресурс формулы, версия которого синхронизирована с нумерацией версий родительской формулы, может использовать ту же проверку с помощью formula :parent.

livecheck do
  formula :parent
end

Запросы POST

Для некоторых проверок требуется отправить запрос POST. Это можно сделать, добавив параметр post_form или post_json в блок livecheck url.

livecheck do
  url "https://example.com/download.php", post_form: {
    Name:     "",
    "E-mail": "",
  }
  regex(/href=.*?example[._-]v?(\d+(?:\.\d+)+)\.t/i)
end

post_form используется для данных формы, а post_json — для данных JSON. Перед отправкой запроса Livecheck кодирует предоставленное значение хеша в подходящий формат.

Поддержка POST распространяется только на стратегии, которые прямо или косвенно используют Strategy::page_headers или ::page_content, поэтому она не применима к ExtractPlist, Git, GithubLatest, GithubReleases и т. д.

Блоки strategy

Если формат версии upstream необходимо преобразовать, чтобы он соответствовал формату формулы/cask, вместо regex можно использовать блок strategy.

Блок стратегии PageMatch strategy

Вот простой пример извлечения простой версии со страницы:

livecheck do
  url "https://example.org/my-app/download"
  regex(%r{href=.*?/MyApp-(\d+(?:\.\d+)*)\.zip}i)
  strategy :page_match
end

Более сложные версии можно обработать, задав блок.

livecheck do
  url "https://example.org/my-app/download"
  regex(%r{href=.*?/(\d+)/MyApp-(\d+(?:\.\d+)*)\.zip}i)
  strategy :page_match do |page, regex|
    match = page.match(regex)
    next if match.blank?

    "#{match[2]},#{match[1]}"
  end
end

В примере ниже мы ищем на главной странице дату в формате 2020-01-01 и преобразуем её в 20200101.

livecheck do
  url :homepage
  strategy :page_match do |page|
    page.scan(/href=.*?example[._-]v?(\d{4}-\d{2}-\d{2})\.t/i)
        .map { |match| match&.first&.gsub(/\D/, "") }
  end
end

Показанный здесь стиль блока PageMatch strategy также применим к любой стратегии для конкретного сайта, которая внутри использует PageMatch.

Блок стратегии HeaderMatch strategy

Блок strategy для HeaderMatch пытается извлечь версию из имени файла (в заголовке Content-Disposition) и конечного URL (в заголовке Location). Если это не удаётся, можно указать regex.

livecheck do
  url "https://example.org/my-app/download/latest"
  regex(/MyApp-(\d+(?:\.\d+)*)\.zip/i)
  strategy :header_match
end

Если версия зависит от нескольких полей заголовка, можно задать блок.

livecheck do
  url "https://example.org/my-app/download/latest"
  strategy :header_match do |headers|
    v = headers["content-disposition"][/MyApp-(\d+(?:\.\d+)*)\.zip/i, 1]
    id = headers["location"][%r{/(\d+)/download$}i, 1]
    next if v.blank? || id.blank?

    "#{v},#{id}"
  end
end

Блок стратегии Git strategy

Блок strategy для Git устроен несколько иначе: вместо строки содержимого страницы он получает массив строк тегов. Как и в примере с PageMatch, здесь теги с датой в формате 2020-01-01 преобразуются в 20200101.

livecheck do
  url :stable
  strategy :git do |tags|
    tags.filter_map { |tag| tag[/^(\d{4}-\d{2}-\d{2})$/i, 1]&.gsub(/\D/, "") }
  end
end

Блок стратегии GithubLatest strategy

Блок strategy для GithubLatest получает разобранные данные JSON из GitHub API для последнего релиза «latest» репозитория, а также регулярное выражение. Если регулярное выражение не задано в блоке livecheck, вместо него в блок strategy передаётся регулярное выражение стратегии по умолчанию.

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

livecheck do
  url :stable
  regex(/^example[._-]v?(\d+(?:\.\d+)+)$/i)
  strategy :github_latest do |json, regex|
    match = json["tag_name"]&.match(regex)
    next if match.blank?

    match[1]
  end
end

Дополнительную информацию о JSON-ответе этой конечной точки API см. в соответствующей документации GitHub REST API.

Блок стратегии GithubReleases strategy

Блок strategy для GithubReleases получает разобранные данные JSON из GitHub API о последних релизах репозитория, а также регулярное выражение. Если регулярное выражение не задано в блоке livecheck, вместо него в блок strategy передаётся регулярное выражение стратегии по умолчанию.

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

livecheck do
  url :stable
  regex(/^example[._-]v?(\d+(?:\.\d+)+)$/i)
  strategy :github_releases do |json, regex|
    json.map do |release|
      next if release["draft"] || release["prerelease"]

      match = release["tag_name"]&.match(regex)
      next if match.blank?

      match[1]
    end
  end
end

По умолчанию логика стратегии пропускает релизы, помеченные как черновики или предварительные версии, но это можно изменить с помощью блока strategy. Если убрать условие release["prerelease"] из предыдущего примера, можно будет обрабатывать предварительные релизы, хотя регулярное выражение также может потребоваться адаптировать для нестабильных форматов версий.

Дополнительную информацию о JSON-ответе этой конечной точки API см. в соответствующей документации GitHub REST API.

Блок стратегии Crate strategy

Блок strategy для Crate получает разобранные данные JSON из конечной точки versions API реестра и предоставленное регулярное выражение стратегии либо регулярное выражение по умолчанию. По умолчанию стратегия использует следующую логику, поэтому этот блок strategy может стать хорошей отправной точкой для изменения подхода:

livecheck do
  url :stable
  strategy :crate do |json, regex|
    json["versions"]&.map do |version|
      next if version["yanked"]
      next unless (match = version["num"]&.match(regex))

      match[1]
    end
  end
end

Блок стратегии ElectronBuilder strategy

Блок strategy для ElectronBuilder загружает содержимое по URL и разбирает его как appcast electron-builder в формате YAML. Он используется для cask приложений macOS, созданных с помощью фреймворка Electron.

livecheck do
  url "https://example.org/my-app/latest-mac.yml"
  strategy :electron_builder
end

Если необходимо изменить версию, можно получить доступ к хешу YAML в блоке strategy следующим образом:

livecheck do
  url "https://example.org/my-app/latest-mac.yml"
  strategy :electron_builder do |yaml|
    yaml["version"]&.gsub(/\D/, "")
  end
end

Аналогичным образом можно работать с массивом files:

livecheck do
  url "https://example.org/my-app/latest-mac.yml"
  regex(/MyApp[._-]v?(\d+(?:\.\d+)+)-(\h+)\.dmg/i)
  strategy :electron_builder do |yaml, regex|
    yaml["files"]&.map do |file|
      match = file["url"]&.match(regex)
      next if match.blank?

      "#{match[1]},#{match[2]}"
    end
  end
end

Блок стратегии Json strategy

Блок strategy для Json получает разобранные данные JSON и, если оно задано, регулярное выражение. Например, если у нас есть объект с массивом объектов, содержащих строку version, можно выбрать только элементы, соответствующие регулярному выражению, и извлечь нужный текст версии следующим образом:

livecheck do
  url "https://www.example.com/example.json"
  regex(/^v?(\d+(?:\.\d+)+)$/i)
  strategy :json do |json, regex|
    json["versions"].select { |item| item["version"]&.match?(regex) }
                    .map { |item| item["version"][regex, 1] }
  end
end

Блок стратегии Sparkle strategy

Блок strategy для Sparkle получает объект item, методы которого позволяют работать с version, short_version, nice_version, url, channel и title. Он ожидает URL XML-ленты с информацией о релизах для приложения macOS, которое обновляется самостоятельно с помощью фреймворка Sparkle. Этот URL можно найти в пакете приложения: он указан в свойстве SUFeedURL файла Contents/Info.plist. Также его можно найти с помощью команды find-appcast. Выполните её так:

brew find-appcast '/path/to/application.app'

По умолчанию стратегия Sparkle формирует "#{item.short_version},#{item.version}" на основе sparkle:shortVersionString и sparkle:version, если заданы оба значения. В примере ниже возвращаемое значение также содержит необходимый идентификатор загрузки из url:

livecheck do
  url "https://www.example.com/example.xml"
  strategy :sparkle do |item|
    "#{item.short_version},#{item.version}:#{item.url[%r{/(\d+)/[^/]+\.zip}i, 1]}"
  end
end

Чтобы использовать только одно значение, укажите &:version, &:short_version или &:nice_version:

livecheck do
  url "https://www.example.com/example.xml"
  strategy :sparkle, &:short_version
end

Если значение, возвращаемое item, не является самым последним или не соответствует нужному, передайте вместо него items, чтобы перебрать все элементы ленты:

livecheck do
  url "https://www.example.com/example.xml"
  strategy :sparkle do |items|
    items.find { |item| item.channel.nil? }&.short_version
  end
end

Блок стратегии Xml strategy

Блок strategy для Xml получает объект REXML::Document и, если оно задано, регулярное выражение. Например, если XML содержит элемент versions с вложенными элементами version, а их внутренний текст содержит строку версии, её можно извлечь с помощью регулярного выражения следующим образом:

livecheck do
  url "https://www.example.com/example.xml"
  regex(/v?(\d+(?:\.\d+)+)/i)
  strategy :xml do |xml, regex|
    xml.get_elements("versions//version").map { |item| item.text[regex, 1] }
  end
end

Дополнительную информацию о работе с объектом REXML::Document см. в документации REXML::Document и REXML::Element.

Блок стратегии Yaml strategy

Блок strategy для Yaml получает разобранные данные YAML и, если оно задано, регулярное выражение. Возьмём за основу пример Json: если у нас есть объект с массивом объектов, содержащих строку version, можно выбрать только элементы, соответствующие регулярному выражению, и извлечь нужный текст версии следующим образом:

livecheck do
  url "https://www.example.com/example.yaml"
  regex(/^v?(\d+(?:\.\d+)+)$/i)
  strategy :yaml do |yaml, regex|
    yaml["versions"].select { |item| item["version"]&.match?(regex) }
                    .map { |item| item["version"][regex, 1] }
  end
end

Блок стратегии ExtractPlist strategy

Если в интернете нет возможности проверить, какая версия пакета macOS является актуальной, в крайнем случае стратегия :extract_plist заставит brew livecheck загрузить файл и получить строку версии из содержащихся в нём файлов .plist.

livecheck do
  url :url
  strategy :extract_plist
end

Блок strategy для ExtractPlist получает хеш, содержащий ключи для каждого найденного идентификатора пакета, и объекты item с методами для каждого version и short_version.

livecheck do
  url :url
  strategy :extract_plist do |items|
    items["com.example.MyApp"].short_version
  end
end

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

throttle

Для программ с очень частыми выпусками, не каждый из которых нужно публиковать в виде обновления формулы/cask, в livecheck можно настроить уменьшение числа отображаемых версий с помощью throttle. В этом примере возвращаются только версии, последняя часть которых делится на 10 без остатка.

livecheck do
  url :stable
  regex(/^v?(\d+(?:\.\d+)+)$/i)
  throttle 10
end

skip

Livecheck автоматически пропускает некоторые формулы/cask по ряду причин (устаревшие, отключённые и т. д.). Однако в редких случаях для ручного пропуска необходимо использовать блок livecheck. Метод skip принимает строку с очень кратким объяснением причины пропуска.

livecheck do
  skip "No version information available"
end

© 2009–present Homebrew contributors
Licensed under the BSD 2-Clause License.
https://docs.brew.sh/Brew-Livecheck

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API