Sparkle: Surface more Item values

Historically, the `Sparkle` strategy's `Item` struct has only
included basic values from the appcast that are commonly useful.
Over time we've selectively added/surfaced more values as we've
encountered outliers that require use of different values in a
`strategy` block.

We now need to use `minimumSystemValue`, so this expands the `Item`
struct to include any appcast value that we could conceivably want
to use in the future. This will hopefully save us from having to make
more modifications to the struct (and related tests) before we can
use a previously-unused value in a `strategy` block.
This commit is contained in:
Sam Ford 2023-10-28 14:04:40 -04:00
parent 97eda64790
commit 86c702abcd
No known key found for this signature in database
GPG Key ID: 7AF5CBEE1DD6F76D
2 changed files with 105 additions and 62 deletions

View File

@ -35,13 +35,21 @@ module Homebrew
# @api public # @api public
:title, :title,
# @api public # @api public
:link,
# @api public
:channel, :channel,
# @api private # @api public
:release_notes_link,
# @api public
:pub_date, :pub_date,
# @api public # @api public
:os,
# @api public
:url, :url,
# @api private # @api private
:bundle_version, :bundle_version,
# @api public
:minimum_system_version,
keyword_init: true, keyword_init: true,
) do ) do
extend Forwardable extend Forwardable
@ -84,12 +92,14 @@ module Homebrew
os = enclosure["os"] os = enclosure["os"]
end end
channel = item.elements["channel"]&.text title = item.elements["title"]&.text&.strip
url ||= item.elements["link"]&.text link = item.elements["link"]&.text&.strip
url ||= link
channel = item.elements["channel"]&.text&.strip
release_notes_link = item.elements["releaseNotesLink"]&.text&.strip
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
title = item.elements["title"]&.text&.strip
pub_date = item.elements["pubDate"]&.text&.strip&.presence&.then do |date_string| pub_date = item.elements["pubDate"]&.text&.strip&.presence&.then do |date_string|
Time.parse(date_string) Time.parse(date_string)
rescue ArgumentError rescue ArgumentError
@ -117,11 +127,15 @@ module Homebrew
end end
data = { data = {
title: title, title: title,
channel: channel, link: link,
pub_date: pub_date, channel: channel,
url: url, release_notes_link: release_notes_link,
bundle_version: bundle_version, pub_date: pub_date,
os: os,
url: url,
bundle_version: bundle_version,
minimum_system_version: minimum_system_version,
}.compact }.compact
next if data.empty? next if data.empty?

View File

