rollout 2.4.5 → 2.4.6

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: acf240ab59dcfdebec335aee19df882f8936e7de5b7a0c347a3c28cfa8b3fc6d
4
- data.tar.gz: 2ca7c2d7c761c6e539790421547b5e8eb82bbe8b56dca246975f6adc0773866d
3
+ metadata.gz: f3e6e9521ed03059b5b673616e985f89231d77d1ca42d8fa7ff00797ef906768
4
+ data.tar.gz: ac66f6f5f0da7e03bbf506d09f62d34e6afd7f1ea09b248b5193d74f3b6a720e
5
5
  SHA512:
6
- metadata.gz: dc61fd463b60a94e85b5b141ad5fb7431f37249d9b899739b52524bd0fc28106135e039cbfe0130a0c35d0934b50339e426e38255516381636ec1ff226068e49
7
- data.tar.gz: 5babd80ccaab8b4f7b4efeac63e5941709913014e5d5d37f71c5f8b04ae62d09a38e50f7f6236df8d09ce359384cb0d877452209a1b63b69284fd649bb49033c
6
+ metadata.gz: ccebf1c2024c332cd921a49b400a7ee8e9a5c0ce95cdf59f5e89fb302bef08684cc04ffae30c952e14ffd5acc97d583871ee590aebe6aa2c519cc416afc17b9f
7
+ data.tar.gz: fe0a400d1f694a6aefb5b1e7d89afb64a8cb28c07a1f510d01655d724bfb97d5b38e7c60e40669aec5fded5581e760549b53564078018cad92c968b6900753ee
@@ -3,24 +3,33 @@ version: 2.1
3
3
  workflows:
4
4
  main:
5
5
  jobs:
6
+ - ruby27
6
7
  - ruby26
7
8
  - ruby25
8
9
  - ruby24
9
10
  - ruby23
10
11
 
11
12
  executors:
13
+ ruby27:
14
+ docker:
15
+ - image: circleci/ruby:2.7
16
+ - image: circleci/redis:alpine
12
17
  ruby26:
13
18
  docker:
14
19
  - image: circleci/ruby:2.6
20
+ - image: circleci/redis:alpine
15
21
  ruby25:
16
22
  docker:
17
23
  - image: circleci/ruby:2.5
24
+ - image: circleci/redis:alpine
18
25
  ruby24:
19
26
  docker:
20
27
  - image: circleci/ruby:2.4
28
+ - image: circleci/redis:alpine
21
29
  ruby23:
22
30
  docker:
23
31
  - image: circleci/ruby:2.3
32
+ - image: circleci/redis:alpine
24
33
 
25
34
  commands:
26
35
  test:
@@ -31,7 +40,7 @@ commands:
31
40
 
32
41
  - run:
33
42
  name: Bundle Install
34
- command: bundle check --path vendor/bundle || bundle install --deployment
43
+ command: bundle check --path vendor/bundle || bundle install
35
44
 
36
45
  - save_cache:
37
46
  key: bundler-{{ checksum "Gemfile.lock" }}
@@ -44,8 +53,8 @@ commands:
44
53
  bundle exec rspec --format documentation --format RspecJunitFormatter --out test_results/rspec.xml
45
54
 
46
55
  jobs:
47
- ruby26:
48
- executor: ruby26
56
+ ruby27:
57
+ executor: ruby27
49
58
  steps:
50
59
  - checkout
51
60
  - test
@@ -61,6 +70,12 @@ jobs:
61
70
  - store_test_results:
62
71
  path: test_results
63
72
 
73
+ ruby26:
74
+ executor: ruby26
75
+ steps:
76
+ - checkout
77
+ - test
78
+
64
79
  ruby25:
65
80
  executor: ruby25
66
81
  steps:
data/README.md CHANGED
@@ -24,6 +24,14 @@ $redis = Redis.new
24
24
  $rollout = Rollout.new($redis)
25
25
  ```
26
26
 
27
+ or even simpler
28
+
29
+ ```ruby
30
+ require 'redis'
31
+ $rollout = Rollout.new(Redis.current) # Will use REDIS_URL env var or default redis url
32
+ ```
33
+
34
+
27
35
  Update data specific to a feature:
28
36
 
29
37
  ```ruby
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'rollout/feature'
3
4
  require 'rollout/version'
4
5
  require 'zlib'
5
6
  require 'set'
@@ -8,133 +9,6 @@ require 'json'
8
9
  class Rollout
9
10
  RAND_BASE = (2**32 - 1) / 100.0
10
11
 
11
- class Feature
12
- attr_accessor :groups, :users, :percentage, :data
13
- attr_reader :name, :options
14
-
15
- def initialize(name, string = nil, opts = {})
16
- @options = opts
17
- @name = name
18
-
19
- if string
20
- raw_percentage, raw_users, raw_groups, raw_data = string.split('|', 4)
21
- @percentage = raw_percentage.to_f
22
- @users = users_from_string(raw_users)
23
- @groups = groups_from_string(raw_groups)
24
- @data = raw_data.nil? || raw_data.strip.empty? ? {} : JSON.parse(raw_data)
25
- else
26
- clear
27
- end
28
- end
29
-
30
- def serialize
31
- "#{@percentage}|#{@users.to_a.join(',')}|#{@groups.to_a.join(',')}|#{serialize_data}"
32
- end
33
-
34
- def add_user(user)
35
- id = user_id(user)
36
- @users << id unless @users.include?(id)
37
- end
38
-
39
- def remove_user(user)
40
- @users.delete(user_id(user))
41
- end
42
-
43
- def add_group(group)
44
- @groups << group.to_sym unless @groups.include?(group.to_sym)
45
- end
46
-
47
- def remove_group(group)
48
- @groups.delete(group.to_sym)
49
- end
50
-
51
- def clear
52
- @groups = groups_from_string('')
53
- @users = users_from_string('')
54
- @percentage = 0
55
- @data = {}
56
- end
57
-
58
- def active?(rollout, user)
59
- if user
60
- id = user_id(user)
61
- user_in_percentage?(id) ||
62
- user_in_active_users?(id) ||
63
- user_in_active_group?(user, rollout)
64
- else
65
- @percentage == 100
66
- end
67
- end
68
-
69
- def user_in_active_users?(user)
70
- @users.include?(user_id(user))
71
- end
72
-
73
- def to_hash
74
- {
75
- percentage: @percentage,
76
- groups: @groups,
77
- users: @users
78
- }
79
- end
80
-
81
- private
82
-
83
- def user_id(user)
84
- if user.is_a?(Integer) || user.is_a?(String)
85
- user.to_s
86
- else
87
- user.send(id_user_by).to_s
88
- end
89
- end
90
-
91
- def id_user_by
92
- @options[:id_user_by] || :id
93
- end
94
-
95
- def user_in_percentage?(user)
96
- Zlib.crc32(user_id_for_percentage(user)) < RAND_BASE * @percentage
97
- end
98
-
99
- def user_id_for_percentage(user)
100
- if @options[:randomize_percentage]
101
- user_id(user).to_s + @name.to_s
102
- else
103
- user_id(user)
104
- end
105
- end
106
-
107
- def user_in_active_group?(user, rollout)
108
- @groups.any? do |g|
109
- rollout.active_in_group?(g, user)
110
- end
111
- end
112
-
113
- def serialize_data
114
- return '' unless @data.is_a? Hash
115
-
116
- @data.to_json
117
- end
118
-
119
- def users_from_string(raw_users)
120
- users = (raw_users || '').split(',').map(&:to_s)
121
- if @options[:use_sets]
122
- users.to_set
123
- else
124
- users
125
- end
126
- end
127
-
128
- def groups_from_string(raw_groups)
129
- groups = (raw_groups || '').split(',').map(&:to_sym)
130
- if @options[:use_sets]
131
- groups.to_set
132
- else
133
- groups
134
- end
135
- end
136
- end
137
-
138
12
  def initialize(storage, opts = {})
139
13
  @storage = storage
140
14
  @options = opts
@@ -296,7 +170,13 @@ class Rollout
296
170
  end
297
171
 
298
172
  def exists?(feature)
299
- @storage.exists(key(feature))
173
+ # since redis-rb v4.2, `#exists?` replaces `#exists` which now returns integer value instead of boolean
174
+ # https://github.com/redis/redis-rb/pull/918
175
+ if @storage.respond_to?(:exists?)
176
+ @storage.exists?(key(feature))
177
+ else
178
+ @storage.exists(key(feature))
179
+ end
300
180
  end
301
181
 
