gitlab-experiment 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83f13c3f8259c739163ada749acee80ecbfb48f1b94f66a4cd69e265c29df874
4
- data.tar.gz: e70fca76e1af2f6234d888473a31cdf088bf44d0bb5dc13dbf84f40e781076bd
3
+ metadata.gz: c92b7e2d77e534a23b8233f11539fa9c2767b21adab9c247e916933724dd7f5d
4
+ data.tar.gz: 7a1144676a16835f64eaefb9ea7bac2b7055c5cf8e329d55dba6c115be17eb50
5
5
  SHA512:
6
- metadata.gz: 9d0964f78bfea29586c176cf001a335df04618e62dfd1a76952d5d12d643de6970d8eeec063b1a28255fabfad8a3fd2b47df233cea6d071b46d98d7867b97185
7
- data.tar.gz: 172778e34c61ffe02f3d11e5538beef44ddd0f8c5e2f6029a449904264eb1365f2f013aad25648e3c1ee0fd19a015aa69a6e62de9867f87c339f8c36e4d14776
6
+ metadata.gz: b7a645b7d2c3cf13d7031fc61dfdaef2626d0092661093a19ff5e21d346adda8cbe031b5c360de21fda3ecee828eaa7bda0a6afe839b6c5ce7ba57f9e10232eb
7
+ data.tar.gz: 1a8e4672a903746f5f31f2cf5dcf815bb6e2c3cb8c8fa73430c93462977310fcd6ed2f6f8676d5e2ccf856289c6befde6469e9f29715341c4bde7fd0b14fa51b
@@ -51,7 +51,7 @@ Gitlab::Experiment.configure do |config|
51
51
  # :percent (recommended), :round_robin, or :random
52
52
  config.default_rollout = :percent, {
53
53
  include_control: true # include control in possible assignments
54
- )
54
+ }
55
55
 
56
56
  # Secret seed used in generating context keys.
57
57
  #
@@ -78,79 +78,33 @@ module Gitlab
78
78
 
79
79
  alias_method :to_param, :id
80
80
 
81
- def variant_names
82
- @_variant_names ||= behaviors.keys.map(&:to_sym) - [:control]
83
- end
81
+ def process_redirect_url(url)
82
+ return unless Configuration.redirect_url_validator&.call(url)
84
83
 
85
- def behaviors
86
- @_behaviors ||= public_behaviors_with_deprecations(registered_behavior_callbacks)
84
+ track('visited', url: url)
85
+ url # return the url, which allows for mutation
87
86
  end
88
87
 
89
- # @deprecated
90
- def public_behaviors_with_deprecations(behaviors)
91
- named_variants = %w[control candidate]
92
- public_methods.each_with_object(behaviors) do |name, behaviors|
93
- name = name.to_s # fixes compatibility for ruby 2.6.x
94
- next unless name.end_with?('_behavior')
95
-
96
- behavior_name = name.sub(/_behavior$/, '')
97
- registration = named_variants.include?(behavior_name) ? behavior_name : "variant :#{behavior_name}"
98
-
99
- Configuration.deprecated(<<~MESSAGE, version: '0.7.0', stack: 2)
100
- using a public `#{name}` method is deprecated and will be removed from {{release}}, instead register variants using:
101
-
102
- class #{self.class.name} < #{Configuration.base_class}
103
- #{registration}
88
+ def key_for(source, seed = name)
89
+ return source if source.is_a?(String)
104
90
 
105
- private
91
+ source = source.keys + source.values if source.is_a?(Hash)
106
92
 
107
- def #{name}
108
- #...
109
- end
110
- end
111
- MESSAGE
112
-
113
- behaviors[behavior_name] ||= -> { send(name) } # rubocop:disable GitlabSecurity/PublicSend
114
- end
115
- end
93
+ ingredients = Array(source).map { |v| identify(v) }
94
+ ingredients.unshift(seed).unshift(Configuration.context_key_secret)
116
95
 
117
- # @deprecated
118
- def session_id
119
- Configuration.deprecated(:session_id, 'instead use `id` or use a custom rollout strategy', version: '0.7.0')
120
- id
96
+ Digest::SHA2.new(Configuration.context_key_bit_length).hexdigest(ingredients.join('|')) # rubocop:disable Fips/OpenSSL
121
97
  end
122
98
 
