gitlab-experiment 0.7.0 → 0.7.1

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: b6d54c567ebebd09762fb8bbd93940efb449f99d546a62776889caebedda6387
4
- data.tar.gz: 87a37b577f0545885ce4c2d6db92f750781017c2235b4d89f0f5db977bec045c
3
+ metadata.gz: 83f13c3f8259c739163ada749acee80ecbfb48f1b94f66a4cd69e265c29df874
4
+ data.tar.gz: e70fca76e1af2f6234d888473a31cdf088bf44d0bb5dc13dbf84f40e781076bd
5
5
  SHA512:
6
- metadata.gz: ed428cb380868eb7e94e9a5b4753c7c09dd73656fa66da4bb90fc728b2e2a460cb8d7f24170e783a63c6c28f86d61b00cb99ae9065a3c02999e7518ecc79e2e2
7
- data.tar.gz: 001edc2f533b5a5c210ada04c73a335b51e0e377be05449f0ae86ba9da078655d54e860294dd8a66ea8564270345cbbd145dc789aae1eb7f76f074db1fd79be3
6
+ metadata.gz: 9d0964f78bfea29586c176cf001a335df04618e62dfd1a76952d5d12d643de6970d8eeec063b1a28255fabfad8a3fd2b47df233cea6d071b46d98d7867b97185
7
+ data.tar.gz: 172778e34c61ffe02f3d11e5538beef44ddd0f8c5e2f6029a449904264eb1365f2f013aad25648e3c1ee0fd19a015aa69a6e62de9867f87c339f8c36e4d14776
@@ -48,10 +48,8 @@ Gitlab::Experiment.configure do |config|
48
48
  # end
49
49
  #
50
50
  # Included rollout strategies:
51
- # Gitlab::Experiment::Rollout::Percent, (recommended)
52
- # Gitlab::Experiment::Rollout::RoundRobin, or
53
- # Gitlab::Experiment::Rollout::Random
54
- config.default_rollout = Gitlab::Experiment::Rollout::Percent.new(
51
+ # :percent (recommended), :round_robin, or :random
52
+ config.default_rollout = :percent, {
55
53
  include_control: true # include control in possible assignments
56
54
  )
57
55
 
@@ -132,7 +130,7 @@ Gitlab::Experiment.configure do |config|
132
130
  # level1 initiated by file_name.rb:2
133
131
  # level2 initiated by file_name.rb:3
134
132
  config.nested_behavior = lambda do |nested_experiment|
135
- raise NestingError.new(experiment: self, nested_experiment: nested_experiment)
133
+ raise Gitlab::Experiment::NestingError.new(experiment: self, nested_experiment: nested_experiment)
136
134
  end
137
135
 
138
136
  # Called at the end of every experiment run, with the result.
@@ -66,10 +66,8 @@ module Gitlab
66
66
 
67
67
  store.write(cache_key, value)
68
68
  store.delete(old_key)
69
- return value
70
- end
71
-
72
- store.fetch(cache_key, &block)
69
+ break value
70
+ end || store.fetch(cache_key, &block)
73
71
  end
74
72
  end
75
73
  end
@@ -82,7 +82,7 @@ module Gitlab
82
82
  end
83
83
 
84
84
  def build_run_callback(filters, **options)
85
- set_callback(:run, *filters, **options)
85
+ set_callback(:run, *filters.compact, **options)
86
86
  end
87
87
 
88
88
  def build_callback(chain, *filters, **options)
@@ -56,12 +56,8 @@ module Gitlab
56
56
  # end
57
57
  #
58
58
  # Included rollout strategies:
59
- # Gitlab::Experiment::Rollout::Percent, (recommended)
60
- # Gitlab::Experiment::Rollout::RoundRobin, or
61
- # Gitlab::Experiment::Rollout::Random
62
- @default_rollout = Gitlab::Experiment::Rollout::Percent.new(
63
- include_control: true # include control in possible assignments
64
- )
59
+ # :percent, (recommended), :round_robin, or :random
60
+ @default_rollout = Rollout.resolve(:percent, include_control: true)
65
61
 
66
62
  # Secret seed used in generating context keys.
67
63
  #
@@ -241,7 +237,24 @@ module Gitlab
241
237
  :publishing_behavior
242
238
  )
