Commit e39ae89c authored by Pavel Shutsin's avatar Pavel Shutsin

Merge branch 'pedropombeiro/356689/2-create-update-check-service' into 'master'

Implement service to check for Runner upgrades

See merge request gitlab-org/gitlab!83551
parents 14d70fcd b1fdf286
# frozen_string_literal: true
module Gitlab
module Ci
class RunnerUpgradeCheck
include Singleton
def initialize
reset!
end
def check_runner_upgrade_status(runner_version)
return :unknown unless runner_version
releases = RunnerReleases.instance.releases
parsed_runner_version = runner_version.is_a?(::Gitlab::VersionInfo) ? runner_version : ::Gitlab::VersionInfo.parse(runner_version)
raise ArgumentError, "'#{runner_version}' is not a valid version" unless parsed_runner_version.valid?
available_releases = releases.reject { |release| release > @gitlab_version }
return :recommended if available_releases.any? { |available_release| patch_update?(available_release, parsed_runner_version) }
return :recommended if outside_backport_window?(parsed_runner_version, releases)
return :available if available_releases.any? { |available_release| available_release > parsed_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
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Ci::RunnerUpgradeCheck do
include StubVersion
using RSpec::Parameterized::TableSyntax
describe '#check_runner_upgrade_status' do
subject(:result) { described_class.instance.check_runner_upgrade_status(runner_version) }
before do
runner_releases_double = instance_double(Gitlab::Ci::RunnerReleases)
allow(Gitlab::Ci::RunnerReleases).to receive(:instance).and_return(runner_releases_double)
allow(runner_releases_double).to receive(:releases).and_return(available_runner_releases.map { |v| ::Gitlab::VersionInfo.parse(v) })
end
context 'with available_runner_releases configured up to 14.1.1' do
let(:available_runner_releases) { %w[13.9.0 13.9.1 13.9.2 13.10.0 13.10.1 14.0.0 14.0.1 14.0.2 14.1.0 14.1.1] }
context 'with nil runner_version' do
let(:runner_version) { nil }
it 'raises :unknown' do
is_expected.to eq(:unknown)
end
end
context 'with invalid runner_version' do
let(:runner_version) { 'junk' }
it 'raises ArgumentError' do
expect { subject }.to raise_error(ArgumentError)
end
end
context 'with Gitlab::VERSION set to 14.1.123' do
before do
stub_version('14.1.123', 'deadbeef')
described_class.instance.reset!
end
context 'with a runner_version that is too recent' do
let(:runner_version) { 'v14.2.0' }
it 'returns :not_available' do
is_expected.to eq(:not_available)
end
end
end
context 'with Gitlab::VERSION set to 14.0.123' do
before do
stub_version('14.0.123', 'deadbeef')
described_class.instance.reset!
end
context 'with valid params' do
where(:runner_version, :expected_result) do
'v14.1.0' | :not_available # not available since the GitLab instance is still on 14.0.x
'v14.0.1' | :recommended # recommended upgrade since 14.0.2 is available
'v14.0.2' | :not_available # not available since 14.0.2 is the latest 14.0.x release available
'v13.10.1' | :available # available upgrade: 14.1.1
'v13.10.0' | :recommended # recommended upgrade since 13.10.1 is available
'v13.9.2' | :recommended # recommended upgrade since backports are no longer released for this version
'v13.9.0' | :recommended # recommended upgrade since backports are no longer released for this version
'v13.8.1' | :recommended # recommended upgrade since build is too old (missing in records)
'v11.4.1' | :recommended # recommended upgrade since build is too old (missing in records)
end
with_them do
it 'returns symbol representing expected upgrade status' do
is_expected.to be_a(Symbol)
is_expected.to eq(expected_result)
end
end
end
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment