diff options
35 files changed, 280 insertions, 73 deletions
diff --git a/app/assets/javascripts/ide/components/panes/right.vue b/app/assets/javascripts/ide/components/panes/right.vue index dedc2988618..5cd2c9ce188 100644 --- a/app/assets/javascripts/ide/components/panes/right.vue +++ b/app/assets/javascripts/ide/components/panes/right.vue @@ -69,7 +69,7 @@ export default { > <icon :size="16" - name="pipeline" + name="rocket" /> </button> </li> diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index 765c926751a..2d66f336076 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -114,7 +114,7 @@ input[type="checkbox"]:hover { } .dropdown-content { - max-height: 302px; + max-height: none; } } diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index cdfe3d6ab1e..9723e400574 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -52,7 +52,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController private def set_application_setting - @application_setting = ApplicationSetting.current_without_cache + @application_setting = Gitlab::CurrentSettings.current_application_settings end def application_setting_params diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index efb30ba4715..c2492a137fb 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -63,7 +63,7 @@ class ProjectsController < Projects::ApplicationController redirect_to(edit_project_path(@project)) end else - flash[:alert] = result[:message] + flash.now[:alert] = result[:message] format.html { render 'edit' } end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 3d58a14882f..bddeb8b0352 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -212,14 +212,6 @@ class ApplicationSetting < ActiveRecord::Base end end - validates_each :disabled_oauth_sign_in_sources do |record, attr, value| - value&.each do |source| - unless Devise.omniauth_providers.include?(source.to_sym) - record.errors.add(attr, "'#{source}' is not an OAuth sign-in source") - end - end - end - validate :terms_exist, if: :enforce_terms? before_validation :ensure_uuid! @@ -330,6 +322,11 @@ class ApplicationSetting < ActiveRecord::Base ::Gitlab::Database.cached_column_exists?(:application_settings, :sidekiq_throttling_enabled) end + def disabled_oauth_sign_in_sources=(sources) + sources = (sources || []).map(&:to_s) & Devise.omniauth_providers.map(&:to_s) + super(sources) + end + def domain_whitelist_raw self.domain_whitelist&.join("\n") end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 52fe529c016..7034c633268 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -228,6 +228,10 @@ class Namespace < ActiveRecord::Base parent.present? end + def root_ancestor + ancestors.reorder(nil).find_by(parent_id: nil) + end + def subgroup? has_parent? end diff --git a/app/models/project_team.rb b/app/models/project_team.rb index 33280eda0b9..9a38806baab 100644 --- a/app/models/project_team.rb +++ b/app/models/project_team.rb @@ -24,7 +24,7 @@ class ProjectTeam end def add_role(user, role, current_user: nil) - send(:"add_#{role}", user, current_user: current_user) # rubocop:disable GitlabSecurity/PublicSend + public_send(:"add_#{role}", user, current_user: current_user) # rubocop:disable GitlabSecurity/PublicSend end def find_member(user_id) diff --git a/app/services/base_count_service.rb b/app/services/base_count_service.rb index f2844854112..975e288301c 100644 --- a/app/services/base_count_service.rb +++ b/app/services/base_count_service.rb @@ -17,7 +17,7 @@ class BaseCountService end def refresh_cache(&block) - Rails.cache.write(cache_key, block_given? ? yield : uncached_count, raw: raw?) + update_cache_for_key(cache_key, &block) end def uncached_count @@ -41,4 +41,8 @@ class BaseCountService def cache_options { raw: raw? } end + + def update_cache_for_key(key, &block) + Rails.cache.write(key, block_given? ? yield : uncached_count, raw: raw?) + end end diff --git a/app/services/projects/count_service.rb b/app/services/projects/count_service.rb index 933829b557b..4c8e000928f 100644 --- a/app/services/projects/count_service.rb +++ b/app/services/projects/count_service.rb @@ -22,8 +22,10 @@ module Projects ) end - def cache_key - ['projects', 'count_service', VERSION, @project.id, cache_key_name] + def cache_key(key = nil) + cache_key = key || cache_key_name + + ['projects', 'count_service', VERSION, @project.id, cache_key] end def self.query(project_ids) diff --git a/app/services/projects/open_issues_count_service.rb b/app/services/projects/open_issues_count_service.rb index 0a004677417..78b1477186a 100644 --- a/app/services/projects/open_issues_count_service.rb +++ b/app/services/projects/open_issues_count_service.rb @@ -4,6 +4,10 @@ module Projects class OpenIssuesCountService < Projects::CountService include Gitlab::Utils::StrongMemoize + # Cache keys used to store issues count + PUBLIC_COUNT_KEY = 'public_open_issues_count'.freeze + TOTAL_COUNT_KEY = 'total_open_issues_count'.freeze + def initialize(project, user = nil) @user = user @@ -11,7 +15,7 @@ module Projects end def cache_key_name - public_only? ? 'public_open_issues_count' : 'total_open_issues_count' + public_only? ? PUBLIC_COUNT_KEY : TOTAL_COUNT_KEY end def public_only? @@ -28,6 +32,32 @@ module Projects end end + def public_count_cache_key + cache_key(PUBLIC_COUNT_KEY) + end + + def total_count_cache_key + cache_key(TOTAL_COUNT_KEY) + end + + def refresh_cache(&block) + if block_given? + super(&block) + else + count_grouped_by_confidential = self.class.query(@project, public_only: false).group(:confidential).count + public_count = count_grouped_by_confidential[false] || 0 + total_count = public_count + (count_grouped_by_confidential[true] || 0) + + update_cache_for_key(public_count_cache_key) do + public_count + end + + update_cache_for_key(total_count_cache_key) do + total_count + end + end + end + # We only show total issues count for reporters # which are allowed to view confidential issues # This will still show a discrepancy on issues number but should be less than before. diff --git a/app/views/admin/labels/_form.html.haml b/app/views/admin/labels/_form.html.haml index 7637471f9ae..ee2d4c8430a 100644 --- a/app/views/admin/labels/_form.html.haml +++ b/app/views/admin/labels/_form.html.haml @@ -10,16 +10,16 @@ .col-sm-10 = f.text_field :description, class: "form-control js-quick-submit" .form-group.row - = f.label :color, "Background color", class: 'col-form-label col-sm-2' + = f.label :color, _("Background color"), class: 'col-form-label col-sm-2' .col-sm-10 .input-group .input-group-prepend .input-group-text.label-color-preview = f.text_field :color, class: "form-control" .form-text.text-muted - Choose any color. + = _('Choose any color.') %br - Or you can choose one of the suggested colors below + = _("Or you can choose one of the suggested colors below") .suggest-colors - suggested_colors.each do |color| @@ -27,5 +27,5 @@ .form-actions - = f.submit 'Save', class: 'btn btn-save js-save-button' - = link_to "Cancel", admin_labels_path, class: 'btn btn-cancel' + = f.submit _('Save'), class: 'btn btn-save js-save-button' + = link_to _("Cancel"), admin_labels_path, class: 'btn btn-cancel' diff --git a/app/views/admin/labels/_label.html.haml b/app/views/admin/labels/_label.html.haml index 009a47dd517..c3ea2352898 100644 --- a/app/views/admin/labels/_label.html.haml +++ b/app/views/admin/labels/_label.html.haml @@ -3,5 +3,5 @@ = render_colored_label(label, tooltip: false) = markdown_field(label, :description) .float-right - = link_to 'Edit', edit_admin_label_path(label), class: 'btn btn-sm' - = link_to 'Delete', admin_label_path(label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Delete this label? Are you sure?"} + = link_to _('Edit'), edit_admin_label_path(label), class: 'btn btn-sm' + = link_to _('Delete'), admin_label_path(label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Delete this label? Are you sure?"} diff --git a/app/views/admin/labels/edit.html.haml b/app/views/admin/labels/edit.html.haml index 96f0d404ac4..652ed095d00 100644 --- a/app/views/admin/labels/edit.html.haml +++ b/app/views/admin/labels/edit.html.haml @@ -1,7 +1,7 @@ -- add_to_breadcrumbs "Labels", admin_labels_path -- breadcrumb_title "Edit Label" -- page_title "Edit", @label.name, "Labels" +- add_to_breadcrumbs _("Labels"), admin_labels_path +- breadcrumb_title _("Edit Label") +- page_title _("Edit"), @label.name, _("Labels") %h3.page-title - Edit Label + = _('Edit Label') %hr = render 'form' diff --git a/app/views/admin/labels/index.html.haml b/app/views/admin/labels/index.html.haml index add38fb333e..d3e5247447a 100644 --- a/app/views/admin/labels/index.html.haml +++ b/app/views/admin/labels/index.html.haml @@ -1,10 +1,10 @@ -- page_title "Labels" +- page_title _("Labels") %div = link_to new_admin_label_path, class: "float-right btn btn-nr btn-new" do - New label + = _('New label') %h3.page-title - Labels + = _('Labels') %hr .labels @@ -14,5 +14,5 @@ = paginate @labels, theme: 'gitlab' - else .card.bg-light - .nothing-here-block There are no labels yet + .nothing-here-block= _('There are no labels yet') diff --git a/app/views/admin/labels/new.html.haml b/app/views/admin/labels/new.html.haml index 0135ad0723d..20103fb8a29 100644 --- a/app/views/admin/labels/new.html.haml +++ b/app/views/admin/labels/new.html.haml @@ -1,5 +1,5 @@ -- page_title "New Label" +- page_title _("New Label") %h3.page-title - New Label + = _('New Label') %hr = render 'form' diff --git a/app/views/projects/deployments/_commit.html.haml b/app/views/projects/deployments/_commit.html.haml index c7ac687e4a6..282566eeadc 100644 --- a/app/views/projects/deployments/_commit.html.haml +++ b/app/views/projects/deployments/_commit.html.haml @@ -14,4 +14,4 @@ = author_avatar(deployment.commit, size: 20) = link_to_markdown commit_title, project_commit_path(@project, deployment.sha), class: "commit-row-message" - else - Cant find HEAD commit for this branch + = _("Can't find HEAD commit for this branch") diff --git a/app/views/projects/deployments/_deployment.html.haml b/app/views/projects/deployments/_deployment.html.haml index 520696b01c6..85bc8ec07e3 100644 --- a/app/views/projects/deployments/_deployment.html.haml +++ b/app/views/projects/deployments/_deployment.html.haml @@ -1,14 +1,14 @@ .gl-responsive-table-row.deployment{ role: 'row' } .table-section.section-10{ role: 'gridcell' } - .table-mobile-header{ role: 'rowheader' } ID + .table-mobile-header{ role: 'rowheader' }= _("ID") %strong.table-mobile-content ##{deployment.iid} .table-section.section-30{ role: 'gridcell' } - .table-mobile-header{ role: 'rowheader' } Commit + .table-mobile-header{ role: 'rowheader' }= _("Commit") = render 'projects/deployments/commit', deployment: deployment .table-section.section-25.build-column{ role: 'gridcell' } - .table-mobile-header{ role: 'rowheader' } Job + .table-mobile-header{ role: 'rowheader' }= _("Job") - if deployment.deployable .table-mobile-content .flex-truncate-parent @@ -21,7 +21,7 @@ = user_avatar(user: deployment.user, size: 20) .table-section.section-15{ role: 'gridcell' } - .table-mobile-header{ role: 'rowheader' } Created + .table-mobile-header{ role: 'rowheader' }= _("Created") %span.table-mobile-content= time_ago_with_tooltip(deployment.created_at) .table-section.section-20.table-button-footer{ role: 'gridcell' } diff --git a/app/views/projects/deployments/_rollback.haml b/app/views/projects/deployments/_rollback.haml index 5941e01c6f1..95f950948ab 100644 --- a/app/views/projects/deployments/_rollback.haml +++ b/app/views/projects/deployments/_rollback.haml @@ -1,6 +1,6 @@ - if can?(current_user, :create_deployment, deployment) && deployment.deployable = link_to [:retry, @project.namespace.becomes(Namespace), @project, deployment.deployable], method: :post, class: 'btn btn-build' do - if deployment.last? - Re-deploy + = _("Re-deploy") - else - Rollback + = _("Rollback") diff --git a/app/views/shared/boards/_show.html.haml b/app/views/shared/boards/_show.html.haml index 496b94ec953..a88d8f61fb4 100644 --- a/app/views/shared/boards/_show.html.haml +++ b/app/views/shared/boards/_show.html.haml @@ -3,8 +3,8 @@ - @no_breadcrumb_container = true - @no_container = true - @content_class = "issue-boards-content" -- breadcrumb_title "Issue Board" -- page_title "Boards" +- breadcrumb_title _("Issue Board") +- page_title _("Boards") - content_for :page_specific_javascripts do diff --git a/app/views/shared/boards/components/_board.html.haml b/app/views/shared/boards/components/_board.html.haml index 76843ce7cc0..65de6172d89 100644 --- a/app/views/shared/boards/components/_board.html.haml +++ b/app/views/shared/boards/components/_board.html.haml @@ -30,7 +30,7 @@ %board-delete{ "inline-template" => true, ":list" => "list", "v-if" => "!list.preset && list.id" } - %button.board-delete.has-tooltip.float-right{ type: "button", title: "Delete list", "aria-label" => "Delete list", data: { placement: "bottom" }, "@click.stop" => "deleteBoard" } + %button.board-delete.has-tooltip.float-right{ type: "button", title: _("Delete list"), "aria-label" => _("Delete list"), data: { placement: "bottom" }, "@click.stop" => "deleteBoard" } = icon("trash") .issue-count-badge.clearfix{ "v-if" => 'list.type !== "blank"' } %span.issue-count-badge-count.float-left{ ":class" => '{ "has-btn": list.type !== "closed" && !disabled }' } @@ -39,8 +39,8 @@ %button.issue-count-badge-add-button.btn.btn-sm.btn-default.has-tooltip.js-no-trigger-collapse{ type: "button", "@click" => "showNewIssueForm", "v-if" => 'list.type !== "closed"', - "aria-label" => "New issue", - "title" => "New issue", + "aria-label" => _("New issue"), + "title" => _("New issue"), data: { placement: "top", container: "body" } } = icon("plus", class: "js-no-trigger-collapse") diff --git a/app/views/shared/boards/components/sidebar/_due_date.html.haml b/app/views/shared/boards/components/sidebar/_due_date.html.haml index 10217b6cbf0..5630375f428 100644 --- a/app/views/shared/boards/components/sidebar/_due_date.html.haml +++ b/app/views/shared/boards/components/sidebar/_due_date.html.haml @@ -1,20 +1,20 @@ .block.due_date .title - Due date + = _("Due date") - if can_admin_issue? = icon("spinner spin", class: "block-loading") - = link_to "Edit", "#", class: "js-sidebar-dropdown-toggle edit-link float-right" + = link_to _("Edit"), "#", class: "js-sidebar-dropdown-toggle edit-link float-right" .value .value-content %span.no-value{ "v-if" => "!issue.dueDate" } - No due date + = _("No due date") %span.bold{ "v-if" => "issue.dueDate" } {{ issue.dueDate | due-date }} - if can_admin_issue? %span.no-value.js-remove-due-date-holder{ "v-if" => "issue.dueDate" } \- %a.js-remove-due-date{ href: "#", role: "button" } - remove due date + = _('remove due date') - if can_admin_issue? .selectbox %input{ type: "hidden", @@ -23,9 +23,9 @@ .dropdown %button.dropdown-menu-toggle.js-due-date-select.js-issue-boards-due-date{ type: 'button', data: { toggle: 'dropdown', field_name: "issue[due_date]", ability_name: "issue" } } - %span.dropdown-toggle-text Due date + %span.dropdown-toggle-text= _("Due date") = icon('chevron-down') .dropdown-menu.dropdown-menu-due-date - = dropdown_title('Due date') + = dropdown_title(_('Due date')) = dropdown_content do .js-due-date-calendar diff --git a/app/views/shared/boards/components/sidebar/_labels.html.haml b/app/views/shared/boards/components/sidebar/_labels.html.haml index daee691e358..607e7f471c9 100644 --- a/app/views/shared/boards/components/sidebar/_labels.html.haml +++ b/app/views/shared/boards/components/sidebar/_labels.html.haml @@ -1,12 +1,12 @@ .block.labels .title - Labels + = _("Labels") - if can_admin_issue? = icon("spinner spin", class: "block-loading") - = link_to "Edit", "#", class: "js-sidebar-dropdown-toggle edit-link float-right" + = link_to _("Edit"), "#", class: "js-sidebar-dropdown-toggle edit-link float-right" .value.issuable-show-labels.dont-hide %span.no-value{ "v-if" => "issue.labels && issue.labels.length === 0" } - None + = _("None") %a{ href: "#", "v-for" => "label in issue.labels" } .badge.color-label.has-tooltip{ ":style" => "{ backgroundColor: label.color, color: label.textColor }" } @@ -28,7 +28,7 @@ namespace_path: @namespace_path, project_path: @project.try(:path) } } %span.dropdown-toggle-text - Label + = _("Label") = icon('chevron-down') .dropdown-menu.dropdown-select.dropdown-menu-paging.dropdown-menu-labels.dropdown-menu-selectable = render partial: "shared/issuable/label_page_default" diff --git a/app/views/shared/boards/components/sidebar/_milestone.html.haml b/app/views/shared/boards/components/sidebar/_milestone.html.haml index f2bedd5e3c9..b15d60002fc 100644 --- a/app/views/shared/boards/components/sidebar/_milestone.html.haml +++ b/app/views/shared/boards/components/sidebar/_milestone.html.haml @@ -1,12 +1,12 @@ .block.milestone .title - Milestone + = _("Milestone") - if can_admin_issue? = icon("spinner spin", class: "block-loading") - = link_to "Edit", "#", class: "js-sidebar-dropdown-toggle edit-link float-right" + = link_to _("Edit"), "#", class: "js-sidebar-dropdown-toggle edit-link float-right" .value %span.no-value{ "v-if" => "!issue.milestone" } - None + = _("None") %span.bold.has-tooltip{ "v-if" => "issue.milestone" } {{ issue.milestone.title }} - if can_admin_issue? @@ -19,10 +19,10 @@ %button.dropdown-menu-toggle.js-milestone-select.js-issue-board-sidebar{ type: "button", data: { toggle: "dropdown", show_no: "true", field_name: "issue[milestone_id]", milestones: milestones_filter_path(format: :json), ability_name: "issue", use_id: "true", default_no: "true" }, ":data-selected" => "milestoneTitle", ":data-issuable-id" => "issue.iid" } - Milestone + = _("Milestone") = icon("chevron-down") .dropdown-menu.dropdown-select.dropdown-menu-selectable - = dropdown_title("Assign milestone") - = dropdown_filter("Search milestones") + = dropdown_title(_("Assign milestone")) + = dropdown_filter(_("Search milestones")) = dropdown_content = dropdown_loading diff --git a/changelogs/unreleased/46783-removed-omniauth-provider-causing-invalid-application-setting.yml b/changelogs/unreleased/46783-removed-omniauth-provider-causing-invalid-application-setting.yml new file mode 100644 index 00000000000..d5ecf5163d4 --- /dev/null +++ b/changelogs/unreleased/46783-removed-omniauth-provider-causing-invalid-application-setting.yml @@ -0,0 +1,5 @@ +--- +title: Ignore unknown OAuth sources in ApplicationSetting +merge_request: 20129 +author: +type: fixed diff --git a/changelogs/unreleased/issue_47729.yml b/changelogs/unreleased/issue_47729.yml new file mode 100644 index 00000000000..e27972af114 --- /dev/null +++ b/changelogs/unreleased/issue_47729.yml @@ -0,0 +1,5 @@ +--- +title: Fix refreshing cache keys for open issues count +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/rails5-fix-mysql-arel-from.yml b/changelogs/unreleased/rails5-fix-mysql-arel-from.yml new file mode 100644 index 00000000000..9883ff306f1 --- /dev/null +++ b/changelogs/unreleased/rails5-fix-mysql-arel-from.yml @@ -0,0 +1,5 @@ +--- +title: Rails5 fix arel from in mysql_median_datetime_sql +merge_request: 20167 +author: Jasper Maes +type: fixed diff --git a/changelogs/unreleased/update-pipeline-icon-in-web-ide-sidebar.yml b/changelogs/unreleased/update-pipeline-icon-in-web-ide-sidebar.yml new file mode 100644 index 00000000000..3f1f3c643e2 --- /dev/null +++ b/changelogs/unreleased/update-pipeline-icon-in-web-ide-sidebar.yml @@ -0,0 +1,5 @@ +--- +title: Update pipeline icon in web ide sidebar +merge_request: 20058 +author: George Tsiolis +type: changed diff --git a/doc/development/i18n/proofreader.md b/doc/development/i18n/proofreader.md index 9a677bf09b2..4091c691a3c 100644 --- a/doc/development/i18n/proofreader.md +++ b/doc/development/i18n/proofreader.md @@ -24,6 +24,7 @@ are very appreciative of the work done by translators and proofreaders! - Paolo Falomo - [GitLab](https://gitlab.com/paolofalomo), [Crowdin](https://crowdin.com/profile/paolo.falomo) - Japanese - Yamana Tokiuji - [GitLab](https://gitlab.com/tokiuji), [Crowdin](https://crowdin.com/profile/yamana) + - Hiroyuki Sato - [GitLab](https://gitlab.com/hiroponz), [Crowdin](https://crowdin.com/profile/hiroponz) - Korean - Chang-Ho Cha - [GitLab](https://gitlab.com/changho-cha), [Crowdin](https://crowdin.com/profile/zzazang) - Huang Tao - [GitLab](https://gitlab.com/htve), [Crowdin](https://crowdin.com/profile/htve) diff --git a/lib/gitlab/database/median.rb b/lib/gitlab/database/median.rb index 3cac007a42c..f64e3d53138 100644 --- a/lib/gitlab/database/median.rb +++ b/lib/gitlab/database/median.rb @@ -33,7 +33,13 @@ module Gitlab end def mysql_median_datetime_sql(arel_table, query_so_far, column_sym) - query = arel_table + arel_from = if Gitlab.rails5? + arel_table.from + else + arel_table + end + + query = arel_from .from(arel_table.project(Arel.sql('*')).order(arel_table[column_sym]).as(arel_table.table_name)) .project(average([arel_table[column_sym]], 'median')) .where( diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 90e698925b6..27f04be3fdf 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -329,7 +329,7 @@ describe ProjectsController do expect { update_project path: 'renamed_path' } .not_to change { project.reload.path } - expect(controller).to set_flash[:alert].to(/container registry tags/) + expect(controller).to set_flash.now[:alert].to(/container registry tags/) expect(response).to have_gitlab_http_status(200) end end diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index e7aca94db66..f3ab4ff771a 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -124,6 +124,29 @@ feature 'Admin updates settings' do expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).not_to include('google_oauth2') end + scenario 'Oauth providers do not raise validation errors when saving unrelated changes' do + expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).to be_empty + + page.within('.as-signin') do + uncheck 'Google' + click_button 'Save changes' + end + + expect(page).to have_content "Application settings saved successfully" + expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).to include('google_oauth2') + + # Remove google_oauth2 from the Omniauth strategies + allow(Devise).to receive(:omniauth_providers).and_return([]) + + # Save an unrelated setting + page.within('.as-ci-cd') do + click_button 'Save changes' + end + + expect(page).to have_content "Application settings saved successfully" + expect(Gitlab::CurrentSettings.disabled_oauth_sign_in_sources).to include('google_oauth2') + end + scenario 'Change Help page' do page.within('.as-help-page') do fill_in 'Help page text', with: 'Example text' diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 3e6656e0f12..02f74e2ea54 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -25,15 +25,6 @@ describe ApplicationSetting do it { is_expected.to allow_value(https).for(:after_sign_out_path) } it { is_expected.not_to allow_value(ftp).for(:after_sign_out_path) } - describe 'disabled_oauth_sign_in_sources validations' do - before do - allow(Devise).to receive(:omniauth_providers).and_return([:github]) - end - - it { is_expected.to allow_value(['github']).for(:disabled_oauth_sign_in_sources) } - it { is_expected.not_to allow_value(['test']).for(:disabled_oauth_sign_in_sources) } - end - describe 'default_artifacts_expire_in' do it 'sets an error if it cannot parse' do setting.update(default_artifacts_expire_in: 'a') @@ -314,6 +305,33 @@ describe ApplicationSetting do end end + describe '#disabled_oauth_sign_in_sources=' do + before do + allow(Devise).to receive(:omniauth_providers).and_return([:github]) + end + + it 'removes unknown sources (as strings) from the array' do + subject.disabled_oauth_sign_in_sources = %w[github test] + + expect(subject).to be_valid + expect(subject.disabled_oauth_sign_in_sources).to eq ['github'] + end + + it 'removes unknown sources (as symbols) from the array' do + subject.disabled_oauth_sign_in_sources = %i[github test] + + expect(subject).to be_valid + expect(subject.disabled_oauth_sign_in_sources).to eq ['github'] + end + + it 'ignores nil' do + subject.disabled_oauth_sign_in_sources = nil + + expect(subject).to be_valid + expect(subject.disabled_oauth_sign_in_sources).to be_empty + end + end + context 'restricted signup domains' do it 'sets single domain' do setting.domain_whitelist_raw = 'example.com' diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb index 18b01c3e6b7..70f1a1c8b38 100644 --- a/spec/models/namespace_spec.rb +++ b/spec/models/namespace_spec.rb @@ -655,6 +655,19 @@ describe Namespace do end end + describe '#root_ancestor' do + it 'returns the top most ancestor', :nested_groups do + root_group = create(:group) + nested_group = create(:group, parent: root_group) + deep_nested_group = create(:group, parent: nested_group) + very_deep_nested_group = create(:group, parent: deep_nested_group) + + expect(nested_group.root_ancestor).to eq(root_group) + expect(deep_nested_group.root_ancestor).to eq(root_group) + expect(very_deep_nested_group.root_ancestor).to eq(root_group) + end + end + describe '#remove_exports' do let(:legacy_project) { create(:project, :with_export, :legacy_storage, namespace: namespace) } let(:hashed_project) { create(:project, :with_export, namespace: namespace) } diff --git a/spec/services/projects/batch_open_issues_count_service_spec.rb b/spec/services/projects/batch_open_issues_count_service_spec.rb new file mode 100644 index 00000000000..599aaf62080 --- /dev/null +++ b/spec/services/projects/batch_open_issues_count_service_spec.rb @@ -0,0 +1,54 @@ +require 'spec_helper' + +describe Projects::BatchOpenIssuesCountService do + let!(:project_1) { create(:project) } + let!(:project_2) { create(:project) } + + let(:subject) { described_class.new([project_1, project_2]) } + + context '#refresh_cache', :use_clean_rails_memory_store_caching do + before do + create(:issue, project: project_1) + create(:issue, project: project_1, confidential: true) + + create(:issue, project: project_2) + create(:issue, project: project_2, confidential: true) + end + + context 'when cache is clean' do + it 'refreshes cache keys correctly' do + subject.refresh_cache + + # It does not update total issues cache + expect(Rails.cache.read(get_cache_key(subject, project_1))).to eq(nil) + expect(Rails.cache.read(get_cache_key(subject, project_2))).to eq(nil) + + expect(Rails.cache.read(get_cache_key(subject, project_1, true))).to eq(1) + expect(Rails.cache.read(get_cache_key(subject, project_1, true))).to eq(1) + end + end + + context 'when issues count is already cached' do + before do + create(:issue, project: project_2) + subject.refresh_cache + end + + it 'does update cache again' do + expect(Rails.cache).not_to receive(:write) + + subject.refresh_cache + end + end + end + + def get_cache_key(subject, project, public_key = false) + service = subject.count_service.new(project) + + if public_key + service.cache_key(service.class::PUBLIC_COUNT_KEY) + else + service.cache_key(service.class::TOTAL_COUNT_KEY) + end + end +end diff --git a/spec/services/projects/open_issues_count_service_spec.rb b/spec/services/projects/open_issues_count_service_spec.rb index 06b470849b3..562c14a8df8 100644 --- a/spec/services/projects/open_issues_count_service_spec.rb +++ b/spec/services/projects/open_issues_count_service_spec.rb @@ -50,5 +50,40 @@ describe Projects::OpenIssuesCountService do end end end + + context '#refresh_cache', :use_clean_rails_memory_store_caching do + let(:subject) { described_class.new(project) } + + before do + create(:issue, :opened, project: project) + create(:issue, :opened, project: project) + create(:issue, :opened, confidential: true, project: project) + end + + context 'when cache is empty' do + it 'refreshes cache keys correctly' do + subject.refresh_cache + + expect(Rails.cache.read(subject.cache_key(described_class::PUBLIC_COUNT_KEY))).to eq(2) + expect(Rails.cache.read(subject.cache_key(described_class::TOTAL_COUNT_KEY))).to eq(3) + end + end + + context 'when cache is outdated' do + before do + subject.refresh_cache + end + + it 'refreshes cache keys correctly' do + create(:issue, :opened, project: project) + create(:issue, :opened, confidential: true, project: project) + + subject.refresh_cache + + expect(Rails.cache.read(subject.cache_key(described_class::PUBLIC_COUNT_KEY))).to eq(3) + expect(Rails.cache.read(subject.cache_key(described_class::TOTAL_COUNT_KEY))).to eq(5) + end + end + end end end |