rollout 2.4.5 → 2.4.6

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: 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