Commit 11fbdc72 authored by Shinya Maeda's avatar Shinya Maeda

Merge branch 'add-active-to-ff-api' into 'master'

Add Active to Feature Flags API

See merge request gitlab-org/gitlab!38350
parents 7b23102e 099a6470
...@@ -45,6 +45,7 @@ Example response: ...@@ -45,6 +45,7 @@ Example response:
{ {
"name":"merge_train", "name":"merge_train",
"description":"This feature is about merge train", "description":"This feature is about merge train",
"active": true,
"version": "new_version_flag", "version": "new_version_flag",
"created_at":"2019-11-04T08:13:51.423Z", "created_at":"2019-11-04T08:13:51.423Z",
"updated_at":"2019-11-04T08:13:51.423Z", "updated_at":"2019-11-04T08:13:51.423Z",
...@@ -68,6 +69,7 @@ Example response: ...@@ -68,6 +69,7 @@ Example response:
{ {
"name":"new_live_trace", "name":"new_live_trace",
"description":"This is a new live trace feature", "description":"This is a new live trace feature",
"active": true,
"version": "new_version_flag", "version": "new_version_flag",
"created_at":"2019-11-04T08:13:10.507Z", "created_at":"2019-11-04T08:13:10.507Z",
"updated_at":"2019-11-04T08:13:10.507Z", "updated_at":"2019-11-04T08:13:10.507Z",
...@@ -112,6 +114,7 @@ Example response: ...@@ -112,6 +114,7 @@ Example response:
{ {
"name": "awesome_feature", "name": "awesome_feature",
"description": null, "description": null,
"active": true,
"version": "new_version_flag", "version": "new_version_flag",
"created_at": "2020-05-13T19:56:33.119Z", "created_at": "2020-05-13T19:56:33.119Z",
"updated_at": "2020-05-13T19:56:33.119Z", "updated_at": "2020-05-13T19:56:33.119Z",
...@@ -146,6 +149,7 @@ POST /projects/:id/feature_flags ...@@ -146,6 +149,7 @@ POST /projects/:id/feature_flags
| `name` | string | yes | The name of the feature flag. | | `name` | string | yes | The name of the feature flag. |
| `version` | string | yes | The version of the feature flag. Must be `new_version_flag`. Omit or set to `legacy_flag` to create a [Legacy Feature Flag](feature_flags_legacy.md). | | `version` | string | yes | The version of the feature flag. Must be `new_version_flag`. Omit or set to `legacy_flag` to create a [Legacy Feature Flag](feature_flags_legacy.md). |
| `description` | string | no | The description of the feature flag. | | `description` | string | no | The description of the feature flag. |
| `active` | boolean | no | The active state of the flag. Defaults to true. [Supported](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38350) in GitLab 13.3 and later. |
| `strategies` | JSON | no | The feature flag [strategies](../operations/feature_flags.md#feature-flag-strategies). | | `strategies` | JSON | no | The feature flag [strategies](../operations/feature_flags.md#feature-flag-strategies). |
| `strategies:name` | JSON | no | The strategy name. | | `strategies:name` | JSON | no | The strategy name. |
| `strategies:parameters` | JSON | no | The strategy parameters. | | `strategies:parameters` | JSON | no | The strategy parameters. |
...@@ -171,6 +175,7 @@ Example response: ...@@ -171,6 +175,7 @@ Example response:
{ {
"name": "awesome_feature", "name": "awesome_feature",
"description": null, "description": null,
"active": true,
"version": "new_version_flag", "version": "new_version_flag",
"created_at": "2020-05-13T19:56:33.119Z", "created_at": "2020-05-13T19:56:33.119Z",
"updated_at": "2020-05-13T19:56:33.119Z", "updated_at": "2020-05-13T19:56:33.119Z",
...@@ -204,6 +209,7 @@ PUT /projects/:id/feature_flags/:name ...@@ -204,6 +209,7 @@ PUT /projects/:id/feature_flags/:name
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | | `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. | | `name` | string | yes | The name of the feature flag. |
| `description` | string | no | The description of the feature flag. | | `description` | string | no | The description of the feature flag. |
| `active` | boolean | no | The active state of the flag. [Supported](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38350) in GitLab 13.3 and later. |
| `strategies` | JSON | no | The feature flag [strategies](../operations/feature_flags.md#feature-flag-strategies). | | `strategies` | JSON | no | The feature flag [strategies](../operations/feature_flags.md#feature-flag-strategies). |
| `strategies:id` | JSON | no | The feature flag strategy id. | | `strategies:id` | JSON | no | The feature flag strategy id. |
| `strategies:name` | JSON | no | The strategy name. | | `strategies:name` | JSON | no | The strategy name. |
...@@ -229,6 +235,7 @@ Example response: ...@@ -229,6 +235,7 @@ Example response:
{ {
"name": "awesome_feature", "name": "awesome_feature",
"description": null, "description": null,
"active": true,
"version": "new_version_flag", "version": "new_version_flag",
"created_at": "2020-05-13T20:10:32.891Z", "created_at": "2020-05-13T20:10:32.891Z",
"updated_at": "2020-05-13T20:10:32.891Z", "updated_at": "2020-05-13T20:10:32.891Z",
......
...@@ -44,6 +44,7 @@ Example response: ...@@ -44,6 +44,7 @@ Example response:
{ {
"name":"merge_train", "name":"merge_train",
"description":"This feature is about merge train", "description":"This feature is about merge train",
"active": true,
"created_at":"2019-11-04T08:13:51.423Z", "created_at":"2019-11-04T08:13:51.423Z",
"updated_at":"2019-11-04T08:13:51.423Z", "updated_at":"2019-11-04T08:13:51.423Z",
"scopes":[ "scopes":[
...@@ -97,6 +98,7 @@ Example response: ...@@ -97,6 +98,7 @@ Example response:
{ {
"name":"new_live_trace", "name":"new_live_trace",
"description":"This is a new live trace feature", "description":"This is a new live trace feature",
"active": true,
"created_at":"2019-11-04T08:13:10.507Z", "created_at":"2019-11-04T08:13:10.507Z",
"updated_at":"2019-11-04T08:13:10.507Z", "updated_at":"2019-11-04T08:13:10.507Z",
"scopes":[ "scopes":[
...@@ -163,6 +165,7 @@ POST /projects/:id/feature_flags ...@@ -163,6 +165,7 @@ POST /projects/:id/feature_flags
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding). | | `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. | | `name` | string | yes | The name of the feature flag. |
| `description` | string | no | The description of the feature flag. | | `description` | string | no | The description of the feature flag. |
| `active` | boolean | no | The active state of the flag. Defaults to true. [Supported](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38350) in GitLab 13.3 and later. |
| `scopes` | JSON | no | The feature flag specs of the feature flag. | | `scopes` | JSON | no | The feature flag specs of the feature flag. |
| `scopes:environment_scope` | string | no | The environment spec. | | `scopes:environment_scope` | string | no | The environment spec. |
| `scopes:active` | boolean | no | Whether the spec is active. | | `scopes:active` | boolean | no | Whether the spec is active. |
...@@ -187,6 +190,7 @@ Example response: ...@@ -187,6 +190,7 @@ Example response:
{ {
"name":"awesome_feature", "name":"awesome_feature",
"description":null, "description":null,
"active": true,
"created_at":"2019-11-04T08:32:27.288Z", "created_at":"2019-11-04T08:32:27.288Z",
"updated_at":"2019-11-04T08:32:27.288Z", "updated_at":"2019-11-04T08:32:27.288Z",
"scopes":[ "scopes":[
...@@ -247,6 +251,7 @@ Example response: ...@@ -247,6 +251,7 @@ Example response:
{ {
"name":"new_live_trace", "name":"new_live_trace",
"description":"This is a new live trace feature", "description":"This is a new live trace feature",
"active": true,
"created_at":"2019-11-04T08:13:10.507Z", "created_at":"2019-11-04T08:13:10.507Z",
"updated_at":"2019-11-04T08:13:10.507Z", "updated_at":"2019-11-04T08:13:10.507Z",
"scopes":[ "scopes":[
......
---
title: Add support for active field to feature flags api
merge_request: 38350
author:
type: fixed
...@@ -40,6 +40,7 @@ module API ...@@ -40,6 +40,7 @@ module API
params do params do
requires :name, type: String, desc: 'The name of feature flag' requires :name, type: String, desc: 'The name of feature flag'
optional :description, type: String, desc: 'The description of the feature flag' optional :description, type: String, desc: 'The description of the feature flag'
optional :active, type: Boolean, desc: 'Active/inactive value of the flag'
optional :version, type: String, desc: 'The version of the feature flag' optional :version, type: String, desc: 'The version of the feature flag'
optional :scopes, type: Array do optional :scopes, type: Array do
requires :environment_scope, type: String, desc: 'The environment scope of the scope' requires :environment_scope, type: String, desc: 'The environment scope of the scope'
...@@ -145,6 +146,7 @@ module API ...@@ -145,6 +146,7 @@ module API
end end
params do params do
optional :description, type: String, desc: 'The description of the feature flag' optional :description, type: String, desc: 'The description of the feature flag'
optional :active, type: Boolean, desc: 'Active/inactive value of the flag'
optional :strategies, type: Array do optional :strategies, type: Array do
optional :id, type: Integer, desc: 'The strategy id' optional :id, type: Integer, desc: 'The strategy id'
optional :name, type: String, desc: 'The strategy type' optional :name, type: String, desc: 'The strategy type'
......
...@@ -6,6 +6,7 @@ module EE ...@@ -6,6 +6,7 @@ module EE
class FeatureFlag < Grape::Entity class FeatureFlag < Grape::Entity
expose :name expose :name
expose :description expose :description
expose :active
expose :version, if: :feature_flags_new_version_enabled expose :version, if: :feature_flags_new_version_enabled
expose :created_at expose :created_at
expose :updated_at expose :updated_at
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
"properties": { "properties": {
"name": { "type": "string" }, "name": { "type": "string" },
"description": { "type": ["string", "null"] }, "description": { "type": ["string", "null"] },
"active": {"type": "boolean" },
"version": { "type": "string" }, "version": { "type": "string" },
"created_at": { "type": "date" }, "created_at": { "type": "date" },
"updated_at": { "type": "date" }, "updated_at": { "type": "date" },
......
...@@ -4,19 +4,21 @@ require 'spec_helper' ...@@ -4,19 +4,21 @@ require 'spec_helper'
RSpec.describe API::FeatureFlags do RSpec.describe API::FeatureFlags do
include FeatureFlagHelpers include FeatureFlagHelpers
let(:project) { create(:project, :repository) } let_it_be(:project) { create(:project) }
let(:developer) { create(:user) } let_it_be(:developer) { create(:user) }
let(:reporter) { create(:user) } let_it_be(:reporter) { create(:user) }
let_it_be(:non_project_member) { create(:user) }
let(:user) { developer } let(:user) { developer }
let(:non_project_member) { create(:user) }
before do
stub_licensed_features(feature_flags: true)
before_all do
project.add_developer(developer) project.add_developer(developer)
project.add_reporter(reporter) project.add_reporter(reporter)
end end
before do
stub_licensed_features(feature_flags: true)
end
shared_examples_for 'check user permission' do shared_examples_for 'check user permission' do
context 'when user is reporter' do context 'when user is reporter' do
let(:user) { reporter } let(:user) { reporter }
...@@ -118,6 +120,7 @@ RSpec.describe API::FeatureFlags do ...@@ -118,6 +120,7 @@ RSpec.describe API::FeatureFlags do
expect(json_response).to eq([{ expect(json_response).to eq([{
'name' => 'feature1', 'name' => 'feature1',
'description' => nil, 'description' => nil,
'active' => true,
'version' => 'new_version_flag', 'version' => 'new_version_flag',
'updated_at' => feature_flag.updated_at.as_json, 'updated_at' => feature_flag.updated_at.as_json,
'created_at' => feature_flag.created_at.as_json, 'created_at' => feature_flag.created_at.as_json,
...@@ -207,6 +210,7 @@ RSpec.describe API::FeatureFlags do ...@@ -207,6 +210,7 @@ RSpec.describe API::FeatureFlags do
expect(json_response).to eq({ expect(json_response).to eq({
'name' => 'feature1', 'name' => 'feature1',
'description' => nil, 'description' => nil,
'active' => true,
'version' => 'new_version_flag', 'version' => 'new_version_flag',
'updated_at' => feature_flag.updated_at.as_json, 'updated_at' => feature_flag.updated_at.as_json,
'created_at' => feature_flag.created_at.as_json, 'created_at' => feature_flag.created_at.as_json,
...@@ -298,6 +302,25 @@ RSpec.describe API::FeatureFlags do ...@@ -298,6 +302,25 @@ RSpec.describe API::FeatureFlags do
expect(json_response.key?('version')).to eq(false) expect(json_response.key?('version')).to eq(false)
end end
context 'with active set to false in the params for a legacy flag' do
let(:params) do
{
name: 'awesome-feature',
version: 'legacy_flag',
active: 'false',
scopes: [scope_default]
}
end
it 'creates an inactive feature flag' do
subject
expect(response).to have_gitlab_http_status(:created)
expect(response).to match_response_schema('public_api/v4/feature_flag', dir: 'ee')
expect(json_response['active']).to eq(false)
end
end
context 'when no scopes passed in parameters' do context 'when no scopes passed in parameters' do
let(:params) { { name: 'awesome-feature' } } let(:params) { { name: 'awesome-feature' } }
...@@ -370,12 +393,37 @@ RSpec.describe API::FeatureFlags do ...@@ -370,12 +393,37 @@ RSpec.describe API::FeatureFlags do
expect(response).to have_gitlab_http_status(:created) expect(response).to have_gitlab_http_status(:created)
expect(response).to match_response_schema('public_api/v4/feature_flag', dir: 'ee') expect(response).to match_response_schema('public_api/v4/feature_flag', dir: 'ee')
expect(json_response).to match(hash_including({
'name' => 'new-feature',
'description' => nil,
'active' => true,
'version' => 'new_version_flag',
'scopes' => [],
'strategies' => []
}))
feature_flag = project.operations_feature_flags.last feature_flag = project.operations_feature_flags.last
expect(feature_flag.name).to eq(params[:name]) expect(feature_flag.name).to eq(params[:name])
expect(feature_flag.version).to eq('new_version_flag') expect(feature_flag.version).to eq('new_version_flag')
end end
it 'creates a new feature flag that is inactive' do
params = {
name: 'new-feature',
version: 'new_version_flag',
active: false
}
post api("/projects/#{project.id}/feature_flags", user), params: params
expect(response).to have_gitlab_http_status(:created)
expect(response).to match_response_schema('public_api/v4/feature_flag', dir: 'ee')
expect(json_response['active']).to eq(false)
feature_flag = project.operations_feature_flags.last
expect(feature_flag.active).to eq(false)
end
it 'creates a new feature flag with strategies' do it 'creates a new feature flag with strategies' do
params = { params = {
name: 'new-feature', name: 'new-feature',
...@@ -691,7 +739,7 @@ RSpec.describe API::FeatureFlags do ...@@ -691,7 +739,7 @@ RSpec.describe API::FeatureFlags do
context 'with a version 2 feature flag' do context 'with a version 2 feature flag' do
let!(:feature_flag) do let!(:feature_flag) do
create(:operations_feature_flag, :new_version_flag, project: project, create(:operations_feature_flag, :new_version_flag, project: project, active: true,
name: 'feature1', description: 'old description') name: 'feature1', description: 'old description')
end end
...@@ -755,6 +803,17 @@ RSpec.describe API::FeatureFlags do ...@@ -755,6 +803,17 @@ RSpec.describe API::FeatureFlags do
expect(feature_flag.reload.description).to eq('new description') expect(feature_flag.reload.description).to eq('new description')
end end
it 'updates the flag active value' do
params = { active: false }
put api("/projects/#{project.id}/feature_flags/feature1", user), params: params
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('public_api/v4/feature_flag', dir: 'ee')
expect(json_response['active']).to eq(false)
expect(feature_flag.reload.active).to eq(false)
end
it 'ignores a provided version parameter' do it 'ignores a provided version parameter' do
params = { description: 'other description', version: 'bad_value' } params = { description: 'other description', version: 'bad_value' }
...@@ -776,6 +835,7 @@ RSpec.describe API::FeatureFlags do ...@@ -776,6 +835,7 @@ RSpec.describe API::FeatureFlags do
expect(json_response).to eq({ expect(json_response).to eq({
'name' => 'feature1', 'name' => 'feature1',
'description' => 'new description', 'description' => 'new description',
'active' => true,
'created_at' => feature_flag.created_at.as_json, 'created_at' => feature_flag.created_at.as_json,
'updated_at' => feature_flag.updated_at.as_json, 'updated_at' => feature_flag.updated_at.as_json,
'scopes' => [], 'scopes' => [],
......
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