gitlab-experiment 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []