flipper-echo 0.0.1 → 0.0.2
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/.gitignore +1 -0
- data/README.md +50 -7
- data/lib/flipper/echo.rb +6 -4
- data/lib/flipper/echo/configuration.rb +27 -1
- data/lib/flipper/echo/event.rb +13 -7
- data/lib/flipper/echo/slack.rb +13 -0
- data/lib/flipper/echo/slack/message.rb +62 -0
- data/lib/flipper/echo/slack/notifier.rb +143 -0
- data/lib/flipper/echo/stdout.rb +12 -0
- data/lib/flipper/echo/stdout/notifier.rb +45 -0
- data/lib/flipper/echo/version.rb +1 -1
- data/spec/flipper/echo/configuration_spec.rb +12 -0
- data/spec/flipper/echo/event_spec.rb +5 -5
- data/spec/flipper/echo/slack/message_spec.rb +82 -0
- data/spec/flipper/echo/slack/notifier_spec.rb +126 -0
- data/spec/flipper/echo/stdout/notifier_spec.rb +52 -0
- data/spec/flipper/echo_spec.rb +4 -4
- metadata +13 -4
- data/spec/flipper/echo/version_spec.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b2f87cd93693142ff67b6ceeed1444b6f7b012f
|
4
|
+
data.tar.gz: 31f38685142d8e670acaf735beaea1432810b873
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d465bf8cf158efb1f6edb3c57ef6f952d9f6b2667cf39c59a1040884b7cbab83b69f2bd33758bd50187b47604b9385b635e65894bd91dcd92695e61582c59bb
|
7
|
+
data.tar.gz: 318e9de9d3ce75c78bd78d2802fecd91eb855f0120b55793428e7a3ee01896f3f56cbf5c004ed5855ba524969a931613f03cf1c4aec1e3faef2113167a0400ed
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
# Flipper::Echo
|
2
2
|
|
3
|
+
[](http://badge.fury.io/rb/flipper-echo)
|
4
|
+
|
3
5
|
This gem adds a simple callback interface for
|
4
6
|
[Flipper](https://github.com/jnunemaker/flipper) adapter events.
|
5
7
|
|
6
8
|
For example, when a Flipper feature is changed, you can:
|
7
9
|
|
8
|
-
* send a Slack notification
|
10
|
+
* send a Slack notification (built-in)
|
9
11
|
* write the change to a database or log file
|
12
|
+
* notify a performance monitoring application
|
10
13
|
* send a YO
|
11
14
|
|
12
15
|
## Installation
|
@@ -34,9 +37,9 @@ normally would (any adapter will do), e.g.:
|
|
34
37
|
FLIPPER = Flipper.new(Flipper::Adapters::Memory.new)
|
35
38
|
```
|
36
39
|
|
37
|
-
Then configure
|
40
|
+
Then configure this gem in any of the following ways:
|
38
41
|
|
39
|
-
####
|
42
|
+
#### Handle event with a proc
|
40
43
|
|
41
44
|
```ruby
|
42
45
|
Flipper::Echo.configure do |config|
|
@@ -50,12 +53,12 @@ Flipper::Echo.configure do |config|
|
|
50
53
|
end
|
51
54
|
```
|
52
55
|
|
53
|
-
####
|
56
|
+
#### Handle event with an object
|
54
57
|
|
55
|
-
|
58
|
+
You can provide any Ruby object with a `notify` method:
|
56
59
|
|
57
60
|
```ruby
|
58
|
-
class
|
61
|
+
class CustomNotifier
|
59
62
|
def notify(event)
|
60
63
|
# Do something with the event...
|
61
64
|
end
|
@@ -63,10 +66,46 @@ end
|
|
63
66
|
|
64
67
|
Flipper::Echo.configure do |config|
|
65
68
|
config.flipper = FLIPPER
|
66
|
-
config.notifier =
|
69
|
+
config.notifier = CustomNotifier.new
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
#### Configure multiple notifiers
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
Flipper::Echo.configure do |config|
|
77
|
+
config.flipper = FLIPPER
|
78
|
+
|
79
|
+
config.notifiers << NewrelicNotifier.new
|
80
|
+
config.notifiers << GraphiteNotifier.new
|
81
|
+
config.notifiers << Flipper::Echo::Stdout::Notifier.new
|
82
|
+
end
|
83
|
+
```
|
84
|
+
|
85
|
+
## Built-in notifiers
|
86
|
+
|
87
|
+
#### Slack
|
88
|
+
|
89
|
+
First [create a Slack webhook url](https://slack.com/services/new/incoming-webhook),
|
90
|
+
then use it in your configuration:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
Flipper::Echo.configure do |config|
|
94
|
+
config.notifiers << Flipper::Echo::Slack::Notifier.new(
|
95
|
+
'https://hooks.slack.com/your/webhook...', channel: '#eng')
|
67
96
|
end
|
68
97
|
```
|
69
98
|
|
99
|
+

|
100
|
+
|
101
|
+

|
102
|
+
|
103
|
+

|
104
|
+
|
105
|
+
## Documentation
|
106
|
+
|
107
|
+
[http://www.rubydoc.info/github/mode/flipper-echo/master](http://www.rubydoc.info/github/mode/flipper-echo/master)
|
108
|
+
|
70
109
|
## Contributing
|
71
110
|
|
72
111
|
1. Fork it ( https://github.com/mode/flipper-echo/fork )
|
@@ -74,3 +113,7 @@ end
|
|
74
113
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
75
114
|
4. Push to the branch (`git push origin my-new-feature`)
|
76
115
|
5. Create a new Pull Request
|
116
|
+
|
117
|
+
## Actual screenshots
|
118
|
+
|
119
|
+

|
data/lib/flipper/echo.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
#
|
3
3
|
require 'flipper/echo/configuration'
|
4
4
|
require 'flipper/echo/event'
|
5
|
+
require 'flipper/echo/slack'
|
6
|
+
require 'flipper/echo/stdout'
|
5
7
|
require 'flipper/echo/version'
|
6
8
|
|
7
9
|
# Flipper namespace
|
@@ -32,7 +34,7 @@ module Flipper
|
|
32
34
|
def enable(feature, gate, target)
|
33
35
|
super.tap do
|
34
36
|
Flipper::Echo::Event.new(
|
35
|
-
feature, :
|
37
|
+
feature, :enabled, gate: gate, target: target).notify
|
36
38
|
end
|
37
39
|
end
|
38
40
|
|
@@ -41,20 +43,20 @@ module Flipper
|
|
41
43
|
def disable(feature, gate, target)
|
42
44
|
super.tap do
|
43
45
|
Flipper::Echo::Event.new(
|
44
|
-
feature, :
|
46
|
+
feature, :disabled, gate: gate, target: target).notify
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
50
|
# Notify adapter remove events
|
49
51
|
#
|
50
52
|
def remove(feature)
|
51
|
-
super.tap { Flipper::Echo::Event.new(feature, :
|
53
|
+
super.tap { Flipper::Echo::Event.new(feature, :removed).notify }
|
52
54
|
end
|
53
55
|
|
54
56
|
# Notify adapter clear events
|
55
57
|
#
|
56
58
|
def clear(feature)
|
57
|
-
super.tap { Flipper::Echo::Event.new(feature, :
|
59
|
+
super.tap { Flipper::Echo::Event.new(feature, :cleared).notify }
|
58
60
|
end
|
59
61
|
end
|
60
62
|
end
|
@@ -10,7 +10,33 @@ module Flipper
|
|
10
10
|
# intended behavior.
|
11
11
|
#
|
12
12
|
class Configuration
|
13
|
-
|
13
|
+
# All configured notifiers
|
14
|
+
#
|
15
|
+
# @return [Array]
|
16
|
+
#
|
17
|
+
def notifiers
|
18
|
+
@notifiers ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
# Convenience method for assigning a single notifier
|
22
|
+
#
|
23
|
+
# @return [Array] all notifiers
|
24
|
+
#
|
25
|
+
def notifier=(notifier)
|
26
|
+
notifiers << notifier
|
27
|
+
end
|
28
|
+
|
29
|
+
# Optional environment name
|
30
|
+
#
|
31
|
+
attr_writer :environment
|
32
|
+
|
33
|
+
# Configured environment name
|
34
|
+
#
|
35
|
+
# @return [String]
|
36
|
+
#
|
37
|
+
def environment
|
38
|
+
@environment ||= ENV['FLIPPER_ECHO_ENVIRONMENT']
|
39
|
+
end
|
14
40
|
|
15
41
|
# Assign Flipper instance
|
16
42
|
#
|
data/lib/flipper/echo/event.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
#
|
3
|
+
require 'flipper'
|
4
|
+
|
3
5
|
module Flipper
|
4
6
|
module Echo
|
5
7
|
# Encapsulates relevant information about a Flipper adapter event
|
@@ -11,7 +13,7 @@ module Flipper
|
|
11
13
|
#
|
12
14
|
# @param feature [Flipper::Feature] the feature that was changed
|
13
15
|
# @param action [Symbol] the action
|
14
|
-
# (`:
|
16
|
+
# (`:enabled`, `:disabled`, `:removed` or `:cleared`)
|
15
17
|
# @param options [optional, Hash] hash of options
|
16
18
|
#
|
17
19
|
# @option options [Flipper::Type] :target the event target
|
@@ -68,10 +70,14 @@ module Flipper
|
|
68
70
|
# Passes this event to the configured notifier
|
69
71
|
#
|
70
72
|
def notify
|
71
|
-
|
72
|
-
notifier.
|
73
|
-
|
74
|
-
|
73
|
+
notifiers.each do |notifier|
|
74
|
+
method = if notifier.is_a?(Proc)
|
75
|
+
:call
|
76
|
+
elsif notifier.respond_to?(:notify)
|
77
|
+
:notify
|
78
|
+
end
|
79
|
+
|
80
|
+
notifier.send(method, self) if method
|
75
81
|
end
|
76
82
|
end
|
77
83
|
|
@@ -93,8 +99,8 @@ module Flipper
|
|
93
99
|
|
94
100
|
private
|
95
101
|
|
96
|
-
def
|
97
|
-
Flipper::Echo.configuration.
|
102
|
+
def notifiers
|
103
|
+
Flipper::Echo.configuration.notifiers
|
98
104
|
end
|
99
105
|
end
|
100
106
|
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
module Flipper
|
4
|
+
module Echo
|
5
|
+
module Slack
|
6
|
+
# Slack message formatter
|
7
|
+
#
|
8
|
+
class Message
|
9
|
+
attr_reader :event
|
10
|
+
|
11
|
+
# Construct a new Message instance
|
12
|
+
#
|
13
|
+
# @param event [Flipper::Echo::Event] the Flipper event
|
14
|
+
#
|
15
|
+
# @return [Flipper::Echo::Slack::Message] the instance
|
16
|
+
#
|
17
|
+
def initialize(event)
|
18
|
+
@event = event
|
19
|
+
end
|
20
|
+
|
21
|
+
# Build message body
|
22
|
+
#
|
23
|
+
# @return [String] the message body
|
24
|
+
#
|
25
|
+
def to_s
|
26
|
+
[base, event.action, filters].compact.join(' ')
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# @return [String]
|
32
|
+
#
|
33
|
+
def base
|
34
|
+
parts = []
|
35
|
+
parts << "[*#{environment}*]" if environment
|
36
|
+
parts << "Feature `#{event.feature.name}`"
|
37
|
+
parts.join(' ')
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [String, nil]
|
41
|
+
#
|
42
|
+
def filters
|
43
|
+
if event.group
|
44
|
+
"for group `#{event.group.name}`"
|
45
|
+
elsif event.actor
|
46
|
+
"for actor `#{event.actor.flipper_id}`"
|
47
|
+
elsif event.percentage_of_actors
|
48
|
+
"for #{event.percentage_of_actors.value}% of actors"
|
49
|
+
elsif event.percentage_of_random
|
50
|
+
"for #{event.percentage_of_random.value}% of random"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# @return [String, nil]
|
55
|
+
#
|
56
|
+
def environment
|
57
|
+
Flipper::Echo.configuration.environment
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
require 'json'
|
4
|
+
require 'net/https'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
module Flipper
|
8
|
+
module Echo
|
9
|
+
module Slack
|
10
|
+
# Customizable Slack webhook notifier
|
11
|
+
#
|
12
|
+
class Notifier
|
13
|
+
attr_reader :webhook_url, :options
|
14
|
+
|
15
|
+
# Construct a new Notifier instance
|
16
|
+
#
|
17
|
+
# @param webhook_url [String] the Slack webhook url
|
18
|
+
# @param options [optional, Hash] hash of options
|
19
|
+
#
|
20
|
+
# @option options [String] :username Slack bot username
|
21
|
+
# @option options [String] :channel name of Slack channel
|
22
|
+
# @option options [String] :icon_url the message icon url
|
23
|
+
#
|
24
|
+
# @return [Flipper::Echo::Slack::Notifier] the instance
|
25
|
+
#
|
26
|
+
def initialize(webhook_url, options = {})
|
27
|
+
@webhook_url = webhook_url
|
28
|
+
@options = self.class.symbolize_keys(options)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Normalized channel name
|
32
|
+
#
|
33
|
+
# @return [String, nil]
|
34
|
+
#
|
35
|
+
def channel
|
36
|
+
@channel ||= self.class.normalize_channel(options[:channel])
|
37
|
+
end
|
38
|
+
|
39
|
+
# Slack message username
|
40
|
+
#
|
41
|
+
# @return [String, nil]
|
42
|
+
#
|
43
|
+
def username
|
44
|
+
options.fetch(:username, DEFAULT_USERNAME)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Slack message icon url
|
48
|
+
#
|
49
|
+
# @return [String, nil]
|
50
|
+
#
|
51
|
+
def icon_url
|
52
|
+
options.fetch(:icon_url, DEFAULT_ICON_URL)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Post notification to Slack webhook url
|
56
|
+
#
|
57
|
+
# @return [HTTPResponse]
|
58
|
+
#
|
59
|
+
def notify(event)
|
60
|
+
message = Flipper::Echo::Slack::Message.new(event)
|
61
|
+
|
62
|
+
payload = {
|
63
|
+
text: message.to_s,
|
64
|
+
channel: channel,
|
65
|
+
username: username,
|
66
|
+
icon_url: icon_url
|
67
|
+
}
|
68
|
+
|
69
|
+
post(payload)
|
70
|
+
end
|
71
|
+
|
72
|
+
class << self
|
73
|
+
# Normalize Slack channel name for API
|
74
|
+
#
|
75
|
+
# @param name [String] the original name
|
76
|
+
#
|
77
|
+
# @return [String] the normalized name
|
78
|
+
#
|
79
|
+
def normalize_channel(name)
|
80
|
+
return unless name && name.size > 0
|
81
|
+
|
82
|
+
name =~ /\A[#@]/ ? name : "##{name}"
|
83
|
+
end
|
84
|
+
|
85
|
+
# Symbolize hash keys
|
86
|
+
#
|
87
|
+
# @param hash [Hash] the original hash
|
88
|
+
#
|
89
|
+
# @return [Hash] hash with symbolized keys
|
90
|
+
#
|
91
|
+
def symbolize_keys(hash)
|
92
|
+
hash.each_with_object({}) do |(key, value), result|
|
93
|
+
result[key.to_sym] = value
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
DEFAULT_USERNAME = 'Flipper'
|
101
|
+
|
102
|
+
DEFAULT_ICON_URL =
|
103
|
+
'https://s3-us-west-2.amazonaws.com/mode.production/' \
|
104
|
+
'flipper-echo/flipper-echo-icon-132.png'
|
105
|
+
|
106
|
+
# @return [Net::HTTP]
|
107
|
+
#
|
108
|
+
def http
|
109
|
+
@http ||= Net::HTTP.new(uri.host, uri.port).tap do |result|
|
110
|
+
result.use_ssl = ssl?
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# @return [URI]
|
115
|
+
#
|
116
|
+
def uri
|
117
|
+
@uri ||= URI.parse(webhook_url)
|
118
|
+
end
|
119
|
+
|
120
|
+
# @return [true, false]
|
121
|
+
#
|
122
|
+
def ssl?
|
123
|
+
uri.scheme == 'https'
|
124
|
+
end
|
125
|
+
|
126
|
+
# @return [HTTPResponse]
|
127
|
+
#
|
128
|
+
def post(payload)
|
129
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
130
|
+
request.set_content_type('application/json')
|
131
|
+
request.body = payload.to_json
|
132
|
+
|
133
|
+
http.request(request).tap do |response|
|
134
|
+
unless response.code == '200'
|
135
|
+
$stderr.puts 'Unexpected Slack notifier response: ' \
|
136
|
+
"#{response.code}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
module Flipper
|
4
|
+
module Echo
|
5
|
+
module Stdout
|
6
|
+
# Simple stdout notifier intended as a basis for more advanced custom
|
7
|
+
# notifiers
|
8
|
+
#
|
9
|
+
class Notifier
|
10
|
+
# Send notification message to stdout
|
11
|
+
#
|
12
|
+
# @return [nil]
|
13
|
+
#
|
14
|
+
def notify(event)
|
15
|
+
parts = []
|
16
|
+
parts << '[Flipper]'
|
17
|
+
parts << "Feature \"#{event.feature.name}\""
|
18
|
+
parts << event.action
|
19
|
+
|
20
|
+
target = target_message(event)
|
21
|
+
|
22
|
+
parts << "for #{target}" if target
|
23
|
+
|
24
|
+
$stdout.puts(parts.join(' '))
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# @return [String, nil]
|
30
|
+
#
|
31
|
+
def target_message(event)
|
32
|
+
if event.group
|
33
|
+
"group #{event.group.name}"
|
34
|
+
elsif event.actor
|
35
|
+
"actor #{event.actor.flipper_id}"
|
36
|
+
elsif event.percentage_of_actors
|
37
|
+
"#{event.percentage_of_actors.value}% of actors"
|
38
|
+
elsif event.percentage_of_random
|
39
|
+
"#{event.percentage_of_random.value}% of random"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/flipper/echo/version.rb
CHANGED
@@ -30,4 +30,16 @@ describe Flipper::Echo::Configuration do
|
|
30
30
|
configuration.flipper = flipper
|
31
31
|
end
|
32
32
|
end
|
33
|
+
|
34
|
+
describe '#notifier=' do
|
35
|
+
it 'appends notifier' do
|
36
|
+
notifier = double(:notifier)
|
37
|
+
|
38
|
+
expect(configuration.notifiers).to eq([])
|
39
|
+
|
40
|
+
configuration.notifier = notifier
|
41
|
+
|
42
|
+
expect(configuration.notifiers).to eq([notifier])
|
43
|
+
end
|
44
|
+
end
|
33
45
|
end
|
@@ -123,7 +123,7 @@ describe Flipper::Echo::Event do
|
|
123
123
|
it 'calls proc' do
|
124
124
|
procedure = proc {}
|
125
125
|
|
126
|
-
allow(event).to receive(:
|
126
|
+
allow(event).to receive(:notifiers).and_return([procedure])
|
127
127
|
|
128
128
|
expect(procedure).to receive(:call)
|
129
129
|
|
@@ -137,7 +137,7 @@ describe Flipper::Echo::Event do
|
|
137
137
|
end
|
138
138
|
|
139
139
|
it 'calls instance method if it exists' do
|
140
|
-
allow(event).to receive(:
|
140
|
+
allow(event).to receive(:notifiers).and_return([notifier])
|
141
141
|
|
142
142
|
expect(notifier).to receive(:notify)
|
143
143
|
|
@@ -160,18 +160,18 @@ describe Flipper::Echo::Event do
|
|
160
160
|
end
|
161
161
|
end
|
162
162
|
|
163
|
-
describe '#
|
163
|
+
describe '#notifiers' do
|
164
164
|
let :notifier do
|
165
165
|
double(:notifier)
|
166
166
|
end
|
167
167
|
|
168
168
|
it 'returns notifier from config' do
|
169
169
|
allow(Flipper::Echo.configuration).to(
|
170
|
-
receive(:
|
170
|
+
receive(:notifiers).and_return([notifier]))
|
171
171
|
|
172
172
|
event = Flipper::Echo::Event.new(feature, action)
|
173
173
|
|
174
|
-
expect(event.send(:
|
174
|
+
expect(event.send(:notifiers)).to eq([notifier])
|
175
175
|
end
|
176
176
|
end
|
177
177
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Flipper::Echo::Slack::Message do
|
6
|
+
let :feature do
|
7
|
+
double(:feature, name: :experimental)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#base' do
|
11
|
+
let :event do
|
12
|
+
Flipper::Echo::Event.new(feature, :enabled)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'builds expected string without environment' do
|
16
|
+
message = Flipper::Echo::Slack::Message.new(event)
|
17
|
+
|
18
|
+
expect(message.send(:base)).to eq('Feature `experimental`')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'builds expected string with environment' do
|
22
|
+
message = Flipper::Echo::Slack::Message.new(event)
|
23
|
+
|
24
|
+
allow(message).to receive(:environment).and_return('staging')
|
25
|
+
|
26
|
+
expect(message.send(:base)).to eq('[*staging*] Feature `experimental`')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#filters' do
|
31
|
+
it 'builds group string' do
|
32
|
+
event = Flipper::Echo::Event.new(feature, :disabled)
|
33
|
+
message = Flipper::Echo::Slack::Message.new(event)
|
34
|
+
|
35
|
+
group = double(:group, name: 'admins')
|
36
|
+
allow(event).to receive(:group).and_return(group)
|
37
|
+
|
38
|
+
expect(message.send(:filters)).to eq('for group `admins`')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'builds actor string' do
|
42
|
+
event = Flipper::Echo::Event.new(feature, :disabled)
|
43
|
+
message = Flipper::Echo::Slack::Message.new(event)
|
44
|
+
|
45
|
+
actor = double(:actor, flipper_id: 'Actor:1')
|
46
|
+
allow(event).to receive(:actor).and_return(actor)
|
47
|
+
|
48
|
+
expect(message.send(:filters)).to eq('for actor `Actor:1`')
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'builds percentage of actors string' do
|
52
|
+
event = Flipper::Echo::Event.new(feature, :disabled)
|
53
|
+
message = Flipper::Echo::Slack::Message.new(event)
|
54
|
+
|
55
|
+
percentage = double(:percentage, value: '10')
|
56
|
+
allow(event).to receive(:percentage_of_actors).and_return(percentage)
|
57
|
+
|
58
|
+
expect(message.send(:filters)).to eq('for 10% of actors')
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'builds percentage of random string' do
|
62
|
+
event = Flipper::Echo::Event.new(feature, :disabled)
|
63
|
+
message = Flipper::Echo::Slack::Message.new(event)
|
64
|
+
|
65
|
+
percentage = double(:percentage, value: '10')
|
66
|
+
allow(event).to receive(:percentage_of_random).and_return(percentage)
|
67
|
+
|
68
|
+
expect(message.send(:filters)).to eq('for 10% of random')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#environment' do
|
73
|
+
it 'returns configured environment' do
|
74
|
+
allow(Flipper::Echo.configuration).to(
|
75
|
+
receive(:environment).and_return('staging'))
|
76
|
+
|
77
|
+
message = Flipper::Echo::Slack::Message.new(nil)
|
78
|
+
|
79
|
+
expect(message.send(:environment)).to eq('staging')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Flipper::Echo::Slack::Notifier do
|
6
|
+
describe '#channel' do
|
7
|
+
it 'is null if options do not include channel' do
|
8
|
+
notifier = Flipper::Echo::Slack::Notifier.new('https://hook')
|
9
|
+
|
10
|
+
expect(notifier.channel).to eq(nil)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns channel from options without prepending' do
|
14
|
+
notifier = Flipper::Echo::Slack::Notifier.new(
|
15
|
+
'https://hook', channel: '#custom_channel')
|
16
|
+
|
17
|
+
expect(notifier.channel).to eq('#custom_channel')
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns channel from options with prepending' do
|
21
|
+
notifier = Flipper::Echo::Slack::Notifier.new(
|
22
|
+
'https://hook', channel: 'custom_channel')
|
23
|
+
|
24
|
+
expect(notifier.channel).to eq('#custom_channel')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#username' do
|
29
|
+
it 'is default if options do not include username' do
|
30
|
+
notifier = Flipper::Echo::Slack::Notifier.new('https://hook')
|
31
|
+
|
32
|
+
expect(notifier.username).to eq('Flipper')
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'returns username from options' do
|
36
|
+
notifier = Flipper::Echo::Slack::Notifier.new(
|
37
|
+
'https://hook', username: 'Custom Username')
|
38
|
+
|
39
|
+
expect(notifier.username).to eq('Custom Username')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#icon_url' do
|
44
|
+
it 'is default if options do not include url' do
|
45
|
+
notifier = Flipper::Echo::Slack::Notifier.new('https://hook')
|
46
|
+
|
47
|
+
expect(notifier.icon_url).to match(/flipper\-echo\-icon/)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'returns username from options' do
|
51
|
+
notifier = Flipper::Echo::Slack::Notifier.new(
|
52
|
+
'https://hook', icon_url: 'custom-icon')
|
53
|
+
|
54
|
+
expect(notifier.icon_url).to eq('custom-icon')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#notify' do
|
59
|
+
let :feature do
|
60
|
+
double(:feature, name: :experimental)
|
61
|
+
end
|
62
|
+
|
63
|
+
let :event do
|
64
|
+
Flipper::Echo::Event.new(feature, :action)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'calls notifier with expected options' do
|
68
|
+
notifier = Flipper::Echo::Slack::Notifier.new('https://hook')
|
69
|
+
|
70
|
+
expect(notifier).to receive(:post) do |options|
|
71
|
+
expect(options[:text]).to match(/experimental/)
|
72
|
+
end
|
73
|
+
|
74
|
+
notifier.notify(event)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '#post' do
|
79
|
+
it 'posts expected json payload' do
|
80
|
+
notifier = Flipper::Echo::Slack::Notifier.new('https://hook')
|
81
|
+
|
82
|
+
expect(notifier.send(:http)).to receive(:request) do |request|
|
83
|
+
expect(request.body).to eq('{"foo":"bar"}')
|
84
|
+
expect(request.content_type).to eq('application/json')
|
85
|
+
|
86
|
+
double(:response, code: '200')
|
87
|
+
end
|
88
|
+
|
89
|
+
notifier.send(:post, foo: 'bar')
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'prints unexpected api response to stderr' do
|
93
|
+
notifier = Flipper::Echo::Slack::Notifier.new('https://hook')
|
94
|
+
|
95
|
+
expect(notifier.send(:http)).to(
|
96
|
+
receive(:request).and_return(double(:response, code: '404')))
|
97
|
+
|
98
|
+
expect { notifier.send(:post, foo: 'bar') }.to output.to_stderr
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '.normalize_channel' do
|
103
|
+
it 'is nil for blank name' do
|
104
|
+
expect(Flipper::Echo::Slack::Notifier.normalize_channel(nil)).to eq(nil)
|
105
|
+
expect(Flipper::Echo::Slack::Notifier.normalize_channel('')).to eq(nil)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'preserves name including number sign' do
|
109
|
+
result = Flipper::Echo::Slack::Notifier.normalize_channel('#channel_name')
|
110
|
+
|
111
|
+
expect(result).to eq('#channel_name')
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'prepends number sign if necessary' do
|
115
|
+
result = Flipper::Echo::Slack::Notifier.normalize_channel('channel_name')
|
116
|
+
|
117
|
+
expect(result).to eq('#channel_name')
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'preserves at sign' do
|
121
|
+
result = Flipper::Echo::Slack::Notifier.normalize_channel('@channel_name')
|
122
|
+
|
123
|
+
expect(result).to eq('@channel_name')
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
#
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Flipper::Echo::Stdout::Notifier do
|
6
|
+
let :feature do
|
7
|
+
double(:feature, name: :experimental)
|
8
|
+
end
|
9
|
+
|
10
|
+
let :event do
|
11
|
+
Flipper::Echo::Event.new(feature, :enabled)
|
12
|
+
end
|
13
|
+
|
14
|
+
let :notifier do
|
15
|
+
Flipper::Echo::Stdout::Notifier.new
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#notify' do
|
19
|
+
it 'sends message to stdout' do
|
20
|
+
expect { notifier.notify(event) }.to output.to_stdout
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#target_message' do
|
25
|
+
it 'builds group message' do
|
26
|
+
allow(event).to receive(:group).and_return(double(:group, name: :admins))
|
27
|
+
|
28
|
+
expect(notifier.send(:target_message, event)).to eq('group admins')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'builds actor message' do
|
32
|
+
allow(event).to(
|
33
|
+
receive(:actor).and_return(double(:actor, flipper_id: 'id')))
|
34
|
+
|
35
|
+
expect(notifier.send(:target_message, event)).to eq('actor id')
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'builds percentage of actors message' do
|
39
|
+
allow(event).to(
|
40
|
+
receive(:percentage_of_actors).and_return(double(:actors, value: 15)))
|
41
|
+
|
42
|
+
expect(notifier.send(:target_message, event)).to eq('15% of actors')
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'builds percentage of random message' do
|
46
|
+
allow(event).to(
|
47
|
+
receive(:percentage_of_random).and_return(double(:random, value: 15)))
|
48
|
+
|
49
|
+
expect(notifier.send(:target_message, event)).to eq('15% of random')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/spec/flipper/echo_spec.rb
CHANGED
@@ -43,7 +43,7 @@ describe Flipper::Echo do
|
|
43
43
|
describe '#enable' do
|
44
44
|
it 'enables feature' do
|
45
45
|
expect_any_instance_of(Flipper::Echo::Event).to receive(:notify) do |e|
|
46
|
-
expect(e.action).to eq(:
|
46
|
+
expect(e.action).to eq(:enabled)
|
47
47
|
end
|
48
48
|
|
49
49
|
adapter.enable(feature, gate, target)
|
@@ -53,7 +53,7 @@ describe Flipper::Echo do
|
|
53
53
|
describe '#disable' do
|
54
54
|
it 'disables feature' do
|
55
55
|
expect_any_instance_of(Flipper::Echo::Event).to receive(:notify) do |e|
|
56
|
-
expect(e.action).to eq(:
|
56
|
+
expect(e.action).to eq(:disabled)
|
57
57
|
end
|
58
58
|
|
59
59
|
adapter.disable(feature, gate, target)
|
@@ -63,7 +63,7 @@ describe Flipper::Echo do
|
|
63
63
|
describe '#remove' do
|
64
64
|
it 'removes feature' do
|
65
65
|
expect_any_instance_of(Flipper::Echo::Event).to receive(:notify) do |e|
|
66
|
-
expect(e.action).to eq(:
|
66
|
+
expect(e.action).to eq(:removed)
|
67
67
|
end
|
68
68
|
|
69
69
|
adapter.remove(feature)
|
@@ -73,7 +73,7 @@ describe Flipper::Echo do
|
|
73
73
|
describe '#clear' do
|
74
74
|
it 'clears feature' do
|
75
75
|
expect_any_instance_of(Flipper::Echo::Event).to receive(:notify) do |e|
|
76
|
-
expect(e.action).to eq(:
|
76
|
+
expect(e.action).to eq(:cleared)
|
77
77
|
end
|
78
78
|
|
79
79
|
adapter.clear(feature)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flipper-echo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Heather Rivers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: flipper
|
@@ -110,10 +110,17 @@ files:
|
|
110
110
|
- lib/flipper/echo.rb
|
111
111
|
- lib/flipper/echo/configuration.rb
|
112
112
|
- lib/flipper/echo/event.rb
|
113
|
+
- lib/flipper/echo/slack.rb
|
114
|
+
- lib/flipper/echo/slack/message.rb
|
115
|
+
- lib/flipper/echo/slack/notifier.rb
|
116
|
+
- lib/flipper/echo/stdout.rb
|
117
|
+
- lib/flipper/echo/stdout/notifier.rb
|
113
118
|
- lib/flipper/echo/version.rb
|
114
119
|
- spec/flipper/echo/configuration_spec.rb
|
115
120
|
- spec/flipper/echo/event_spec.rb
|
116
|
-
- spec/flipper/echo/
|
121
|
+
- spec/flipper/echo/slack/message_spec.rb
|
122
|
+
- spec/flipper/echo/slack/notifier_spec.rb
|
123
|
+
- spec/flipper/echo/stdout/notifier_spec.rb
|
117
124
|
- spec/flipper/echo_spec.rb
|
118
125
|
- spec/spec_helper.rb
|
119
126
|
- spec/support/adapter_support.rb
|
@@ -144,7 +151,9 @@ summary: Flipper event notifier
|
|
144
151
|
test_files:
|
145
152
|
- spec/flipper/echo/configuration_spec.rb
|
146
153
|
- spec/flipper/echo/event_spec.rb
|
147
|
-
- spec/flipper/echo/
|
154
|
+
- spec/flipper/echo/slack/message_spec.rb
|
155
|
+
- spec/flipper/echo/slack/notifier_spec.rb
|
156
|
+
- spec/flipper/echo/stdout/notifier_spec.rb
|
148
157
|
- spec/flipper/echo_spec.rb
|
149
158
|
- spec/spec_helper.rb
|
150
159
|
- spec/support/adapter_support.rb
|
File without changes
|