gitlab-experiment 0.6.1 → 0.6.2

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: 0d1ad31e8b977491ccdd1a9d21fc348482d3942c80a3e2935a6ccabc515b4243
4
- data.tar.gz: bdf9a4b67bb2b5a72931c081fed88ac246853a2e90f4f7f5c08bf7bdb9d8f55e
3
+ metadata.gz: cd00eb06f769b8268e0e02e7d48b38dbef6be029c8f4d02b127e9f2b44f9dbc3
4
+ data.tar.gz: 7a3b9c5357489afd4b14bd6411536b1a2484c50f44934cc646b20abd1607ab0b
5
5
  SHA512:
6
- metadata.gz: dc1cc5077144d4e5514b6804599bba8e6829ad6472e5e362cde88940995b174f9989733fea17da91be92dc172694a4394ee0db7974efba8d6eb4e77e769a57ee
7
- data.tar.gz: 958cf74fa36b1588fd7f83776e87c7f8c92120cb8a6d421c09a4bd207adffdfcfe69ea295dd1e6a49d371225988f6fde3f559baf64d755a0c9176a33e7efddca
6
+ metadata.gz: '08ea7e0b62c92e7674a72271e388dd104878ad2b9328ad016fba758762e244b51da1a089cec0d74e1db11fba4da3e2bc59524ef2839424295fa3c7307c73cb87'
7
+ data.tar.gz: 7ecfc7bbaa0803b67ccfd642c7c06baec43cde54b41cc768a7c1a1537e5c6cae6e13a355bdf342d4cdaebef15f5a1b99e76676c87612d857affb865bb543e07d
@@ -56,6 +56,16 @@ Gitlab::Experiment.configure do |config|
56
56
  # '/-/experiment', '/redirect', nil
57
57
  config.mount_at = '/experiment'
58
58
 
59
+ # When using the middleware, links can be instrumented and redirected
60
+ # elsewhere. This can be exploited to make a harmful url look innocuous or
61
+ # that it's a valid url on your domain. To avoid this, you can provide your
62
+ # own logic for what urls will be considered valid and redirected to.
63
+ #
64
+ # Expected to return a boolean value.
65
+ config.redirect_url_validator = lambda do |redirect_url|
66
+ true
67
+ end
68
+
59
69
  # Logic this project uses to determine inclusion in a given experiment.
60
70
  #
61
71
  # Expected to return a boolean value.
@@ -120,6 +120,13 @@ module Gitlab
120
120
  instance_exec(action, event_args, &Configuration.tracking_behavior)
121
121
  end
122
122
 
123
+ def process_redirect_url(url)
124
+ return unless Configuration.redirect_url_validator&.call(url)
125
+
126
+ track('visited', url: url)
127
+ url # return the url, which allows for mutation
128
+ end
129
+
123
130
  def enabled?
124
131
  true
125
132
  end
@@ -29,7 +29,7 @@ module Gitlab
29
29
 
30
30
  def from_param(id)
31
31
  %r{/?(?<name>.*):(?<key>.*)$} =~ id
32
- Gitlab::Experiment.new(name).tap { |e| e.context.key(key) }
32
+ constantize(name).new(name).tap { |e| e.context.key(key) }
33
33
  end
34
34
  end
35
35
 
@@ -39,17 +39,19 @@ module Gitlab
39
39
 
40
40
  # The default base path that the middleware (or rails engine) will be
41
41
  # mounted.
42
- @mount_at = '/experiment'
42
+ @mount_at = nil
43
+
44
+ # The middleware won't redirect to urls that aren't considered valid.
45
+ # Expected to return a boolean value.
46
+ @redirect_url_validator = ->(_redirect_url) { true }
43
47
 
44
48
  # Logic this project uses to determine inclusion in a given experiment.
45
49
  # Expected to return a boolean value.
46
- @inclusion_resolver = lambda do |requested_variant|
47
- false
48
- end
50
+ @inclusion_resolver = ->(_requested_variant) { false }
49
51
 
50
52
  # Tracking behavior can be implemented to link an event to an experiment.
51
53
  @tracking_behavior = lambda do |event, args|
52
- Configuration.logger.info "Gitlab::Experiment[#{name}] #{event}: #{args.merge(signature: signature)}"
54
+ Configuration.logger.info("#{self.class.name}[#{name}] #{event}: #{args.merge(signature: signature)}")
53
55
  end
54
56
 
55
57
  # Called at the end of every experiment run, with the result.
