summaryrefslogtreecommitdiff
path: root/doc/development/feature_flags/development.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/development/feature_flags/development.md')
-rw-r--r--doc/development/feature_flags/development.md113
1 files changed, 35 insertions, 78 deletions
diff --git a/doc/development/feature_flags/development.md b/doc/development/feature_flags/development.md
index 067e480f6f8..2855662e1db 100644
--- a/doc/development/feature_flags/development.md
+++ b/doc/development/feature_flags/development.md
@@ -35,7 +35,6 @@ used so that unfinished code can be deployed in production.
A `development` feature flag should have a rollout issue,
ideally created using the [Feature Flag Roll Out template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Feature%20Flag%20Roll%20Out.md).
-NOTE: **Note:**
This is the default type used when calling `Feature.enabled?`.
### `ops` type
@@ -61,30 +60,6 @@ Feature.disabled?(:my_ops_flag, project, type: :ops)
push_frontend_feature_flag(:my_ops_flag, project, type: :ops)
```
-### `licensed` type
-
-`licensed` feature flags are used to temporarily disable licensed features. There
-should be a one-to-one mapping of `licensed` feature flags to licensed features.
-
-`licensed` feature flags must be `default_enabled: true`, because that's the only
-supported option in the current implementation. This is under development as per
-the [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/218667).
-
-The `licensed` type has a dedicated set of functions to check if a licensed
-feature is available for a project or namespace. This check validates
-if the license is assigned to the namespace and feature flag itself.
-The `licensed` feature flag has the same name as a licensed feature name:
-
-```ruby
-# Good: checks if feature flag is enabled
-project.feature_available?(:my_licensed_feature)
-namespace.feature_available?(:my_licensed_feature)
-
-# Bad: licensed flag must be accessed via `feature_available?`
-Feature.enabled?(:my_licensed_feature, type: :licensed)
-push_frontend_feature_flag(:my_licensed_feature, type: :licensed)
-```
-
## Feature flag definition and validation
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229161) in GitLab 13.3.
@@ -128,7 +103,7 @@ a YAML definition in `config/feature_flags` or `ee/config/feature_flags`.
Only feature flags that have a YAML definition file can be used when running the development or testing environments.
```shell
-$ bin/feature-flag my-feature-flag
+$ bin/feature-flag my_feature_flag
>> Specify the group introducing the feature flag, like `group::apm`:
?> group::memory
@@ -140,9 +115,9 @@ https://gitlab.com/gitlab-org/gitlab/-/issues/new?issue%5Btitle%5D=%5BFeature+fl
>> URL of the rollout issue (enter to skip):
?> https://gitlab.com/gitlab-org/gitlab/-/issues/232533
-create config/feature_flags/development/test-flag.yml
+create config/feature_flags/development/my_feature_flag.yml
---
-name: test-flag
+name: my_feature_flag
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38602
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/232533
group: group::memory
@@ -212,6 +187,30 @@ if Feature.disabled?(:my_feature_flag, project, type: :ops)
end
```
+DANGER: **Warning:**
+Don't use feature flags at application load time. For example, using the `Feature` class in
+`config/initializers/*` or at the class level could cause an unexpected error. This error occurs
+because a database that a feature flag adapter might depend on doesn't exist at load time
+(especially for fresh installations). Checking for the database's existence at the caller isn't
+recommended, as some adapters don't require a database at all (for example, the HTTP adapter). The
+feature flag setup check must be abstracted in the `Feature` namespace. This approach also requires
+application reload when the feature flag changes. You must therefore ask SREs to reload the
+Web/API/Sidekiq fleet on production, which takes time to fully rollout/rollback the changes. For
+these reasons, use environment variables (for example, `ENV['YOUR_FEATURE_NAME']`) or `gitlab.yml`
+instead.
+
+Here's an example of a pattern that you should avoid:
+
+```ruby
+class MyClass
+ if Feature.enabled?(:...)
+ new_process
+ else
+ legacy_process
+ end
+end
+```
+
### Frontend
Use the `push_frontend_feature_flag` method for frontend code, which is
@@ -309,57 +308,16 @@ used as an actor for `Feature.enabled?`.
### Feature flags for licensed features
-If a feature is license-gated, there's no need to add an additional
-explicit feature flag check since the flag is checked as part of the
-`License.feature_available?` call. Similarly, there's no need to "clean up" a
-feature flag once the feature has reached general availability.
-
-The [`Project#feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/app/models/project_feature.rb#L63-68),
-[`Namespace#feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/ee/app/models/ee/namespace.rb#L71-85) (EE), and
-[`License.feature_available?`](https://gitlab.com/gitlab-org/gitlab/blob/4cc1c62918aa4c31750cb21dfb1a6c3492d71080/ee/app/models/license.rb#L293-300) (EE) methods all implicitly check for
-a by default enabled feature flag with the same name as the provided argument.
-
-**An important side-effect of the implicit feature flags mentioned above is that
-unless the feature is explicitly disabled or limited to a percentage of users,
-the feature flag check defaults to `true`.**
-
-NOTE: **Note:**
-Due to limitations with `feature_available?`, the YAML definition for `licensed` feature
-flags accepts only `default_enabled: true`. This is under development as per the
-[related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/218667).
-
-#### Alpha/beta licensed feature flags
-
-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/gitlab-the-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/gitlab-the-product/#alpha-beta-ga). This ensures the feature is disabled unless the feature flag is
-_explicitly_ enabled.
-
-CAUTION: **Caution:**
-If `alpha_feature_available?` or `beta_feature_available?` is used, the YAML definition
-for the feature flag must use `default_enabled: [false, true]`, because the usage
-of the feature flag is undefined. These methods may change, as per the
-[related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/218667).
+You can't use a feature flag with the same name as a licensed feature name, because
+it would cause a naming collision. This was [widely discussed and removed](https://gitlab.com/gitlab-org/gitlab/-/issues/259611)
+because it is confusing.
-The resulting YAML should be similar to:
+To check for licensed features, add a dedicated feature flag under a different name
+and check it explicitly, for example:
-```yaml
-name: scoped_labels
-group: group::memory
-type: licensed
-# The `default_enabled:` is undefined
-# as `feature_available?` uses `default_enabled: true`
-# as `beta_feature_available?` uses `default_enabled: false`
-default_enabled: [false, true]
+```ruby
+Feature.enabled?(:licensed_feature_feature_flag, project) &&
+ project.feature_available?(:licensed_feature)
```
### Feature groups
@@ -397,7 +355,6 @@ Introducing a feature flag into the codebase creates an additional code path tha
It is strongly advised to test all code affected by a feature flag, both when **enabled** and **disabled**
to ensure the feature works properly.
-NOTE: **Note:**
When using the testing environment, all feature flags are enabled by default.
To disable a feature flag in a test, use the `stub_feature_flags`