diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb index 9e00fa69f94ee04c660982aa3576c06e42e6b57f..2553074d0ffc444176bf383d3e4b99f2c2a9531e 100644 --- a/app/controllers/groups/settings/ci_cd_controller.rb +++ b/app/controllers/groups/settings/ci_cd_controller.rb @@ -6,7 +6,7 @@ class CiCdController < Groups::ApplicationController layout 'group_settings' skip_cross_project_access_check :show before_action :authorize_admin_group!, except: :show - before_action :authorize_admin_cicd_variables!, only: :show + before_action :authorize_show_cicd_settings!, only: :show before_action :authorize_update_max_artifacts_size!, only: [:update] before_action :define_variables, only: [:show] before_action :push_licensed_features, only: [:show] @@ -47,6 +47,15 @@ def update_auto_devops private + def authorize_show_cicd_settings! + return if can_any?(current_user, [ + :admin_cicd_variables, + :admin_runner + ], group) + + access_denied! + end + def define_variables define_ci_variables end diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb index c428f78960bab8512058dac9ae317b01a0c22017..bbdd27a7184eeba2da53fb9397dde1a30b6a211a 100644 --- a/app/controllers/projects/runners_controller.rb +++ b/app/controllers/projects/runners_controller.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class Projects::RunnersController < Projects::ApplicationController - before_action :authorize_admin_build! + before_action :authorize_admin_runner! before_action :authorize_create_runner!, only: [:new, :register] before_action :runner, only: [:edit, :update, :destroy, :pause, :resume, :show, :register] diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index 193ef7bb9afd65d065c1739e9766cb6144698840..8efae6f8a1d5e0bbb5fec4c42ef44c813c8fcdec 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -9,7 +9,7 @@ class CiCdController < Projects::ApplicationController layout 'project_settings' before_action :authorize_admin_pipeline!, except: :show - before_action :authorize_admin_cicd_variables!, only: :show + before_action :authorize_show_cicd_settings!, only: :show before_action :check_builds_available! before_action :define_variables @@ -75,6 +75,15 @@ def runner_setup_scripts private + def authorize_show_cicd_settings! + return if can_any?(current_user, [ + :admin_cicd_variables, + :admin_runner + ], project) + + access_denied! + end + def highlight_badge(name, content, language = nil) Gitlab::Highlight.highlight(name, content, language: language) end diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb index 554bdf97dfce1e1163d412ffa75ba69c477a574a..b4cf906e37ccc9238370ae83c99ef6b30d1038f1 100644 --- a/app/policies/group_policy.rb +++ b/app/policies/group_policy.rb @@ -267,6 +267,7 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy enable :admin_namespace enable :admin_group_member enable :admin_package + enable :admin_runner enable :admin_integrations enable :change_visibility_level diff --git a/app/policies/namespaces/user_namespace_policy.rb b/app/policies/namespaces/user_namespace_policy.rb index f2ac0f0403d4199a4c69802b20ead83d1509400c..325bd88027aa1867ad936dc2a03c9e5cc077e7a1 100644 --- a/app/policies/namespaces/user_namespace_policy.rb +++ b/app/policies/namespaces/user_namespace_policy.rb @@ -13,6 +13,7 @@ class UserNamespacePolicy < ::NamespacePolicy enable :create_projects enable :import_projects enable :admin_namespace + enable :admin_runner enable :read_namespace enable :read_namespace_via_membership enable :read_statistics diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index bb6f917d42691671f890f79d72c851ec3785e0dd..22728c08b306fe0aa593f191b0f62b26f05209fd 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -619,6 +619,7 @@ class ProjectPolicy < BasePolicy enable :read_import_error enable :admin_cicd_variables enable :admin_push_rules + enable :admin_runner enable :manage_deploy_tokens enable :manage_merge_request_settings enable :change_restrict_user_defined_variables diff --git a/app/services/groups/update_shared_runners_service.rb b/app/services/groups/update_shared_runners_service.rb index 60ef838a34c33c4f8f96f3e49058da7d9841bb31..dfa7631f499d389045658760d083e1675e7cc602 100644 --- a/app/services/groups/update_shared_runners_service.rb +++ b/app/services/groups/update_shared_runners_service.rb @@ -3,7 +3,7 @@ module Groups class UpdateSharedRunnersService < Groups::BaseService def execute - return error('Operation not allowed', 403) unless can?(current_user, :admin_group, group) + return error('Operation not allowed', 403) unless can?(current_user, :admin_runner, group) validate_params diff --git a/app/validators/json_schemas/member_role_permissions.json b/app/validators/json_schemas/member_role_permissions.json index e56df0c903036ae4fbbb4139a850c881f22fb595..843bcbc4f6c9e08b19faa1dacec5ada90515e6bd 100644 --- a/app/validators/json_schemas/member_role_permissions.json +++ b/app/validators/json_schemas/member_role_permissions.json @@ -22,6 +22,9 @@ "admin_push_rules": { "type": "boolean" }, + "admin_runners": { + "type": "boolean" + }, "admin_terraform_state": { "type": "boolean" }, diff --git a/app/views/groups/settings/ci_cd/show.html.haml b/app/views/groups/settings/ci_cd/show.html.haml index c03747400348f39716475dc7a3612f448a1d4eec..3f6a9a976f1168d7a3dcc61e7cf6ff63727ea033 100644 --- a/app/views/groups/settings/ci_cd/show.html.haml +++ b/app/views/groups/settings/ci_cd/show.html.haml @@ -26,7 +26,7 @@ .settings-content = render 'ci/variables/index', save_endpoint: group_variables_path -- if can?(current_user, :admin_group, @group) +- if can?(current_user, :admin_runner, @group) %section.settings#runners-settings.no-animate{ class: ('expanded' if expanded) } .settings-header %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only @@ -39,6 +39,7 @@ .settings-content = render 'groups/runners/settings' +- if can?(current_user, :admin_group, @group) %section.settings#auto-devops-settings.no-animate{ class: ('expanded' if expanded) } .settings-header %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml index 322d958763d395585336d9ecbddcb3b310f5c681..6df016c4ed265e8f227045359cf72ac108724d0b 100644 --- a/app/views/projects/settings/ci_cd/show.html.haml +++ b/app/views/projects/settings/ci_cd/show.html.haml @@ -34,6 +34,7 @@ = render_if_exists 'projects/settings/ci_cd/protected_environments', expanded: expanded +- if can?(current_user, :admin_runner, @project) - expand_runners = expanded || params[:expand_runners] %section.settings.no-animate#js-runners-settings{ class: ('expanded' if expand_runners), data: { testid: 'runners-settings-content' } } .settings-header @@ -47,6 +48,7 @@ .settings-content = render 'projects/runners/settings' +- if can?(current_user, :admin_pipeline, @project) - if Gitlab::CurrentSettings.current_application_settings.keep_latest_artifact? %section.settings.no-animate#js-artifacts-settings{ class: ('expanded' if expanded) } .settings-header diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index a98d44929ad09b57b4af32c31b0ba77a6849e350..4080f8a90dadac5016ebde26d94c3570b3b7b5fe 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -34350,6 +34350,7 @@ Member role permission. | `ADMIN_INTEGRATIONS` | Create, read, update, and delete integrations with external applications. | | `ADMIN_MERGE_REQUEST` | Allows approval of merge requests. | | `ADMIN_PUSH_RULES` | Configure push rules for repositories at the group or project level. | +| `ADMIN_RUNNERS` | Create, view, edit, and delete group or project Runners. Includes configuring Runner settings. | | `ADMIN_TERRAFORM_STATE` | Execute terraform commands, lock/unlock terraform state files, and remove file versions. | | `ADMIN_VULNERABILITY` | Edit the vulnerability object, including the status and linking an issue. Includes the `read_vulnerability` permission actions. | | `ADMIN_WEB_HOOK` | Manage webhooks. | diff --git a/doc/user/custom_roles/abilities.md b/doc/user/custom_roles/abilities.md index e9e5f33682115dbaa1591529488a6062b9767dd4..427a23ac22dad8cec7a22cfd47bb2a0f9932f4e5 100644 --- a/doc/user/custom_roles/abilities.md +++ b/doc/user/custom_roles/abilities.md @@ -62,6 +62,12 @@ These requirements are documented in the `Required permission` column in the fol |:-----|:------------|:------------------|:---------|:--------------|:---------| | [`admin_integrations`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/TODO) | | Create, read, update, and delete integrations with external applications. | GitLab [17.1](https://gitlab.com/gitlab-org/gitlab/-/issues/460522) | | | +## Runner + +| Name | Required permission | Description | Introduced in | Feature flag | Enabled in | +|:-----|:------------|:------------------|:---------|:--------------|:---------| +| [`admin_runners`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/151825) | | Create, view, edit, and delete group or project Runners. Includes configuring Runner settings. | GitLab [17.1](https://gitlab.com/gitlab-org/gitlab/-/issues/442851) | `custom_ability_admin_runners` | | + ## Secrets management | Name | Required permission | Description | Introduced in | Feature flag | Enabled in | diff --git a/ee/app/graphql/types/ci/namespace_ci_cd_setting_type.rb b/ee/app/graphql/types/ci/namespace_ci_cd_setting_type.rb index f7d722a663dff131761ec6e4de20a0067ecbf293..a3aba78fcafed861c5765165a5b0d4b866192c87 100644 --- a/ee/app/graphql/types/ci/namespace_ci_cd_setting_type.rb +++ b/ee/app/graphql/types/ci/namespace_ci_cd_setting_type.rb @@ -5,7 +5,7 @@ module Ci class NamespaceCiCdSettingType < BaseObject graphql_name 'NamespaceCiCdSetting' - authorize :admin_namespace + authorize :admin_runner field :allow_stale_runner_pruning, GraphQL::Types::Boolean, null: true, diff --git a/ee/app/policies/ee/ci/runner_policy.rb b/ee/app/policies/ee/ci/runner_policy.rb index 70a43aed142977e41dfdbbda4535d1c14336f528..a5be8e92bed93c58e8d843145b78fb6b40a5ba9b 100644 --- a/ee/app/policies/ee/ci/runner_policy.rb +++ b/ee/app/policies/ee/ci/runner_policy.rb @@ -10,6 +10,12 @@ module RunnerPolicy enable :read_runner enable :read_builds end + + condition(:custom_role_enables_admin_runners) do + ::Authz::CustomAbility.allowed?(@user, :admin_runners, @subject) + end + + rule { custom_role_enables_admin_runners }.enable :read_runner end end end diff --git a/ee/app/policies/ee/group_policy.rb b/ee/app/policies/ee/group_policy.rb index d7970ea5282dd87f75dcd4cd8ab4d33356ec31fc..478c47e8b00b0e3637ef5dd661880e4f4239a7bf 100644 --- a/ee/app/policies/ee/group_policy.rb +++ b/ee/app/policies/ee/group_policy.rb @@ -592,6 +592,8 @@ module GroupPolicy enable :read_licenses end + rule { custom_role_enables_admin_runners }.enable(*create_read_update_admin_destroy(:runner)) + rule { admin | owner }.policy do enable :owner_access enable :read_billable_member diff --git a/ee/app/policies/ee/project_policy.rb b/ee/app/policies/ee/project_policy.rb index b17b5d7b3602ff9b1100b9cee0e763a711836a1e..7297de2a4b49cf09489554001978d0cc8c6db653 100644 --- a/ee/app/policies/ee/project_policy.rb +++ b/ee/app/policies/ee/project_policy.rb @@ -318,6 +318,8 @@ module ProjectPolicy enable :admin_integrations end + rule { custom_role_enables_admin_runners }.enable(*create_read_update_admin_destroy(:runner)) + condition(:ci_cancellation_maintainers_only, scope: :subject) do project.ci_cancellation_restriction.maintainers_only_allowed? end diff --git a/ee/config/custom_abilities/admin_runners.yml b/ee/config/custom_abilities/admin_runners.yml new file mode 100644 index 0000000000000000000000000000000000000000..e09255970450fd0a85daab8e917cf3601858f753 --- /dev/null +++ b/ee/config/custom_abilities/admin_runners.yml @@ -0,0 +1,13 @@ +--- +name: admin_runners +description: Create, view, edit, and delete group or project Runners. Includes configuring + Runner settings. +introduced_by_issue: https://gitlab.com/gitlab-org/gitlab/-/issues/442851 +introduced_by_mr: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/151825 +feature_category: runner +milestone: '17.1' +group_ability: true +project_ability: true +requirements: [] +available_from_access_level: +feature_flag: custom_ability_admin_runners diff --git a/ee/config/feature_flags/wip/custom_ability_admin_runners.yml b/ee/config/feature_flags/wip/custom_ability_admin_runners.yml new file mode 100644 index 0000000000000000000000000000000000000000..6ade55627567996e51eb547c1d7f04f999410e44 --- /dev/null +++ b/ee/config/feature_flags/wip/custom_ability_admin_runners.yml @@ -0,0 +1,9 @@ +--- +name: custom_ability_admin_runners +feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/442851 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/151825 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/461448 +milestone: '17.1' +group: group::authorization +type: wip +default_enabled: false diff --git a/ee/lib/ee/sidebars/groups/menus/settings_menu.rb b/ee/lib/ee/sidebars/groups/menus/settings_menu.rb index 4eb03cc003d7b139a23d8f699d1087ac5f62f92d..31f7dafbc62fe38b1a7d80f08d84c696c46c5a15 100644 --- a/ee/lib/ee/sidebars/groups/menus/settings_menu.rb +++ b/ee/lib/ee/sidebars/groups/menus/settings_menu.rb @@ -29,7 +29,7 @@ def configure_menu_items add_menu_item_for_abilities(integrations_menu_item, :admin_integrations) add_menu_item_for_abilities(access_tokens_menu_item, :read_resource_access_tokens) add_menu_item_for_abilities(repository_menu_item, [:admin_push_rules, :manage_deploy_tokens]) - add_menu_item_for_abilities(ci_cd_menu_item, :admin_cicd_variables) + add_menu_item_for_abilities(ci_cd_menu_item, [:admin_cicd_variables, :admin_runner]) add_menu_item_for_abilities(billing_menu_item, :read_billing) end end diff --git a/ee/lib/ee/sidebars/projects/menus/settings_menu.rb b/ee/lib/ee/sidebars/projects/menus/settings_menu.rb index 00a068da2280a3388b457d3a5dfd84d2f7f3bbdc..c22fc668da41cd91722702932192fa014520741f 100644 --- a/ee/lib/ee/sidebars/projects/menus/settings_menu.rb +++ b/ee/lib/ee/sidebars/projects/menus/settings_menu.rb @@ -22,7 +22,8 @@ module SettingsMenu :manage_merge_request_settings ], ci_cd_menu_item: [ - :admin_cicd_variables + :admin_cicd_variables, + :admin_runner ], integrations_menu_item: [ :admin_integrations diff --git a/ee/spec/lib/ee/sidebars/groups/menus/settings_menu_spec.rb b/ee/spec/lib/ee/sidebars/groups/menus/settings_menu_spec.rb index 4a1ee1a491bd3eca87471f3de35dc0e8daabccae..d82eeb719ab5087adeb952b04fd6edaa493faa62 100644 --- a/ee/spec/lib/ee/sidebars/groups/menus/settings_menu_spec.rb +++ b/ee/spec/lib/ee/sidebars/groups/menus/settings_menu_spec.rb @@ -314,6 +314,7 @@ :admin_cicd_variables | 'CI/CD' :admin_compliance_framework | 'General' :admin_push_rules | 'Repository' + :admin_runners | 'CI/CD' :manage_deploy_tokens | 'Repository' :manage_group_access_tokens | 'Access Tokens' :manage_merge_request_settings | 'General' diff --git a/ee/spec/lib/ee/sidebars/projects/menus/settings_menu_spec.rb b/ee/spec/lib/ee/sidebars/projects/menus/settings_menu_spec.rb index 9047663cec545b1345609ba404955b328a6e614c..89f1927225e9a8156ff4fde516fa00f2897d02f9 100644 --- a/ee/spec/lib/ee/sidebars/projects/menus/settings_menu_spec.rb +++ b/ee/spec/lib/ee/sidebars/projects/menus/settings_menu_spec.rb @@ -119,6 +119,8 @@ where(:ability, :menu_item) do :admin_cicd_variables | 'CI/CD' :admin_push_rules | 'Repository' + :admin_runners | 'CI/CD' + :manage_deploy_tokens | 'Repository' :manage_merge_request_settings | 'Merge requests' :manage_project_access_tokens | 'Access Tokens' :admin_integrations | 'Integrations' diff --git a/ee/spec/policies/ee/ci/runner_policy_spec.rb b/ee/spec/policies/ee/ci/runner_policy_spec.rb index 22fc47815dd9c1301369ae4d5b263ec4e9347ba1..50eeeeb8b6c6d0bbeea0dc6fb95909d9e347008c 100644 --- a/ee/spec/policies/ee/ci/runner_policy_spec.rb +++ b/ee/spec/policies/ee/ci/runner_policy_spec.rb @@ -45,5 +45,44 @@ end end end + + context 'with `admin_runner` access via a custom role' do + let_it_be_with_reload(:user) { create(:user) } + let_it_be(:role) { create(:member_role, :guest, :admin_runners, namespace: project.group) } + + before do + stub_licensed_features(custom_roles: true) + end + + context 'with project runner' do + let_it_be(:membership) { create(:project_member, :guest, member_role: role, user: user, project: project) } + let_it_be_with_reload(:runner) { create(:ci_runner, :project, projects: [project]) } + + it { expect_allowed :read_runner } + + it 'avoids N+1 queries' do + control = ActiveRecord::QueryRecorder.new do + described_class.new(user, runner).allowed?(:read_runner) + end + + create_list(:project, 3).each do |project| + project.add_member(user, :guest) + runner.runner_projects.create!(project: project) + end + + expect do + described_class.new(user, runner).allowed?(:read_runner) + end.not_to exceed_query_limit(control) + end + + context 'with `custom_ability_admin_runners` disabled' do + before do + stub_feature_flags(custom_ability_admin_runners: false) + end + + it { expect_disallowed :read_runner } + end + end + end end end diff --git a/ee/spec/policies/group_policy_spec.rb b/ee/spec/policies/group_policy_spec.rb index 33f0fd83c802d4ea355bf72aadccbe670dea6515..e35e04778a3f8dcd6adf25ece8e5f60eb7a1b6d4 100644 --- a/ee/spec/policies/group_policy_spec.rb +++ b/ee/spec/policies/group_policy_spec.rb @@ -3671,6 +3671,21 @@ def create_member_role(member, abilities = member_role_abilities) end end + context 'for a member role with `admin_runners` true' do + let(:member_role_abilities) { { admin_runners: true } } + let(:allowed_abilities) do + [ + :admin_runner, + :create_runner, + :destroy_runner, + :read_runner, + :update_runner + ] + end + + it_behaves_like 'custom roles abilities' + end + context 'for a custom role with the `admin_integrations` permission' do let(:member_role_abilities) { { admin_integrations: true } } diff --git a/ee/spec/policies/project_policy_spec.rb b/ee/spec/policies/project_policy_spec.rb index 2deb620351467a7d8e8160ab9cde6e4495d3c65c..47bd43a06d2d0ebff82a8b7ddd151234dd8258d8 100644 --- a/ee/spec/policies/project_policy_spec.rb +++ b/ee/spec/policies/project_policy_spec.rb @@ -2769,6 +2769,21 @@ def create_member_role(member, abilities = member_role_abilities) it_behaves_like 'custom roles abilities' end + context 'for a member role with admin_runners true' do + let(:member_role_abilities) { { admin_runners: true } } + let(:allowed_abilities) do + [ + :admin_runner, + :create_runner, + :destroy_runner, + :read_runner, + :update_runner + ] + end + + it_behaves_like 'custom roles abilities' + end + context 'for a member role with read_vulnerability true' do let(:member_role_abilities) { { read_vulnerability: true } } let(:allowed_abilities) do diff --git a/ee/spec/requests/custom_roles/admin_runners/request_spec.rb b/ee/spec/requests/custom_roles/admin_runners/request_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..317032121447e544f1a9a97657a310d3b633bd3d --- /dev/null +++ b/ee/spec/requests/custom_roles/admin_runners/request_spec.rb @@ -0,0 +1,155 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "User with admin_runners custom role", feature_category: :runner do + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :in_group) } + let_it_be_with_reload(:group) { project.group } + let_it_be(:role) { create(:member_role, :guest, :admin_runners, namespace: project.group) } + + before do + stub_licensed_features(custom_roles: true) + end + + describe Projects::RunnersController do + let_it_be(:membership) { create(:project_member, :guest, member_role: role, user: user, project: project) } + + before do + sign_in(user) + end + + it "#index" do + get project_runners_path(project) + + expect(response).to redirect_to(project_settings_ci_cd_path(project, anchor: 'js-runners-settings')) + end + + it "#new" do + get new_project_runner_path(project) + + expect(response).to have_gitlab_http_status(:ok) + end + + it "#update" do + runner = create(:ci_runner, :project, active: true, projects: [project]) + + patch project_runner_path(project, runner), params: { runner: { description: "hello world" } } + + expect(response).to redirect_to(project_runner_path(project, runner)) + end + + it "#toggle_shared_runners" do + post toggle_shared_runners_project_runners_path(project) + + expect(response).to have_gitlab_http_status(:ok) + end + + it "#destroy" do + runner = create(:ci_runner, :project, projects: [project]) + + expect_next_instance_of(Ci::Runners::UnregisterRunnerService, runner, user) do |service| + expect(service).to receive(:execute).once.and_call_original + end + + delete project_runner_path(project, runner) + + expect(response).to redirect_to(project_runners_path(project)) + end + + it "#pause" do + runner = create(:ci_runner, :project, active: true, projects: [project]) + + post pause_project_runner_path(project, runner) + + expect(response).to redirect_to(project_runners_path(project)) + end + end + + describe ::Projects::Settings::CiCdController do + let_it_be(:membership) { create(:project_member, :guest, member_role: role, user: user, project: project) } + + before do + sign_in(user) + end + + it "#show" do + get project_settings_ci_cd_path(project) + + expect(response).to have_gitlab_http_status(:ok) + expect(response.body).to include('CI/CD Settings') + end + end + + describe ::Groups::Settings::CiCdController do + let_it_be(:membership) { create(:group_member, :guest, member_role: role, user: user, group: group) } + + before do + sign_in(user) + end + + it "#show" do + get group_settings_ci_cd_path(group) + + expect(response).to have_gitlab_http_status(:ok) + expect(response.body).to include('CI/CD Settings') + end + end + + describe API::Groups do + include ApiHelpers + + let_it_be(:membership) { create(:group_member, :guest, member_role: role, user: user, group: group) } + + pending "PUT /groups/:id" do + put api("/groups/#{group.id}", user), params: { + shared_runners_setting: 'disabled_and_unoverridable' + } + + expect(response).to have_gitlab_http_status(:ok) + expect(group.reload.shared_runners_setting).to eq('disabled_and_unoverridable') + end + end + + describe Mutations::Ci::Runner::Create do + include GraphqlHelpers + + let_it_be(:membership) { create(:project_member, :guest, member_role: role, user: user, project: project) } + + it "creates a runner" do + post_graphql_mutation(graphql_mutation(:runner_create, { + runner_type: 'PROJECT_TYPE', + project_id: project.to_global_id + }), current_user: user) + + expect(response).to have_gitlab_http_status(:success) + + mutation_response = graphql_mutation_response(:runner_create) + + expect(mutation_response).to be_present + expect(mutation_response['runner']).to be_present + expect(mutation_response['errors']).to be_empty + end + end + + describe Mutations::Ci::NamespaceCiCdSettingsUpdate do + include GraphqlHelpers + + let_it_be(:membership) { create(:group_member, :guest, member_role: role, user: user, group: group) } + + pending "updates the `allow_stale_runner_pruning` setting" do + post_graphql_mutation(graphql_mutation(:namespace_ci_cd_settings_update, { + full_path: group.full_path, + allow_stale_runner_pruning: true + }), current_user: user) + + expect(response).to have_gitlab_http_status(:success) + expect(fresh_response_data['errors']).to be_blank + + mutation_response = graphql_mutation_response(:namespace_ci_cd_settings_update) + expect(mutation_response).to be_present + expect(mutation_response['ciCdSettings']).to be_present + expect(mutation_response['errors']).to be_empty + end + end +end diff --git a/spec/policies/namespaces/user_namespace_policy_spec.rb b/spec/policies/namespaces/user_namespace_policy_spec.rb index b4fbc7e0417a5897b4877f0d9d0b5a1bda68bfd6..c88794ffe0140ad11fcdfff8a98d2844f4543f17 100644 --- a/spec/policies/namespaces/user_namespace_policy_spec.rb +++ b/spec/policies/namespaces/user_namespace_policy_spec.rb @@ -8,7 +8,7 @@ let_it_be(:admin) { create(:admin) } let_it_be(:namespace) { create(:user_namespace, owner: owner) } - let(:owner_permissions) { [:owner_access, :create_projects, :admin_namespace, :read_namespace, :read_namespace_via_membership, :read_statistics, :transfer_projects, :admin_package, :read_billing, :edit_billing, :import_projects] } + let(:owner_permissions) { [:owner_access, :create_projects, :admin_runner, :admin_namespace, :read_namespace, :read_namespace_via_membership, :read_statistics, :transfer_projects, :admin_package, :read_billing, :edit_billing, :import_projects] } subject { described_class.new(current_user, namespace) } diff --git a/spec/support/shared_contexts/policies/group_policy_shared_context.rb b/spec/support/shared_contexts/policies/group_policy_shared_context.rb index 241ca8cf6fd17443ec12e147044f6fc424027fb2..fbcb4feeaad2c5edd655b12f9048327b6a3b5a66 100644 --- a/spec/support/shared_contexts/policies/group_policy_shared_context.rb +++ b/spec/support/shared_contexts/policies/group_policy_shared_context.rb @@ -78,6 +78,7 @@ admin_namespace admin_group_member admin_package + admin_runner change_visibility_level set_note_created_at create_subgroup diff --git a/spec/support/shared_contexts/policies/project_policy_shared_context.rb b/spec/support/shared_contexts/policies/project_policy_shared_context.rb index 984584f72a8b92dc1473a605102aa209fd07ffb3..452fd74b3478f4a292508b8055930b3cc37a9c9b 100644 --- a/spec/support/shared_contexts/policies/project_policy_shared_context.rb +++ b/spec/support/shared_contexts/policies/project_policy_shared_context.rb @@ -67,7 +67,7 @@ %i[ add_cluster admin_build admin_commit_status admin_container_image admin_cicd_variables admin_deployment admin_environment admin_note admin_pipeline - admin_project admin_project_member admin_push_rules admin_snippet admin_terraform_state + admin_project admin_project_member admin_push_rules admin_runner admin_snippet admin_terraform_state admin_wiki create_deploy_token destroy_deploy_token manage_deploy_tokens push_to_delete_protected_branch read_deploy_token update_snippet destroy_upload admin_member_access_request rename_project manage_merge_request_settings