@@ -88,6 +90,7 @@ module Gitlab
88
90
  :context_key_bit_length,
89
91
  :mount_at,
90
92
  :default_rollout,
93
+ :redirect_url_validator,
91
94
  :inclusion_resolver,
92
95
  :tracking_behavior,
93
96
  :publishing_behavior
@@ -3,6 +3,10 @@
3
3
  module Gitlab
4
4
  class Experiment
5
5
  module Dsl
6
+ def self.include_in(klass, with_helper: false)
7
+ klass.include(self).tap { |base| base.helper_method(:experiment) if with_helper }
8
+ end
9
+
6
10
  def experiment(name, variant_name = nil, **context, &block)
7
11
  raise ArgumentError, 'name is required' if name.nil?
8
12
 
@@ -1,34 +1,42 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_model'
4
+
3
5
  module Gitlab
4
6
  class Experiment
7
+ include ActiveModel::Model
8
+
9
+ # used for generating routes
10
+ def self.model_name
11
+ ActiveModel::Name.new(self, Gitlab)
12
+ end
13
+
5
14
  class Engine < ::Rails::Engine
6
- def self.include_dsl
7
- if defined?(ActionController)
8
- ActionController::Base.include(Dsl)
9
- ActionController::Base.helper_method(:experiment)
10
- end
15
+ isolate_namespace Experiment
11
16
 
12
- return unless defined?(ActionMailer)
17
+ initializer('gitlab_experiment.include_dsl') { include_dsl }
18
+ initializer('gitlab_experiment.mount_engine') { |app| mount_engine(app, Configuration.mount_at) }
13
19
 
14
- ActionMailer::Base.include(Dsl)
15
- ActionMailer::Base.helper_method(:experiment)
20
+ private
21
+
22
+ def include_dsl
23
+ Dsl.include_in(ActionController::Base, with_helper: true) if defined?(ActionController)
24
+ Dsl.include_in(ActionMailer::Base, with_helper: true) if defined?(ActionMailer)
16
25
  end
17
26
 
18
- def add_middleware(app, base_path)
19
- return if base_path.blank?
27
+ def mount_engine(app, mount_at)
28
+ return if mount_at.blank?
20
29
 
21
- app.config.middleware.use(Middleware, base_path)
22
- app.routes.append do
23
- direct :experiment_redirect do |experiment, to_url|
24
- [base_path, experiment.to_param].join('/') + "?#{to_url}"
25
- end
30
+ engine = routes do
31
+ default_url_options app.routes.default_url_options
32
+ resources :experiments, path: '/', only: :show
26
33
  end
27
- end
28
34
 
29
- config.after_initialize { include_dsl }
30
- initializer 'gitlab_experiment.add_middleware' do |app|
31
- add_middleware(app, Configuration.mount_at)
35
+ app.config.middleware.use(Middleware, mount_at)
36
+ app.routes.append do
37
+ mount Engine, at: mount_at, as: :experiment_engine
38
+ direct(:experiment_redirect) { |ex, url:| "#{engine.url_helpers.experiment_url(ex)}?#{url}" }
39
+ end
32
40
  end
33
41
  end
34
42
  end
@@ -6,8 +6,8 @@ module Gitlab
6
6
  def self.redirect(id, url)
7
7
  raise Error, 'no url to redirect to' if url.blank?
8
8
 
9
- Gitlab::Experiment.from_param(id).tap { |e| e.track('visited', url: url) }
10
- [303, { 'Location' => url }, []]
9
+ experiment = Gitlab::Experiment.from_param(id)
10
+ [303, { 'Location' => experiment.process_redirect_url(url) || raise(Error, 'not redirecting') }, []]
11
11
  end
12
12
 
13
13
  def initialize(app, base_path)
@@ -82,7 +82,7 @@ module Gitlab
82
82
  extend RSpec::Matchers::DSL
83
83
 
84
84
  def require_experiment(experiment, matcher_name, classes: false)
85
- klass = experiment.class == Class ? experiment : experiment.class
85
+ klass = experiment.instance_of?(Class) ? experiment : experiment.class
86
86
  unless klass <= Gitlab::Experiment
