Commit 46f66c7f authored by James Edwards-Jones's avatar James Edwards-Jones

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.
parent 82423ac3
---
title: Allow setting feature flags per GitLab group through the API
merge_request: 25022
author:
type: added
......@@ -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
......
......@@ -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
......
......@@ -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
......@@ -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
......
......@@ -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' }
......
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