Commit dcc29451 authored by Rémy Coutable's avatar Rémy Coutable

Merge branch 'docs/recommend_beta_feature_available' into 'master'

Implement and document alpha/beta_feature_available? method

See merge request gitlab-org/gitlab!20840
parents b4eeb72a 290004ef
......@@ -38,7 +38,7 @@ Feature.enabled?(:feature_flag, project, default_enabled: true)
The [`Project#feature_available?`][project-fa],
[`Namespace#feature_available?`][namespace-fa] (EE), and
[`License.feature_available?`][license-fa] (EE) methods all implicitly check for
a feature flag by the same name as the provided argument.
a by default enabled feature flag with the same name as the provided argument.
For example if a feature is license-gated, there's no need to add an additional
explicit feature flag check since the flag will be checked as part of the
......@@ -56,12 +56,19 @@ isn't gated by a License or Plan.
unless the feature is explicitly disabled or limited to a percentage of users,
the feature flag check will default to `true`.**
As an example, if you were to ship the backend half of a feature behind a flag,
you'd want to explicitly disable that flag until the frontend half is also ready
to be shipped. To make sure this feature is disabled for both GitLab.com and
self-managed instances you'd need to explicitly call `Feature.enabled?` method
before the `feature_available` method. This ensures the feature_flag is defaulting
to `false`.
This is relevant when developing the feature using
[several smaller merge requests](https://about.gitlab.com/handbook/values/#make-small-merge-requests), or when the feature is considered to be an
[alpha or beta](https://about.gitlab.com/handbook/product/#alpha-beta-ga), and
should not be available by default.
As an example, if you were to ship the frontend half of a feature without the
backend, you'd want to disable the feature entirely until the backend half is
also ready to be shipped. To make sure this feature is disabled for both
GitLab.com and self-managed instances, you should use the
[`Namespace#alpha_feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/458749872f4a8f27abe8add930dbb958044cb926/ee/app/models/ee/namespace.rb#L113) or
[`Namespace#beta_feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/458749872f4a8f27abe8add930dbb958044cb926/ee/app/models/ee/namespace.rb#L100-112)
method, according to our [definitions](https://about.gitlab.com/handbook/product/#alpha-beta-ga). This ensures the feature is disabled unless the feature flag is
_explicitly_ enabled.
## Feature groups
......
......@@ -112,6 +112,7 @@ module EE
::Feature.enabled?(feature, self) ||
(::Feature.enabled?(feature) && feature_available?(feature))
end
alias_method :alpha_feature_available?, :beta_feature_available?
# Checks features (i.e. https://about.gitlab.com/pricing/) availabily
# for a given Namespace plan. This method should consider ancestor groups
......
......@@ -297,6 +297,7 @@ module EE
::Feature.enabled?(feature, self) ||
(::Feature.enabled?(feature) && feature_available?(feature))
end
alias_method :alpha_feature_available?, :beta_feature_available?
def push_audit_events_enabled?
::Feature.enabled?(:repository_push_audit_event, self)
......
......@@ -607,8 +607,8 @@ describe Group do
end
end
describe '#beta_feature_available?' do
it_behaves_like 'an entity with beta feature support' do
describe '#alpha/beta_feature_available?' do
it_behaves_like 'an entity with alpha/beta feature support' do
let(:entity) { group }
end
end
......
......@@ -545,8 +545,8 @@ describe Project do
end
end
describe '#beta_feature_available?' do
it_behaves_like 'an entity with beta feature support' do
describe '#alpha/beta_feature_available?' do
it_behaves_like 'an entity with alpha/beta feature support' do
let(:entity) { create(:project) }
end
end
......
# frozen_string_literal: true
# This needs an `entity` object: Project or Group.
RSpec.shared_examples 'an entity with alpha/beta feature support' do
where(level: %w[alpha beta])
with_them do
let(:method_name) { "#{level}_feature_available?" }
context 'when license does not allow it' do
before do
stub_licensed_features(insights: false)
end
context 'when the feature flag is disabled globally' do
before do
stub_feature_flags(insights: false)
end
it { expect(entity.public_send(method_name, :insights)).to be_falsy }
end
context 'when the feature flag is enabled globally' do
before do
stub_feature_flags(insights: true)
end
it { expect(entity.public_send(method_name, :insights)).to be_truthy }
end
context 'when the feature flag is enabled for the entity' do
before do
stub_feature_flags(insights: { enabled: true, thing: entity })
end
it { expect(entity.public_send(method_name, :insights)).to be_truthy }
end
end
context 'when license allows it' do
before do
stub_licensed_features(insights: true)
end
context 'when the feature flag is disabled globally' do
before do
stub_feature_flags(insights: false)
end
it { expect(entity.public_send(method_name, :insights)).to be_falsy }
end
context 'when the feature flag is enabled globally' do
before do
stub_feature_flags(insights: true)
end
it { expect(entity.public_send(method_name, :insights)).to be_truthy }
end
context 'when the feature flag is enabled for the entity' do
before do
stub_feature_flags(insights: { enabled: true, thing: entity })
end
it { expect(entity.public_send(method_name, :insights)).to be_truthy }
end
end
end
end
# frozen_string_literal: true
# This needs an `entity` object: Project or Group.
RSpec.shared_examples 'an entity with beta feature support' do
context 'when license does not allow it' do
before do
stub_licensed_features(insights: false)
end
context 'when the feature flag is disabled globally' do
before do
stub_feature_flags(insights: false)
end
it { expect(entity.beta_feature_available?(:insights)).to be_falsy }
end
context 'when the feature flag is enabled globally' do
before do
stub_feature_flags(insights: true)
end
it { expect(entity.beta_feature_available?(:insights)).to be_truthy }
end
context 'when the feature flag is enabled for the entity' do
before do
stub_feature_flags(insights: { enabled: true, thing: entity })
end
it { expect(entity.beta_feature_available?(:insights)).to be_truthy }
end
end
context 'when license allows it' do
before do
stub_licensed_features(insights: true)
end
context 'when the feature flag is disabled globally' do
before do
stub_feature_flags(insights: false)
end
it { expect(entity.beta_feature_available?(:insights)).to be_falsy }
end
context 'when the feature flag is enabled globally' do
before do
stub_feature_flags(insights: true)
end
it { expect(entity.beta_feature_available?(:insights)).to be_truthy }
end
context 'when the feature flag is enabled for the entity' do
before do
stub_feature_flags(insights: { enabled: true, thing: entity })
end
it { expect(entity.beta_feature_available?(:insights)).to be_truthy }
end
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