Commit 149fdb79 authored by Robert Speicher's avatar Robert Speicher

Merge branch 'jj-update-experiments-api' into 'master'

Use feature definitions for experiments api

See merge request gitlab-org/gitlab!56900
parents 46cadb70 7ff22cb0
......@@ -11,9 +11,7 @@ module API
success EE::API::Entities::Experiment
end
get do
experiments = Gitlab::Experimentation::EXPERIMENTS.keys.map do |experiment_key|
{ key: experiment_key, enabled: Gitlab::Experimentation.active?(experiment_key) }
end
experiments = Feature::Definition.definitions.values.select { |d| d.attributes[:type] == 'experiment' }
present experiments, with: EE::API::Entities::Experiment, current_user: current_user
end
......
......@@ -3,9 +3,24 @@
module EE
module API
module Entities
class Experiment < Grape::Entity
expose :key
expose :enabled
class Experiment < ::API::Entities::Feature::Definition
expose :key do |definition|
definition.attributes[:name].gsub(/_experiment_percentage$/, '')
end
expose :enabled do |definition|
feature(definition).state != :off
end
expose :state do |definition|
feature(definition).state
end
private
def feature(definition)
@feature ||= ::Feature.get(definition.attributes[:name]) # rubocop:disable Gitlab/AvoidFeatureGet
end
end
end
end
......
......@@ -3,12 +3,49 @@
require 'spec_helper'
RSpec.describe EE::API::Entities::Experiment do
describe '#as_json' do
let(:experiment) { { key: 'experiment_1', enabled: true } }
let(:entity) { described_class.new(experiment) }
let(:experiment) { Feature::Definition.get(:null_hypothesis) }
let(:entity) { described_class.new(experiment) }
subject { entity.as_json }
subject { entity.as_json }
it { is_expected.to match({ key: experiment[:key], enabled: experiment[:enabled] }) }
it do
is_expected.to match(
key: "null_hypothesis",
state: :off,
enabled: false,
name: "null_hypothesis",
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45840",
rollout_issue_url: nil,
milestone: "13.7",
type: "experiment",
group: "group::adoption",
default_enabled: false
)
end
it "understands conditional state and what that means" do
Feature.enable_percentage_of_time(:null_hypothesis, 1)
expect(subject).to include(
state: :conditional,
enabled: true
)
end
it "understands state and what that means for if its enabled or not" do
Feature.enable_percentage_of_time(:null_hypothesis, 100)
expect(subject).to include(
state: :on,
enabled: true
)
end
it "truncates the name since some experiments include extra data in their feature flag name" do
experiment.attributes[:name] = 'foo_experiment_percentage'
expect(subject).to include(
key: 'foo'
)
end
end
......@@ -6,26 +6,21 @@ RSpec.describe API::Experiments do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group, name: 'GitLab.com', path: 'gitlab-com') }
let(:definition_yaml) { Rails.root.join('config', 'feature_flags', 'experiment', 'null_hypothesis.yml') }
describe 'GET /experiments' do
context 'when on .com' do
let(:experiments) do
{
experiment_1: {
tracking_category: 'something'
},
experiment_2: {
tracking_category: 'something_else'
}
}
end
before do
skip_feature_flags_yaml_validation
skip_default_enabled_yaml_check
stub_const('Gitlab::Experimentation::EXPERIMENTS', experiments)
Feature.enable_percentage_of_time('experiment_1_experiment_percentage', 10)
Feature.disable('experiment_2_experiment_percentage')
allow(Gitlab).to receive(:com?).and_return(true)
definition = YAML.load_file(definition_yaml).deep_symbolize_keys!
allow(Feature::Definition.definitions).to receive(:values).and_return([
Feature::Definition.new(definition_yaml.to_s, definition),
Feature::Definition.new(
"foo/non_experiment.yml",
definition.merge(type: 'development', name: 'non_experiment')
)
])
end
it 'returns a 401 for anonymous users' do
......@@ -49,23 +44,41 @@ RSpec.describe API::Experiments do
expect(response).to have_gitlab_http_status(:forbidden)
end
it 'returns the feature list for gitlab team members' do
expected_experiments = [
{
'key' => 'experiment_1',
'enabled' => true
},
{
'key' => 'experiment_2',
'enabled' => false
}
]
group.add_developer(user)
get api('/experiments', user)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to match_array(expected_experiments)
context 'for gitlab team members' do
before do
group.add_developer(user)
end
it 'returns the feature flag details' do
get api('/experiments', user)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to include({
key: "null_hypothesis",
state: :off,
enabled: false,
name: "null_hypothesis",
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45840",
rollout_issue_url: nil,
milestone: "13.7",
type: "experiment",
group: "group::adoption",
default_enabled: false
}.as_json)
end
it 'understands the state of the feature flag and what that means for an experiment' do
Feature.enable_percentage_of_actors(:null_hypothesis, 1)
get api('/experiments', user)
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to include(hash_including({
state: :conditional,
enabled: true,
name: "null_hypothesis"
}.as_json))
end
end
end
......
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