123
99
  # @deprecated
124
- def flipper_id
125
- Configuration.deprecated(:flipper_id, 'instead use `id` or use a custom rollout strategy', version: '0.7.0')
126
- "Experiment;#{id}"
127
- end
128
-
129
- # @deprecated
130
- def use(&block)
131
- Configuration.deprecated(:use, 'instead use `control`', version: '0.7.0')
132
-
133
- control(&block)
134
- end
135
-
136
- # @deprecated
137
- def try(name = nil, &block)
138
- if name.present?
139
- Configuration.deprecated(:try, "instead use `variant(:#{name})`", version: '0.7.0')
140
- variant(name, &block)
141
- else
142
- Configuration.deprecated(:try, 'instead use `candidate`', version: '0.7.0')
143
- candidate(&block)
144
- end
145
- end
146
-
147
- protected
148
-
149
- def cached_variant_resolver(provided_variant)
150
- return :control if excluded?
100
+ def variant_names
101
+ Configuration.deprecated(
102
+ :variant_names,
103
+ 'instead use `behavior.names`, which includes :control',
104
+ version: '0.8.0'
105
+ )
151
106
 
152
- result = cache_variant(provided_variant) { resolve_variant_name }
153
- result.to_sym if result.present?
107
+ behaviors.keys - [:control]
154
108
  end
155
109
  end
156
110
  end
@@ -49,7 +49,7 @@ module Gitlab
49
49
  result = migrated_cache_fetch(cache.store, &block)
50
50
  return result unless specified.present?
51
51
 
52
- cache.write(specified) if result != specified
52
+ cache.write(specified) if result.to_s != specified.to_s
53
53
  specified
54
54
  end
55
55
 
@@ -47,14 +47,14 @@ module Gitlab
47
47
  private
48
48
 
49
49
  def build_behavior_callback(filters, variant, **options, &block)
50
- if registered_behavior_callbacks[variant.to_s]
50
+ if registered_behavior_callbacks[variant]
51
51
  raise ExistingBehaviorError, "a behavior for the `#{variant}` variant has already been registered"
52
52
  end
53
53
 
54
54
  callback_behavior = "#{variant}_behavior".to_sym
55
55
 
56
56
  # Register a the behavior so we can define the block later.
57
- registered_behavior_callbacks[variant.to_s] = callback_behavior
57
+ registered_behavior_callbacks[variant] = callback_behavior
58
58
 
59
59
  # Add our block or default behavior method.
60
60
  filters.push(block) if block.present?
@@ -57,7 +57,7 @@ module Gitlab
57
57
  #
58
58
  # Included rollout strategies:
59
59
  # :percent, (recommended), :round_robin, or :random
60
- @default_rollout = Rollout.resolve(:percent, include_control: true)
60
+ @default_rollout = Rollout.resolve(:percent)
61
61
 
62
62
  # Secret seed used in generating context keys.
63
63
  #
@@ -165,61 +165,6 @@ module Gitlab
165
165
  end
166
166
 
167
167
  class << self
