Commit 81b8d7a6 authored by Miguel Rincon's avatar Miguel Rincon

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.
parent a3966076
import { initGroupRunners } from '~/runner/group_runners';
initGroupRunners();
<script>
import RunnerTypeHelp from '../components/runner_type_help.vue';
export default {
components: {
RunnerTypeHelp,
},
};
</script>
<template>
<div>
<div class="row">
<div class="col-sm-6">
<runner-type-help />
</div>
</div>
</div>
</template>
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);
},
});
};
# frozen_string_literal: true # frozen_string_literal: true
class Groups::RunnersController < Groups::ApplicationController class Groups::RunnersController < Groups::ApplicationController
# Proper policies should be implemented per # TODO Proper policies, such as `read_group_runners, should be implemented per
# https://gitlab.com/gitlab-org/gitlab-foss/issues/45894 # https://gitlab.com/gitlab-org/gitlab/-/issues/334802
before_action :authorize_admin_group! 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] before_action :runner, only: [:edit, :update, :destroy, :pause, :resume, :show]
feature_category :runner 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 def show
end end
......
...@@ -250,6 +250,12 @@ module GroupsHelper ...@@ -250,6 +250,12 @@ module GroupsHelper
can?(current_user, "read_group_#{resource}".to_sym, @group) can?(current_user, "read_group_#{resource}".to_sym, @group)
end 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) if can?(current_user, :read_cluster, @group)
links << :kubernetes links << :kubernetes
end end
......
- page_title s_('Runners|Runners')
%h2.page-title
= s_('Runners|Group Runners')
#js-group-runners
...@@ -92,6 +92,23 @@ ...@@ -92,6 +92,23 @@
= render_if_exists "layouts/nav/ee/push_rules_link" # EE-specific = 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) - if group_sidebar_link?(:kubernetes)
= nav_link(controller: [:clusters]) do = nav_link(controller: [:clusters]) do
= link_to group_clusters_path(@group) do = link_to group_clusters_path(@group) do
...@@ -145,7 +162,7 @@ ...@@ -145,7 +162,7 @@
%span %span
= _('Repository') = _('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 = link_to group_settings_ci_cd_path(@group), title: _('CI/CD') do
%span %span
= _('CI/CD') = _('CI/CD')
......
---
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
...@@ -105,6 +105,7 @@ RSpec.describe 'Group navbar' do ...@@ -105,6 +105,7 @@ RSpec.describe 'Group navbar' do
before do before do
group.add_owner(user) 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(_('Analytics'), new_nav_item: settings_nav_item)
insert_after_nav_item(_('Settings'), new_nav_item: administration_nav_item) insert_after_nav_item(_('Settings'), new_nav_item: administration_nav_item)
...@@ -120,6 +121,7 @@ RSpec.describe 'Group navbar' do ...@@ -120,6 +121,7 @@ RSpec.describe 'Group navbar' do
group.add_owner(user) 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(_('Analytics'), new_nav_item: settings_nav_item)
insert_after_nav_item( insert_after_nav_item(
_('Settings'), _('Settings'),
...@@ -156,6 +158,7 @@ RSpec.describe 'Group navbar' do ...@@ -156,6 +158,7 @@ RSpec.describe 'Group navbar' do
stub_licensed_features(security_dashboard: true, group_level_compliance_dashboard: true) 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(_('Analytics'), new_nav_item: settings_nav_item)
insert_after_nav_item(_('Settings'), new_nav_item: administration_nav_item) insert_after_nav_item(_('Settings'), new_nav_item: administration_nav_item)
......
...@@ -28198,6 +28198,9 @@ msgstr "" ...@@ -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." 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 "" msgstr ""
msgid "Runners|Group Runners"
msgstr ""
msgid "Runners|IP Address" msgid "Runners|IP Address"
msgstr "" msgstr ""
...@@ -28270,6 +28273,9 @@ msgstr "" ...@@ -28270,6 +28273,9 @@ msgstr ""
msgid "Runners|Runner registration" msgid "Runners|Runner registration"
msgstr "" 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." 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 "" msgstr ""
......
...@@ -15,6 +15,33 @@ RSpec.describe Groups::RunnersController do ...@@ -15,6 +15,33 @@ RSpec.describe Groups::RunnersController do
sign_in(user) sign_in(user)
end 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 describe '#show' do
context 'when user is owner' do context 'when user is owner' do
before do before do
......
...@@ -40,7 +40,7 @@ RSpec.describe 'User searches group settings', :js do ...@@ -40,7 +40,7 @@ RSpec.describe 'User searches group settings', :js do
visit group_settings_ci_cd_path(group) visit group_settings_ci_cd_path(group)
end end
it_behaves_like 'can search settings', 'Variables', 'Runners' it_behaves_like 'can search settings', 'Variables', 'Auto DevOps'
end end
context 'in Packages & Registries page' do context 'in Packages & Registries page' do
......
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);
});
});
...@@ -313,15 +313,30 @@ RSpec.describe GroupsHelper do ...@@ -313,15 +313,30 @@ RSpec.describe GroupsHelper do
it 'returns all the expected links' do it 'returns all the expected links' do
links = [ links = [
:overview, :activity, :issues, :labels, :milestones, :merge_requests, :overview, :activity, :issues, :labels, :milestones, :merge_requests,
:group_members, :settings :runners, :group_members, :settings
] ]
expect(helper.group_sidebar_links).to include(*links) expect(helper.group_sidebar_links).to include(*links)
end 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(: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) expect(helper.group_sidebar_links).not_to include(:settings)
end end
......
...@@ -176,6 +176,15 @@ RSpec.shared_context 'group navbar structure' do ...@@ -176,6 +176,15 @@ RSpec.shared_context 'group navbar structure' do
} }
end end
let(:ci_cd_nav_item) do
{
nav_item: _('CI/CD'),
nav_sub_items: [
s_('Runners|Runners')
]
}
end
let(:issues_nav_items) do let(:issues_nav_items) do
[ [
_('List'), _('List'),
......
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