Class: Lich::Util::Update::ChannelResolver

Inherits:
Object
  • Object
show all
Defined in:
documented/common/update/channel_resolver.rb

Overview

Resolves update channel names to git references.

Determines the appropriate git ref (tag or branch) for stable and beta channels by querying GitHub releases and branches. Handles semantic versioning comparison to find the latest eligible beta.

See Also:

Instance Method Summary collapse

Constructor Details

#initialize(client) ⇒ void

Initializes a new ChannelResolver instance.

Parameters:

  • client (Object)

    the client used to fetch GitHub data



26
27
28
# File 'documented/common/update/channel_resolver.rb', line 26

def initialize(client)
  @client = client
end

Instance Method Details

#latest_prefixed_branch_greater_than(prefix, stable_major, stable_minor, stable_patch = 0) ⇒ String?

Finds the latest branch with a specified prefix that is greater than the specified version.

Parameters:

  • prefix (String)

    the prefix to filter branches

  • stable_major (Integer)

    the major version of the stable release

  • stable_minor (Integer)

    the minor version of the stable release

  • stable_patch (Integer) (defaults to: 0)

    the patch version of the stable release

Returns:

  • (String, nil)

    the latest branch name or nil if not found



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'documented/common/update/channel_resolver.rb', line 106

def latest_prefixed_branch_greater_than(prefix, stable_major, stable_minor, stable_patch = 0)
  branches = @client.fetch_github_json("https://api.github.com/repos/#{GITHUB_REPO}/branches?per_page=100")
  return nil unless branches.is_a?(Array)

  names = branches.map { |b| b['name'] }.compact
  candidates = names.select { |n| n.start_with?(prefix) }
  filtered = candidates.select do |n|
    maj, min, patch = major_minor_patch_from(n)
    maj && min && (
      (maj > stable_major) ||
      (maj == stable_major && min > stable_minor) ||
      (maj == stable_major && min == stable_minor && patch > stable_patch)
    )
  end
  return nil if filtered.empty?

  begin
    filtered.max_by { |n| version_key(n) }
  rescue => e
    respond "Update notice: ordering branches (latest_prefixed_branch_greater_than): #{e.message}"
    filtered.sort.last
  end
end

#latest_prerelease_tag_greater_than(stable_major, stable_minor, stable_patch = 0) ⇒ String?

Finds the latest prerelease tag greater than the specified version.

Parameters:

  • stable_major (Integer)

    the major version of the stable release

  • stable_minor (Integer)

    the minor version of the stable release

  • stable_patch (Integer) (defaults to: 0)

    the patch version of the stable release

Returns:

  • (String, nil)

    the latest prerelease tag or nil if not found



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'documented/common/update/channel_resolver.rb', line 78

def latest_prerelease_tag_greater_than(stable_major, stable_minor, stable_patch = 0)
  releases = @client.fetch_github_json("https://api.github.com/repos/#{GITHUB_REPO}/releases")
  return nil unless releases.is_a?(Array)

  prereleases = releases.select { |r| r['prerelease'] && r['tag_name'] }
  return nil if prereleases.empty?

  candidates = prereleases.select do |r|
    maj, min, patch = major_minor_patch_from(r['tag_name'])
    next false unless maj && min

    (maj > stable_major) ||
      (maj == stable_major && min > stable_minor) ||
      (maj == stable_major && min == stable_minor && patch > stable_patch)
  end
  return nil if candidates.empty?

  tag = candidates.max_by { |r| version_key(r['tag_name']) }['tag_name']
  tag.sub(/^v/, '')
end

#latest_stable_tagString?

Fetches the latest stable tag from GitHub releases.

Returns:

  • (String, nil)

    the latest stable tag or nil if not found



64
65
66
67
68
69
70
# File 'documented/common/update/channel_resolver.rb', line 64

def latest_stable_tag
  releases = @client.fetch_github_json("https://api.github.com/repos/#{GITHUB_REPO}/releases")
  return nil unless releases.is_a?(Array)

  stable = releases.select { |r| !r['prerelease'] && r['tag_name'] }.max_by { |r| version_key(r['tag_name']) }
  stable && stable['tag_name']
end

#major_minor_from(str) ⇒ Array<Integer, Integer>

Extracts the major and minor version numbers from a version string.

Parameters:

  • str (String)

    the version string to parse

Returns:

  • (Array<Integer, Integer>)

    an array containing major and minor version numbers



164
165
166
167
# File 'documented/common/update/channel_resolver.rb', line 164

def major_minor_from(str)
  maj, min, _patch = major_minor_patch_from(str)
  [maj, min]
end

#major_minor_patch_from(str) ⇒ Array<Integer, Integer, Integer>

Extracts the major, minor, and patch version numbers from a version string.

Parameters:

  • str (String)

    the version string to parse

Returns:

  • (Array<Integer, Integer, Integer>)

    an array containing major, minor, and patch version numbers



147
148
149
150
151
152
153
154
155
156
157
158
# File 'documented/common/update/channel_resolver.rb', line 147

def major_minor_patch_from(str)
  return [nil, nil, nil] if str.nil?

  s = str.to_s.sub(/^v/, '')
  if s =~ /(\d+)\.(\d+)\.(\d+)/
    [$1.to_i, $2.to_i, $3.to_i]
  elsif s =~ /(\d+)\.(\d+)/
    [$1.to_i, $2.to_i, 0]
  else
    [nil, nil, nil]
  end
end

#resolve_channel_ref(channel) ⇒ String?

Resolves the git reference for the specified channel.

Examples:

Resolve stable channel

resolver.resolve_channel_ref(:stable)

Resolve beta channel

resolver.resolve_channel_ref(:beta)

Parameters:

  • channel (Symbol, String)

    the channel to resolve (e.g., :stable, :beta)

Returns:

  • (String, nil)

    the resolved git reference or nil if not found



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'documented/common/update/channel_resolver.rb', line 38

def resolve_channel_ref(channel)
  case channel
  when :stable, 'production'
    STABLE_REF
  when :beta
    env = ENV['LICH_BETA_REF']
    return env unless env.nil? || env.empty?

    stable_tag = latest_stable_tag
    stable_major, stable_minor, stable_patch = major_minor_patch_from(stable_tag)
    return nil unless stable_major

    tag = latest_prerelease_tag_greater_than(stable_major, stable_minor, stable_patch)
    return tag if tag

    branch = latest_prefixed_branch_greater_than(BETA_BRANCH_PREFIX, stable_major, stable_minor, stable_patch)
    return branch if branch

    nil
  else
    STABLE_REF
  end
end

#version_key(tag_or_name) ⇒ Gem::Version

Generates a version key from a tag or branch name for comparison.

Parameters:

  • tag_or_name (String)

    the tag or branch name to generate a version key from

Returns:

  • (Gem::Version)

    the version key



134
135
136
137
138
139
140
141
# File 'documented/common/update/channel_resolver.rb', line 134

def version_key(tag_or_name)
  s = tag_or_name.to_s.sub(/^v/, '')
  if s =~ /(\d+\.\d+(?:\.\d+)?(?:-[0-9A-Za-z\.]+)?)/
    s = Regexp.last_match(1)
  end
  s = s.gsub('-beta.', '.beta.').gsub(/-beta(?!\.)/, '.beta')
  Gem::Version.new(s)
end