243
239
 
244
- # Internal helpers warnings.
240
+ # Attribute method overrides.
241
+
242
+ 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 || {})
254
+ end
255
+
256
+ # Internal warning helpers.
257
+
245
258
  def deprecated(*args, version:, stack: 0)
246
259
  deprecator = deprecator(version)
247
260
  args << args.pop.to_s.gsub('{{release}}', "#{deprecator.gem_name} #{deprecator.deprecation_horizon}")
@@ -25,15 +25,25 @@ module Gitlab
25
25
  class Stack
26
26
  include Singleton
27
27
 
28
- @stack = []
28
+ delegate :pop, :length, :size, :[], to: :stack
29
29
 
30
30
  class << self
31
- delegate :pop, :length, :size, :[], to: :@stack
31
+ delegate :pop, :push, :length, :size, :[], to: :instance
32
+ end
33
+
34
+ def initialize
35
+ @thread_key = "#{self.class};#{object_id}".to_sym
36
+ end
37
+
38
+ def push(instance)
39
+ stack.last&.nest_experiment(instance)
40
+ stack.push(instance)
41
+ end
42
+
43
+ private
32
44
 
33
- def push(instance)
34
- @stack.last&.nest_experiment(instance)
35
- @stack.push(instance)
36
- end
45
+ def stack
46
+ Thread.current[@thread_key] ||= []
37
47
  end
38
48
  end
39
49
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "zlib"
4
+
3
5
  # The percent rollout strategy is the most comprehensive included with Gitlab::Experiment. It allows specifying the
4
6
  # percentages per variant using an array, a hash, or will default to even distribution when no rules are provided.
5
7
  #
@@ -41,7 +43,7 @@ module Gitlab
41
43
  end
42
44
  end
43
45
 
44
- def execute_assigment
46
+ def execute_assignment
45
47
  crc = normalized_id
46
48
  total = 0
47
49
 
@@ -27,7 +27,7 @@ module Gitlab
27
27
  class Random < Base
28
28
  protected
29
29
 
30
- def execute_assigment
30
+ def execute_assignment
31
31
  behavior_names.sample # pick a random variant
32
32
  end
33
33
  end
@@ -31,7 +31,7 @@ module Gitlab
31
31
 
32
32
  protected
33
33
 
34
- def execute_assigment
34
+ def execute_assignment
35
35
  behavior_names[(cache.attr_inc(KEY_NAME) - 1) % behavior_names.size]
36
36
  end
37
37
  end
@@ -7,10 +7,17 @@ module Gitlab
7
7
  autoload :Random, 'gitlab/experiment/rollout/random.rb'
8
8
  autoload :RoundRobin, 'gitlab/experiment/rollout/round_robin.rb'
9
9
 
10
- def self.resolve(klass)
11
- return "#{name}::#{klass.to_s.classify}".constantize if klass.is_a?(Symbol) || klass.is_a?(String)
12
-
13
- klass
10
+ def self.resolve(klass, options = {})
11
+ case klass
12
+ when String
13
+ Strategy.new(klass.classify.constantize, options)
14
+ when Symbol
15
+ Strategy.new("#{name}::#{klass.to_s.classify}".constantize, options)
16
+ when Class
17
+ Strategy.new(klass, options)
18
+ else
19
+ raise ArgumentError, "unable to resolve rollout from #{klass.inspect}"
20
+ end
14
21
  end
15
22
 
16
23
  class Base
@@ -47,7 +54,7 @@ module Gitlab
47
54
 
48
55
  validate! # allow the rollout strategy to validate itself