87
87
  raise(
88
88
  ArgumentError,
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  class Experiment
5
- VERSION = '0.6.1'
5
+ VERSION = '0.6.2'
6
6
  end
7
7
  end
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.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-22 00:00:00.000000000 Z
11
+ date:
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -65,38 +65,52 @@ executables: []
65
65
  extensions: []
66
66
  extra_rdoc_files: []
67
67
  files:
68
- - LICENSE.txt
69
- - README.md
70
- - lib/generators/gitlab/experiment/USAGE
71
- - lib/generators/gitlab/experiment/experiment_generator.rb
68
+ - lib/generators/gitlab
69
+ - lib/generators/gitlab/experiment
70
+ - lib/generators/gitlab/experiment/install
72
71
  - lib/generators/gitlab/experiment/install/install_generator.rb
73
- - lib/generators/gitlab/experiment/install/templates/POST_INSTALL
72
+ - lib/generators/gitlab/experiment/install/templates
74
73
  - lib/generators/gitlab/experiment/install/templates/application_experiment.rb.tt
75
74
  - lib/generators/gitlab/experiment/install/templates/initializer.rb.tt
75
+ - lib/generators/gitlab/experiment/install/templates/POST_INSTALL
76
+ - lib/generators/gitlab/experiment/USAGE
77
+ - lib/generators/gitlab/experiment/experiment_generator.rb
78
+ - lib/generators/gitlab/experiment/templates
76
79
  - lib/generators/gitlab/experiment/templates/experiment.rb.tt
77
- - lib/generators/rspec/experiment/experiment_generator.rb
78
- - lib/generators/rspec/experiment/templates/experiment_spec.rb.tt
80
+ - lib/generators/test_unit
81
+ - lib/generators/test_unit/experiment
79
82
  - lib/generators/test_unit/experiment/experiment_generator.rb
83
+ - lib/generators/test_unit/experiment/templates
80
84
  - lib/generators/test_unit/experiment/templates/experiment_test.rb.tt
85
+ - lib/generators/rspec
86
+ - lib/generators/rspec/experiment
87
+ - lib/generators/rspec/experiment/experiment_generator.rb
88
+ - lib/generators/rspec/experiment/templates
89
+ - lib/generators/rspec/experiment/templates/experiment_spec.rb.tt
81
90
  - lib/gitlab/experiment.rb
82
- - lib/gitlab/experiment/base_interface.rb
83
- - lib/gitlab/experiment/cache.rb
91
+ - lib/gitlab/experiment
92
+ - lib/gitlab/experiment/variant.rb
93
+ - lib/gitlab/experiment/middleware.rb
94
+ - lib/gitlab/experiment/cache
84
95
  - lib/gitlab/experiment/cache/redis_hash_store.rb
96
+ - lib/gitlab/experiment/errors.rb
85
97
  - lib/gitlab/experiment/callbacks.rb
86
- - lib/gitlab/experiment/configuration.rb
98
+ - lib/gitlab/experiment/rollout.rb
99
+ - lib/gitlab/experiment/base_interface.rb
87
100
  - lib/gitlab/experiment/context.rb
88
- - lib/gitlab/experiment/cookies.rb
89
- - lib/gitlab/experiment/dsl.rb
90
101
  - lib/gitlab/experiment/engine.rb
91
- - lib/gitlab/experiment/errors.rb
92
- - lib/gitlab/experiment/middleware.rb
93
- - lib/gitlab/experiment/rollout.rb
94
- - lib/gitlab/experiment/rollout/percent.rb
102
+ - lib/gitlab/experiment/rspec.rb
103
+ - lib/gitlab/experiment/rollout
95
104
  - lib/gitlab/experiment/rollout/random.rb
96
105
  - lib/gitlab/experiment/rollout/round_robin.rb
97
- - lib/gitlab/experiment/rspec.rb
98
- - lib/gitlab/experiment/variant.rb
106
+ - lib/gitlab/experiment/rollout/percent.rb
107
+ - lib/gitlab/experiment/cache.rb
99
108
  - lib/gitlab/experiment/version.rb
109
+ - lib/gitlab/experiment/cookies.rb
110
+ - lib/gitlab/experiment/configuration.rb
111
+ - lib/gitlab/experiment/dsl.rb
112
+ - LICENSE.txt
113
+ - README.md
100
114
  homepage: https://gitlab.com/gitlab-org/gitlab-experiment
101
115
  licenses:
102
116
  - MIT
@@ -116,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
130
  - !ruby/object:Gem::Version
117
131
  version: '0'
118
132
  requirements: []
119
- rubygems_version: 3.2.20
133
+ rubygems_version: 3.1.4
120
134
  signing_key:
121
135
  specification_version: 4
122
136
  summary: GitLab experiment library built on top of scientist.