Commit 64bf537f authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents a742af61 58450269
# frozen_string_literal: true
module Mutations
module Ci
module Runner
class Update < BaseMutation
graphql_name 'RunnerUpdate'
authorize :update_runner
RunnerID = ::Types::GlobalIDType[::Ci::Runner]
argument :id, RunnerID,
required: true,
description: 'ID of the runner to update.'
argument :description, GraphQL::STRING_TYPE,
required: false,
description: 'Description of the runner.'
argument :maximum_timeout, GraphQL::INT_TYPE,
required: false,
description: 'Maximum timeout (in seconds) for jobs processed by the runner.'
argument :access_level, ::Types::Ci::RunnerAccessLevelEnum,
required: false,
description: 'Access level of the runner.'
argument :active, GraphQL::BOOLEAN_TYPE,
required: false,
description: 'Indicates the runner is allowed to receive jobs.'
argument :locked, GraphQL::BOOLEAN_TYPE, required: false,
description: 'Indicates the runner is locked.'
argument :run_untagged, GraphQL::BOOLEAN_TYPE,
required: false,
description: 'Indicates the runner is able to run untagged jobs.'
argument :tag_list, [GraphQL::STRING_TYPE], required: false,
description: 'Tags associated with the runner.'
field :runner,
Types::Ci::RunnerType,
null: true,
description: 'The runner after mutation.'
def resolve(id:, **runner_attrs)
runner = authorized_find!(id)
unless ::Ci::UpdateRunnerService.new(runner).update(runner_attrs)
return { runner: nil, errors: runner.errors.full_messages }
end
{ runner: runner, errors: [] }
end
def find_object(id)
# TODO: remove this line when the compatibility layer is removed
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883
id = RunnerID.coerce_isolated_input(id)
GitlabSchema.find_by_gid(id)
end
end
end
end
end
...@@ -99,6 +99,7 @@ module Types ...@@ -99,6 +99,7 @@ module Types
mount_mutation Mutations::Ci::CiCdSettingsUpdate mount_mutation Mutations::Ci::CiCdSettingsUpdate
mount_mutation Mutations::Ci::Job::Play mount_mutation Mutations::Ci::Job::Play
mount_mutation Mutations::Ci::Job::Retry mount_mutation Mutations::Ci::Job::Retry
mount_mutation Mutations::Ci::Runner::Update, feature_flag: :runner_graphql_query
mount_mutation Mutations::Namespace::PackageSettings::Update mount_mutation Mutations::Namespace::PackageSettings::Update
mount_mutation Mutations::UserCallouts::Create mount_mutation Mutations::UserCallouts::Create
end end
......
---
name: usage_data_i_testing_group_code_coverage_project_click_total
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51411
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/299893
milestone: '13.8'
type: development
group: group::testing
default_enabled: true
...@@ -3568,6 +3568,34 @@ Input type: `RunDASTScanInput` ...@@ -3568,6 +3568,34 @@ Input type: `RunDASTScanInput`
| <a id="mutationrundastscanerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | | <a id="mutationrundastscanerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationrundastscanpipelineurl"></a>`pipelineUrl` | [`String`](#string) | URL of the pipeline that was created. | | <a id="mutationrundastscanpipelineurl"></a>`pipelineUrl` | [`String`](#string) | URL of the pipeline that was created. |
### `Mutation.runnerUpdate`
Available only when feature flag `runner_graphql_query` is enabled.
Input type: `RunnerUpdateInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationrunnerupdateaccesslevel"></a>`accessLevel` | [`CiRunnerAccessLevel`](#cirunneraccesslevel) | Access level of the runner. |
| <a id="mutationrunnerupdateactive"></a>`active` | [`Boolean`](#boolean) | Indicates the runner is allowed to receive jobs. |
| <a id="mutationrunnerupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationrunnerupdatedescription"></a>`description` | [`String`](#string) | Description of the runner. |
| <a id="mutationrunnerupdateid"></a>`id` | [`CiRunnerID!`](#cirunnerid) | ID of the runner to update. |
| <a id="mutationrunnerupdatelocked"></a>`locked` | [`Boolean`](#boolean) | Indicates the runner is locked. |
| <a id="mutationrunnerupdatemaximumtimeout"></a>`maximumTimeout` | [`Int`](#int) | Maximum timeout (in seconds) for jobs processed by the runner. |
| <a id="mutationrunnerupdaterununtagged"></a>`runUntagged` | [`Boolean`](#boolean) | Indicates the runner is able to run untagged jobs. |
| <a id="mutationrunnerupdatetaglist"></a>`tagList` | [`[String!]`](#string) | Tags associated with the runner. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationrunnerupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationrunnerupdateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationrunnerupdaterunner"></a>`runner` | [`CiRunner`](#cirunner) | The runner after mutation. |
### `Mutation.terraformStateDelete` ### `Mutation.terraformStateDelete`
Input type: `TerraformStateDeleteInput` Input type: `TerraformStateDeleteInput`
......
...@@ -6,7 +6,6 @@ import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format'; ...@@ -6,7 +6,6 @@ import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format';
import { joinPaths } from '~/lib/utils/url_utility'; import { joinPaths } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale'; import { __, s__ } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import getProjectsTestCoverage from '../graphql/queries/get_projects_test_coverage.query.graphql'; import getProjectsTestCoverage from '../graphql/queries/get_projects_test_coverage.query.graphql';
import SelectProjectsDropdown from './select_projects_dropdown.vue'; import SelectProjectsDropdown from './select_projects_dropdown.vue';
...@@ -21,7 +20,6 @@ export default { ...@@ -21,7 +20,6 @@ export default {
SelectProjectsDropdown, SelectProjectsDropdown,
TimeAgoTooltip, TimeAgoTooltip,
}, },
mixins: [glFeatureFlagsMixin()],
inject: { inject: {
groupFullPath: { groupFullPath: {
default: '', default: '',
...@@ -124,9 +122,7 @@ export default { ...@@ -124,9 +122,7 @@ export default {
this.hasError = true; this.hasError = true;
}, },
onProjectClick() { onProjectClick() {
if (this.glFeatures.usageDataITestingGroupCodeCoverageProjectClickTotal) {
api.trackRedisHllUserEvent(this.$options.usagePingProjectEvent); api.trackRedisHllUserEvent(this.$options.usagePingProjectEvent);
}
}, },
selectAllProjects() { selectAllProjects() {
this.allProjectsSelected = true; this.allProjectsSelected = true;
......
...@@ -8,7 +8,6 @@ class Groups::Analytics::RepositoryAnalyticsController < Groups::Analytics::Appl ...@@ -8,7 +8,6 @@ class Groups::Analytics::RepositoryAnalyticsController < Groups::Analytics::Appl
before_action -> { authorize_view_by_action!(:read_group_repository_analytics) } before_action -> { authorize_view_by_action!(:read_group_repository_analytics) }
before_action only: [:show] do before_action only: [:show] do
push_frontend_feature_flag(:usage_data_i_testing_group_code_coverage_visit_total, @group, default_enabled: :yaml) push_frontend_feature_flag(:usage_data_i_testing_group_code_coverage_visit_total, @group, default_enabled: :yaml)
push_frontend_feature_flag(:usage_data_i_testing_group_code_coverage_project_click_total, @group, default_enabled: :yaml)
end end
def show def show
......
...@@ -170,13 +170,9 @@ describe('Test coverage table component', () => { ...@@ -170,13 +170,9 @@ describe('Test coverage table component', () => {
}); });
describe('with usage metrics', () => { describe('with usage metrics', () => {
describe('with :usageDataITestingGroupCodeCoverageProjectClickTotal enabled', () => {
it('tracks i_testing_group_code_coverage_project_click_total metric', async () => { it('tracks i_testing_group_code_coverage_project_click_total metric', async () => {
const { id } = projects[0]; const { id } = projects[0];
createComponent({ createComponent({ mountFn: mount });
glFeatures: { usageDataITestingGroupCodeCoverageProjectClickTotal: true },
mountFn: mount,
});
await clickSelectAllProjects(); await clickSelectAllProjects();
...@@ -188,21 +184,4 @@ describe('Test coverage table component', () => { ...@@ -188,21 +184,4 @@ describe('Test coverage table component', () => {
); );
}); });
}); });
describe('with :usageDataITestingGroupCodeCoverageProjectClickTotal disabled', () => {
it('does not track i_testing_group_code_coverage_project_click_total metric', async () => {
const { id } = projects[0];
createComponent({
glFeatures: { usageDataITestingGroupCodeCoverageProjectClickTotal: false },
mountFn: mount,
});
await clickSelectAllProjects();
findProjectNameById(id).trigger('click');
expect(Api.trackRedisHllUserEvent).not.toHaveBeenCalled();
});
});
});
}); });
...@@ -180,7 +180,6 @@ ...@@ -180,7 +180,6 @@
category: testing category: testing
redis_slot: testing redis_slot: testing
aggregation: weekly aggregation: weekly
feature_flag: usage_data_i_testing_group_code_coverage_project_click_total
- name: i_testing_load_performance_widget_total - name: i_testing_load_performance_widget_total
category: testing category: testing
redis_slot: testing redis_slot: testing
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Mutations::Ci::Runner::Update do
include GraphqlHelpers
let_it_be(:user) { create(:user) }
let_it_be(:runner) { create(:ci_runner, active: true, locked: false, run_untagged: true) }
let(:current_ctx) { { current_user: user } }
let(:mutated_runner) { subject[:runner] }
let(:mutation_params) do
{
id: runner.to_global_id,
description: 'updated description'
}
end
specify { expect(described_class).to require_graphql_authorizations(:update_runner) }
describe '#resolve' do
subject do
sync(resolve(described_class, args: mutation_params, ctx: current_ctx))
end
context 'when the user cannot admin the runner' do
it 'raises an error' do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
context 'with invalid params' do
it 'raises an error' do
mutation_params[:id] = "invalid-id"
expect { subject }.to raise_error(::GraphQL::CoercionError)
end
end
context 'when required arguments are missing' do
let(:mutation_params) { {} }
it 'raises an error' do
expect { subject }.to raise_error(ArgumentError, "missing keyword: :id")
end
end
context 'when user can update runner', :enable_admin_mode do
let(:admin_user) { create(:user, :admin) }
let(:current_ctx) { { current_user: admin_user } }
let(:mutation_params) do
{
id: runner.to_global_id,
description: 'updated description',
maximum_timeout: 900,
access_level: 'ref_protected',
active: false,
locked: true,
run_untagged: false,
tag_list: %w(tag1 tag2)
}
end
context 'with valid arguments' do
it 'updates runner with correct values' do
expected_attributes = mutation_params.except(:id)
subject
expect(subject[:errors]).to be_empty
expect(subject[:runner]).to be_an_instance_of(Ci::Runner)
expect(subject[:runner]).to have_attributes(expected_attributes)
expect(runner.reload).to have_attributes(expected_attributes)
end
end
context 'with out-of-range maximum_timeout and missing tag_list' do
it 'returns a descriptive error' do
mutation_params[:maximum_timeout] = 100
mutation_params.delete(:tag_list)
expect(subject[:errors]).to contain_exactly(
'Maximum timeout needs to be at least 10 minutes',
'Tags list can not be empty when runner is not allowed to pick untagged jobs'
)
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