Sparkle: Provide channel information in Item

Making `channel` information available in the `Item` is necessary
to be able to filter out unstable items using a `strategy` block. If
an item doesn't specify a channel, then it uses the default channel
(this is what Sparkle itself uses for updates). Channels like `beta`
are something we want to avoid for stable casks and this allows for
that type of [cask-specific] filtering.

It's technically possible to automatically filter out items that
aren't using the default channel (i.e., `channel != nil`) in
`#items_from_content` but some casks use an unstable version, so we
can't do this internally. That is to say, we wouldn't be able to
override internal filtering in a `strategy` block, as any omitted
items wouldn't be provided to the block. Conversely, if we pass all
items to a `strategy` block, we can easily filter by channel there.
We haven't been filtering by channel internally and we've only found
one cask where this has been a problem, so it seems fine for now.
This commit is contained in:
Sam Ford 2022-06-02 10:04:34 -04:00
parent 68043d4e72
commit c6907f911f
No known key found for this signature in database
GPG Key ID: 7AF5CBEE1DD6F76D
2 changed files with 27 additions and 1 deletions

View File

@ -36,6 +36,8 @@ module Homebrew
Item = Struct.new( Item = Struct.new(
# @api public # @api public
:title, :title,
# @api public
:channel,
# @api private # @api private
:pub_date, :pub_date,
# @api public # @api public
@ -102,6 +104,7 @@ module Homebrew
os = enclosure["os"] os = enclosure["os"]
end end
channel = item.elements["channel"]&.text
url ||= item.elements["link"]&.text url ||= item.elements["link"]&.text
short_version ||= item.elements["shortVersionString"]&.text&.strip short_version ||= item.elements["shortVersionString"]&.text&.strip
version ||= item.elements["version"]&.text&.strip version ||= item.elements["version"]&.text&.strip
@ -135,6 +138,7 @@ module Homebrew
data = { data = {
title: title, title: title,
channel: channel,
pub_date: pub_date, pub_date: pub_date,
url: url, url: url,
bundle_version: bundle_version, bundle_version: bundle_version,

View File

@ -75,6 +75,13 @@ describe Homebrew::Livecheck::Strategy::Sparkle do
EOS EOS
appcast_with_omitted_items = appcast_xml.sub("</item>", "</item>\n#{extra_items}") appcast_with_omitted_items = appcast_xml.sub("</item>", "</item>\n#{extra_items}")
beta_channel_item = appcast_xml.sub(
first_item,
first_item.sub(
"</title",
"</title>\n<sparkle:channel>beta</sparkle:channel>",
),
)
no_versions_item = no_versions_item =
appcast_xml appcast_xml
.sub(second_item, "") .sub(second_item, "")
@ -89,6 +96,7 @@ describe Homebrew::Livecheck::Strategy::Sparkle do
{ {
appcast: appcast_xml, appcast: appcast_xml,
appcast_with_omitted_items: appcast_with_omitted_items, appcast_with_omitted_items: appcast_with_omitted_items,
beta_channel_item: beta_channel_item,
no_versions_item: no_versions_item, no_versions_item: no_versions_item,
no_items: no_items, no_items: no_items,
undefined_namespace: undefined_namespace_xml, undefined_namespace: undefined_namespace_xml,
@ -98,7 +106,7 @@ describe Homebrew::Livecheck::Strategy::Sparkle do
let(:title_regex) { /Version\s+v?(\d+(?:\.\d+)+)\s*$/i } let(:title_regex) { /Version\s+v?(\d+(?:\.\d+)+)\s*$/i }
let(:items) { let(:items) {
{ items = {
appcast: [ appcast: [
Homebrew::Livecheck::Strategy::Sparkle::Item.new( Homebrew::Livecheck::Strategy::Sparkle::Item.new(
title: item_hash[0][:title], title: item_hash[0][:title],
@ -122,6 +130,12 @@ describe Homebrew::Livecheck::Strategy::Sparkle do
), ),
], ],
} }
beta_channel_item = items[:appcast][0].clone
beta_channel_item.channel = "beta"
items[:beta_channel_item] = [beta_channel_item, items[:appcast][1].clone]
items
} }
let(:versions) { [items[:appcast][0].nice_version] } let(:versions) { [items[:appcast][0].nice_version] }
@ -152,6 +166,7 @@ describe Homebrew::Livecheck::Strategy::Sparkle do
expect(first_item.short_version).to eq(item_hash[0][:short_version]) expect(first_item.short_version).to eq(item_hash[0][:short_version])
expect(first_item.version).to eq(item_hash[0][:version]) expect(first_item.version).to eq(item_hash[0][:version])
expect(sparkle.items_from_content(xml[:beta_channel_item])).to eq(items[:beta_channel_item])
expect(sparkle.items_from_content(xml[:no_versions_item])).to eq(items[:no_versions_item]) expect(sparkle.items_from_content(xml[:no_versions_item])).to eq(items[:no_versions_item])
end end
end end
@ -162,6 +177,7 @@ describe Homebrew::Livecheck::Strategy::Sparkle do
it "returns an array of version strings when given content" do it "returns an array of version strings when given content" do
expect(sparkle.versions_from_content(xml[:appcast])).to eq(versions) expect(sparkle.versions_from_content(xml[:appcast])).to eq(versions)
expect(sparkle.versions_from_content(xml[:appcast_with_omitted_items])).to eq(versions) expect(sparkle.versions_from_content(xml[:appcast_with_omitted_items])).to eq(versions)
expect(sparkle.versions_from_content(xml[:beta_channel_item])).to eq(versions)
expect(sparkle.versions_from_content(xml[:no_versions_item])).to eq([]) expect(sparkle.versions_from_content(xml[:no_versions_item])).to eq([])
expect(sparkle.versions_from_content(xml[:undefined_namespace])).to eq(versions) expect(sparkle.versions_from_content(xml[:undefined_namespace])).to eq(versions)
end end
@ -184,6 +200,12 @@ describe Homebrew::Livecheck::Strategy::Sparkle do
items.map { |item| item.nice_version&.sub("1", "0") } items.map { |item| item.nice_version&.sub("1", "0") }
end, end,
).to eq(subbed_items) ).to eq(subbed_items)
expect(
sparkle.versions_from_content(xml[:beta_channel_item]) do |items|
items.find { |item| item.channel.nil? }&.nice_version
end,
).to eq([items[:appcast][1].nice_version])
end end
it "returns an array of version strings when given content, a regex, and a block" do it "returns an array of version strings when given content, a regex, and a block" do