168
- # @deprecated
169
- def context_hash_strategy=(block)
170
- deprecated(
171
- :context_hash_strategy,
172
- 'instead use `context_key_secret` and `context_key_bit_length`',
173
- version: '0.7.0'
174
- )
175
-
176
- @__context_hash_strategy = block
177
- end
178
-
179
- # @deprecated
180
- def variant_resolver
181
- deprecated(
182
- :variant_resolver,
183
- 'instead use `inclusion_resolver` with a block that returns a boolean',
184
- version: '0.6.5'
185
- )
186
-
187
- @__inclusion_resolver
188
- end
189
-
190
- # @deprecated
191
- def variant_resolver=(block)
192
- deprecated(
193
- :variant_resolver,
194
- 'instead use `inclusion_resolver` with a block that returns a boolean',
195
- version: '0.6.5'
196
- )
197
-
198
- @__inclusion_resolver = block
199
- end
200
-
201
- # @deprecated
202
- def inclusion_resolver=(block)
203
- deprecated(
204
- :inclusion_resolver,
205
- 'instead put this logic into custom rollout strategies',
206
- version: '0.7.0'
207
- )
208
-
209
- @__inclusion_resolver = block
210
- end
211
-
212
- # @deprecated
213
- def inclusion_resolver
214
- deprecated(
215
- :inclusion_resolver,
216
- 'instead put this logic into custom rollout strategies',
217
- version: '0.7.0'
218
- )
219
-
220
- @__inclusion_resolver
221
- end
222
-
223
168
  attr_accessor(
224
169
  :name_prefix,
225
170
  :logger,
@@ -240,17 +185,7 @@ module Gitlab
240
185
  # Attribute method overrides.
241
186
 
242
187
  def default_rollout=(args) # rubocop:disable Lint/DuplicateMethods
243
- rollout, options = Array(args)
244
- if rollout.is_a?(Rollout::Base)
245
- options = rollout.options
246
- rollout = rollout.class
247
-
248
- deprecated(<<~MESSAGE, version: '0.7.0')
249
- using a rollout instance with `default_rollout` is deprecated and will be removed from {{release}} (instead use `default_rollout = #{rollout.name}, #{options.inspect}`)
250
- MESSAGE
251
- end
252
-
253
- @default_rollout = Rollout.resolve(rollout, options || {})
188
+ @default_rollout = Rollout.resolve(*args)
254
189
  end
255
190
 
256
191
  # Internal warning helpers.
@@ -21,6 +21,7 @@ module Gitlab
21
21
  private
22
22
 
23
23
  def include_dsl
24
+ Dsl.include_in(ActionController::API, with_helper: false) if defined?(ActionController)
24
25
  Dsl.include_in(ActionController::Base, with_helper: true) if defined?(ActionController)
25
26
  Dsl.include_in(ActionMailer::Base, with_helper: true) if defined?(ActionMailer)
26
27
  end
@@ -36,7 +36,7 @@ module Gitlab
36
36
  when nil then nil
37
37
  when Array, Hash
38
38
  if distribution_rules.length != behavior_names.length
39
- raise InvalidRolloutRules, "the distribution rules don't match the number of variants defined"
39
+ raise InvalidRolloutRules, "the distribution rules don't match the number of behaviors defined"
40
40
  end
41
41
  else
42
42
  raise InvalidRolloutRules, 'unknown distribution options type'
@@ -8,6 +8,7 @@ module Gitlab
8
8
  autoload :RoundRobin, 'gitlab/experiment/rollout/round_robin.rb'
9
9
 
10
10
  def self.resolve(klass, options = {})
11
+ options ||= {}
11
12
  case klass
12
13
  when String
13
14
  Strategy.new(klass.classify.constantize, options)
@@ -21,44 +22,29 @@ module Gitlab
21
22
  end
22
23
 
23
24
  class Base
24
- DEFAULT_OPTIONS = {
25
- include_control: false
26
- }.freeze
27
-
28
25
  attr_reader :experiment, :options
29
26
 
30
- delegate :variant_names, :cache, :id, to: :experiment
31
-
32
- def initialize(options = {})
33
- @options = DEFAULT_OPTIONS.merge(options)
34
- end
27
+ delegate :cache, :id, to: :experiment
35
28
 
36
- def for(experiment)
29
+ def initialize(experiment, options = {})
37
30
  raise ArgumentError, 'you must provide an experiment instance' unless experiment.class <= Gitlab::Experiment
38
31
 
39
32
  @experiment = experiment
40
-
41
- self
33
+ @options = options
42
34
  end
43
35
 
44
36
  def enabled?
45
- require_experiment(__method__)
46
-
47
37
  true
48
38
  end
49
39
 
50
40
  def resolve
51
- require_experiment(__method__)
52
-
53
- return nil if @experiment.respond_to?(:experiment_group?) && !@experiment.experiment_group?
54
-
55
41
  validate! # allow the rollout strategy to validate itself
56
42
 
57
43
  assignment = execute_assignment
58
- assignment == :control ? nil : assignment # avoid caching control
44
+ assignment == :control ? nil : assignment # avoid caching control by returning nil
59
45
  end
60
46
 
61
- protected
47
+ private
62
48
 
63
49
  def validate!
64
50
  # base is always valid
@@ -68,22 +54,14 @@ module Gitlab
68
54
  behavior_names.first
69
55
  end
70
56
 
71
- private
72
-
73
- def require_experiment(method_name)
74
- return if @experiment.present?
75
-
76
- raise ArgumentError, "you need to call `for` with an experiment instance before chaining `#{method_name}`"
77
- end
78
-
79
57
  def behavior_names
80
- options[:include_control] ? [:control] + variant_names : variant_names
58
+ experiment.behaviors.keys
81
59
  end
82
60
  end
83
61
 
84
62
  Strategy = Struct.new(:klass, :options) do
85
63
  def for(experiment)
86
- klass.new(options).for(experiment)
64
+ klass.new(experiment, options)
87
65
  end
88
66
  end
89
67
  end
@@ -14,13 +14,13 @@ module Gitlab
14
14
  def self.track_gitlab_experiment_receiver(method, receiver)
15
15
  # Leverage the `>=` method on Gitlab::Experiment to determine if the receiver is an experiment, not the other
16
16
  # way round -- `receiver.<=` could be mocked and we want to be extra careful.
17
- (@__gitlab_experiment_receivers[method.to_s] ||= []) << receiver if Gitlab::Experiment >= receiver
17
+ (@__gitlab_experiment_receivers[method] ||= []) << receiver if Gitlab::Experiment >= receiver
18
18
  rescue StandardError # again, let's just be extra careful
19
19
  false
20
20
  end
21
21
 
22
22
  def self.bind_gitlab_experiment_receiver(method)
23
- method.unbind.bind(@__gitlab_experiment_receivers[method.to_s].pop)
23
+ method.unbind.bind(@__gitlab_experiment_receivers[method].pop)
24
24
  end
25
25
 
26
26
  module MethodDouble
@@ -28,6 +28,7 @@ module Gitlab
28
28
  RSpecMocks.track_gitlab_experiment_receiver(original_method, receiver)
29
29
  super
30
30
  end
31
+ ruby2_keywords :proxy_method_invoked if respond_to?(:ruby2_keywords, true)
31
32
  end
32
33
  end
33
34
 
@@ -37,9 +38,6 @@ module Gitlab
37
38
  wrapped_experiment(experiment, remock: true) do |instance, wrapped|
38
39
  # Stub internal methods that will make it behave as we've instructed.
39
40
  allow(instance).to receive(:enabled?) { wrapped.variant_name != false }
40
- if instance.respond_to?(:experiment_group?, true)
41
- allow(instance).to receive(:experiment_group?) { !(wrapped.variant_name == false) }
42
- end
43
41
 
44
42
  # Stub the variant resolution logic to handle true/false, and named variants.
45
43
  allow(instance).to receive(:resolve_variant_name).and_wrap_original { |method|
@@ -72,8 +70,8 @@ module Gitlab
72
70
  def wrapped_experiment_chain_for(klass)
73
71
  @__wrapped_experiment_chains ||= {}
74
72
  @__wrapped_experiment_chains[klass.name || klass.object_id] ||= begin
75
- allow(klass).to receive(:new).and_wrap_original do |method, *args, &original_block|
76
- RSpecMocks.bind_gitlab_experiment_receiver(method).call(*args).tap do |instance|
73
+ allow(klass).to receive(:new).and_wrap_original do |method, *args, **kwargs, &original_block|
74
+ RSpecMocks.bind_gitlab_experiment_receiver(method).call(*args, **kwargs).tap do |instance|
77
75
  wrapped = @__wrapped_experiments[instance.instance_variable_get(:@_name)]
78
76
  wrapped&.blocks&.each { |b| b.call(instance, wrapped) }
79
77
 
@@ -128,7 +126,7 @@ module Gitlab
128
126
  match do |experiment|
129
127
  @experiment = require_experiment(experiment, 'register_behavior')
130
128
 
131
- block = @experiment.behaviors[behavior_name.to_s]
129
+ block = @experiment.behaviors[behavior_name]
132
130
  @return_expected = false unless block
133
131
 
134
132
  if @return_expected
@@ -193,13 +191,13 @@ module Gitlab
193
191
  @experiment.run_callbacks(:segmentation)
194
192
 
195
193
  @actual_variant = @experiment.instance_variable_get(:@_assigned_variant_name)
196
- @expected_variant ? @actual_variant.to_s == @expected_variant.to_s : @actual_variant.present?
194
+ @expected_variant ? @actual_variant == @expected_variant : @actual_variant.present?
197
195
  end
198
196
 
199
197
  chain :into do |expected|
200
198
  raise ArgumentError, 'variant name must be provided' if expected.blank?
201
199
 
202
- @expected_variant = expected.to_s
200
+ @expected_variant = expected
203
201
  end
204
202
 
205
203
  failure_message do
@@ -239,7 +237,7 @@ module Gitlab
239
237
  chain(:for) do |expected|
240
238
  raise ArgumentError, 'variant name must be provided' if expected.blank?
241
239
 
242
- @expected_variant = expected.to_s
240
+ @expected_variant = expected
243
241
  end
244
242
 
245
243
  chain(:with_context) do |expected|
@@ -303,17 +301,16 @@ RSpec.configure do |config|
303
301
  config.include Gitlab::Experiment::RSpecHelpers
304
302
  config.include Gitlab::Experiment::Dsl
305
303
 
306
- clear_cache = proc do
307
- RequestStore.clear!
304
+ config.before(:each) do |example|
305
+ if example.metadata[:experiment] == true || example.metadata[:type] == :experiment
306
+ RequestStore.clear!
308
307
 
309
- if defined?(Gitlab::Experiment::TestBehaviors::TrackedStructure)
310
- Gitlab::Experiment::TestBehaviors::TrackedStructure.reset!
308
+ if defined?(Gitlab::Experiment::TestBehaviors::TrackedStructure)
309
+ Gitlab::Experiment::TestBehaviors::TrackedStructure.reset!
310
+ end
311
311
  end
312
312
  end
313
313
 
314
- config.before(:each, :experiment, &clear_cache)
315
- config.before(:each, type: :experiment, &clear_cache)
316
-
317
314
  config.include Gitlab::Experiment::RSpecMatchers, :experiment
318
315
  config.include Gitlab::Experiment::RSpecMatchers, type: :experiment
319
316
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  class Experiment
5
- VERSION = '0.7.1'
5
+ VERSION = '0.8.0'
6
6
  end
7
7
  end
@@ -3,6 +3,7 @@
3
3
  require 'request_store'
4
4
  require 'active_support'
5
5
  require 'active_support/core_ext/module/delegation'
6
+ require 'active_support/core_ext/object/blank'
6
7
  require 'active_support/core_ext/string/inflections'
7
8
 
8
9
  require 'gitlab/experiment/errors'
@@ -87,34 +88,15 @@ module Gitlab
87
88
  variant(:control, &block)
88
89
  end
89
90
 
90
- def candidate(name = nil, &block)
91
- if name.present?
92
- Configuration.deprecated(<<~MESSAGE, version: '0.7.0')
93
- passing name to `candidate` is deprecated and will be removed from {{release}} (instead use `variant(#{name.inspect})`)
94
- MESSAGE
95
- end
96
-
97
- variant(name || :candidate, &block)
91
+ def candidate(&block)
92
+ variant(:candidate, &block)
98
93
  end
99
94
 
100
- def variant(name = nil, &block)
101
- if block.present? # we know we're defining a variant block
102
- raise ArgumentError, 'missing variant name' if name.blank?
103
-
104
- return behaviors[name.to_s] = block
105
- end
106
-
107
- if name.present?
108
- Configuration.deprecated(<<~MESSAGE, version: '0.7.0')
109
- setting the variant using `variant` is deprecated and will be removed from {{release}} (instead use `assigned(#{name.inspect})`)
110
- MESSAGE
111
- else
112
- Configuration.deprecated(<<~MESSAGE, version: '0.7.0')
113
- getting the assigned variant using `variant` is deprecated and will be removed from {{release}} (instead use `assigned`)
114
- MESSAGE
115
- end
95
+ def variant(name, &block)
96
+ raise ArgumentError, 'name required' if name.blank?
97
+ raise ArgumentError, 'block required' unless block.present?
116
98
 
117
- assigned(name)
99
+ behaviors[name] = block
118
100
  end
119
101
 
120
102
  def context(value = nil)
@@ -126,9 +108,7 @@ module Gitlab
126
108
 
127
109
  def assigned(value = nil)
128
110
  @_assigned_variant_name = cache_variant(value) if value.present?
129
- if @_assigned_variant_name || @_resolving_variant
130
- return Variant.new(name: (@_assigned_variant_name || :unresolved).to_s)
131
- end
111
+ return Variant.new(name: @_assigned_variant_name || :unresolved) if @_assigned_variant_name || @_resolving_variant
132
112
 
133
113
  if enabled?
134
114
  @_resolving_variant = true
@@ -137,7 +117,7 @@ module Gitlab
137
117
 
138
118
  run_callbacks(segmentation_callback_chain) do
139
119
  @_assigned_variant_name ||= :control
140
- Variant.new(name: @_assigned_variant_name.to_s)
120
+ Variant.new(name: @_assigned_variant_name)
141
121
  end
142
122
  ensure
143
123
  @_resolving_variant = false
@@ -171,13 +151,6 @@ module Gitlab
171
151
  instance_exec(action, tracking_context(event_args).try(:compact) || {}, &Configuration.tracking_behavior)
172
152
  end
173
153
 
174
- def process_redirect_url(url)
175
- return unless Configuration.redirect_url_validator&.call(url)
176
-
177
- track('visited', url: url)
178
- url # return the url, which allows for mutation
179
- end
180
-
181
154
  def enabled?
182
155
  rollout.enabled?
183
156
  end
@@ -193,23 +166,11 @@ module Gitlab
193
166
  end
194
167
 
195
168
  def signature
196
- { variant: assigned.name, experiment: name }.merge(context.signature)
169
+ { variant: assigned.name.to_s, experiment: name }.merge(context.signature)
197
170
  end
198
171
 
199
- def key_for(source, seed = name)
200
- # TODO: Remove - deprecated in release 0.7.0
201
- if (block = Configuration.instance_variable_get(:@__context_hash_strategy))
202
- return instance_exec(source, seed, &block)
203
- end
204
-
205
- return source if source.is_a?(String)
206
-
207
- source = source.keys + source.values if source.is_a?(Hash)
208
-
209
- ingredients = Array(source).map { |v| identify(v) }
210
- ingredients.unshift(seed).unshift(Configuration.context_key_secret)
211
-
212
- Digest::SHA2.new(Configuration.context_key_bit_length).hexdigest(ingredients.join('|'))
172
+ def behaviors
173
+ @_behaviors ||= registered_behavior_callbacks
213
174
  end
214
175
 
215
176
  protected
@@ -218,23 +179,15 @@ module Gitlab
218
179
  (object.respond_to?(:to_global_id) ? object.to_global_id : object).to_s
219
180
  end
220
181
 
182
+ def cached_variant_resolver(provided_variant)
183
+ return :control if excluded?
184
+
185
+ result = cache_variant(provided_variant) { resolve_variant_name }
186
+ result.to_sym if result.present?
187
+ end
188
+
221
189
  def resolve_variant_name
222
- if respond_to?(:experiment_group?, true)
223
- # TODO: Remove - deprecated in release 0.7.0
224
- Configuration.deprecated(:experiment_group?, <<~MESSAGE, version: '0.7.0')
225
- instead put this logic into custom rollout strategies
226
- MESSAGE
227
-
228
- rollout.resolve if experiment_group?
229
- elsif (block = Configuration.instance_variable_get(:@__inclusion_resolver))
230
- # TODO: Remove - deprecated in release 0.7.0
231
- rollout.resolve if instance_exec(@_assigned_variant_name, &block)
232
- elsif (block = Configuration.instance_variable_get(:@__variant_resolver))
233
- # TODO: Remove - deprecated in release 0.6.5
234
- instance_exec(@_assigned_variant_name, &block)
235
- else
236
- rollout.resolve # this is the end result of all deprecations
237
- end
190
+ rollout.resolve
238
191
  end
239
192
 
240
193
  def tracking_context(event_args)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-experiment
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date:
11
+ date: 2023-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -38,68 +38,52 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.0'
41
- description:
41
+ description:
42
42
  email:
43
43
  - gitlab_rubygems@gitlab.com
44
44
  executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
- - lib/generators/gitlab
49
- - lib/generators/gitlab/experiment
50
- - lib/generators/gitlab/experiment/install
48
+ - LICENSE.txt
49
+ - README.md
50
+ - lib/generators/gitlab/experiment/USAGE
51
+ - lib/generators/gitlab/experiment/experiment_generator.rb
51
52
  - lib/generators/gitlab/experiment/install/install_generator.rb
52
- - lib/generators/gitlab/experiment/install/templates
53
+ - lib/generators/gitlab/experiment/install/templates/POST_INSTALL
53
54
  - lib/generators/gitlab/experiment/install/templates/application_experiment.rb.tt
54
55
  - lib/generators/gitlab/experiment/install/templates/initializer.rb.tt
55
- - lib/generators/gitlab/experiment/install/templates/POST_INSTALL
56
- - lib/generators/gitlab/experiment/USAGE
57
- - lib/generators/gitlab/experiment/experiment_generator.rb
58
- - lib/generators/gitlab/experiment/templates
59
56
  - lib/generators/gitlab/experiment/templates/experiment.rb.tt
60
- - lib/generators/test_unit
61
- - lib/generators/test_unit/experiment
62
- - lib/generators/test_unit/experiment/experiment_generator.rb
63
- - lib/generators/test_unit/experiment/templates
64
- - lib/generators/test_unit/experiment/templates/experiment_test.rb.tt
65
- - lib/generators/rspec
66
- - lib/generators/rspec/experiment
67
57
  - lib/generators/rspec/experiment/experiment_generator.rb
68
- - lib/generators/rspec/experiment/templates
69
58
  - lib/generators/rspec/experiment/templates/experiment_spec.rb.tt
59
+ - lib/generators/test_unit/experiment/experiment_generator.rb
60
+ - lib/generators/test_unit/experiment/templates/experiment_test.rb.tt
70
61
  - lib/gitlab/experiment.rb
71
- - lib/gitlab/experiment
72
- - lib/gitlab/experiment/variant.rb
73
- - lib/gitlab/experiment/middleware.rb
74
- - lib/gitlab/experiment/test_behaviors
75
- - lib/gitlab/experiment/test_behaviors/trackable.rb
76
- - lib/gitlab/experiment/cache
62
+ - lib/gitlab/experiment/base_interface.rb
63
+ - lib/gitlab/experiment/cache.rb
77
64
  - lib/gitlab/experiment/cache/redis_hash_store.rb
78
- - lib/gitlab/experiment/errors.rb
79
65
  - lib/gitlab/experiment/callbacks.rb
80
- - lib/gitlab/experiment/rollout.rb
81
- - lib/gitlab/experiment/base_interface.rb
82
- - lib/gitlab/experiment/nestable.rb
66
+ - lib/gitlab/experiment/configuration.rb
83
67
  - lib/gitlab/experiment/context.rb
68
+ - lib/gitlab/experiment/cookies.rb
69
+ - lib/gitlab/experiment/dsl.rb
84
70
  - lib/gitlab/experiment/engine.rb
85
- - lib/gitlab/experiment/rspec.rb
86
- - lib/gitlab/experiment/rollout
71
+ - lib/gitlab/experiment/errors.rb
72
+ - lib/gitlab/experiment/middleware.rb
73
+ - lib/gitlab/experiment/nestable.rb
74
+ - lib/gitlab/experiment/rollout.rb
75
+ - lib/gitlab/experiment/rollout/percent.rb
87
76
  - lib/gitlab/experiment/rollout/random.rb
88
77
  - lib/gitlab/experiment/rollout/round_robin.rb
89
- - lib/gitlab/experiment/rollout/percent.rb
90
- - lib/gitlab/experiment/rollout/concerns
91
- - lib/gitlab/experiment/cache.rb
78
+ - lib/gitlab/experiment/rspec.rb
79
+ - lib/gitlab/experiment/test_behaviors/trackable.rb
80
+ - lib/gitlab/experiment/variant.rb
92
81
  - lib/gitlab/experiment/version.rb
93
- - lib/gitlab/experiment/cookies.rb
94
- - lib/gitlab/experiment/configuration.rb
95
- - lib/gitlab/experiment/dsl.rb
96
- - LICENSE.txt
97
- - README.md
98
82
  homepage: https://gitlab.com/gitlab-org/ruby/gems/gitlab-experiment
99
83
  licenses:
100
84
  - MIT
101
85
  metadata: {}
102
- post_install_message:
86
+ post_install_message:
103
87
  rdoc_options: []
104
88
  require_paths:
105
89
  - lib
@@ -114,8 +98,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
98
  - !ruby/object:Gem::Version
115
99
  version: '0'
116
100
  requirements: []
117
- rubygems_version: 3.1.6
118
- signing_key:
101
+ rubygems_version: 3.4.7
102
+ signing_key:
119
103
  specification_version: 4
120
104
  summary: GitLab experimentation library.
121
105
  test_files: []