gitlab-experiment 0.5.3 → 0.5.4
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 +4 -4
- data/lib/gitlab/experiment.rb +15 -8
- data/lib/gitlab/experiment/configuration.rb +9 -6
- data/lib/gitlab/experiment/rollout.rb +10 -2
- data/lib/gitlab/experiment/rspec.rb +4 -0
- data/lib/gitlab/experiment/version.rb +1 -1
- metadata +17 -4
- data/lib/gitlab/experiment/rollout/first.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9d7bc7a1946d06b5188ccfe761342209779f75cf635d894bb8743519ff2830dc
|
4
|
+
data.tar.gz: 7a5c347f8b58e5caa2fe814ce013dbf1ca71f6e017148528a0ff2ca74bd562de
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '01927d9db97ad4b087d445db642aa39615faa68322e2bd0e0b82ae99441478bae3f1939b94956218121fe52d01f432836ba272d0b1ff052537c80f0d0ff107b3'
|
7
|
+
data.tar.gz: f53702ea5bb97fe6c73427850534b9e156744336a37029dce2b96926b70b7a5c4959708ac626f6ac0435125ad4ffe62f2ba9fd528f756af811c6ff66abc47846
|
data/lib/gitlab/experiment.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'scientist'
|
4
|
+
require 'request_store'
|
4
5
|
require 'active_support/callbacks'
|
5
6
|
require 'active_support/cache'
|
6
7
|
require 'active_support/concern'
|
@@ -27,10 +28,10 @@ module Gitlab
|
|
27
28
|
include Callbacks
|
28
29
|
|
29
30
|
class << self
|
30
|
-
def default_rollout(rollout = nil)
|
31
|
+
def default_rollout(rollout = nil, options = {})
|
31
32
|
return @rollout ||= Configuration.default_rollout if rollout.blank?
|
32
33
|
|
33
|
-
@rollout = Rollout.resolve(rollout)
|
34
|
+
@rollout = Rollout.resolve(rollout).new(options)
|
34
35
|
end
|
35
36
|
|
36
37
|
def exclude(*filter_list, **options, &block)
|
@@ -44,6 +45,10 @@ module Gitlab
|
|
44
45
|
target.variant(variant) if target.instance_variable_get(:@variant_name).nil? && callback.call(target, nil)
|
45
46
|
end
|
46
47
|
end
|
48
|
+
|
49
|
+
def published_experiments
|
50
|
+
RequestStore.store[:published_gitlab_experiments] || {}
|
51
|
+
end
|
47
52
|
end
|
48
53
|
|
49
54
|
def name
|
@@ -85,10 +90,10 @@ module Gitlab
|
|
85
90
|
@resolving_variant = false
|
86
91
|
end
|
87
92
|
|
88
|
-
def rollout(rollout = nil)
|
89
|
-
return @rollout ||= self.class.default_rollout if rollout.blank?
|
93
|
+
def rollout(rollout = nil, options = {})
|
94
|
+
return @rollout ||= self.class.default_rollout(nil, options) if rollout.blank?
|
90
95
|
|
91
|
-
@rollout = Rollout.resolve(rollout)
|
96
|
+
@rollout = Rollout.resolve(rollout).new(options)
|
92
97
|
end
|
93
98
|
|
94
99
|
def exclude!
|
@@ -101,6 +106,8 @@ module Gitlab
|
|
101
106
|
|
102
107
|
def publish(result)
|
103
108
|
instance_exec(result, &Configuration.publishing_behavior)
|
109
|
+
|
110
|
+
(RequestStore.store[:published_gitlab_experiments] ||= {})[name] = signature.merge(excluded: excluded?)
|
104
111
|
end
|
105
112
|
|
106
113
|
def track(action, **event_args)
|
@@ -131,8 +138,8 @@ module Gitlab
|
|
131
138
|
{ variant: variant.name, experiment: name }.merge(context.signature)
|
132
139
|
end
|
133
140
|
|
134
|
-
def key_for(
|
135
|
-
instance_exec(
|
141
|
+
def key_for(source, seed = name)
|
142
|
+
instance_exec(source, seed, &Configuration.context_hash_strategy)
|
136
143
|
end
|
137
144
|
|
138
145
|
protected
|
@@ -144,7 +151,7 @@ module Gitlab
|
|
144
151
|
end
|
145
152
|
|
146
153
|
def resolve_variant_name
|
147
|
-
rollout.
|
154
|
+
rollout.rollout_for(self) if experiment_group?
|
148
155
|
end
|
149
156
|
end
|
150
157
|
end
|
@@ -26,8 +26,10 @@ module Gitlab
|
|
26
26
|
# The domain to use on cookies.
|
27
27
|
@cookie_domain = :all
|
28
28
|
|
29
|
-
# The default rollout strategy
|
30
|
-
|
29
|
+
# The default rollout strategy only works for single variant experiments.
|
30
|
+
# It's expected that you use a more advanced rollout for multiple variant
|
31
|
+
# experiments.
|
32
|
+
@default_rollout = Rollout::Base.new
|
31
33
|
|
32
34
|
# Logic this project uses to determine inclusion in a given experiment.
|
33
35
|
# Expected to return a boolean value.
|
@@ -45,10 +47,11 @@ module Gitlab
|
|
45
47
|
track(:assignment)
|
46
48
|
end
|
47
49
|
|
48
|
-
# Algorithm that consistently generates a hash key for a given
|
49
|
-
@context_hash_strategy = lambda do |
|
50
|
-
|
51
|
-
|
50
|
+
# Algorithm that consistently generates a hash key for a given source.
|
51
|
+
@context_hash_strategy = lambda do |source, seed|
|
52
|
+
source = source.keys + source.values if source.is_a?(Hash)
|
53
|
+
data = Array(source).map { |v| (v.respond_to?(:to_global_id) ? v.to_global_id : v).to_s }
|
54
|
+
Digest::MD5.hexdigest(data.unshift(seed).join('|'))
|
52
55
|
end
|
53
56
|
|
54
57
|
class << self
|
@@ -3,7 +3,6 @@
|
|
3
3
|
module Gitlab
|
4
4
|
class Experiment
|
5
5
|
module Rollout
|
6
|
-
autoload :First, 'gitlab/experiment/rollout/first.rb' # default strategy
|
7
6
|
autoload :Random, 'gitlab/experiment/rollout/random.rb'
|
8
7
|
autoload :RoundRobin, 'gitlab/experiment/rollout/round_robin.rb'
|
9
8
|
|
@@ -18,8 +17,17 @@ module Gitlab
|
|
18
17
|
|
19
18
|
delegate :variant_names, :cache, to: :experiment
|
20
19
|
|
21
|
-
def initialize(
|
20
|
+
def initialize(options = {})
|
21
|
+
@options = options
|
22
|
+
end
|
23
|
+
|
24
|
+
def rollout_for(experiment)
|
22
25
|
@experiment = experiment
|
26
|
+
execute
|
27
|
+
end
|
28
|
+
|
29
|
+
def execute
|
30
|
+
variant_names.first
|
23
31
|
end
|
24
32
|
end
|
25
33
|
end
|
@@ -232,6 +232,10 @@ RSpec.configure do |config|
|
|
232
232
|
config.include Gitlab::Experiment::RSpecHelpers
|
233
233
|
config.include Gitlab::Experiment::Dsl
|
234
234
|
|
235
|
+
config.before(:each, :experiment) do
|
236
|
+
RequestStore.clear!
|
237
|
+
end
|
238
|
+
|
235
239
|
config.include Gitlab::Experiment::RSpecMatchers, :experiment
|
236
240
|
config.define_derived_metadata(file_path: Regexp.new('/spec/experiments/')) do |metadata|
|
237
241
|
metadata[:type] = :experiment
|
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.5.
|
4
|
+
version: 0.5.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitLab
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: request_store
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: scientist
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,7 +89,6 @@ files:
|
|
75
89
|
- lib/gitlab/experiment/dsl.rb
|
76
90
|
- lib/gitlab/experiment/engine.rb
|
77
91
|
- lib/gitlab/experiment/rollout.rb
|
78
|
-
- lib/gitlab/experiment/rollout/first.rb
|
79
92
|
- lib/gitlab/experiment/rollout/random.rb
|
80
93
|
- lib/gitlab/experiment/rollout/round_robin.rb
|
81
94
|
- lib/gitlab/experiment/rspec.rb
|
@@ -100,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
113
|
- !ruby/object:Gem::Version
|
101
114
|
version: '0'
|
102
115
|
requirements: []
|
103
|
-
rubygems_version: 3.
|
116
|
+
rubygems_version: 3.2.17
|
104
117
|
signing_key:
|
105
118
|
specification_version: 4
|
106
119
|
summary: GitLab experiment library built on top of scientist.
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Gitlab
|
4
|
-
class Experiment
|
5
|
-
module Rollout
|
6
|
-
class First < Base
|
7
|
-
# This rollout strategy just picks the first variant name. It's the
|
8
|
-
# default resolver as it assumes a single variant. You should consider
|
9
|
-
# using a more advanced rollout if you have multiple variants.
|
10
|
-
def execute
|
11
|
-
variant_names.first
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|