@ -29,32 +29,42 @@ describe Homebrew::Livecheck::Strategy::Sparkle do
let(:item_hashes) do let(:item_hashes) do
{ {
v123: { v123: {
title: "Version 1.2.3", title: "Version 1.2.3",
pub_date: "Fri, 01 Jan 2021 01:23:45 +0000", release_notes_link: "https://www.example.com/example/1.2.3.html",
url: "https://www.example.com/example/example-1.2.3.tar.gz", pub_date: "Fri, 01 Jan 2021 01:23:45 +0000",
short_version: "1.2.3", url: "https://www.example.com/example/example-1.2.3.tar.gz",
version: "123", short_version: "1.2.3",
version: "123",
minimum_system_version: "10.10",
}, },
v122: { v122: {
title: "Version 1.2.2", title: "Version 1.2.2",
pub_date: "Not a parseable date string", release_notes_link: "https://www.example.com/example/1.2.2.html",
url: "https://www.example.com/example/example-1.2.2.tar.gz", pub_date: "Not a parseable date string",
short_version: "1.2.2", link: "https://www.example.com/example/example-1.2.2.tar.gz",
version: "122", short_version: "1.2.2",
version: "122",
minimum_system_version: "10.10",
}, },
v121: { v121: {
title: "Version 1.2.1", title: "Version 1.2.1",
pub_date: "Thu, 31 Dec 2020 01:23:45 +0000", release_notes_link: "https://www.example.com/example/1.2.1.html",
url: "https://www.example.com/example/example-1.2.1.tar.gz", pub_date: "Thu, 31 Dec 2020 01:23:45 +0000",
short_version: "1.2.1", os: "osx",
version: "121", url: "https://www.example.com/example/example-1.2.1.tar.gz",
short_version: "1.2.1",
version: "121",
minimum_system_version: "10.10",
}, },
v120: { v120: {
title: "Version 1.2.0", title: "Version 1.2.0",
pub_date: "Wed, 30 Dec 2020 01:23:45 +0000", release_notes_link: "https://www.example.com/example/1.2.0.html",
url: "https://www.example.com/example/example-1.2.0.tar.gz", pub_date: "Wed, 30 Dec 2020 01:23:45 +0000",
short_version: "1.2.0", os: "macos",
version: "120", url: "https://www.example.com/example/example-1.2.0.tar.gz",
short_version: "1.2.0",
version: "120",
minimum_system_version: "10.10",
}, },
} }
end end
@ -63,8 +73,8 @@ describe Homebrew::Livecheck::Strategy::Sparkle do
v123_item = <<~EOS v123_item = <<~EOS
<item> <item>
<title>#{item_hashes[:v123][:title]}</title> <title>#{item_hashes[:v123][:title]}</title>
<sparkle:minimumSystemVersion>10.10</sparkle:minimumSystemVersion> <sparkle:minimumSystemVersion>#{item_hashes[:v123][:minimum_system_version]}</sparkle:minimumSystemVersion>
<sparkle:releaseNotesLink>https://www.example.com/example/#{item_hashes[:v123][:short_version]}.html</sparkle:releaseNotesLink> <sparkle:releaseNotesLink>#{item_hashes[:v123][:release_notes_link]}</sparkle:releaseNotesLink>
<pubDate>#{item_hashes[:v123][:pub_date]}</pubDate> <pubDate>#{item_hashes[:v123][:pub_date]}</pubDate>
<enclosure url="#{item_hashes[:v123][:url]}" sparkle:shortVersionString="#{item_hashes[:v123][:short_version]}" sparkle:version="#{item_hashes[:v123][:version]}" length="12345678" type="application/octet-stream" sparkle:dsaSignature="ABCDEF+GHIJKLMNOPQRSTUVWXYZab/cdefghijklmnopqrst/uvwxyz1234567==" /> <enclosure url="#{item_hashes[:v123][:url]}" sparkle:shortVersionString="#{item_hashes[:v123][:short_version]}" sparkle:version="#{item_hashes[:v123][:version]}" length="12345678" type="application/octet-stream" sparkle:dsaSignature="ABCDEF+GHIJKLMNOPQRSTUVWXYZab/cdefghijklmnopqrst/uvwxyz1234567==" />
</item> </item>
@ -73,32 +83,32 @@ describe Homebrew::Livecheck::Strategy::Sparkle do
v122_item = <<~EOS v122_item = <<~EOS
<item> <item>
<title>#{item_hashes[:v122][:title]}</title> <title>#{item_hashes[:v122][:title]}</title>
<sparkle:minimumSystemVersion>10.10</sparkle:minimumSystemVersion> <link>#{item_hashes[:v122][:link]}</link>
<sparkle:releaseNotesLink>https://www.example.com/example/#{item_hashes[:v122][:short_version]}.html</sparkle:releaseNotesLink> <sparkle:minimumSystemVersion>#{item_hashes[:v122][:minimum_system_version]}</sparkle:minimumSystemVersion>
<sparkle:releaseNotesLink>#{item_hashes[:v122][:release_notes_link]}</sparkle:releaseNotesLink>
<pubDate>#{item_hashes[:v122][:pub_date]}</pubDate> <pubDate>#{item_hashes[:v122][:pub_date]}</pubDate>
<sparkle:version>#{item_hashes[:v122][:version]}</sparkle:version> <sparkle:version>#{item_hashes[:v122][:version]}</sparkle:version>
<sparkle:shortVersionString>#{item_hashes[:v122][:short_version]}</sparkle:shortVersionString> <sparkle:shortVersionString>#{item_hashes[:v122][:short_version]}</sparkle:shortVersionString>
<link>#{item_hashes[:v122][:url]}</link>
</item> </item>
EOS EOS
v121_item_with_osx_os = <<~EOS v121_item_with_osx_os = <<~EOS
<item> <item>
<title>#{item_hashes[:v121][:title]}</title> <title>#{item_hashes[:v121][:title]}</title>
<sparkle:minimumSystemVersion>10.10</sparkle:minimumSystemVersion> <sparkle:minimumSystemVersion>#{item_hashes[:v121][:minimum_system_version]}</sparkle:minimumSystemVersion>
<sparkle:releaseNotesLink>https://www.example.com/example/#{item_hashes[:v121][:short_version]}.html</sparkle:releaseNotesLink> <sparkle:releaseNotesLink>#{item_hashes[:v121][:release_notes_link]}</sparkle:releaseNotesLink>
<pubDate>#{item_hashes[:v121][:pub_date]}</pubDate> <pubDate>#{item_hashes[:v121][:pub_date]}</pubDate>
<enclosure os="osx" url="#{item_hashes[:v121][:url]}" sparkle:shortVersionString="#{item_hashes[:v121][:short_version]}" sparkle:version="#{item_hashes[:v121][:version]}" length="12345678" type="application/octet-stream" sparkle:dsaSignature="ABCDEF+GHIJKLMNOPQRSTUVWXYZab/cdefghijklmnopqrst/uvwxyz1234567==" /> <enclosure os="#{item_hashes[:v121][:os]}" url="#{item_hashes[:v121][:url]}" sparkle:shortVersionString="#{item_hashes[:v121][:short_version]}" sparkle:version="#{item_hashes[:v121][:version]}" length="12345678" type="application/octet-stream" sparkle:dsaSignature="ABCDEF+GHIJKLMNOPQRSTUVWXYZab/cdefghijklmnopqrst/uvwxyz1234567==" />
</item> </item>
EOS EOS
v120_item_with_macos_os = <<~EOS v120_item_with_macos_os = <<~EOS
<item> <item>
<title>#{item_hashes[:v120][:title]}</title> <title>#{item_hashes[:v120][:title]}</title>
<sparkle:minimumSystemVersion>10.10</sparkle:minimumSystemVersion> <sparkle:minimumSystemVersion>#{item_hashes[:v120][:minimum_system_version]}</sparkle:minimumSystemVersion>
<sparkle:releaseNotesLink>https://www.example.com/example/#{item_hashes[:v120][:short_version]}.html</sparkle:releaseNotesLink> <sparkle:releaseNotesLink>#{item_hashes[:v120][:release_notes_link]}</sparkle:releaseNotesLink>
<pubDate>#{item_hashes[:v120][:pub_date]}</pubDate> <pubDate>#{item_hashes[:v120][:pub_date]}</pubDate>
<enclosure os="macos" url="#{item_hashes[:v120][:url]}" sparkle:shortVersionString="#{item_hashes[:v120][:short_version]}" sparkle:version="#{item_hashes[:v120][:version]}" length="12345678" type="application/octet-stream" sparkle:dsaSignature="ABCDEF+GHIJKLMNOPQRSTUVWXYZab/cdefghijklmnopqrst/uvwxyz1234567==" /> <enclosure os="#{item_hashes[:v120][:os]}" url="#{item_hashes[:v120][:url]}" sparkle:shortVersionString="#{item_hashes[:v120][:short_version]}" sparkle:version="#{item_hashes[:v120][:version]}" length="12345678" type="application/octet-stream" sparkle:dsaSignature="ABCDEF+GHIJKLMNOPQRSTUVWXYZab/cdefghijklmnopqrst/uvwxyz1234567==" />
</item> </item>
EOS EOS
@ -131,8 +141,8 @@ describe Homebrew::Livecheck::Strategy::Sparkle do
no_versions_item = create_appcast_xml <<~EOS no_versions_item = create_appcast_xml <<~EOS
<item> <item>
<title>Version</title> <title>Version</title>
<sparkle:minimumSystemVersion>10.10</sparkle:minimumSystemVersion> <sparkle:minimumSystemVersion>#{item_hashes[:v123][:minimum_system_version]}</sparkle:minimumSystemVersion>
<sparkle:releaseNotesLink>https://www.example.com/example/#{item_hashes[:v123][:short_version]}.html</sparkle:releaseNotesLink> <sparkle:releaseNotesLink>#{item_hashes[:v123][:release_notes_link]}</sparkle:releaseNotesLink>
<pubDate>#{item_hashes[:v123][:pub_date]}</pubDate> <pubDate>#{item_hashes[:v123][:pub_date]}</pubDate>
<enclosure url="#{item_hashes[:v123][:url]}" length="12345678" type="application/octet-stream" sparkle:dsaSignature="ABCDEF+GHIJKLMNOPQRSTUVWXYZab/cdefghijklmnopqrst/uvwxyz1234567==" /> <enclosure url="#{item_hashes[:v123][:url]}" length="12345678" type="application/octet-stream" sparkle:dsaSignature="ABCDEF+GHIJKLMNOPQRSTUVWXYZab/cdefghijklmnopqrst/uvwxyz1234567==" />
</item> </item>
@ -157,34 +167,53 @@ describe Homebrew::Livecheck::Strategy::Sparkle do
let(:items) do let(:items) do
{ {
v123: Homebrew::Livecheck::Strategy::Sparkle::Item.new( v123: Homebrew::Livecheck::Strategy::Sparkle::Item.new(
title: item_hashes[:v123][:title], title: item_hashes[:v123][:title],
pub_date: Time.parse(item_hashes[:v123][:pub_date]), release_notes_link: item_hashes[:v123][:release_notes_link],
url: item_hashes[:v123][:url], pub_date: Time.parse(item_hashes[:v123][:pub_date]),
bundle_version: Homebrew::BundleVersion.new(item_hashes[:v123][:short_version], url: item_hashes[:v123][:url],
item_hashes[:v123][:version]), bundle_version: Homebrew::BundleVersion.new(
item_hashes[:v123][:short_version],
item_hashes[:v123][:version],
),
minimum_system_version: item_hashes[:v123][:minimum_system_version],
), ),
v122: Homebrew::Livecheck::Strategy::Sparkle::Item.new( v122: Homebrew::Livecheck::Strategy::Sparkle::Item.new(
title: item_hashes[:v122][:title], title: item_hashes[:v122][:title],
link: item_hashes[:v122][:link],
release_notes_link: item_hashes[:v122][:release_notes_link],
# `#items_from_content` falls back to a default `pub_date` when # `#items_from_content` falls back to a default `pub_date` when
# one isn't provided or can't be successfully parsed. # one isn't provided or can't be successfully parsed.
pub_date: Time.new(0), pub_date: Time.new(0),
url: item_hashes[:v122][:url], url: item_hashes[:v122][:link],
bundle_version: Homebrew::BundleVersion.new(item_hashes[:v122][:short_version], bundle_version: Homebrew::BundleVersion.new(
item_hashes[:v122][:version]), item_hashes[:v122][:short_version],
item_hashes[:v122][:version],
),
minimum_system_version: item_hashes[:v122][:minimum_system_version],
), ),
v121: Homebrew::Livecheck::Strategy::Sparkle::Item.new( v121: Homebrew::Livecheck::Strategy::Sparkle::Item.new(
title: item_hashes[:v121][:title], title: item_hashes[:v121][:title],
pub_date: Time.parse(item_hashes[:v121][:pub_date]), release_notes_link: item_hashes[:v121][:release_notes_link],
url: item_hashes[:v121][:url], pub_date: Time.parse(item_hashes[:v121][:pub_date]),
bundle_version: Homebrew::BundleVersion.new(item_hashes[:v121][:short_version], os: item_hashes[:v121][:os],
item_hashes[:v121][:version]), url: item_hashes[:v121][:url],
bundle_version: Homebrew::BundleVersion.new(
item_hashes[:v121][:short_version],
item_hashes[:v121][:version],
),
minimum_system_version: item_hashes[:v121][:minimum_system_version],
), ),
v120: Homebrew::Livecheck::Strategy::Sparkle::Item.new( v120: Homebrew::Livecheck::Strategy::Sparkle::Item.new(
title: item_hashes[:v120][:title], title: item_hashes[:v120][:title],
pub_date: Time.parse(item_hashes[:v120][:pub_date]), release_notes_link: item_hashes[:v120][:release_notes_link],
url: item_hashes[:v120][:url], pub_date: Time.parse(item_hashes[:v120][:pub_date]),
bundle_version: Homebrew::BundleVersion.new(item_hashes[:v120][:short_version], os: item_hashes[:v120][:os],
item_hashes[:v120][:version]), url: item_hashes[:v120][:url],
bundle_version: Homebrew::BundleVersion.new(
item_hashes[:v120][:short_version],
item_hashes[:v120][:version],
),
minimum_system_version: item_hashes[:v120][:minimum_system_version],
), ),
} }
end end