brew livecheck

brew livecheck 指令透過檢查上游來尋找公式或 cask 軟體的最新版本。Livecheck 具有 策略,可從各種來源(例如 Git 儲存庫、網站等)識別版本。

行為

當 livecheck 未收到如何檢查上游版本的指示時,它會預設執行下列動作

  1. 對於公式:按順序收集 stableheadhomepage URL(資源僅使用其 url)。對於 cask:按順序收集 urlhomepage URL。
  2. 判斷是否有任何策略適用於第一個 URL。如果沒有,則嘗試下一個 URL。
  3. 如果可以套用策略,則使用它來檢查新版本。
  4. 傳回最新版本(或如果在任何可用 URL 中找不到版本,則傳回錯誤)。

有時需要覆寫此預設行為才能建立運作良好的檢查。如果來源未提供最新版本,我們需要檢查其他來源。如果 livecheck 無法正確比對版本文字,我們需要提供適當的正規表示法或 strategy 區塊。

這可透過將 livecheck 區塊新增至公式/cask/資源來達成。如需有關可用方法的更多資訊,請參閱 Livecheck 類別文件

建立檢查

  1. 使用偵錯輸出了解情況brew livecheck --debug <formula>|<cask> 提供有關 livecheck 嘗試的 URL、任何適用的策略、比對版本等資訊。

  2. 研究可用來源以選擇 URL。嘗試從 stable/url 中移除檔案名稱,看看它是否提供目錄清單頁面。如果這不起作用,請嘗試尋找連結至檔案的頁面(例如下載頁面)。如果無法在網站上找到最新版本,請嘗試檢查公式/cask 中的其他來源。必要時,請在公式/cask 外搜尋其他來源。

  3. 必要時建立正規表示法。如果檢查在沒有正規表示法的情況下運作,而且不會從中受益,則通常可以省略它。有關建立正規表示法的更多資訊,請參閱 正規表示法指南 部分。

一般指南

URL 指南

Regex 指南

livecheck 區塊 regex 將比對限制在擷取內容的子集,並在版本文字周圍使用擷取群組。

範例 livecheck 區塊

以下範例涵蓋您可能會遇到的許多模式。這些範例旨在成為具代表性的範例,而且可以輕鬆調整。

如果您有疑問,請從這些範例中挑選一個開始,而不是從隨機公式/cask 複製貼上 livecheck 區塊。

檔案名稱

當從 HTML 頁面上的檔案名稱比對版本時,我們通常會將比對限制在 href 屬性。 href=.*? 會比對開啟分隔符號 ("') 以及檔案名稱之前的任何 URL 部分。

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

我們有時會更明確地排除不需要的比對。有前置路徑的 URL 可以使用 href=.*?/,其他 URL 則可以使用 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 標籤

stable URL 使用 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 可以使用 formulacask 來使用與另一個相同的檢查。

livecheck do
  formula "another-formula"
end

參考的公式/cask 應該在同一個 tap 中,因為如果使用者尚未 tap 另一個 tap 中的公式/cask,參考會產生錯誤。

strategy 區塊

如果上游版本格式需要經過處理才能與公式/cask 格式相符,可以使用 strategy 區塊,而不是 regex

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 策略 區塊

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 策略 區塊

Git策略 區塊有點不同,因為區塊接收標籤字串陣列,而不是頁面內容字串。類似於 PageMatch 範例,這會將日期格式為 2020-01-01 的標籤轉換為 20200101

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

GithubLatest 策略 區塊

GithubLatest策略 區塊會接收 GitHub API 解析的 JSON 資料,以取得儲存庫的「最新」版本,以及一個 regex。如果在 livecheck 區塊中未提供 regex,則會將策略的預設 regex 傳遞到 策略 區塊中。

預設情況下,策略會比對版本文字在版本標籤或標題中,但可以使用 策略 區塊來檢查版本 JSON 中的任何欄位。下列 策略 區塊中的邏輯類似於預設行為,但僅檢查版本標籤,以示範為目的

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

您可以在相關的 GitHub REST API 文件 中找到更多關於此 API 端點回應 JSON 的資訊。

GithubReleases 策略 區塊

GithubReleases策略 區塊會接收 GitHub API 解析的 JSON 資料,以取得儲存庫的最新版本,以及一個 regex。如果在 livecheck 區塊中未提供 regex,則會將策略的預設 regex 傳遞到 策略 區塊中。

預設情況下,策略會比對每個版本標籤或標題中的版本文字,但可以使用 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

您可以在相關的 GitHub REST API 文件 中找到此 API 端點的回應 JSON 的更多資訊。

Crate strategy 區塊

針對 Cratestrategy 區塊會從登錄 API 的 versions 端點接收已剖析的 JSON 資料,以及提供的或預設的策略正規表示式。預設情況下,策略會使用下列邏輯,因此這個 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 區塊

針對 ElectronBuilderstrategy 區塊會擷取 URL 中的內容,並將其剖析為 YAML 格式的 electron-builder appcast。它用於使用 Electron 架構建置的 macOS 應用程式的 cask。

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

Json strategy 區塊

針對 Jsonstrategy 區塊會接收已剖析的 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 區塊

針對 Sparklestrategy 區塊會接收一個 item,其中有 versionshort_versionnice_versionurlchanneltitle 的方法。它預期有一個 XML 饋送的 URL,提供版本資訊給使用 Sparkle 架構進行自我更新的 macOS 應用程式。這個 URL 可以從應用程式套件中找到,作為 Contents/Info.plist 中的 SUFeedURL 屬性,或使用 find-appcast 腳本。使用下列方式執行

"$(brew --repository homebrew/cask)/developer/bin/find-appcast" '/path/to/application.app'

針對 Sparkle 策略的預設模式是從 sparkle:shortVersionStringsparkle:version 產生 "#{item.short_version},#{item.version}",如果兩個都設定的話。在下列範例中,url 也包含一個需要的下載 ID

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

Xml 策略 區塊

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::DocumentREXML::Element 文件。

Yaml 策略 區塊

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 策略 區塊

如果網路上沒有任何方法可以查看 macOS 套件的哪個版本是目前的,那麼作為最後的手段,:extract_plist 策略會讓 brew livecheck 下載成品,並從包含的 .plist 檔案中擷取其版本字串。

livecheck do
  url :url
  strategy :extract_plist
end

一個 strategy 區塊用於 ExtractPlist 接收一個雜湊,其中包含每個已找到的套件識別碼的鍵,以及具有每個 versionshort_version 方法的 item

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

略過

Livecheck 會自動略過一些公式/木桶,原因有很多(已棄用、已停用等)。但是,在極少數情況下,我們需要使用 livecheck 區塊進行手動略過。 skip 方法會取得一個包含略過原因的簡短字串。

livecheck do
  skip "No version information available"
end
Fork me on GitHub