gitlab-org--gitlab-foss/lib/gitlab/ci/runner_upgrade_check.rb

91 lines
3.8 KiB
Ruby

# frozen_string_literal: true
module Gitlab
module Ci
class RunnerUpgradeCheck
def initialize(gitlab_version, runner_releases_store = nil)
@gitlab_version = ::Gitlab::VersionInfo.parse(gitlab_version, parse_suffix: true)
@releases_store = runner_releases_store
end
def check_runner_upgrade_suggestion(runner_version)
check_runner_upgrade_suggestions(runner_version).first
end
private
def runner_releases_store
@releases_store ||= RunnerReleases.instance
end
def add_suggestion(suggestions, runner_version, version, status)
return false unless version && version > runner_version
suggestions[version] = status
true
end
def check_runner_upgrade_suggestions(runner_version)
runner_version = ::Gitlab::VersionInfo.parse(runner_version, parse_suffix: true)
return { runner_version => :invalid_version } unless runner_version.valid?
return { runner_version => :error } unless runner_releases_store.releases
suggestions = {}
# Recommend update if outside of backport window
unless add_recommendation_if_outside_backport_window(runner_version, suggestions)
# Recommend patch update if there's a newer release in a same minor branch as runner
add_recommended_runner_release_update(runner_version, suggestions)
end
# Consider update if there's a newer release within the currently deployed GitLab version
add_available_runner_release(runner_version, suggestions)
suggestions[runner_version] = :not_available if suggestions.empty?
suggestions
end
def add_recommended_runner_release_update(runner_version, suggestions)
recommended_release = runner_releases_store.releases_by_minor[runner_version.without_patch]
return true if add_suggestion(suggestions, runner_version, recommended_release, :recommended)
# Consider the edge case of pre-release runner versions that get registered, but are never published.
# In this case, suggest the latest compatible runner version
latest_release = runner_releases_store.releases_by_minor.values.select { |v| v < @gitlab_version }.max
add_suggestion(suggestions, runner_version, latest_release, :recommended)
end
def add_available_runner_release(runner_version, suggestions)
available_version = runner_releases_store.releases_by_minor[@gitlab_version.without_patch]
unless suggestions.include?(available_version)
add_suggestion(suggestions, runner_version, available_version, :available)
end
end
def add_recommendation_if_outside_backport_window(runner_version, suggestions)
return false if runner_releases_store.releases.empty?
return false if runner_version >= runner_releases_store.releases.last # return early if runner version is too new
minor_releases_with_index = runner_releases_store.releases_by_minor.keys.each_with_index.to_h
runner_minor_version_index = minor_releases_with_index[runner_version.without_patch]
if runner_minor_version_index
# https://docs.gitlab.com/ee/policy/maintenance.html#backporting-to-older-releases
outside_window = minor_releases_with_index.count - runner_minor_version_index > 3
if outside_window
recommended_version = runner_releases_store.releases_by_minor[@gitlab_version.without_patch]
return add_suggestion(suggestions, runner_version, recommended_version, :recommended)
end
else
# If unknown runner version, then recommend the latest version for the GitLab instance
return add_recommended_runner_release_update(@gitlab_version, suggestions)
end
false
end
end
end
end