302
182
  private
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Rollout
4
+ class Feature
5
+ attr_accessor :groups, :users, :percentage, :data
6
+ attr_reader :name, :options
7
+
8
+ def initialize(name, string = nil, opts = {})
9
+ @options = opts
10
+ @name = name
11
+
12
+ if string
13
+ raw_percentage, raw_users, raw_groups, raw_data = string.split('|', 4)
14
+ @percentage = raw_percentage.to_f
15
+ @users = users_from_string(raw_users)
16
+ @groups = groups_from_string(raw_groups)
17
+ @data = raw_data.nil? || raw_data.strip.empty? ? {} : JSON.parse(raw_data)
18
+ else
19
+ clear
20
+ end
21
+ end
22
+
23
+ def serialize
24
+ "#{@percentage}|#{@users.to_a.join(',')}|#{@groups.to_a.join(',')}|#{serialize_data}"
25
+ end
26
+
27
+ def add_user(user)
28
+ id = user_id(user)
29
+ @users << id unless @users.include?(id)
30
+ end
31
+
32
+ def remove_user(user)
33
+ @users.delete(user_id(user))
34
+ end
35
+
36
+ def add_group(group)
37
+ @groups << group.to_sym unless @groups.include?(group.to_sym)
38
+ end
39
+
40
+ def remove_group(group)
41
+ @groups.delete(group.to_sym)
42
+ end
43
+
44
+ def clear
45
+ @groups = groups_from_string('')
46
+ @users = users_from_string('')
47
+ @percentage = 0
48
+ @data = {}
49
+ end
50
+
51
+ def active?(rollout, user)
52
+ if user
53
+ id = user_id(user)
54
+ user_in_percentage?(id) ||
55
+ user_in_active_users?(id) ||
56
+ user_in_active_group?(user, rollout)
57
+ else
58
+ @percentage == 100
59
+ end
60
+ end
61
+
62
+ def user_in_active_users?(user)
63
+ @users.include?(user_id(user))
64
+ end
65
+
66
+ def to_hash
67
+ {
68
+ percentage: @percentage,
69
+ groups: @groups,
70
+ users: @users
71
+ }
72
+ end
73
+
74
+ private
75
+
76
+ def user_id(user)
77
+ if user.is_a?(Integer) || user.is_a?(String)
78
+ user.to_s
79
+ else
80
+ user.send(id_user_by).to_s
81
+ end
82
+ end
83
+
84
+ def id_user_by
85
+ @options[:id_user_by] || :id
86
+ end
87
+
88
+ def user_in_percentage?(user)
89
+ Zlib.crc32(user_id_for_percentage(user)) < RAND_BASE * @percentage
90
+ end
91
+
92
+ def user_id_for_percentage(user)
93
+ if @options[:randomize_percentage]
94
+ user_id(user).to_s + @name.to_s
95
+ else
96
+ user_id(user)
97
+ end
98
+ end
99
+
100
+ def user_in_active_group?(user, rollout)
101
+ @groups.any? do |g|
102
+ rollout.active_in_group?(g, user)
103
+ end
104
+ end
105
+
106
+ def serialize_data
107
+ return '' unless @data.is_a? Hash
108
+
109
+ @data.to_json
110
+ end
111
+
112
+ def users_from_string(raw_users)
113
+ users = (raw_users || '').split(',').map(&:to_s)
114
+ if @options[:use_sets]
115
+ users.to_set
116
+ else
117
+ users
118
+ end
119
+ end
120
+
121
+ def groups_from_string(raw_groups)
122
+ groups = (raw_groups || '').split(',').map(&:to_sym)
123
+ if @options[:use_sets]
124
+ groups.to_set
125
+ else
126
+ groups
127
+ end
128
+ end
129
+ end
130
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Rollout
4
- VERSION = '2.4.5'
4
+ VERSION = '2.4.6'
5
5
  end
@@ -22,10 +22,10 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_dependency 'redis', '~> 4.0'
24
24
 
25
- spec.add_development_dependency 'bundler', '~> 1.17'
26
- spec.add_development_dependency 'fakeredis'
25
+ spec.add_development_dependency 'bundler', '>= 1.17'
26
+ spec.add_development_dependency 'pry'
27
27
  spec.add_development_dependency 'rspec', '~> 3.0'
28
28
  spec.add_development_dependency 'rspec_junit_formatter', '~> 0.4'
29
29
  spec.add_development_dependency 'rubocop', '~> 0.71'
30
- spec.add_development_dependency 'simplecov', '~> 0.16'
30
+ spec.add_development_dependency 'simplecov', '0.17'
31
31
  end
@@ -2,8 +2,7 @@ require "spec_helper"
2
2
 
3
3
  RSpec.describe "Rollout" do
4
4
  before do
5
- @redis = Redis.new
6
- @rollout = Rollout.new(@redis)
5
+ @rollout = Rollout.new(Redis.current)
7
6
  end
8
7
 
9
8
  describe "when a group is activated" do
