diff options
-rw-r--r-- | changelogs/unreleased/jej-feature-gates-can-be-set-by-group-path.yml | 5 | ||||
-rw-r--r-- | doc/api/features.md | 3 | ||||
-rw-r--r-- | lib/api/features.rb | 1 | ||||
-rw-r--r-- | lib/feature.rb | 10 | ||||
-rw-r--r-- | spec/lib/feature_spec.rb | 5 | ||||
-rw-r--r-- | spec/requests/api/features_spec.rb | 34 |
6 files changed, 53 insertions, 5 deletions
diff --git a/changelogs/unreleased/jej-feature-gates-can-be-set-by-group-path.yml b/changelogs/unreleased/jej-feature-gates-can-be-set-by-group-path.yml new file mode 100644 index 00000000000..ba882112f70 --- /dev/null +++ b/changelogs/unreleased/jej-feature-gates-can-be-set-by-group-path.yml @@ -0,0 +1,5 @@ +--- +title: Allow setting feature flags per GitLab group through the API +merge_request: 25022 +author: +type: added diff --git a/doc/api/features.md b/doc/api/features.md index 47f104e1f20..6ecd4ec14b9 100644 --- a/doc/api/features.md +++ b/doc/api/features.md @@ -60,10 +60,11 @@ POST /features/:name | `value` | integer/string | yes | `true` or `false` to enable/disable, or an integer for percentage of time | | `feature_group` | string | no | A Feature group name | | `user` | string | no | A GitLab username | +| `group` | string | no | A GitLab group's path, for example 'gitlab-org' | | `project` | string | no | A projects path, for example 'gitlab-org/gitlab-ce' | Note that you can enable or disable a feature for a `feature_group`, a `user`, -and a `project` in a single API call. +a `group`, and a `project` in a single API call. ```bash curl --data "value=30" --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/features/new_library diff --git a/lib/api/features.rb b/lib/api/features.rb index 835aac05905..4dc1834c644 100644 --- a/lib/api/features.rb +++ b/lib/api/features.rb @@ -42,6 +42,7 @@ module API 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 :user, type: String, desc: 'A GitLab username' + optional :group, type: String, desc: "A GitLab group's path, such as 'gitlab-org'" optional :project, type: String, desc: 'A projects path, like gitlab-org/gitlab-ce' end post ':name' do diff --git a/lib/feature.rb b/lib/feature.rb index e59cd70f822..749c861d740 100644 --- a/lib/feature.rb +++ b/lib/feature.rb @@ -111,11 +111,11 @@ class Feature end def gate_specified? - %i(user project feature_group).any? { |key| params.key?(key) } + %i(user project group feature_group).any? { |key| params.key?(key) } end def targets - [feature_group, user, project].compact + [feature_group, user, project, group].compact end private @@ -139,5 +139,11 @@ class Feature Project.find_by_full_path(params[:project]) end + + def group + return unless params.key?(:group) + + Group.find_by_full_path(params[:group]) + end end end diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb index 630732614b2..a7163048370 100644 --- a/spec/lib/feature_spec.rb +++ b/spec/lib/feature_spec.rb @@ -186,13 +186,14 @@ describe Feature do describe Feature::Target do describe '#targets' do let(:project) { create(:project) } + let(:group) { create(:group) } let(:user_name) { project.owner.username } - subject { described_class.new(user: user_name, project: project.full_path) } + subject { described_class.new(user: user_name, project: project.full_path, group: group.full_path) } it 'returns all found targets' do expect(subject.targets).to be_an(Array) - expect(subject.targets).to eq([project.owner, project]) + expect(subject.targets).to eq([project.owner, project, group]) end end end diff --git a/spec/requests/api/features_spec.rb b/spec/requests/api/features_spec.rb index 22a9e36ca31..57a57e69a00 100644 --- a/spec/requests/api/features_spec.rb +++ b/spec/requests/api/features_spec.rb @@ -163,6 +163,40 @@ describe API::Features do end end + context 'when enabling for a group by path' do + context 'when the group exists' do + it 'sets the feature gate' do + group = create(:group) + + post api("/features/#{feature_name}", admin), params: { value: 'true', group: group.full_path } + + expect(response).to have_gitlab_http_status(201) + expect(json_response).to eq( + 'name' => 'my_feature', + 'state' => 'conditional', + 'gates' => [ + { 'key' => 'boolean', 'value' => false }, + { 'key' => 'actors', 'value' => ["Group:#{group.id}"] } + ]) + end + end + + context 'when the group does not exist' do + it 'sets no new values and keeps the feature disabled' do + post api("/features/#{feature_name}", admin), params: { value: 'true', group: 'not/a/group' } + + expect(response).to have_gitlab_http_status(201) + expect(json_response).to eq( + "name" => "my_feature", + "state" => "off", + "gates" => [ + { "key" => "boolean", "value" => false } + ] + ) + end + end + end + it 'creates a feature with the given percentage if passed an integer' do post api("/features/#{feature_name}", admin), params: { value: '50' } |