49
56
 
50
- assignment = execute_assigment
57
+ assignment = execute_assignment
51
58
  assignment == :control ? nil : assignment # avoid caching control
52
59
  end
53
60
 
@@ -57,7 +64,7 @@ module Gitlab
57
64
  # base is always valid
58
65
  end
59
66
 
60
- def execute_assigment
67
+ def execute_assignment
61
68
  behavior_names.first
62
69
  end
63
70
 
@@ -73,6 +80,12 @@ module Gitlab
73
80
  options[:include_control] ? [:control] + variant_names : variant_names
74
81
  end
75
82
  end
83
+
84
+ Strategy = Struct.new(:klass, :options) do
85
+ def for(experiment)
86
+ klass.new(options).for(experiment)
87
+ end
88
+ end
76
89
  end
77
90
  end
78
91
  end
@@ -303,7 +303,7 @@ RSpec.configure do |config|
303
303
  config.include Gitlab::Experiment::RSpecHelpers
304
304
  config.include Gitlab::Experiment::Dsl
305
305
 
306
- config.before(:each, :experiment) do
306
+ clear_cache = proc do
307
307
  RequestStore.clear!
308
308
 
309
309
  if defined?(Gitlab::Experiment::TestBehaviors::TrackedStructure)
@@ -311,9 +311,14 @@ RSpec.configure do |config|
311
311
  end
312
312
  end
313
313
 
314
+ config.before(:each, :experiment, &clear_cache)
315
+ config.before(:each, type: :experiment, &clear_cache)
316
+
314
317
  config.include Gitlab::Experiment::RSpecMatchers, :experiment
315
- config.define_derived_metadata(file_path: Regexp.new('/spec/experiments/')) do |metadata|
316
- metadata[:type] = :experiment
318
+ config.include Gitlab::Experiment::RSpecMatchers, type: :experiment
319
+
320
+ config.define_derived_metadata(file_path: Regexp.new('spec/experiments/')) do |metadata|
321
+ metadata[:type] ||= :experiment
317
322
  end
318
323
 
319
324
  # We need to monkeypatch rspec-mocks because there's an issue around stubbing class methods that impacts us here.
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  class Experiment
5
- VERSION = '0.7.0'
5
+ VERSION = '0.7.1'
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/string/inflections'
6
7
 
7
8
  require 'gitlab/experiment/errors'
8
9
  require 'gitlab/experiment/base_interface'
@@ -68,7 +69,7 @@ module Gitlab
68
69
  def default_rollout(rollout = nil, options = {})
69
70
  return @_rollout ||= Configuration.default_rollout if rollout.blank?
70
71
 
71
- @_rollout = Rollout.resolve(rollout).new(options)
72
+ @_rollout = Rollout.resolve(rollout, options)
72
73
  end
73
74
 
74
75
  # Class level accessor methods.
@@ -145,7 +146,7 @@ module Gitlab
145
146
  def rollout(rollout = nil, options = {})
146
147
  return @_rollout ||= self.class.default_rollout(nil, options).for(self) if rollout.blank?
147
148
 
148
- @_rollout = Rollout.resolve(rollout).new(options).for(self)
149
+ @_rollout = Rollout.resolve(rollout, options).for(self)
149
150
  end
150
151
 
151
152
  def exclude!
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-experiment
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab
@@ -45,53 +45,54 @@ executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
- - lib/generators/test_unit
49
- - lib/generators/test_unit/experiment
50
- - lib/generators/test_unit/experiment/templates
51
- - lib/generators/test_unit/experiment/templates/experiment_test.rb.tt
52
- - lib/generators/test_unit/experiment/experiment_generator.rb
53
- - lib/generators/rspec
54
- - lib/generators/rspec/experiment
55
- - lib/generators/rspec/experiment/templates
56
- - lib/generators/rspec/experiment/templates/experiment_spec.rb.tt
57
- - lib/generators/rspec/experiment/experiment_generator.rb
58
48
  - lib/generators/gitlab
