From d587f345b4fe9483c69ba55cbe7647504b90c78b Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 13 Apr 2022 00:10:42 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- app/views/groups/runners/_settings.html.haml | 208 ++++++++++--------- doc/api/projects.md | 2 +- doc/raketasks/backup_restore.md | 17 ++ doc/user/profile/index.md | 2 +- lib/backup/manager.rb | 2 +- spec/features/groups/settings/ci_cd_spec.rb | 95 +++++---- spec/features/runners_spec.rb | 1 + spec/lib/backup/manager_spec.rb | 17 ++ 8 files changed, 201 insertions(+), 143 deletions(-) diff --git a/app/views/groups/runners/_settings.html.haml b/app/views/groups/runners/_settings.html.haml index bbcadc08a8b..087b06ee37d 100644 --- a/app/views/groups/runners/_settings.html.haml +++ b/app/views/groups/runners/_settings.html.haml @@ -1,4 +1,6 @@ - if Feature.enabled?(:runner_list_group_view_vue_ui, @group, default_enabled: :yaml) + .gl-mb-6 + #update-shared-runners-form{ data: group_shared_runners_settings_data(@group) } .gl-card.gl-px-8.gl-py-6.gl-line-height-20 .gl-card-body.gl-display-flex{ :class => "gl-p-0!" } .gl-banner-illustration @@ -11,107 +13,107 @@ %a.btn.btn-confirm.btn-md.gl-button{ :href => group_runners_path(@group) } %span.gl-button-text = s_('Runners|Take me there!') - -= render 'shared/runners/runner_description' - -%hr - -.row - .col-sm-6 - = render 'groups/runners/group_runners' - .col-sm-6 - = render 'groups/runners/shared_runners' - -%h4.underlined-title - = _('Available runners: %{runners}').html_safe % { runners: limited_counter_with_delimiter(@all_group_runners) } - --# haml-lint:disable NoPlainNodes -.row - .col-sm-9 - = form_tag group_settings_ci_cd_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: group_settings_ci_cd_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: '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_tag class: 'gl-button btn btn-link' do - {{ 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: '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| - - next if runner_type == 'instance_type' - %li.filter-dropdown-item{ data: { value: runner_type } } - = button_tag class: '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_tag class: 'gl-button btn btn-link' do - = _('No Tag') - %li.divider.droplab-item-ignore - %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } } - %li.filter-dropdown-item - = button_tag class: 'gl-button btn btn-link js-data-value' do - %span.dropdown-light-content - {{name}} - - = button_tag class: 'clear-search hidden' do - = sprite_icon('close', size: 16, css_class: 'clear-search-icon') - .filter-dropdown-container - = 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) } - - -- if @group_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' } - - - @group_runners.each do |runner| - - runner = runner.present(current_user: current_user) - = render 'groups/runners/runner', runner: runner - = paginate @group_runners, theme: 'gitlab', :params => { :anchor => 'runners-settings' } - else - .nothing-here-block= _('No runners found') + = render 'shared/runners/runner_description' + + %hr + + .row + .col-sm-6 + = render 'groups/runners/group_runners' + .col-sm-6 + = render 'groups/runners/shared_runners' + + %h4.underlined-title + = _('Available runners: %{runners}').html_safe % { runners: limited_counter_with_delimiter(@all_group_runners) } + + -# haml-lint:disable NoPlainNodes + .row + .col-sm-9 + = form_tag group_settings_ci_cd_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: group_settings_ci_cd_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: '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_tag class: 'gl-button btn btn-link' do + {{ 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: '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| + - next if runner_type == 'instance_type' + %li.filter-dropdown-item{ data: { value: runner_type } } + = button_tag class: '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_tag class: 'gl-button btn btn-link' do + = _('No Tag') + %li.divider.droplab-item-ignore + %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } } + %li.filter-dropdown-item + = button_tag class: 'gl-button btn btn-link js-data-value' do + %span.dropdown-light-content + {{name}} + + = button_tag class: 'clear-search hidden' do + = sprite_icon('close', size: 16, css_class: 'clear-search-icon') + .filter-dropdown-container + = 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) } + + + - if @group_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' } + + - @group_runners.each do |runner| + - runner = runner.present(current_user: current_user) + = render 'groups/runners/runner', runner: runner + = paginate @group_runners, theme: 'gitlab', :params => { :anchor => 'runners-settings' } + - else + .nothing-here-block= _('No runners found') diff --git a/doc/api/projects.md b/doc/api/projects.md index 1a1b8ffb733..4b8fd0d675b 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -375,7 +375,7 @@ Get a list of visible projects owned by the given user. When accessed without authentication, only public projects are returned. NOTE: -Only the projects in the user's (specified in `user_id`) namespace are returned. Projects owned by the user in any group or subgroups are not returned. +Only the projects in the user's (specified in `user_id`) namespace are returned. Projects owned by the user in any group or subgroups are not returned. An empty list is returned if a profile is set to private. This endpoint supports [keyset pagination](index.md#keyset-based-pagination) for selected `order_by` options. diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index bd4c1021c98..5458e9952fa 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -724,6 +724,23 @@ sudo gitlab-backup create DIRECTORY=weekly Users of GitLab 12.1 and earlier should use the command `gitlab-rake gitlab:backup:create` instead. +#### Skip uploading backups to remote storage + +If you have configured GitLab to [upload backups in a remote storage](#uploading-backups-to-a-remote-cloud-storage), +you can use the `SKIP=remote` option to skip uploading your backups to the remote storage. + +For Omnibus GitLab packages: + +```shell +sudo gitlab-backup create SKIP=remote +``` + +For installations from source: + +```shell +sudo -u git -H bundle exec rake gitlab:backup:create SKIP=remote RAILS_ENV=production +``` + #### Uploading to locally mounted shares You may also send backups to a mounted share (for example, `NFS`,`CIFS`, or diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md index 6ea0f3cfbe2..a86968654c7 100644 --- a/doc/user/profile/index.md +++ b/doc/user/profile/index.md @@ -88,7 +88,7 @@ The following is hidden from your user profile page (`https://gitlab.example.com - Tabs for activity, groups, contributed projects, personal projects, starred projects, snippets NOTE: -Making your user profile page private does not hide your public resources from the REST or GraphQL APIs. +Making your user profile page private does not hide all your public resources from the REST or GraphQL APIs. ### User visibility diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb index 71cb4d818a7..fffaffda71c 100644 --- a/lib/backup/manager.rb +++ b/lib/backup/manager.rb @@ -271,7 +271,7 @@ module Backup def upload connection_settings = Gitlab.config.backup.upload.connection - if connection_settings.blank? + if connection_settings.blank? || skipped?('remote') puts_time "Uploading backup archive to remote storage #{remote_directory} ... ".color(:blue) + "[SKIPPED]".color(:cyan) return end diff --git a/spec/features/groups/settings/ci_cd_spec.rb b/spec/features/groups/settings/ci_cd_spec.rb index 8851aeb6381..c5ad524e647 100644 --- a/spec/features/groups/settings/ci_cd_spec.rb +++ b/spec/features/groups/settings/ci_cd_spec.rb @@ -5,52 +5,73 @@ require 'spec_helper' RSpec.describe 'Group CI/CD settings' do include WaitForRequests - let(:user) { create(:user) } - let(:group) { create(:group) } + let_it_be(:user) { create(:user) } + let_it_be(:group, reload: true) { create(:group) } + + before_all do + group.add_owner(user) + end before do - group.add_owner(user) sign_in(user) end - describe 'new group runners view banner' do - it 'displays banner' do - visit group_settings_ci_cd_path(group) - - expect(page).to have_content(s_('Runners|New group runners view')) - expect(page).to have_link(href: group_runners_path(group)) - end - - it 'does not display banner' do - stub_feature_flags(runner_list_group_view_vue_ui: false) - - visit group_settings_ci_cd_path(group) - - expect(page).not_to have_content(s_('Runners|New group runners view')) - expect(page).not_to have_link(href: group_runners_path(group)) - end - end - - describe 'runners registration token' do - let!(:token) { group.runners_token } - - before do - visit group_settings_ci_cd_path(group) - end - - it 'has a registration token' do - expect(page.find('#registration_token')).to have_content(token) - end - - describe 'reload registration token' do - let(:page_token) { find('#registration_token').text } + describe 'Runners section' do + let(:shared_runners_toggle) { page.find('[data-testid="enable-runners-toggle"]') } + context 'with runner_list_group_view_vue_ui enabled' do before do - click_button 'Reset registration token' + visit group_settings_ci_cd_path(group) end - it 'changes registration token' do - expect(page_token).not_to eq token + it 'displays the new group runners view banner' do + expect(page).to have_content(s_('Runners|New group runners view')) + expect(page).to have_link(href: group_runners_path(group)) + end + + it 'has "Enable shared runners for this group" toggle', :js do + expect(shared_runners_toggle).to have_content(_('Enable shared runners for this group')) + end + end + + context 'with runner_list_group_view_vue_ui disabled' do + before do + stub_feature_flags(runner_list_group_view_vue_ui: false) + + visit group_settings_ci_cd_path(group) + end + + it 'does not display the new group runners view banner' do + expect(page).not_to have_content(s_('Runners|New group runners view')) + expect(page).not_to have_link(href: group_runners_path(group)) + end + + it 'has "Enable shared runners for this group" toggle', :js do + expect(shared_runners_toggle).to have_content(_('Enable shared runners for this group')) + end + + context 'with runners registration token' do + let!(:token) { group.runners_token } + + before do + visit group_settings_ci_cd_path(group) + end + + it 'displays the registration token' do + expect(page.find('#registration_token')).to have_content(token) + end + + describe 'reload registration token' do + let(:page_token) { find('#registration_token').text } + + before do + click_button 'Reset registration token' + end + + it 'changes the registration token' do + expect(page_token).not_to eq token + end + end end end end diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb index 49c468976b9..2dddcd62a6c 100644 --- a/spec/features/runners_spec.rb +++ b/spec/features/runners_spec.rb @@ -352,6 +352,7 @@ RSpec.describe 'Runners' do before do group.add_owner(user) + stub_feature_flags(runner_list_group_view_vue_ui: false) end context 'group with no runners' do diff --git a/spec/lib/backup/manager_spec.rb b/spec/lib/backup/manager_spec.rb index 24b18ef95a4..192739d05a7 100644 --- a/spec/lib/backup/manager_spec.rb +++ b/spec/lib/backup/manager_spec.rb @@ -440,6 +440,23 @@ RSpec.describe Backup::Manager do connection.directories.create(key: Gitlab.config.backup.upload.remote_directory) # rubocop:disable Rails/SaveBang end + context 'skipped upload' do + let(:backup_information) do + { + backup_created_at: Time.zone.parse('2019-01-01'), + gitlab_version: '12.3', + skipped: ['remote'] + } + end + + it 'informs the user' do + stub_env('SKIP', 'remote') + subject.create # rubocop:disable Rails/SaveBang + + expect(Gitlab::BackupLogger).to have_received(:info).with(message: 'Uploading backup archive to remote storage directory ... [SKIPPED]') + end + end + context 'target path' do it 'uses the tar filename by default' do expect_any_instance_of(Fog::Collection).to receive(:create)