diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-01 18:06:28 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-10-01 18:06:28 +0000 |
commit | ed3b1698883bd4ac2c4faf6c05c3a8155748bf91 (patch) | |
tree | e4725e36aaee9141e9ac4da66faf8a19edd74c2a /lib/gitlab/experimentation.rb | |
parent | 05f4b2fb34dbb051b2ce5ddbc801ec42998c019c (diff) | |
download | gitlab-ce-ed3b1698883bd4ac2c4faf6c05c3a8155748bf91.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'lib/gitlab/experimentation.rb')
-rw-r--r-- | lib/gitlab/experimentation.rb | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/lib/gitlab/experimentation.rb b/lib/gitlab/experimentation.rb new file mode 100644 index 00000000000..678d47150e8 --- /dev/null +++ b/lib/gitlab/experimentation.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +# == Experimentation +# +# Utility module used for A/B testing experimental features. Define your experiments in the `EXPERIMENTS` constant. +# The feature_toggle and environment keys are optional. If the feature_toggle is not set, a feature with the name of +# the experiment will be checked, with a default value of true. The enabled_ratio is required and should be +# the ratio for the number of users for which this experiment is enabled. For example: a ratio of 0.1 will +# enable the experiment for 10% of the users (determined by the `experimentation_subject_index`). +# +module Gitlab + module Experimentation + EXPERIMENTS = { + signup_flow: { + feature_toggle: :experimental_separate_sign_up_flow, + environment: ::Gitlab.dev_env_or_com?, + enabled_ratio: 0.1 + } + }.freeze + + # Controller concern that checks if an experimentation_subject_id cookie is present and sets it if absent. + # Used for A/B testing of experimental features. Exposes the `experiment_enabled?(experiment_name)` method + # to controllers and views. + # + module ControllerConcern + extend ActiveSupport::Concern + + included do + before_action :set_experimentation_subject_id_cookie + helper_method :experiment_enabled? + end + + def set_experimentation_subject_id_cookie + return if cookies[:experimentation_subject_id].present? + + cookies.permanent.signed[:experimentation_subject_id] = { + value: SecureRandom.uuid, + domain: :all, + secure: ::Gitlab.config.gitlab.https + } + end + + def experiment_enabled?(experiment) + Experimentation.enabled?(experiment, experimentation_subject_index) + end + + private + + def experimentation_subject_index + experimentation_subject_id = cookies.signed[:experimentation_subject_id] + return if experimentation_subject_id.blank? + + experimentation_subject_id.delete('-').hex % 100 + end + end + + class << self + def enabled?(experiment_key, experimentation_subject_index) + return false unless EXPERIMENTS.key?(experiment_key) + + experiment = Experiment.new(EXPERIMENTS[experiment_key].merge(key: experiment_key)) + + experiment.feature_toggle_enabled? && + experiment.enabled_for_environment? && + experiment.enabled_for_experimentation_subject?(experimentation_subject_index) + end + end + + Experiment = Struct.new(:key, :feature_toggle, :environment, :enabled_ratio, keyword_init: true) do + def feature_toggle_enabled? + return Feature.enabled?(key, default_enabled: true) if feature_toggle.nil? + + Feature.enabled?(feature_toggle) + end + + def enabled_for_environment? + return true if environment.nil? + + environment + end + + def enabled_for_experimentation_subject?(experimentation_subject_index) + return false if enabled_ratio.nil? || experimentation_subject_index.blank? + + experimentation_subject_index <= enabled_ratio * 100 + end + end + end +end |