59
49
  - lib/generators/gitlab/experiment
60
- - lib/generators/gitlab/experiment/USAGE
61
- - lib/generators/gitlab/experiment/templates
62
- - lib/generators/gitlab/experiment/templates/experiment.rb.tt
63
50
  - lib/generators/gitlab/experiment/install
51
+ - lib/generators/gitlab/experiment/install/install_generator.rb
64
52
  - lib/generators/gitlab/experiment/install/templates
65
53
  - lib/generators/gitlab/experiment/install/templates/application_experiment.rb.tt
66
54
  - lib/generators/gitlab/experiment/install/templates/initializer.rb.tt
67
55
  - lib/generators/gitlab/experiment/install/templates/POST_INSTALL
68
- - lib/generators/gitlab/experiment/install/install_generator.rb
56
+ - lib/generators/gitlab/experiment/USAGE
69
57
  - lib/generators/gitlab/experiment/experiment_generator.rb
58
+ - lib/generators/gitlab/experiment/templates
59
+ - 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
+ - lib/generators/rspec/experiment/experiment_generator.rb
68
+ - lib/generators/rspec/experiment/templates
69
+ - lib/generators/rspec/experiment/templates/experiment_spec.rb.tt
70
+ - lib/gitlab/experiment.rb
70
71
  - lib/gitlab/experiment
71
- - lib/gitlab/experiment/dsl.rb
72
- - lib/gitlab/experiment/rspec.rb
73
- - lib/gitlab/experiment/context.rb
74
- - lib/gitlab/experiment/nestable.rb
75
- - lib/gitlab/experiment/configuration.rb
76
- - lib/gitlab/experiment/rollout.rb
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
77
76
  - lib/gitlab/experiment/cache
78
77
  - lib/gitlab/experiment/cache/redis_hash_store.rb
79
- - lib/gitlab/experiment/engine.rb
80
- - lib/gitlab/experiment/base_interface.rb
81
- - lib/gitlab/experiment/middleware.rb
82
- - lib/gitlab/experiment/version.rb
83
- - lib/gitlab/experiment/cookies.rb
84
78
  - lib/gitlab/experiment/errors.rb
85
- - lib/gitlab/experiment/cache.rb
86
- - lib/gitlab/experiment/variant.rb
79
+ - lib/gitlab/experiment/callbacks.rb
80
+ - lib/gitlab/experiment/rollout.rb
81
+ - lib/gitlab/experiment/base_interface.rb
82
+ - lib/gitlab/experiment/nestable.rb
83
+ - lib/gitlab/experiment/context.rb
84
+ - lib/gitlab/experiment/engine.rb
85
+ - lib/gitlab/experiment/rspec.rb
87
86
  - lib/gitlab/experiment/rollout
88
87
  - lib/gitlab/experiment/rollout/random.rb
89
- - lib/gitlab/experiment/rollout/percent.rb
90
88
  - lib/gitlab/experiment/rollout/round_robin.rb
91
- - lib/gitlab/experiment/callbacks.rb
92
- - lib/gitlab/experiment/test_behaviors
93
- - lib/gitlab/experiment/test_behaviors/trackable.rb
94
- - lib/gitlab/experiment.rb
89
+ - lib/gitlab/experiment/rollout/percent.rb
90
+ - lib/gitlab/experiment/rollout/concerns
91
+ - lib/gitlab/experiment/cache.rb
92
+ - lib/gitlab/experiment/version.rb
93
+ - lib/gitlab/experiment/cookies.rb
94
+ - lib/gitlab/experiment/configuration.rb
95
+ - lib/gitlab/experiment/dsl.rb
95
96
  - LICENSE.txt
96
97
  - README.md
97
98
  homepage: https://gitlab.com/gitlab-org/ruby/gems/gitlab-experiment