Commit 5ccdaeee authored by Shinya Maeda's avatar Shinya Maeda

Feature flag API documentation

This commit adds feature flag API documentation
parent 264290e7
This diff is collapsed.
# Feature Flags API **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/9566) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.5.
API for accessing resources of [GitLab Feature Flags](../user/project/operations/feature_flags.md).
Users with Developer or higher [permissions](../user/permissions.md) can access Feature Flag API.
## Feature Flags pagination
By default, `GET` requests return 20 results at a time because the API results
are [paginated](README.md#pagination).
## List feature flags for a project
Gets all feature flags of the requested project.
```
GET /projects/:id/feature_flags
```
| Attribute | Type | Required | Description |
| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `scope` | string | no | The condition of feature flags, one of: `enabled`, `disabled`. |
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/feature_flags
```
Example response:
```json
[
{
"name":"merge_train",
"description":"This feature is about merge train",
"created_at":"2019-11-04T08:13:51.423Z",
"updated_at":"2019-11-04T08:13:51.423Z",
"scopes":[
{
"id":82,
"active":false,
"environment_scope":"*",
"strategies":[
{
"name":"default",
"parameters":{
}
}
],
"created_at":"2019-11-04T08:13:51.425Z",
"updated_at":"2019-11-04T08:13:51.425Z"
},
{
"id":83,
"active":true,
"environment_scope":"review/*",
"strategies":[
{
"name":"default",
"parameters":{
}
}
],
"created_at":"2019-11-04T08:13:51.427Z",
"updated_at":"2019-11-04T08:13:51.427Z"
},
{
"id":84,
"active":false,
"environment_scope":"production",
"strategies":[
{
"name":"default",
"parameters":{
}
}
],
"created_at":"2019-11-04T08:13:51.428Z",
"updated_at":"2019-11-04T08:13:51.428Z"
}
]
},
{
"name":"new_live_trace",
"description":"This is a new live trace feature",
"created_at":"2019-11-04T08:13:10.507Z",
"updated_at":"2019-11-04T08:13:10.507Z",
"scopes":[
{
"id":79,
"active":false,
"environment_scope":"*",
"strategies":[
{
"name":"default",
"parameters":{
}
}
],
"created_at":"2019-11-04T08:13:10.516Z",
"updated_at":"2019-11-04T08:13:10.516Z"
},
{
"id":80,
"active":true,
"environment_scope":"staging",
"strategies":[
{
"name":"default",
"parameters":{
}
}
],
"created_at":"2019-11-04T08:13:10.525Z",
"updated_at":"2019-11-04T08:13:10.525Z"
},
{
"id":81,
"active":false,
"environment_scope":"production",
"strategies":[
{
"name":"default",
"parameters":{
}
}
],
"created_at":"2019-11-04T08:13:10.527Z",
"updated_at":"2019-11-04T08:13:10.527Z"
}
]
}
]
```
## New feature flag
Creates a new feature flag.
```
POST /projects/:id/feature_flags
```
| Attribute | Type | Required | Description |
| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `name` | string | yes | The name of the feature flag. |
| `description` | string | no | The description of the feature flag. |
| `scopes` | JSON | no | The [feature flag specs](../user/project/operations/feature_flags.md#define-environment-specs) of the feature flag. |
| `scopes:environment_scope` | string | no | The [environment spec](../ci/environments.md#scoping-environments-with-specs). |
| `scopes:active` | boolean | no | Whether the spec is active. |
| `scopes:strategies` | JSON | no | The [strategies](../user/project/operations/feature_flags.md#feature-flag-strategies) of the feature flag spec. |
```bash
curl https://gitlab.example.com/api/v4/projects/1/feature_flags \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-type: application/json" \
--data @- << EOF
{
"name": "awesome_feature",
"scopes": [{ "environment_scope": "*", "active": false, "strategies": [{ "name": "default", "parameters": {} }] },
{ "environment_scope": "production", "active": true, "strategies": [{ "name": "userWithId", "parameters": { "userIds": "1,2,3" } }] }]
}
EOF
```
Example response:
```json
{
"name":"awesome_feature",
"description":null,
"created_at":"2019-11-04T08:32:27.288Z",
"updated_at":"2019-11-04T08:32:27.288Z",
"scopes":[
{
"id":85,
"active":false,
"environment_scope":"*",
"strategies":[
{
"name":"default",
"parameters":{
}
}
],
"created_at":"2019-11-04T08:32:29.324Z",
"updated_at":"2019-11-04T08:32:29.324Z"
},
{
"id":86,
"active":true,
"environment_scope":"production",
"strategies":[
{
"name":"userWithId",
"parameters":{
"userIds":"1,2,3"
}
}
],
"created_at":"2019-11-04T08:32:29.328Z",
"updated_at":"2019-11-04T08:32:29.328Z"
}
]
}
```
## Single feature flag
Gets a single feature flag.
```
GET /projects/:id/feature_flags/:name
```
| Attribute | Type | Required | Description |
| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `name` | string | yes | The name of the feature flag. |
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/feature_flags/new_live_trace
```
Example response:
```json
{
"name":"new_live_trace",
"description":"This is a new live trace feature",
"created_at":"2019-11-04T08:13:10.507Z",
"updated_at":"2019-11-04T08:13:10.507Z",
"scopes":[
{
"id":79,
"active":false,
"environment_scope":"*",
"strategies":[
{
"name":"default",
"parameters":{
}
}
],
"created_at":"2019-11-04T08:13:10.516Z",
"updated_at":"2019-11-04T08:13:10.516Z"
},
{
"id":80,
"active":true,
"environment_scope":"staging",
"strategies":[
{
"name":"default",
"parameters":{
}
}
],
"created_at":"2019-11-04T08:13:10.525Z",
"updated_at":"2019-11-04T08:13:10.525Z"
},
{
"id":81,
"active":false,
"environment_scope":"production",
"strategies":[
{
"name":"default",
"parameters":{
}
}
],
"created_at":"2019-11-04T08:13:10.527Z",
"updated_at":"2019-11-04T08:13:10.527Z"
}
]
}
```
## Delete feature flag
Deletes a feature flag.
```
DELETE /projects/:id/feature_flags/:name
```
| Attribute | Type | Required | Description |
| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). |
| `name` | string | yes | The name of the feature flag. |
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" --request DELETE https://gitlab.example.com/api/v4/projects/1/feature_flags/awesome_feature
```
......@@ -103,6 +103,7 @@ The following table depicts the various user permission levels in a project.
| Apply code change suggestions | | | ✓ | ✓ | ✓ |
| Create and edit wiki pages | | | ✓ | ✓ | ✓ |
| Rewrite/remove Git tags | | | ✓ | ✓ | ✓ |
| Manage Feature Flags **(PREMIUM)** | | | ✓ | ✓ | ✓ |
| Use environment terminals | | | | ✓ | ✓ |
| Run Web IDE's Interactive Web Terminals **(ULTIMATE ONLY)** | | | | ✓ | ✓ |
| Add new team members | | | | ✓ | ✓ |
......
......@@ -81,7 +81,14 @@ NOTE: **NOTE**
We'd highly recommend you to use the [Environment](../../../ci/environments.md)
feature in order to quickly assess which flag is enabled per environment.
## Rollout strategy
## Feature Flag strategies
GitLab Feature Flag adopts [Unleash](https://unleash.github.io)
as the feature flag engine. In unleash, there is a concept of rulesets for granular feature flag controls,
called [strategies](https://unleash.github.io/docs/activation_strategy).
Supported strategies for GitLab Feature Flags are described below.
### Rollout strategy
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/8240) in GitLab 12.2.
......@@ -91,13 +98,13 @@ The status of an environment spec ultimately determines whether or not a feature
For instance, a feature will always be disabled for every user if the matching environment spec has a disabled status, regardless of the chosen rollout strategy.
However, a feature will be enabled for 50% of logged-in users if the matching environment spec has an enabled status along with a **Percent rollout (logged in users)** strategy set to 50%.
### All users
#### All users
Enables the feature for all users. It is implemented using the Unleash
[`default`](https://unleash.github.io/docs/activation_strategy#default)
activation strategy.
### Percent rollout (logged in users)
#### Percent rollout (logged in users)
Enables the feature for a percentage of authenticated users. It is
implemented using the Unleash
......@@ -112,7 +119,7 @@ CAUTION: **Caution:**
If this strategy is selected, then the Unleash client **must** be given a user
ID for the feature to be enabled. See the [Ruby example](#ruby-application-example) below.
## Target users
### Target users strategy
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/8240) in GitLab 12.2.
......@@ -134,7 +141,7 @@ In order to use Feature Flags, you need to first
[get the access credentials](#configuring-feature-flags) from GitLab and then
prepare your application and hook it with a [client library](#client-libraries).
### Configuring Feature Flags
## Configuring Feature Flags
To get the access credentials that your application will need to talk to GitLab:
......@@ -153,7 +160,7 @@ if **Instance ID** will be single token or multiple tokens, assigned to the
**Environment**. Also, **Application name** could describe the version of
application instead of the running environment.
### Client libraries
## Client libraries
GitLab currently implements a single backend that is compatible with
[Unleash](https://github.com/Unleash/unleash#client-implementations) clients.
......@@ -178,7 +185,7 @@ Community contributed clients:
- [Unofficial .Net Core Unleash client](https://github.com/onybo/unleash-client-core)
- [Unleash client for Python 3](https://github.com/aes/unleash-client-python)
### Golang application example
## Golang application example
Here's an example of how to integrate the feature flags in a Golang application:
......@@ -219,7 +226,7 @@ func main() {
}
```
### Ruby application example
## Ruby application example
Here's an example of how to integrate the feature flags in a Ruby application.
......@@ -249,3 +256,11 @@ else
puts "hello, world!"
end
```
## Feature Flags API
You can create, update, read, and delete Feature Flags via API
to control them in an automated flow:
- [Feature Flags API](../../../api/feature_flags.md)
- [Feature Flag Specs API](../../../api/feature_flag_specs.md)
---
title: Add public API for Feature Flags
merge_request: 19547
author:
type: added
......@@ -4,11 +4,10 @@ module API
class FeatureFlagScopes < Grape::API
include PaginationParams
ENVIRONMENT_SCOPE_ENDPOINT_REQUIREMETS = FeatureFlags::FEATURE_FLAG_ENDPOINT_REQUIREMENTS
ENVIRONMENT_SCOPE_ENDPOINT_REQUIREMENTS = FeatureFlags::FEATURE_FLAG_ENDPOINT_REQUIREMENTS
.merge(environment_scope: API::NO_SLASH_URL_PART_REGEX)
before do
not_found! unless Feature.enabled?(:feature_flag_api, user_project)
authorize_read_feature_flags!
end
......@@ -18,7 +17,7 @@ module API
resource 'projects/:id', requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
resource :feature_flag_scopes do
desc 'Get all effective feature flags under the environment' do
detail 'This feature is going to be introduced in GitLab 12.5 if `feature_flag_api` feature flag is removed'
detail 'This feature was introduced in GitLab 12.5'
success EE::API::Entities::FeatureFlag::DetailedScope
end
params do
......@@ -35,7 +34,7 @@ module API
resource 'feature_flags/:name', requirements: FeatureFlags::FEATURE_FLAG_ENDPOINT_REQUIREMENTS do
resource :scopes do
desc 'Get all scopes of a feature flag' do
detail 'This feature is going to be introduced in GitLab 12.5 if `feature_flag_api` feature flag is removed'
detail 'This feature was introduced in GitLab 12.5'
success EE::API::Entities::FeatureFlag::Scope
end
params do
......@@ -46,12 +45,12 @@ module API
end
desc 'Create a scope of a feature flag' do
detail 'This feature is going to be introduced in GitLab 12.5 if `feature_flag_api` feature flag is removed'
detail 'This feature was introduced in GitLab 12.5'
success EE::API::Entities::FeatureFlag::Scope
end
params do
requires :environment_scope, type: String, desc: 'The environment scope of the scope'
requires :active, type: Boolean, desc: 'Active/inactive of the scope'
requires :active, type: Boolean, desc: 'Whether the scope is active'
requires :strategies, type: JSON, desc: 'The strategies of the scope'
end
post do
......@@ -71,9 +70,9 @@ module API
params do
requires :environment_scope, type: String, desc: 'URL-encoded environment scope'
end
resource ':environment_scope', requirements: ENVIRONMENT_SCOPE_ENDPOINT_REQUIREMETS do
resource ':environment_scope', requirements: ENVIRONMENT_SCOPE_ENDPOINT_REQUIREMENTS do
desc 'Get a scope of a feature flag' do
detail 'This feature is going to be introduced in GitLab 12.5 if `feature_flag_api` feature flag is removed'
detail 'This feature was introduced in GitLab 12.5'
success EE::API::Entities::FeatureFlag::Scope
end
get do
......@@ -81,11 +80,11 @@ module API
end
desc 'Update a scope of a feature flag' do
detail 'This feature is going to be introduced in GitLab 12.5 if `feature_flag_api` feature flag is removed'
detail 'This feature was introduced in GitLab 12.5'
success EE::API::Entities::FeatureFlag::Scope
end
params do
optional :active, type: Boolean, desc: 'Active/inactive of the scope'
optional :active, type: Boolean, desc: 'Whether the scope is active'
optional :strategies, type: JSON, desc: 'The strategies of the scope'
end
put do
......@@ -108,7 +107,7 @@ module API
end
desc 'Delete a scope from a feature flag' do
detail 'This feature is going to be introduced in GitLab 12.5 if `feature_flag_api` feature flag is removed'
detail 'This feature was introduced in GitLab 12.5'
success EE::API::Entities::FeatureFlag::Scope
end
delete do
......
......@@ -8,7 +8,6 @@ module API
.merge(name: API::NO_SLASH_URL_PART_REGEX)
before do
not_found! unless Feature.enabled?(:feature_flag_api, user_project)
authorize_read_feature_flags!
end
......@@ -18,7 +17,7 @@ module API
resource 'projects/:id', requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
resource :feature_flags do
desc 'Get all feature flags of a project' do
detail 'This feature is going to be introduced in GitLab 12.5 if `feature_flag_api` feature flag is removed'
detail 'This feature was introduced in GitLab 12.5'
success EE::API::Entities::FeatureFlag
end
params do
......@@ -35,7 +34,7 @@ module API
end
desc 'Create a new feature flag' do
detail 'This feature is going to be introduced in GitLab 12.5 if `feature_flag_api` feature flag is removed'
detail 'This feature was introduced in GitLab 12.5'
success EE::API::Entities::FeatureFlag
end
params do
......@@ -70,7 +69,7 @@ module API
end
resource 'feature_flags/:name', requirements: FEATURE_FLAG_ENDPOINT_REQUIREMENTS do
desc 'Get a feature flag of a project' do
detail 'This feature is going to be introduced in GitLab 12.5 if `feature_flag_api` feature flag is removed'
detail 'This feature was introduced in GitLab 12.5'
success EE::API::Entities::FeatureFlag
end
get do
......@@ -80,7 +79,7 @@ module API
end
desc 'Enable a strategy for a feature flag on an environment' do
detail 'This feature is going to be introduced in GitLab 12.5 if `feature_flag_api` feature flag is removed'
detail 'This feature was introduced in GitLab 12.5'
success EE::API::Entities::FeatureFlag
end
params do
......@@ -88,6 +87,8 @@ module API
requires :strategy, type: JSON, desc: 'The strategy to be enabled on the scope'
end
post :enable do
not_found! unless Feature.enabled?(:feature_flag_api, user_project)
result = ::FeatureFlags::EnableService
.new(user_project, current_user, params).execute
......@@ -108,6 +109,8 @@ module API
requires :strategy, type: JSON, desc: 'The strategy to be disabled on the scope'
end
post :disable do
not_found! unless Feature.enabled?(:feature_flag_api, user_project)
result = ::FeatureFlags::DisableService
.new(user_project, current_user, params).execute
......@@ -120,7 +123,7 @@ module API
end
desc 'Delete a feature flag' do
detail 'This feature is going to be introduced in GitLab 12.5 if `feature_flag_api` feature flag is removed'
detail 'This feature was introduced in GitLab 12.5'
success EE::API::Entities::FeatureFlag
end
delete do
......
......@@ -38,18 +38,6 @@ describe API::FeatureFlagScopes do
expect(response).to have_gitlab_http_status(:forbidden)
end
end
context 'when feature_flag_api feature flag is disabled' do
before do
stub_feature_flags(feature_flag_api: false)
end
it 'forbids the request' do
subject
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
shared_examples_for 'not found' do
......
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