Commit e8b38b2c authored by Thong Kuah's avatar Thong Kuah

Merge branch '330969-feature-flag-removal' into 'master'

Remove runner_list_view_vue_ui feature flag

See merge request gitlab-org/gitlab!67021
parents 19c3dc1f 1532ee45
import { __ } from '~/locale';
import FilteredSearchTokenKeys from './filtered_search_token_keys';
const tokenKeys = [
{
formattedKey: __('Status'),
key: 'status',
type: 'string',
param: 'status',
symbol: '',
icon: 'messages',
tag: 'status',
},
{
formattedKey: __('Type'),
key: 'type',
type: 'string',
param: 'type',
symbol: '',
icon: 'cube',
tag: 'type',
},
{
formattedKey: __('Tag'),
key: 'tag',
type: 'array',
param: 'name[]',
symbol: '~',
icon: 'tag',
tag: '~tag',
},
];
const AdminRunnersFilteredSearchTokenKeys = new FilteredSearchTokenKeys(tokenKeys);
export default AdminRunnersFilteredSearchTokenKeys;
import AdminRunnersFilteredSearchTokenKeys from '~/filtered_search/admin_runners_filtered_search_token_keys';
import { FILTERED_SEARCH } from '~/pages/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
import { initAdminRunners } from '~/runner/admin_runners';
initFilteredSearch({
page: FILTERED_SEARCH.ADMIN_RUNNERS,
filteredSearchTokenKeys: AdminRunnersFilteredSearchTokenKeys,
useDefaultState: true,
});
initInstallRunner();
if (gon.features?.runnerListViewVueUi) {
initAdminRunners();
}
initAdminRunners();
......@@ -4,19 +4,11 @@ class Admin::RunnersController < Admin::ApplicationController
include RunnerSetupScripts
before_action :runner, except: [:index, :tag_list, :runner_setup_scripts]
before_action only: [:index] do
push_frontend_feature_flag(:runner_list_view_vue_ui, current_user, default_enabled: :yaml)
end
feature_category :runner
NUMBER_OF_RUNNERS_PER_PAGE = 30
def index
finder = Ci::RunnersFinder.new(current_user: current_user, params: params)
@runners = finder.execute.page(params[:page]).per(NUMBER_OF_RUNNERS_PER_PAGE)
@active_runners_count = Ci::Runner.online.count
@sort = finder.sort_key
end
def show
......
-# Note: This file should stay aligned with:
-# `app/views/groups/runners/_runner.html.haml`
.gl-responsive-table-row{ data: { testid: "runner-row-#{runner.id}" } }
.table-section.section-10.section-wrap
.table-mobile-header{ role: 'rowheader' }= _('Type')
.table-mobile-content
- if runner.instance_type?
%span.badge.badge-pill.gl-badge.sm.badge-success= s_('Runners|shared')
- elsif runner.group_type?
%span.badge.badge-pill.gl-badge.sm.badge-success= s_('Runners|group')
- else
%span.badge.badge-pill.gl-badge.sm.badge-info= s_('Runners|specific')
- if runner.locked?
%span.badge.badge-pill.gl-badge.sm.badge-warning= s_('Runners|locked')
- unless runner.active?
%span.badge.badge-pill.gl-badge.sm.badge-danger= s_('Runners|paused')
.table-section.section-30
.table-mobile-header{ role: 'rowheader' }= s_('Runners|Runner')
.table-mobile-content
= link_to("##{runner.id} (#{runner.short_sha})", admin_runner_path(runner))
.gl-text-truncate
%span{ title: runner.description, data: { toggle: 'tooltip', container: 'body' } }
= runner.description
.table-section.section-10
.table-mobile-header{ role: 'rowheader' }= _('Version')
.table-mobile-content.str-truncated.has-tooltip{ title: runner.version }
= runner.version
.table-section.section-10
.table-mobile-header{ role: 'rowheader' }= _('IP Address')
.table-mobile-content.str-truncated.has-tooltip{ title: runner.ip_address }
= runner.ip_address
.table-section.section-5
.table-mobile-header{ role: 'rowheader' }= _('Projects')
.table-mobile-content
- if runner.instance_type? || runner.group_type?
= _('n/a')
- else
= runner.projects.count(:all)
.table-section.section-5
.table-mobile-header{ role: 'rowheader' }= _('Jobs')
.table-mobile-content
= limited_counter_with_delimiter(runner.builds)
.table-section.section-10.section-wrap
.table-mobile-header{ role: 'rowheader' }= _('Tags')
.table-mobile-content
- runner.tags.map(&:name).sort.each do |tag|
%span.badge.badge-primary.str-truncated.has-tooltip{ title: tag }
= tag
.table-section.section-10
.table-mobile-header{ role: 'rowheader' }= _('Last contact')
.table-mobile-content
- contacted_at = runner_contacted_at(runner)
- if contacted_at
= time_ago_with_tooltip contacted_at
- else
= _('Never')
.table-section.table-button-footer.section-10
.btn-group.table-action-buttons
.btn-group
= link_to admin_runner_path(runner), class: 'gl-button btn btn-default btn-icon has-tooltip', title: _('Edit'), ref: 'tooltip', aria: { label: _('Edit') }, data: { placement: 'top', container: 'body'} do
= sprite_icon('pencil', css_class: 'gl-icon')
.btn-group
- if runner.active?
= link_to [:pause, :admin, runner], method: :post, class: 'gl-button btn btn-default btn-icon has-tooltip', title: _('Pause'), ref: 'tooltip', aria: { label: _('Pause') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do
= sprite_icon('pause', css_class: 'gl-icon')
- else
= link_to [:resume, :admin, runner], method: :post, class: 'gl-button btn btn-default btn-icon has-tooltip gl-px-3', title: _('Resume'), ref: 'tooltip', aria: { label: _('Resume') }, data: { placement: 'top', container: 'body'} do
= sprite_icon('play', css_class: 'gl-icon')
.btn-group
= link_to [:admin, runner], method: :delete, class: 'gl-button btn btn-danger btn-icon has-tooltip', title: _('Remove'), ref: 'tooltip', aria: { label: _('Remove') }, data: { placement: 'top', container: 'body', confirm: _('Are you sure?') } do
= sprite_icon('close', css_class: 'gl-icon')
- breadcrumb_title _('Runners')
- page_title _('Runners')
- if Feature.enabled?(:runner_list_view_vue_ui, current_user, default_enabled: :yaml)
#js-admin-runners{ data: { registration_token: Gitlab::CurrentSettings.runners_registration_token, runner_install_help_page: 'https://docs.gitlab.com/runner/install/', active_runners_count: @active_runners_count } }
- else
.row
.col-sm-6
.bs-callout
%p
= _("Runners are processes that pick up and execute CI/CD jobs for GitLab.")
%br
= _('You can register runners as separate users, on separate servers, and on your local machine. Register as many runners as you want.')
%br
%div
%span= _('Runners can be:')
%ul
%li
%span.badge.badge-pill.gl-badge.sm.badge-success= s_('Runners|shared')
\-
= _('Runs jobs from all unassigned projects.')
%li
%span.badge.badge-pill.gl-badge.sm.badge-success= s_('Runners|group')
\-
= _('Runs jobs from all unassigned projects in its group.')
%li
%span.badge.badge-pill.gl-badge.sm.badge-info= s_('Runners|specific')
\-
= _('Runs jobs from assigned projects.')
%li
%span.badge.badge-pill.gl-badge.sm.badge-warning= s_('Runners|locked')
\-
= _('Cannot be assigned to other projects.')
%li
%span.badge.badge-pill.gl-badge.sm.badge-danger= s_('Runners|paused')
\-
= _('Not available to run jobs.')
.col-sm-6
.bs-callout
= render partial: 'ci/runner/how_to_setup_runner',
locals: { registration_token: Gitlab::CurrentSettings.runners_registration_token,
type: s_('Runners|shared'),
reset_token_url: reset_registration_token_admin_application_settings_path,
project_path: '',
group_path: '' }
.row
.col-sm-9
= form_tag admin_runners_path, id: 'runners-search', method: :get, class: 'filter-form js-filter-form' do
.filtered-search-wrapper.d-flex
.filtered-search-box
= dropdown_tag(_('Recent searches'),
options: { wrapper_class: 'filtered-search-history-dropdown-wrapper',
toggle_class: 'gl-button btn btn-default filtered-search-history-dropdown-toggle-button',
dropdown_class: 'filtered-search-history-dropdown',
content_class: 'filtered-search-history-dropdown-content' }) do
.js-filtered-search-history-dropdown{ data: { full_path: admin_runners_path } }
.filtered-search-box-input-container.droplab-dropdown
.scroll-container
%ul.tokens-container.list-unstyled
%li.input-token
%input.form-control.filtered-search{ search_filter_input_options('runners') }
#js-dropdown-hint.filtered-search-input-dropdown-menu.dropdown-menu.hint-dropdown
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item{ data: {hint: "#{'{{hint}}'}", tag: "#{'{{tag}}'}", action: "#{'{{hint === \'search\' ? \'submit\' : \'\' }}'}" } }
= button_tag class: %w[gl-button btn btn-link] do
-# Encapsulate static class name `{{icon}}` inside #{} to bypass
-# haml lint's ClassAttributeWithStaticValue
%svg
%use{ 'xlink:href': "#{'{{icon}}'}" }
%span.js-filter-hint
{{formattedKey}}
#js-dropdown-operator.filtered-search-input-dropdown-menu.dropdown-menu
%ul.filter-dropdown{ data: { dropdown: true, dynamic: true } }
%li.filter-dropdown-item{ data: { value: "{{ title }}" } }
%button.gl-button.btn.btn-link{ type: 'button' }
{{ title }}
%span.btn-helptext
{{ help }}
#js-dropdown-admin-runner-status.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
- Ci::Runner::AVAILABLE_STATUSES.each do |status|
%li.filter-dropdown-item{ data: { value: status } }
= button_tag class: %w[gl-button btn btn-link] do
= status.titleize
#js-dropdown-admin-runner-type.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
- Ci::Runner::AVAILABLE_TYPES.each do |runner_type|
%li.filter-dropdown-item{ data: { value: runner_type } }
= button_tag class: %w[gl-button btn btn-link] do
= runner_type.titleize
#js-dropdown-admin-runner-type.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
- Ci::Runner::AVAILABLE_TYPES.each do |runner_type|
%li.filter-dropdown-item{ data: { value: runner_type } }
= button_tag class: %w[gl-button btn btn-link] do
= runner_type.titleize
#js-dropdown-runner-tag.filtered-search-input-dropdown-menu.dropdown-menu
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'none' } }
%button.gl-button.btn.btn-link
= _('No Tag')
%li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
%button.gl-button.btn.btn-link.js-data-value
%span.dropdown-light-content
{{name}}
= button_tag class: %w[clear-search hidden] do
= sprite_icon('close', size: 16, css_class: 'clear-search-icon')
.filter-dropdown-container
= render 'sort_dropdown'
.col-sm-3.text-right-lg
= _('Runners currently online: %{active_runners_count}') % { active_runners_count: @active_runners_count }
- if @runners.any?
.content-list{ data: { testid: 'runners-table' } }
.table-holder
.gl-responsive-table-row.table-row-header{ role: 'row' }
.table-section.section-10{ role: 'rowheader' }= _('Type/State')
.table-section.section-30{ role: 'rowheader' }= s_('Runners|Runner')
.table-section.section-10{ role: 'rowheader' }= _('Version')
.table-section.section-10{ role: 'rowheader' }= _('IP Address')
.table-section.section-5{ role: 'rowheader' }= _('Projects')
.table-section.section-5{ role: 'rowheader' }= _('Jobs')
.table-section.section-10{ role: 'rowheader' }= _('Tags')
.table-section.section-10{ role: 'rowheader' }= _('Last contact')
.table-section.section-10{ role: 'rowheader' }
- @runners.each do |runner|
= render 'admin/runners/runner', runner: runner
= paginate @runners, theme: 'gitlab'
- else
.nothing-here-block= _('No runners found')
#js-admin-runners{ data: { registration_token: Gitlab::CurrentSettings.runners_registration_token, runner_install_help_page: 'https://docs.gitlab.com/runner/install/', active_runners_count: @active_runners_count } }
......@@ -75,7 +75,7 @@
= button_tag class: 'clear-search hidden' do
= sprite_icon('close', size: 16, css_class: 'clear-search-icon')
.filter-dropdown-container
= render 'admin/runners/sort_dropdown'
= render 'groups/runners/sort_dropdown'
.col-sm-3.text-right-lg
= _('Runners currently online: %{active_runners_count}') % { active_runners_count: limited_counter_with_delimiter(@all_group_runners.online) }
......
......@@ -8,4 +8,3 @@
%li
= sortable_item(sort_title_created_date, page_filter_path(sort: sort_value_created_date), sorted_by)
= sortable_item(sort_title_contacted_date, page_filter_path(sort: sort_value_contacted_date), sorted_by)
---
name: runner_list_view_vue_ui
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61241
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330969
milestone: '13.12'
type: development
group: group::runner
default_enabled: true
......@@ -12,42 +12,11 @@ RSpec.describe Admin::RunnersController do
describe '#index' do
render_views
before do
stub_feature_flags(runner_list_view_vue_ui: false)
end
it 'lists all runners' do
get :index
expect(response).to have_gitlab_http_status(:ok)
end
it 'avoids N+1 queries', :request_store do
get :index
control_count = ActiveRecord::QueryRecorder.new { get :index }.count
create_list(:ci_runner, 5, :tagged_only)
# There is still an N+1 query for `runner.builds.count`
# We also need to add 1 because it takes 2 queries to preload tags
# also looking for token nonce requires database queries
expect { get :index }.not_to exceed_query_limit(control_count + 16)
expect(response).to have_gitlab_http_status(:ok)
expect(response.body).to have_content('tag1')
expect(response.body).to have_content('tag2')
end
it 'paginates runners' do
stub_const("Admin::RunnersController::NUMBER_OF_RUNNERS_PER_PAGE", 1)
create(:ci_runner)
get :index
expect(response).to have_gitlab_http_status(:ok)
expect(assigns(:runners).count).to be(1)
expect(response).to render_template(:index)
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