@@ -5,8 +5,14 @@ require 'simplecov'
5
5
  SimpleCov.start
6
6
 
7
7
  require 'bundler/setup'
8
- require ENV["USE_REAL_REDIS"] == "true" ? "redis" : "fakeredis"
9
- require "rollout"
8
+ require 'redis'
9
+ require 'rollout'
10
+
11
+ Redis.current = Redis.new(
12
+ host: ENV.fetch('REDIS_HOST', '127.0.0.1'),
13
+ port: ENV.fetch('REDIS_PORT', '6379'),
14
+ db: ENV.fetch('REDIS_DB', '7'),
15
+ )
10
16
 
11
17
  RSpec.configure do |config|
12
18
  config.example_status_persistence_file_path = '.rspec_status'
@@ -17,5 +23,5 @@ RSpec.configure do |config|
17
23
  c.syntax = :expect
18
24
  end
19
25
 
20
- config.before { Redis.new.flushdb }
26
+ config.before { Redis.current.flushdb }
21
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rollout
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.5
4
+ version: 2.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Golick
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-07 00:00:00.000000000 Z
11
+ date: 2020-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -28,18 +28,18 @@ dependencies:
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.17'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.17'
41
41
  - !ruby/object:Gem::Dependency
42
- name: fakeredis
42
+ name: pry
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -98,16 +98,16 @@ dependencies:
98
98
  name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - '='
102
102
  - !ruby/object:Gem::Version
103
- version: '0.16'
103
+ version: '0.17'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
108
+ - - '='
109
109
  - !ruby/object:Gem::Version
110
- version: '0.16'
110
+ version: '0.17'
111
111
  description: Feature flippers with redis.
112
112
  email:
113
113
  - jamesgolick@gmail.com
@@ -121,11 +121,11 @@ files:
121
121
  - ".rubocop.yml"
122
122
  - ".travis.yml"
123
123
  - Gemfile
124
- - Gemfile.lock
125
124
  - LICENSE
126
125
  - README.md
127
126
  - Rakefile
128
127
  - lib/rollout.rb
128
+ - lib/rollout/feature.rb
129
129
  - lib/rollout/version.rb
130
130
  - rollout.gemspec
131
131
  - spec/rollout_spec.rb
@@ -1,65 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- rollout (2.4.5)
5
- redis (~> 4.0)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- ast (2.4.0)
11
- diff-lcs (1.3)
12
- docile (1.3.2)
13
- fakeredis (0.7.0)
14
- redis (>= 3.2, < 5.0)
15
- jaro_winkler (1.5.3)
16
- json (2.2.0)
17
- parallel (1.17.0)
18
- parser (2.6.3.0)
19
- ast (~> 2.4.0)
20
- rainbow (3.0.0)
21
- redis (4.1.2)
22
- rspec (3.8.0)
23
- rspec-core (~> 3.8.0)
24
- rspec-expectations (~> 3.8.0)
25
- rspec-mocks (~> 3.8.0)
26
- rspec-core (3.8.2)
27
- rspec-support (~> 3.8.0)
28
- rspec-expectations (3.8.4)
29
- diff-lcs (>= 1.2.0, < 2.0)
30
- rspec-support (~> 3.8.0)
31
- rspec-mocks (3.8.1)
32
- diff-lcs (>= 1.2.0, < 2.0)
33
- rspec-support (~> 3.8.0)
34
- rspec-support (3.8.2)
35
- rspec_junit_formatter (0.4.1)
36
- rspec-core (>= 2, < 4, != 2.12.0)
37
- rubocop (0.72.0)
38
- jaro_winkler (~> 1.5.1)
39
- parallel (~> 1.10)
40
- parser (>= 2.6)
41
- rainbow (>= 2.2.2, < 4.0)
42
- ruby-progressbar (~> 1.7)
43
- unicode-display_width (>= 1.4.0, < 1.7)
44
- ruby-progressbar (1.10.1)
45
- simplecov (0.16.1)
46
- docile (~> 1.1)
47
- json (>= 1.8, < 3)
48
- simplecov-html (~> 0.10.0)
49
- simplecov-html (0.10.2)
50
- unicode-display_width (1.6.0)
51
-
52
- PLATFORMS
53
- ruby
54
-
55
- DEPENDENCIES
56
- bundler (~> 1.17)
57
- fakeredis
58
- rollout!
59
- rspec (~> 3.0)
60
- rspec_junit_formatter (~> 0.4)
61
- rubocop (~> 0.71)
62
- simplecov (~> 0.16)
63
-
64
- BUNDLED WITH
65
- 1.17.2