From 81b8d7a62a6664efd757cf49cb2b8c9c8af59a9d Mon Sep 17 00:00:00 2001 From: Miguel Rincon Date: Mon, 19 Jul 2021 16:31:51 +0200 Subject: [PATCH] Add group runners page This change add a new page to manage group runners behind the feature flag runner_list_group_view_vue_ui. The new page is added to the sidebar menu as CI/CD -> Runners. --- .../javascripts/pages/groups/runners/index.js | 3 +++ .../group_runners/group_runners_app.vue | 19 +++++++++++++ .../javascripts/runner/group_runners/index.js | 17 ++++++++++++ app/controllers/groups/runners_controller.rb | 13 ++++++--- app/helpers/groups_helper.rb | 6 +++++ app/views/groups/runners/index.html.haml | 6 +++++ .../nav/sidebar/_group_menus.html.haml | 19 ++++++++++++- .../runner_list_group_view_vue_ui.yml | 8 ++++++ ee/spec/features/groups/navbar_spec.rb | 3 +++ locale/gitlab.pot | 6 +++++ .../groups/runners_controller_spec.rb | 27 +++++++++++++++++++ .../user_searches_in_settings_spec.rb | 2 +- .../group_runners/group_runners_app_spec.js | 21 +++++++++++++++ spec/helpers/groups_helper_spec.rb | 21 ++++++++++++--- .../navbar_structure_context.rb | 9 +++++++ 15 files changed, 172 insertions(+), 8 deletions(-) create mode 100644 app/assets/javascripts/pages/groups/runners/index.js create mode 100644 app/assets/javascripts/runner/group_runners/group_runners_app.vue create mode 100644 app/assets/javascripts/runner/group_runners/index.js create mode 100644 app/views/groups/runners/index.html.haml create mode 100644 config/feature_flags/development/runner_list_group_view_vue_ui.yml create mode 100644 spec/frontend/runner/group_runners/group_runners_app_spec.js diff --git a/app/assets/javascripts/pages/groups/runners/index.js b/app/assets/javascripts/pages/groups/runners/index.js new file mode 100644 index 00000000000000..ca1a6bdab75bc7 --- /dev/null +++ b/app/assets/javascripts/pages/groups/runners/index.js @@ -0,0 +1,3 @@ +import { initGroupRunners } from '~/runner/group_runners'; + +initGroupRunners(); diff --git a/app/assets/javascripts/runner/group_runners/group_runners_app.vue b/app/assets/javascripts/runner/group_runners/group_runners_app.vue new file mode 100644 index 00000000000000..92d881c43ea564 --- /dev/null +++ b/app/assets/javascripts/runner/group_runners/group_runners_app.vue @@ -0,0 +1,19 @@ + + + diff --git a/app/assets/javascripts/runner/group_runners/index.js b/app/assets/javascripts/runner/group_runners/index.js new file mode 100644 index 00000000000000..5a72b09de3a4f7 --- /dev/null +++ b/app/assets/javascripts/runner/group_runners/index.js @@ -0,0 +1,17 @@ +import Vue from 'vue'; +import GroupRunnersApp from './group_runners_app.vue'; + +export const initGroupRunners = (selector = '#js-group-runners') => { + const el = document.querySelector(selector); + + if (!el) { + return null; + } + + return new Vue({ + el, + render(h) { + return h(GroupRunnersApp); + }, + }); +}; diff --git a/app/controllers/groups/runners_controller.rb b/app/controllers/groups/runners_controller.rb index 1cff658dd52400..dbbfdd76fe8bfe 100644 --- a/app/controllers/groups/runners_controller.rb +++ b/app/controllers/groups/runners_controller.rb @@ -1,14 +1,21 @@ # frozen_string_literal: true class Groups::RunnersController < Groups::ApplicationController - # Proper policies should be implemented per - # https://gitlab.com/gitlab-org/gitlab-foss/issues/45894 + # TODO Proper policies, such as `read_group_runners, should be implemented per + # https://gitlab.com/gitlab-org/gitlab/-/issues/334802 before_action :authorize_admin_group! - + before_action :runner_list_group_view_vue_ui_enabled, only: [:index] before_action :runner, only: [:edit, :update, :destroy, :pause, :resume, :show] feature_category :runner + def index + end + + def runner_list_group_view_vue_ui_enabled + return render_404 unless Feature.enabled?(:runner_list_group_view_vue_ui, group, default_enabled: :yaml) + end + def show end diff --git a/app/helpers/groups_helper.rb b/app/helpers/groups_helper.rb index ff74f62f9fbfab..4adf648d5aba07 100644 --- a/app/helpers/groups_helper.rb +++ b/app/helpers/groups_helper.rb @@ -250,6 +250,12 @@ def get_group_sidebar_links can?(current_user, "read_group_#{resource}".to_sym, @group) end + # TODO Proper policies, such as `read_group_runners, should be implemented per + # See https://gitlab.com/gitlab-org/gitlab/-/issues/334802 + if can?(current_user, :admin_group, @group) && Feature.enabled?(:runner_list_group_view_vue_ui, @group, default_enabled: :yaml) + links << :runners + end + if can?(current_user, :read_cluster, @group) links << :kubernetes end diff --git a/app/views/groups/runners/index.html.haml b/app/views/groups/runners/index.html.haml new file mode 100644 index 00000000000000..08be0f93d82daf --- /dev/null +++ b/app/views/groups/runners/index.html.haml @@ -0,0 +1,6 @@ +- page_title s_('Runners|Runners') + +%h2.page-title + = s_('Runners|Group Runners') + +#js-group-runners diff --git a/app/views/layouts/nav/sidebar/_group_menus.html.haml b/app/views/layouts/nav/sidebar/_group_menus.html.haml index e14fbfb3bb4903..2196ef5b311eba 100644 --- a/app/views/layouts/nav/sidebar/_group_menus.html.haml +++ b/app/views/layouts/nav/sidebar/_group_menus.html.haml @@ -92,6 +92,23 @@ = render_if_exists "layouts/nav/ee/push_rules_link" # EE-specific +- if group_sidebar_link?(:runners) + = nav_link(path: 'groups/runners#index') do + = link_to group_runners_path(@group), title: _('CI/CD'), class: 'has-sub-items' do + .nav-icon-container + = sprite_icon('rocket') + %span.nav-item-name + = _('CI/CD') + %ul.sidebar-sub-level-items + = nav_link(path: 'groups/runners#index', html_options: { class: "fly-out-top-item" } ) do + = link_to group_runners_path(@group), title: _('CI/CD') do + %strong.fly-out-top-item-name + = _('CI/CD') + %li.divider.fly-out-top-item + = nav_link(path: 'groups/runners#index') do + = link_to group_runners_path(@group), title: s_('Runners|Runners') do + %span= s_('Runners|Runners') + - if group_sidebar_link?(:kubernetes) = nav_link(controller: [:clusters]) do = link_to group_clusters_path(@group) do @@ -145,7 +162,7 @@ %span = _('Repository') - = nav_link(controller: [:ci_cd, 'groups/runners']) do + = nav_link(path: ['groups/runners#show', 'groups/runners#edit'], controller: [:ci_cd]) do = link_to group_settings_ci_cd_path(@group), title: _('CI/CD') do %span = _('CI/CD') diff --git a/config/feature_flags/development/runner_list_group_view_vue_ui.yml b/config/feature_flags/development/runner_list_group_view_vue_ui.yml new file mode 100644 index 00000000000000..3bda540ba5ba3c --- /dev/null +++ b/config/feature_flags/development/runner_list_group_view_vue_ui.yml @@ -0,0 +1,8 @@ +--- +name: runner_list_group_view_vue_ui +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66376 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/336405 +milestone: '14.2' +type: development +group: group::runner +default_enabled: false diff --git a/ee/spec/features/groups/navbar_spec.rb b/ee/spec/features/groups/navbar_spec.rb index 61b05503138a9f..5aaf97b13e60d3 100644 --- a/ee/spec/features/groups/navbar_spec.rb +++ b/ee/spec/features/groups/navbar_spec.rb @@ -105,6 +105,7 @@ before do group.add_owner(user) + insert_after_nav_item(_('Push Rules'), new_nav_item: ci_cd_nav_item) insert_after_nav_item(_('Analytics'), new_nav_item: settings_nav_item) insert_after_nav_item(_('Settings'), new_nav_item: administration_nav_item) @@ -120,6 +121,7 @@ group.add_owner(user) + insert_after_nav_item(_('Push Rules'), new_nav_item: ci_cd_nav_item) insert_after_nav_item(_('Analytics'), new_nav_item: settings_nav_item) insert_after_nav_item( _('Settings'), @@ -156,6 +158,7 @@ stub_licensed_features(security_dashboard: true, group_level_compliance_dashboard: true) + insert_after_nav_item(_('Push Rules'), new_nav_item: ci_cd_nav_item) insert_after_nav_item(_('Analytics'), new_nav_item: settings_nav_item) insert_after_nav_item(_('Settings'), new_nav_item: administration_nav_item) diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 6ce46772e8e7e2..2bb3701cf7614f 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -28198,6 +28198,9 @@ msgstr "" msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet." msgstr "" +msgid "Runners|Group Runners" +msgstr "" + msgid "Runners|IP Address" msgstr "" @@ -28270,6 +28273,9 @@ msgstr "" msgid "Runners|Runner registration" msgstr "" +msgid "Runners|Runners" +msgstr "" + msgid "Runners|Shared runners are available to every project in a GitLab instance. If you want a runner to build only specific projects, restrict the project in the table below. After you restrict a runner to a project, you cannot change it back to a shared runner." msgstr "" diff --git a/spec/controllers/groups/runners_controller_spec.rb b/spec/controllers/groups/runners_controller_spec.rb index 2f1c6c813cf720..1808969cd60dc3 100644 --- a/spec/controllers/groups/runners_controller_spec.rb +++ b/spec/controllers/groups/runners_controller_spec.rb @@ -15,6 +15,33 @@ sign_in(user) end + describe '#index' do + context 'when user is owner' do + before do + group.add_owner(user) + end + + it 'renders show with 200 status code' do + get :index, params: { group_id: group } + + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template(:index) + end + end + + context 'when user is not owner' do + before do + group.add_maintainer(user) + end + + it 'renders a 404' do + get :index, params: { group_id: group } + + expect(response).to have_gitlab_http_status(:not_found) + end + end + end + describe '#show' do context 'when user is owner' do before do diff --git a/spec/features/groups/settings/user_searches_in_settings_spec.rb b/spec/features/groups/settings/user_searches_in_settings_spec.rb index c258dd41b03fc8..abf56232affad2 100644 --- a/spec/features/groups/settings/user_searches_in_settings_spec.rb +++ b/spec/features/groups/settings/user_searches_in_settings_spec.rb @@ -40,7 +40,7 @@ visit group_settings_ci_cd_path(group) end - it_behaves_like 'can search settings', 'Variables', 'Runners' + it_behaves_like 'can search settings', 'Variables', 'Auto DevOps' end context 'in Packages & Registries page' do diff --git a/spec/frontend/runner/group_runners/group_runners_app_spec.js b/spec/frontend/runner/group_runners/group_runners_app_spec.js new file mode 100644 index 00000000000000..06329686a0032e --- /dev/null +++ b/spec/frontend/runner/group_runners/group_runners_app_spec.js @@ -0,0 +1,21 @@ +import { shallowMount } from '@vue/test-utils'; +import RunnerTypeHelp from '~/runner/components/runner_type_help.vue'; +import GroupRunnersApp from '~/runner/group_runners/group_runners_app.vue'; + +describe('GroupRunnersApp', () => { + let wrapper; + + const findRunnerTypeHelp = () => wrapper.findComponent(RunnerTypeHelp); + + const createComponent = ({ mountFn = shallowMount } = {}) => { + wrapper = mountFn(GroupRunnersApp); + }; + + beforeEach(() => { + createComponent(); + }); + + it('shows the runner type help', () => { + expect(findRunnerTypeHelp().exists()).toBe(true); + }); +}); diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb index ad6852f63df0f2..13f84fecaa59dd 100644 --- a/spec/helpers/groups_helper_spec.rb +++ b/spec/helpers/groups_helper_spec.rb @@ -313,15 +313,30 @@ it 'returns all the expected links' do links = [ :overview, :activity, :issues, :labels, :milestones, :merge_requests, - :group_members, :settings + :runners, :group_members, :settings ] expect(helper.group_sidebar_links).to include(*links) end - it 'includes settings when the user can admin the group' do + it 'excludes runners when the user cannot admin the group' do expect(helper).to receive(:current_user) { user } - expect(helper).to receive(:can?).with(user, :admin_group, group) { false } + # TODO Proper policies, such as `read_group_runners, should be implemented per + # See https://gitlab.com/gitlab-org/gitlab/-/issues/334802 + expect(helper).to receive(:can?).twice.with(user, :admin_group, group) { false } + + expect(helper.group_sidebar_links).not_to include(:runners) + end + + it 'excludes runners when the feature "runner_list_group_view_vue_ui" is disabled' do + stub_feature_flags(runner_list_group_view_vue_ui: false) + + expect(helper.group_sidebar_links).not_to include(:runners) + end + + it 'excludes settings when the user can admin the group' do + expect(helper).to receive(:current_user) { user } + expect(helper).to receive(:can?).twice.with(user, :admin_group, group) { false } expect(helper.group_sidebar_links).not_to include(:settings) end diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb index b7eb03de8f0ac3..8ae0885056e751 100644 --- a/spec/support/shared_contexts/navbar_structure_context.rb +++ b/spec/support/shared_contexts/navbar_structure_context.rb @@ -176,6 +176,15 @@ } end + let(:ci_cd_nav_item) do + { + nav_item: _('CI/CD'), + nav_sub_items: [ + s_('Runners|Runners') + ] + } + end + let(:issues_nav_items) do [ _('List'), -- GitLab