81 lines
3 KiB
Ruby
81 lines
3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Gitlab
|
|
module Ci
|
|
class RunnerUpgradeCheck
|
|
include Singleton
|
|
|
|
STATUSES = {
|
|
invalid: 'Runner version is not valid.',
|
|
not_available: 'Upgrade is not available for the runner.',
|
|
available: 'Upgrade is available for the runner.',
|
|
recommended: 'Upgrade is available and recommended for the runner.'
|
|
}.freeze
|
|
|
|
def initialize
|
|
reset!
|
|
end
|
|
|
|
def check_runner_upgrade_status(runner_version)
|
|
return :invalid unless runner_version
|
|
|
|
releases = RunnerReleases.instance.releases
|
|
orig_runner_version = runner_version
|
|
runner_version = ::Gitlab::VersionInfo.parse(runner_version) unless runner_version.is_a?(::Gitlab::VersionInfo)
|
|
|
|
raise ArgumentError, "'#{orig_runner_version}' is not a valid version" unless runner_version.valid?
|
|
|
|
gitlab_minor_version = version_without_patch(@gitlab_version)
|
|
|
|
available_releases = releases
|
|
.reject { |release| release.major > @gitlab_version.major }
|
|
.reject do |release|
|
|
release_minor_version = version_without_patch(release)
|
|
|
|
# Do not reject a patch update, even if the runner is ahead of the instance version
|
|
next false if version_without_patch(runner_version) == release_minor_version
|
|
|
|
release_minor_version > gitlab_minor_version
|
|
end
|
|
|
|
return :recommended if available_releases.any? { |available_rel| patch_update?(available_rel, runner_version) }
|
|
return :recommended if outside_backport_window?(runner_version, releases)
|
|
return :available if available_releases.any? { |available_rel| available_rel > runner_version }
|
|
|
|
:not_available
|
|
end
|
|
|
|
def reset!
|
|
@gitlab_version = ::Gitlab::VersionInfo.parse(::Gitlab::VERSION)
|
|
end
|
|
|
|
public_class_method :instance
|
|
|
|
private
|
|
|
|
def patch_update?(available_release, runner_version)
|
|
# https://docs.gitlab.com/ee/policy/maintenance.html#patch-releases
|
|
available_release.major == runner_version.major &&
|
|
available_release.minor == runner_version.minor &&
|
|
available_release.patch > runner_version.patch
|
|
end
|
|
|
|
def outside_backport_window?(runner_version, releases)
|
|
return false if runner_version >= releases.last # return early if runner version is too new
|
|
|
|
latest_minor_releases = releases.map { |r| version_without_patch(r) }.uniq { |v| v.to_s }
|
|
latest_version_position = latest_minor_releases.count - 1
|
|
runner_version_position = latest_minor_releases.index(version_without_patch(runner_version))
|
|
|
|
return true if runner_version_position.nil? # consider outside if version is too old
|
|
|
|
# https://docs.gitlab.com/ee/policy/maintenance.html#backporting-to-older-releases
|
|
latest_version_position - runner_version_position > 2
|
|
end
|
|
|
|
def version_without_patch(version)
|
|
::Gitlab::VersionInfo.new(version.major, version.minor, 0)
|
|
end
|
|
end
|
|
end
|
|
end
|