Class: Homebrew::Livecheck::Strategy::GithubReleases

Inherits:
Object
  • Object
show all
Defined in:
livecheck/strategy/github_releases.rb

Overview

The GithubReleases strategy identifies versions of software at github.com by checking a repository’s recent releases using the GitHub API.

GitHub URLs take a few different formats:

  • https://github.com/example/example/releases/download/1.2.3/example-1.2.3.tar.gz
  • https://github.com/example/example/archive/v1.2.3.tar.gz
  • https://github.com/downloads/example/example/example-1.2.3.tar.gz

GithubReleases should only be used when the upstream repository has releases for suitable versions and the strategy is necessary or appropriate (e.g. the formula/cask uses a release asset and the GithubLatest strategy isn’t sufficient to identify the newest version. The strategy can only be applied by using strategy :github_releases in a livecheck block.

The default regex identifies versions like 1.2.3/v1.2.3 in each release’s tag or title. This is a common tag format but a modified regex can be provided in a livecheck block to override the default if a repository uses a different format (e.g. 1.2.3d, 1.2.3-4, etc.).

Constant Summary collapse

NICE_NAME =
"GitHub - Releases"
PRIORITY =

A priority of zero causes livecheck to skip the strategy. We do this for Homebrew::Livecheck::Strategy::GithubReleases so we can selectively apply the strategy using strategy :github_releases in a livecheck block.

0
URL_MATCH_REGEX =

The Regexp used to determine if the strategy applies to the URL.

%r{
  ^https?://github\.com
  /(?:downloads/)?(?<username>[^/]+) # The GitHub username
  /(?<repository>[^/]+)              # The GitHub repository name
}ix
DEFAULT_REGEX =

The default regex used to identify a version from a tag when a regex isn’t provided.

/v?(\d+(?:\.\d+)+)/i
VERSION_KEYS =

Keys in the release JSON that could contain the version. The tag name is checked first, to better align with the Homebrew::Livecheck::Strategy::Git strategy.

["tag_name", "name"].freeze

Class Method Summary collapse

Class Method Details

.find_versions(url:, regex: DEFAULT_REGEX, **_unused, &block) ⇒ Hash{Symbol => T.untyped}

Generates the GitHub API URL for the repository’s recent releases and identifies versions from the JSON response.

Parameters:

  • url (String)

    the URL of the content to check

  • regex (Regexp) (defaults to: DEFAULT_REGEX)

    a regex used for matching versions in content

  • _unused (T.untyped)
  • block (Proc, nil)

Returns:



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'livecheck/strategy/github_releases.rb', line 136

def self.find_versions(url:, regex: DEFAULT_REGEX, **_unused, &block)
  match_data = { matches: {}, regex: regex, url: url }

  generated = generate_input_values(url)
  return match_data if generated.blank?

  match_data[:url] = generated[:url]

  releases = GitHub::API.open_rest(generated[:url])
  versions_from_content(releases, regex, &block).each do |match_text|
    match_data[:matches][match_text] = Version.new(match_text)
  end

  match_data
end

.generate_input_values(url) ⇒ Hash{Symbol => T.untyped}

Extracts information from a provided URL and uses it to generate various input values used by the strategy to check for new versions. Some of these values act as defaults and can be overridden in a livecheck block.

Parameters:

  • url (String)

    the URL used to generate values

Returns:



72
73
74
75
76
77
78
79
80
81
82
83
# File 'livecheck/strategy/github_releases.rb', line 72

def self.generate_input_values(url)
  values = {}

  match = url.delete_suffix(".git").match(URL_MATCH_REGEX)
  return values if match.blank?

  values[:url] = "#{GitHub::API_URL}/repos/#{match[:username]}/#{match[:repository]}/releases"
  values[:username] = match[:username]
  values[:repository] = match[:repository]

  values
end

.match?(url) ⇒ Boolean

Whether the strategy can be applied to the provided URL.

Parameters:

  • url (String)

    the URL to match against

Returns:

  • (Boolean)


60
61
62
# File 'livecheck/strategy/github_releases.rb', line 60

def self.match?(url)
  URL_MATCH_REGEX.match?(url)
end

.versions_from_content(content, regex, &block) ⇒ Array<String>

Uses a regex to match versions from release JSON or, if a block is provided, passes the JSON to the block to handle matching. With either approach, an array of unique matches is returned.

content

Parameters:

  • content (Array<Hash{String => T.untyped}>, Hash{String => T.untyped})

    array of releases or a single release

  • regex (Regexp)

    a regex used for matching versions in the

  • block (Proc, nil)

    a block to match the content

Returns:



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'livecheck/strategy/github_releases.rb', line 101

def self.versions_from_content(content, regex, &block)
  if block.present?
    block_return_value = yield(content, regex)
    return Strategy.handle_block_return(block_return_value)
  end

  content = [content] unless content.is_a?(Array)
  content.compact_blank.filter_map do |release|
    next if release["draft"] || release["prerelease"]

    value = T.let(nil, T.untyped)
    VERSION_KEYS.find do |key|
      match = release[key]&.match(regex)
      next if match.blank?

      value = match[1]
    end
    value
  end.uniq
end