Commit 096c2166 authored by Rémy Coutable's avatar Rémy Coutable

[EE] Allow to enable the performance bar per user or Feature group

Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parent 0115f8f0
...@@ -125,6 +125,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController ...@@ -125,6 +125,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
:metrics_port, :metrics_port,
:metrics_sample_interval, :metrics_sample_interval,
:metrics_timeout, :metrics_timeout,
:performance_bar_allowed_group_id,
:performance_bar_enabled,
:recaptcha_enabled, :recaptcha_enabled,
:recaptcha_private_key, :recaptcha_private_key,
:recaptcha_site_key, :recaptcha_site_key,
......
...@@ -9,7 +9,7 @@ class ApplicationController < ActionController::Base ...@@ -9,7 +9,7 @@ class ApplicationController < ActionController::Base
include SentryHelper include SentryHelper
include WorkhorseHelper include WorkhorseHelper
include EnforcesTwoFactorAuthentication include EnforcesTwoFactorAuthentication
include Peek::Rblineprof::CustomControllerHelpers include WithPerformanceBar
before_action :authenticate_user_from_private_token! before_action :authenticate_user_from_private_token!
before_action :authenticate_user_from_rss_token! before_action :authenticate_user_from_rss_token!
...@@ -68,21 +68,6 @@ class ApplicationController < ActionController::Base ...@@ -68,21 +68,6 @@ class ApplicationController < ActionController::Base
end end
end end
def peek_enabled?
return false unless Gitlab::PerformanceBar.enabled?
return false unless current_user
if RequestStore.active?
if RequestStore.store.key?(:peek_enabled)
RequestStore.store[:peek_enabled]
else
RequestStore.store[:peek_enabled] = cookies[:perf_bar_enabled].present?
end
else
cookies[:perf_bar_enabled].present?
end
end
protected protected
# This filter handles both private tokens and personal access tokens # This filter handles both private tokens and personal access tokens
......
module WithPerformanceBar
extend ActiveSupport::Concern
included do
include Peek::Rblineprof::CustomControllerHelpers
end
def peek_enabled?
return false unless Gitlab::PerformanceBar.enabled?(current_user)
if RequestStore.active?
RequestStore.fetch(:peek_enabled) { cookies[:perf_bar_enabled].present? }
else
cookies[:perf_bar_enabled].present?
end
end
end
...@@ -23,7 +23,7 @@ module NavHelper ...@@ -23,7 +23,7 @@ module NavHelper
def nav_header_class def nav_header_class
class_name = '' class_name = ''
class_name << " with-horizontal-nav" if defined?(nav) && nav class_name << " with-horizontal-nav" if defined?(nav) && nav
class_name << " with-peek" if peek_enabled? class_name << " with-peek" if performance_bar_enabled?
class_name class_name
end end
......
module PerformanceBarHelper
# This is a hack since using `alias_method :performance_bar_enabled?, :peek_enabled?`
# in WithPerformanceBar breaks tests (but works in the browser).
def performance_bar_enabled?
peek_enabled?
end
end
...@@ -247,6 +247,7 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -247,6 +247,7 @@ class ApplicationSetting < ActiveRecord::Base
koding_url: nil, koding_url: nil,
max_artifacts_size: Settings.artifacts['max_size'], max_artifacts_size: Settings.artifacts['max_size'],
max_attachment_size: Settings.gitlab['max_attachment_size'], max_attachment_size: Settings.gitlab['max_attachment_size'],
performance_bar_allowed_group_id: nil,
plantuml_enabled: false, plantuml_enabled: false,
plantuml_url: nil, plantuml_url: nil,
recaptcha_enabled: false, recaptcha_enabled: false,
...@@ -379,6 +380,42 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -379,6 +380,42 @@ class ApplicationSetting < ActiveRecord::Base
super(levels.map { |level| Gitlab::VisibilityLevel.level_value(level) }) super(levels.map { |level| Gitlab::VisibilityLevel.level_value(level) })
end end
def performance_bar_allowed_group_id=(group_full_path)
group = Group.find_by_full_path(group_full_path)
return unless group && group.id != performance_bar_allowed_group_id
super(group.id)
Gitlab::PerformanceBar.expire_allowed_user_ids_cache
end
def performance_bar_allowed_group
Group.find_by_id(performance_bar_allowed_group_id)
end
# Return true is the Performance Bar is available globally or for the
# `performance_team` feature group
def performance_bar_enabled?
feature = Feature.get(:performance_bar)
feature.on? || feature.groups_value.include?('performance_team')
end
# - If `enable` is true, enable the `performance_bar` feature for the
# `performance_team` feature group
# - If `enable` is false, disable the `performance_bar` feature globally
def performance_bar_enabled=(enable)
feature = Feature.get(:performance_bar)
performance_bar_on = performance_bar_enabled?
if enable && !performance_bar_on
feature.enable_group(:performance_team)
Gitlab::PerformanceBar.expire_allowed_user_ids_cache
elsif !enable && performance_bar_on
feature.disable
Gitlab::PerformanceBar.expire_allowed_user_ids_cache
end
end
# Choose one of the available repository storage options. Currently all have # Choose one of the available repository storage options. Currently all have
# equal weighting. # equal weighting.
def pick_repository_storage def pick_repository_storage
......
...@@ -358,6 +358,22 @@ ...@@ -358,6 +358,22 @@
%strong.cred WARNING: %strong.cred WARNING:
Environment variable `prometheus_multiproc_dir` does not exist or is not pointing to a valid directory. Environment variable `prometheus_multiproc_dir` does not exist or is not pointing to a valid directory.
%fieldset
%legend Profiling - Performance Bar
%p
Enable the Performance Bar for a given group.
= link_to icon('question-circle'), help_page_path('administration/monitoring/performance/performance_bar')
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
= f.label :performance_bar_enabled do
= f.check_box :performance_bar_enabled
Enable the Performance Bar
.form-group
= f.label :performance_bar_allowed_group_id, 'Allowed group', class: 'control-label col-sm-2'
.col-sm-10
= f.text_field :performance_bar_allowed_group_id, class: 'form-control', placeholder: 'my-org/my-group', value: @application_setting.performance_bar_allowed_group&.full_path
%fieldset %fieldset
%legend Background Jobs %legend Background Jobs
%p %p
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
= stylesheet_link_tag "application", media: "all" = stylesheet_link_tag "application", media: "all"
= stylesheet_link_tag "print", media: "print" = stylesheet_link_tag "print", media: "print"
= stylesheet_link_tag "test", media: "all" if Rails.env.test? = stylesheet_link_tag "test", media: "all" if Rails.env.test?
= stylesheet_link_tag 'peek' if peek_enabled? = stylesheet_link_tag 'peek' if performance_bar_enabled?
- if show_new_nav? - if show_new_nav?
= stylesheet_link_tag "new_nav", media: "all" = stylesheet_link_tag "new_nav", media: "all"
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
= webpack_bundle_tag "main" = webpack_bundle_tag "main"
= webpack_bundle_tag "raven" if current_application_settings.clientside_sentry_enabled = webpack_bundle_tag "raven" if current_application_settings.clientside_sentry_enabled
= webpack_bundle_tag "test" if Rails.env.test? = webpack_bundle_tag "test" if Rails.env.test?
= webpack_bundle_tag 'peek' if peek_enabled? = webpack_bundle_tag 'peek' if performance_bar_enabled?
- if content_for?(:page_specific_javascripts) - if content_for?(:page_specific_javascripts)
= yield :page_specific_javascripts = yield :page_specific_javascripts
......
---
title: Allow to enable the performance bar per user or Feature group
merge_request: 12362
author:
require 'flipper/middleware/memoizer' require 'flipper/middleware/memoizer'
Rails.application.config.middleware.use Flipper::Middleware::Memoizer, unless Rails.env.test?
Rails.application.config.middleware.use Flipper::Middleware::Memoizer,
lambda { Feature.flipper } lambda { Feature.flipper }
Feature.register_feature_groups
end
class AddPerformanceBarAllowedGroupIdToApplicationSettings < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
add_column :application_settings, :performance_bar_allowed_group_id, :integer
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170627211700) do ActiveRecord::Schema.define(version: 20170706151212) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -144,6 +144,7 @@ ActiveRecord::Schema.define(version: 20170627211700) do ...@@ -144,6 +144,7 @@ ActiveRecord::Schema.define(version: 20170627211700) do
t.boolean "authorized_keys_enabled", default: true, null: false t.boolean "authorized_keys_enabled", default: true, null: false
t.boolean "help_page_hide_commercial_content", default: false t.boolean "help_page_hide_commercial_content", default: false
t.string "help_page_support_url" t.string "help_page_support_url"
t.integer "performance_bar_allowed_group_id"
end end
create_table "approvals", force: :cascade do |t| create_table "approvals", force: :cascade do |t|
......
...@@ -193,6 +193,7 @@ have access to GitLab administration tools and settings. ...@@ -193,6 +193,7 @@ have access to GitLab administration tools and settings.
- [Operations](administration/operations.md): Keeping GitLab up and running. - [Operations](administration/operations.md): Keeping GitLab up and running.
- [Polling](administration/polling.md): Configure how often the GitLab UI polls for updates. - [Polling](administration/polling.md): Configure how often the GitLab UI polls for updates.
- [Request Profiling](administration/monitoring/performance/request_profiling.md): Get a detailed profile on slow requests. - [Request Profiling](administration/monitoring/performance/request_profiling.md): Get a detailed profile on slow requests.
- [Performance Bar](administration/monitoring/performance/performance_bar.md): Get performance information for the current page.
### Customization ### Customization
......
# Performance Bar
A Performance Bar can be displayed, to dig into the performance of a page. When
activated, it looks as follows:
![Performance Bar](img/performance_bar.png)
It allows you to:
- see the current host serving the page
- see the timing of the page (backend, frontend)
- the number of DB queries, the time it took, and the detail of these queries
![SQL profiling using the Performance Bar](img/performance_bar_sql_queries.png)
- the number of calls to Redis, and the time it took
- the number of background jobs created by Sidekiq, and the time it took
- the number of Ruby GC calls, and the time it took
- profile the code used to generate the page, line by line
![Line profiling using the Performance Bar](img/performance_bar_line_profiling.png)
## Enable the Performance Bar via the Admin panel
GitLab Performance Bar is disabled by default. To enable it for a given group,
navigate to the Admin area in **Settings > Profiling - Performance Bar**
(`/admin/application_settings`).
The only required setting you need to set is the full path of the group that
will be allowed to display the Performance Bar.
Make sure _Enable the Performance Bar_ is checked and hit
**Save** to save the changes.
---
![GitLab Performance Bar Admin Settings](img/performance_bar_configuration_settings.png)
---
## Enable the Performance Bar via the API
Under the hood, the Performance Bar activation is done via the `performance_bar`
[Feature Flag](../../../development/features_flags.md).
That means you can also enable or disable it via the
[Features API](../../../api/features.md#set-or-create-a-feature).
### For the `performance_team` feature group
The `performance_team` feature group maps to the group specified in your [Admin
area](#enable-the-performance-bar-via-the-admin-panel).
```
curl --data "feature_group=performance_team" --data "value=true" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/features/performance_bar
```
### For specific users
It's also possible to enable the Performance Bar for specific users in addition
to a group, or even instead of a group:
```
curl --data "user=my_username" --data "value=true" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/features/performance_bar
```
[reconfigure]: ../../restart_gitlab.md#omnibus-gitlab-reconfigure
...@@ -17,6 +17,7 @@ following locations: ...@@ -17,6 +17,7 @@ following locations:
- [Deploy Keys](deploy_keys.md) - [Deploy Keys](deploy_keys.md)
- [Environments](environments.md) - [Environments](environments.md)
- [Events](events.md) - [Events](events.md)
- [Feature flags](features.md)
- [Gitignores templates](templates/gitignores.md) - [Gitignores templates](templates/gitignores.md)
- [GitLab CI Config templates](templates/gitlab_ci_ymls.md) - [GitLab CI Config templates](templates/gitlab_ci_ymls.md)
- [Groups](groups.md) - [Groups](groups.md)
......
# Features API # Features flags API
All methods require administrator authorization. All methods require administrator authorization.
...@@ -61,7 +61,8 @@ POST /features/:name ...@@ -61,7 +61,8 @@ POST /features/:name
| `feature_group` | string | no | A Feature group name | | `feature_group` | string | no | A Feature group name |
| `user` | string | no | A GitLab username | | `user` | string | no | A GitLab username |
Note that `feature_group` and `user` are mutually exclusive. Note that you can enable or disable a feature for both a `feature_group` and a
`user` with a single API call.
```bash ```bash
curl --data "value=30" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/features/new_library curl --data "value=30" --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/features/new_library
......
...@@ -3,5 +3,20 @@ ...@@ -3,5 +3,20 @@
Starting from GitLab 9.3 we support feature flags via Starting from GitLab 9.3 we support feature flags via
[Flipper](https://github.com/jnunemaker/flipper/). You should use the `Feature` [Flipper](https://github.com/jnunemaker/flipper/). You should use the `Feature`
class (defined in `lib/feature.rb`) in your code to get, set and list feature class (defined in `lib/feature.rb`) in your code to get, set and list feature
flags. During runtime you can set the values for the gates via the flags.
[admin API](../api/features.md).
During runtime you can set the values for the gates via the
[features API](../api/features.md) (accessible to admins only).
## Feature groups
Starting from GitLab 9.4 we support feature groups via
[Flipper groups](https://github.com/jnunemaker/flipper/blob/v0.10.2/docs/Gates.md#2-group).
Feature groups must be defined statically in `lib/feature.rb` (in the
`.register_feature_groups` method), but their implementation can obviously be
dynamic (querying the DB etc.). You can see how the `performance_team` feature
group for a concrete example.
Once defined in `lib/feature.rb`, you will be able to activate a
feature for a given feature group via the [`feature_group` param of the features API](../api/features.md#set-or-create-a-feature)
...@@ -14,14 +14,12 @@ module API ...@@ -14,14 +14,12 @@ module API
end end
end end
def gate_target(params) def gate_targets(params)
if params[:feature_group] targets = []
Feature.group(params[:feature_group]) targets << Feature.group(params[:feature_group]) if params[:feature_group]
elsif params[:user] targets << User.find_by_username(params[:user]) if params[:user]
User.find_by_username(params[:user])
else targets
gate_value(params)
end
end end
end end
...@@ -42,18 +40,25 @@ module API ...@@ -42,18 +40,25 @@ module API
requires :value, type: String, desc: '`true` or `false` to enable/disable, an integer for percentage of time' requires :value, type: String, desc: '`true` or `false` to enable/disable, an integer for percentage of time'
optional :feature_group, type: String, desc: 'A Feature group name' optional :feature_group, type: String, desc: 'A Feature group name'
optional :user, type: String, desc: 'A GitLab username' optional :user, type: String, desc: 'A GitLab username'
mutually_exclusive :feature_group, :user
end end
post ':name' do post ':name' do
feature = Feature.get(params[:name]) feature = Feature.get(params[:name])
target = gate_target(params) targets = gate_targets(params)
value = gate_value(params) value = gate_value(params)
case value case value
when true when true
feature.enable(target) if targets.present?
targets.each { |target| feature.enable(target) }
else
feature.enable
end
when false when false
feature.disable(target) if targets.present?
targets.each { |target| feature.disable(target) }
else
feature.disable
end
else else
feature.enable_percentage_of_time(value) feature.enable_percentage_of_time(value)
end end
......
...@@ -57,5 +57,13 @@ class Feature ...@@ -57,5 +57,13 @@ class Feature
Flipper.new(adapter) Flipper.new(adapter)
end end
end end
def register_feature_groups
Flipper.register(:performance_team) do |actor|
user = actor.thing
user&.is_a?(User) && Gitlab::PerformanceBar.allowed_user?(user)
end
end
end end
end end
module Gitlab module Gitlab
module PerformanceBar module PerformanceBar
def self.enabled? include Gitlab::CurrentSettings
Feature.enabled?('gitlab_performance_bar')
ALLOWED_USER_IDS_KEY = 'performance_bar_allowed_user_ids'.freeze
# The time (in seconds) after which a set of allowed user IDs is expired
# automatically.
ALLOWED_USER_IDS_TIME_TO_LIVE = 10.minutes
def self.enabled?(current_user = nil)
Feature.enabled?(:performance_bar, current_user)
end
def self.allowed_user?(user)
return false unless allowed_group_id
allowed_user_ids.include?(user.id)
end
def self.allowed_group_id
current_application_settings.performance_bar_allowed_group_id
end
def self.allowed_user_ids
Rails.cache.fetch(ALLOWED_USER_IDS_KEY, expires_in: ALLOWED_USER_IDS_TIME_TO_LIVE) do
group = Group.find_by_id(allowed_group_id)
if group
GroupMembersFinder.new(group).execute.pluck(:user_id)
else
[]
end
end
end
def self.expire_allowed_user_ids_cache
Rails.cache.delete(ALLOWED_USER_IDS_KEY)
end end
end end
end end
...@@ -38,17 +38,17 @@ describe 'User can display performance bar', :js do ...@@ -38,17 +38,17 @@ describe 'User can display performance bar', :js do
visit root_path visit root_path
end end
context 'when the gitlab_performance_bar feature is disabled' do context 'when the performance_bar feature is disabled' do
before do before do
Feature.disable('gitlab_performance_bar') Feature.disable(:performance_bar)
end end
it_behaves_like 'performance bar is disabled' it_behaves_like 'performance bar is disabled'
end end
context 'when the gitlab_performance_bar feature is enabled' do context 'when the performance_bar feature is enabled' do
before do before do
Feature.enable('gitlab_performance_bar') Feature.enable(:performance_bar)
end end
it_behaves_like 'performance bar is disabled' it_behaves_like 'performance bar is disabled'
...@@ -62,17 +62,17 @@ describe 'User can display performance bar', :js do ...@@ -62,17 +62,17 @@ describe 'User can display performance bar', :js do
visit root_path visit root_path
end end
context 'when the gitlab_performance_bar feature is disabled' do context 'when the performance_bar feature is disabled' do
before do before do
Feature.disable('gitlab_performance_bar') Feature.disable(:performance_bar)
end end
it_behaves_like 'performance bar is disabled' it_behaves_like 'performance bar is disabled'
end end
context 'when the gitlab_performance_bar feature is enabled' do context 'when the performance_bar feature is enabled' do
before do before do
Feature.enable('gitlab_performance_bar') Feature.enable(:performance_bar)
end end
it_behaves_like 'performance bar is enabled' it_behaves_like 'performance bar is enabled'
......
require 'spec_helper'
describe Gitlab::PerformanceBar do
describe '.enabled?' do
it 'returns false when given actor is nil' do
expect(described_class.enabled?(nil)).to be_falsy
end
it 'returns false when feature is disabled' do
actor = double('actor')
expect(Feature).to receive(:enabled?)
.with(:performance_bar, actor).and_return(false)
expect(described_class.enabled?(actor)).to be_falsy
end
it 'returns true when feature is enabled' do
actor = double('actor')
expect(Feature).to receive(:enabled?)
.with(:performance_bar, actor).and_return(true)
expect(described_class.enabled?(actor)).to be_truthy
end
end
shared_examples 'allowed user IDs are cached in Redis for 10 minutes' do
before do
# Warm the Redis cache
described_class.allowed_user?(user)
end
it 'caches the allowed user IDs in cache', :caching do
expect do
expect(described_class.allowed_user?(user)).to be_truthy
end.not_to exceed_query_limit(0)
end
end
describe '.allowed_user?' do
let(:user) { create(:user) }
before do
stub_performance_bar_setting(allowed_group: 'my-group')
end
context 'when allowed group does not exist' do
it 'returns false' do
expect(described_class.allowed_user?(user)).to be_falsy
end
end
context 'when allowed group exists' do
let!(:my_group) { create(:group, path: 'my-group') }
context 'when user is not a member of the allowed group' do
it 'returns false' do
expect(described_class.allowed_user?(user)).to be_falsy
end
it_behaves_like 'allowed user IDs are cached in Redis for 10 minutes'
end
context 'when user is a member of the allowed group' do
before do
my_group.add_developer(user)
end
it 'returns true' do
expect(described_class.allowed_user?(user)).to be_truthy
end
it_behaves_like 'allowed user IDs are cached in Redis for 10 minutes'
end
end
context 'when allowed group is nested', :nested_groups do
let!(:nested_my_group) { create(:group, parent: create(:group, path: 'my-org'), path: 'my-group') }
before do
create(:group, path: 'my-group')
nested_my_group.add_developer(user)
stub_performance_bar_setting(allowed_group: 'my-org/my-group')
end
it 'returns the nested group' do
expect(described_class.allowed_user?(user)).to be_truthy
end
end
context 'when a nested group has the same path', :nested_groups do
before do
create(:group, :nested, path: 'my-group').add_developer(user)
end
it 'returns false' do
expect(described_class.allowed_user?(user)).to be_falsy
end
end
end
end
...@@ -233,6 +233,151 @@ describe ApplicationSetting, models: true do ...@@ -233,6 +233,151 @@ describe ApplicationSetting, models: true do
end end
end end
describe 'performance bar settings' do
before do
Flipper.unregister_groups
Flipper.register(:performance_team)
end
after do
Flipper.unregister_groups
end
describe 'performance_bar_allowed_group_id=' do
it 'does not persist an invalid group path' do
setting.performance_bar_allowed_group_id = 'foo'
expect(setting.performance_bar_allowed_group_id).to be_nil
end
context 'with a path to an existing group' do
let(:group) { create(:group) }
it 'persists a valid group path and clears allowed user IDs cache' do
expect(Gitlab::PerformanceBar).to receive(:expire_allowed_user_ids_cache)
setting.performance_bar_allowed_group_id = group.full_path
expect(setting.performance_bar_allowed_group_id).to eq(group.id)
end
context 'when the given path is the same' do
before do
setting.performance_bar_allowed_group_id = group.full_path
end
it 'clears the cached allowed user IDs' do
expect(Gitlab::PerformanceBar).not_to receive(:expire_allowed_user_ids_cache)
setting.performance_bar_allowed_group_id = group.full_path
end
end
end
end
describe 'performance_bar_allowed_group' do
context 'with no performance_bar_allowed_group_id saved' do
it 'returns nil' do
expect(setting.performance_bar_allowed_group).to be_nil
end
end
context 'with a performance_bar_allowed_group_id saved' do
let(:group) { create(:group) }
before do
setting.performance_bar_allowed_group_id = group.full_path
end
it 'returns the group' do
expect(setting.performance_bar_allowed_group).to eq(group)
end
end
end
describe 'performance_bar_enabled?' do
context 'with the Performance Bar is enabled globally' do
before do
Feature.enable(:performance_bar)
end
it 'returns true' do
expect(setting).to be_performance_bar_enabled
end
end
context 'with the Performance Bar is enabled for the performance_team group' do
before do
Feature.enable_group(:performance_bar, :performance_team)
end
it 'returns true' do
expect(setting).to be_performance_bar_enabled
end
end
context 'with the Performance Bar is enabled for a specific user' do
before do
Feature.enable(:performance_team, create(:user))
end
it 'returns false' do
expect(setting).not_to be_performance_bar_enabled
end
end
end
describe 'performance_bar_enabled=' do
context 'when the performance bar is enabled' do
before do
Feature.enable(:performance_bar)
end
context 'when passing true' do
it 'does not clear allowed user IDs cache' do
expect(Gitlab::PerformanceBar).not_to receive(:expire_allowed_user_ids_cache)
setting.performance_bar_enabled = true
expect(setting).to be_performance_bar_enabled
end
end
context 'when passing false' do
it 'disables the performance bar and clears allowed user IDs cache' do
expect(Gitlab::PerformanceBar).to receive(:expire_allowed_user_ids_cache)
setting.performance_bar_enabled = false
expect(setting).not_to be_performance_bar_enabled
end
end
end
context 'when the performance bar is disabled' do
before do
Feature.disable(:performance_bar)
end
context 'when passing true' do
it 'enables the performance bar and clears allowed user IDs cache' do
expect(Gitlab::PerformanceBar).to receive(:expire_allowed_user_ids_cache)
setting.performance_bar_enabled = true
expect(setting).to be_performance_bar_enabled
end
end
context 'when passing false' do
it 'does not clear allowed user IDs cache' do
expect(Gitlab::PerformanceBar).not_to receive(:expire_allowed_user_ids_cache)
setting.performance_bar_enabled = false
expect(setting).not_to be_performance_bar_enabled
end
end
end
end
end
describe 'usage ping settings' do describe 'usage ping settings' do
context 'when the usage ping is disabled in gitlab.yml' do context 'when the usage ping is disabled in gitlab.yml' do
before do before do
......
...@@ -113,6 +113,20 @@ describe API::Features do ...@@ -113,6 +113,20 @@ describe API::Features do
{ 'key' => 'actors', 'value' => ["User:#{user.id}"] } { 'key' => 'actors', 'value' => ["User:#{user.id}"] }
]) ])
end end
it 'creates an enabled feature for the given user and feature group when passed user=username and feature_group=perf_team' do
post api("/features/#{feature_name}", admin), value: 'true', user: user.username, feature_group: 'perf_team'
expect(response).to have_http_status(201)
expect(json_response).to eq(
'name' => 'my_feature',
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'groups', 'value' => ['perf_team'] },
{ 'key' => 'actors', 'value' => ["User:#{user.id}"] }
])
end
end end
it 'creates a feature with the given percentage if passed an integer' do it 'creates a feature with the given percentage if passed an integer' do
......
...@@ -39,6 +39,10 @@ module StubConfiguration ...@@ -39,6 +39,10 @@ module StubConfiguration
allow(Gitlab.config.omniauth).to receive_messages(messages) allow(Gitlab.config.omniauth).to receive_messages(messages)
end end
def stub_performance_bar_setting(messages)
allow(Gitlab.config.performance_bar).to receive_messages(messages)
end
private private
# Modifies stubbed messages to also stub possible predicate versions # Modifies stubbed messages to also stub possible predicate versions
......
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