diff --git a/app/graphql/types/ci/runner_upgrade_status_type_enum.rb b/app/graphql/types/ci/runner_upgrade_status_type_enum.rb new file mode 100644 index 0000000000000000000000000000000000000000..e3d77e485bc6b5b9f60784a78838c28f1d56bd80 --- /dev/null +++ b/app/graphql/types/ci/runner_upgrade_status_type_enum.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Types + module Ci + class RunnerUpgradeStatusTypeEnum < BaseEnum + graphql_name 'CiRunnerUpgradeStatusType' + + value 'NOT_AVAILABLE', + description: "An update is not available for the runner.", + value: :not_available + + value 'AVAILABLE', + description: "An update is available for the runner.", + value: :available + + value 'RECOMMENDED', + description: "An update is available and recommended for the runner.", + value: :recommended + end + end +end diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index f1cdf46625d12491992e3fba1cf96915ded858b5..879d836bc7a8a287ab44d0d82982072a2d699cd7 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -9450,6 +9450,7 @@ Represents the total number of issues and their weights for a particular day. | <a id="cirunnershortsha"></a>`shortSha` | [`String`](#string) | First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID. | | <a id="cirunnertaglist"></a>`tagList` | [`[String!]`](#string) | Tags associated with the runner. | | <a id="cirunnertokenexpiresat"></a>`tokenExpiresAt` | [`Time`](#time) | Runner token expiration time. | +| <a id="cirunnerupgradestatus"></a>`upgradeStatus` **{warning-solid}** | [`CiRunnerUpgradeStatusType`](#cirunnerupgradestatustype) | **Deprecated** in 14.10. This feature is in Alpha, and can be removed or changed at any point. | | <a id="cirunneruserpermissions"></a>`userPermissions` | [`RunnerPermissions!`](#runnerpermissions) | Permissions for the current user on the resource. | | <a id="cirunnerversion"></a>`version` | [`String`](#string) | Version of the runner. | @@ -17841,6 +17842,14 @@ Values for sorting runners. | <a id="cirunnertypeinstance_type"></a>`INSTANCE_TYPE` | A runner that is instance type. | | <a id="cirunnertypeproject_type"></a>`PROJECT_TYPE` | A runner that is project type. | +### `CiRunnerUpgradeStatusType` + +| Value | Description | +| ----- | ----------- | +| <a id="cirunnerupgradestatustypeavailable"></a>`AVAILABLE` | An update is available for the runner. | +| <a id="cirunnerupgradestatustypenot_available"></a>`NOT_AVAILABLE` | An update is not available for the runner. | +| <a id="cirunnerupgradestatustyperecommended"></a>`RECOMMENDED` | An update is available and recommended for the runner. | + ### `CodeQualityDegradationSeverity` | Value | Description | diff --git a/ee/app/graphql/ee/types/ci/runner_type.rb b/ee/app/graphql/ee/types/ci/runner_type.rb index ae59b74bcf81ebe3e967a8a51b3eb2ffdd4c1f38..d882353b4101c8a2d6e5d69d914f4098dd4fcc4a 100644 --- a/ee/app/graphql/ee/types/ci/runner_type.rb +++ b/ee/app/graphql/ee/types/ci/runner_type.rb @@ -11,6 +11,14 @@ module RunnerType description: 'Public projects\' "minutes cost factor" associated with the runner (GitLab.com only).' field :private_projects_minutes_cost_factor, GraphQL::Types::Float, null: true, description: 'Private projects\' "minutes cost factor" associated with the runner (GitLab.com only).' + + field :upgrade_status, ::Types::Ci::RunnerUpgradeStatusTypeEnum, null: true, + description: 'Availability of upgrades for the runner.', + deprecated: { milestone: '14.10', reason: :alpha } + + def upgrade_status + ::Gitlab::Ci::RunnerUpgradeCheck.instance.check_runner_upgrade_status(object.version) + end end end end diff --git a/ee/spec/graphql/types/ci/runner_type_spec.rb b/ee/spec/graphql/types/ci/runner_type_spec.rb index 9d986ac9d13ede8eea698995b15027e19c277ae5..999e5024ec93a6d9442a90e9f3c6304aff81f3d1 100644 --- a/ee/spec/graphql/types/ci/runner_type_spec.rb +++ b/ee/spec/graphql/types/ci/runner_type_spec.rb @@ -6,7 +6,7 @@ it { expect(described_class.graphql_name).to eq('CiRunner') } it 'includes the ee specific fields' do - expected_fields = %w[public_projects_minutes_cost_factor private_projects_minutes_cost_factor] + expected_fields = %w[public_projects_minutes_cost_factor private_projects_minutes_cost_factor upgrade_status] expect(described_class).to include_graphql_fields(*expected_fields) end diff --git a/ee/spec/requests/api/graphql/ci/runner_spec.rb b/ee/spec/requests/api/graphql/ci/runner_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..3e954695d0c0be0b45c149066b89c87c21a758ab --- /dev/null +++ b/ee/spec/requests/api/graphql/ci/runner_spec.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Query.runner(id)' do + include GraphqlHelpers + + let_it_be(:user) { create(:user, :admin) } + + shared_examples 'runner details fetch operation returning expected upgradeStatus' do + let(:query) do + wrap_fields(query_graphql_path(query_path, all_graphql_fields_for('CiRunner'))) + end + + let(:query_path) do + [ + [:runner, { id: runner.to_global_id.to_s }] + ] + end + + it 'retrieves expected fields' do + post_graphql(query, current_user: user) + + runner_data = graphql_data_at(:runner) + expect(runner_data).not_to be_nil + + expect(runner_data).to match a_hash_including( + 'id' => runner.to_global_id.to_s, + 'upgradeStatus' => expected_upgrade_status + ) + end + end + + describe 'upgradeStatus' do + let_it_be(:runner) { create(:ci_runner, description: 'Runner 1', version: 'adfe156', revision: 'a') } + + before do + expect(::Gitlab::Ci::RunnerUpgradeCheck.instance).to receive(:check_runner_upgrade_status) + .and_return(upgrade_status) + .once + end + + context 'with RunnerUpgradeCheck returning :not_available' do + let(:upgrade_status) { :not_available } + let(:expected_upgrade_status) { 'NOT_AVAILABLE' } + + it_behaves_like('runner details fetch operation returning expected upgradeStatus') + end + + context 'with RunnerUpgradeCheck returning :available' do + let(:upgrade_status) { :available } + let(:expected_upgrade_status) { 'AVAILABLE' } + + it_behaves_like('runner details fetch operation returning expected upgradeStatus') + end + + context 'with RunnerUpgradeCheck returning :recommended' do + let(:upgrade_status) { :recommended } + let(:expected_upgrade_status) { 'RECOMMENDED' } + + it_behaves_like('runner details fetch operation returning expected upgradeStatus') + end + end +end diff --git a/spec/requests/api/graphql/ci/runner_spec.rb b/spec/requests/api/graphql/ci/runner_spec.rb index 6102e15012b9e6c5dc6f3f17cd96bbc31400d790..39f0f696b081ad70893d74222bef12f2aff11d28 100644 --- a/spec/requests/api/graphql/ci/runner_spec.rb +++ b/spec/requests/api/graphql/ci/runner_spec.rb @@ -27,6 +27,10 @@ let_it_be(:active_project_runner) { create(:ci_runner, :project) } + before do + allow(Gitlab::Ci::RunnerUpgradeCheck.instance).to receive(:check_runner_upgrade_status) + end + shared_examples 'runner details fetch' do let(:query) do wrap_fields(query_graphql_path(query_path, all_graphql_fields_for('CiRunner'))) diff --git a/spec/requests/api/graphql/ci/runners_spec.rb b/spec/requests/api/graphql/ci/runners_spec.rb index 267dd1b5e6fda9ba5842fe951dd3c5904bd330cc..6b88c82b025c16f123e9052793b92a56654b69ac 100644 --- a/spec/requests/api/graphql/ci/runners_spec.rb +++ b/spec/requests/api/graphql/ci/runners_spec.rb @@ -34,6 +34,8 @@ end before do + allow(Gitlab::Ci::RunnerUpgradeCheck.instance).to receive(:check_runner_upgrade_status) + post_graphql(query, current_user: current_user) end