summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Edwards-Jones <jedwardsjones@gitlab.com>2019-02-07 20:27:03 +0000
committerJames Edwards-Jones <jedwardsjones@gitlab.com>2019-02-19 14:57:03 +0800
commit46f66c7f0aa5ddf2f8d996880936d88e6977f6c0 (patch)
tree92b9eea7e05202549d8fb47ac014930dc3a6acdd
parent82423ac34ac90e3ff3443495a14af0105feff67d (diff)
downloadgitlab-ce-46f66c7f0aa5ddf2f8d996880936d88e6977f6c0.tar.gz
Allow setting feature flags per GitLab group
Building on support for setting feature flags by project, this adds support for setting them by GitLab group path. This is different from setting them by Flipper feature_groups, which are for batch updating pre-registered collections.
-rw-r--r--changelogs/unreleased/jej-feature-gates-can-be-set-by-group-path.yml5
-rw-r--r--doc/api/features.md3
-rw-r--r--lib/api/features.rb1
-rw-r--r--lib/feature.rb10
-rw-r--r--spec/lib/feature_spec.rb5
-rw-r--r--spec/requests/api/features_spec.rb34
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' }