Skip to content

Commit 46f66c7

Browse files
author
James Edwards-Jones
committed
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.
1 parent 82423ac commit 46f66c7

File tree

6 files changed

+53
-5
lines changed

6 files changed

+53
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
title: Allow setting feature flags per GitLab group through the API
3+
merge_request: 25022
4+
author:
5+
type: added

doc/api/features.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,11 @@ POST /features/:name
6060
| `value` | integer/string | yes | `true` or `false` to enable/disable, or an integer for percentage of time |
6161
| `feature_group` | string | no | A Feature group name |
6262
| `user` | string | no | A GitLab username |
63+
| `group` | string | no | A GitLab group's path, for example 'gitlab-org' |
6364
| `project` | string | no | A projects path, for example 'gitlab-org/gitlab-ce' |
6465

6566
Note that you can enable or disable a feature for a `feature_group`, a `user`,
66-
and a `project` in a single API call.
67+
a `group`, and a `project` in a single API call.
6768

6869
```bash
6970
curl --data "value=30" --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/features/new_library

lib/api/features.rb

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ def gate_specified?(params)
4242
requires :value, type: String, desc: '`true` or `false` to enable/disable, an integer for percentage of time'
4343
optional :feature_group, type: String, desc: 'A Feature group name'
4444
optional :user, type: String, desc: 'A GitLab username'
45+
optional :group, type: String, desc: "A GitLab group's path, such as 'gitlab-org'"
4546
optional :project, type: String, desc: 'A projects path, like gitlab-org/gitlab-ce'
4647
end
4748
post ':name' do

lib/feature.rb

+8-2
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,11 @@ def initialize(params)
111111
end
112112

113113
def gate_specified?
114-
%i(user project feature_group).any? { |key| params.key?(key) }
114+
%i(user project group feature_group).any? { |key| params.key?(key) }
115115
end
116116

117117
def targets
118-
[feature_group, user, project].compact
118+
[feature_group, user, project, group].compact
119119
end
120120

121121
private
@@ -139,5 +139,11 @@ def project
139139

140140
Project.find_by_full_path(params[:project])
141141
end
142+
143+
def group
144+
return unless params.key?(:group)
145+
146+
Group.find_by_full_path(params[:group])
147+
end
142148
end
143149
end

spec/lib/feature_spec.rb

+3-2
Original file line numberDiff line numberDiff line change
@@ -186,13 +186,14 @@
186186
describe Feature::Target do
187187
describe '#targets' do
188188
let(:project) { create(:project) }
189+
let(:group) { create(:group) }
189190
let(:user_name) { project.owner.username }
190191

191-
subject { described_class.new(user: user_name, project: project.full_path) }
192+
subject { described_class.new(user: user_name, project: project.full_path, group: group.full_path) }
192193

193194
it 'returns all found targets' do
194195
expect(subject.targets).to be_an(Array)
195-
expect(subject.targets).to eq([project.owner, project])
196+
expect(subject.targets).to eq([project.owner, project, group])
196197
end
197198
end
198199
end

spec/requests/api/features_spec.rb

+34
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,40 @@
163163
end
164164
end
165165

166+
context 'when enabling for a group by path' do
167+
context 'when the group exists' do
168+
it 'sets the feature gate' do
169+
group = create(:group)
170+
171+
post api("/features/#{feature_name}", admin), params: { value: 'true', group: group.full_path }
172+
173+
expect(response).to have_gitlab_http_status(201)
174+
expect(json_response).to eq(
175+
'name' => 'my_feature',
176+
'state' => 'conditional',
177+
'gates' => [
178+
{ 'key' => 'boolean', 'value' => false },
179+
{ 'key' => 'actors', 'value' => ["Group:#{group.id}"] }
180+
])
181+
end
182+
end
183+
184+
context 'when the group does not exist' do
185+
it 'sets no new values and keeps the feature disabled' do
186+
post api("/features/#{feature_name}", admin), params: { value: 'true', group: 'not/a/group' }
187+
188+
expect(response).to have_gitlab_http_status(201)
189+
expect(json_response).to eq(
190+
"name" => "my_feature",
191+
"state" => "off",
192+
"gates" => [
193+
{ "key" => "boolean", "value" => false }
194+
]
195+
)
196+
end
197+
end
198+
end
199+
166200
it 'creates a feature with the given percentage if passed an integer' do
167201
post api("/features/#{feature_name}", admin), params: { value: '50' }
168202

0 commit comments

Comments
 (0)