agile_notifier 1.1.1 → 2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +12 -3
- data/agile_notifier.gemspec +1 -1
- data/lib/agile_notifier/composer.rb +34 -7
- data/lib/agile_notifier/configuration.rb +30 -5
- data/lib/agile_notifier/its.rb +12 -10
- data/lib/agile_notifier/jira.rb +43 -1
- data/lib/agile_notifier/judger.rb +8 -0
- data/lib/agile_notifier/response_helper.rb +12 -6
- data/lib/agile_notifier.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 381bca60d1cdcef7b0e28496244aa7213c097821
|
4
|
+
data.tar.gz: 7dc6ba3581331d1287e11ef0591d81f74d3e1a72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14097412a80312dcfadb891f78e9c24da4105a177f5e5145e84acb5b74aa101945da21f572d1396da69228b55e04783d982fdc25bb678ec35ea0b9a32e2114d8
|
7
|
+
data.tar.gz: 1b12fb78c97282349b18065f615d0924d3f67e5413987bc074d347353b176db1c2883016cef054520d5795c0acd3bb1926a86b1c841c2e426fcbacbbcc1cdded
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
.idea/
|
data/README.md
CHANGED
@@ -31,6 +31,17 @@ AgileNotifier::Configuration.set do
|
|
31
31
|
alert_on_fail
|
32
32
|
alert_on_fix
|
33
33
|
alert_on_unstable
|
34
|
+
|
35
|
+
its_url 'https://jira.atlassian.com'
|
36
|
+
its_auth 'jira_username', 'jira_password'
|
37
|
+
its_get 'Jira'
|
38
|
+
its_set_wip 'BAM', 'project = BAM AND status = Resolved AND resolution = Unresolved', 3
|
39
|
+
its_set_wip 'XXX', 'project = XXX AND status = Resolved AND resolution = Unresolved', 5
|
40
|
+
|
41
|
+
speak 'en'
|
42
|
+
play 'Alex'
|
43
|
+
|
44
|
+
alert_on_wip
|
34
45
|
end
|
35
46
|
```
|
36
47
|
|
@@ -39,6 +50,4 @@ end
|
|
39
50
|
|
40
51
|
* TTS service benefits from online MARY TTS Web Client: http://mary.dfki.de:59125/ While it has limited languages support, please check before use.
|
41
52
|
* play command comes from package sox which is not pre-installed, you have to install manually beforehand by:
|
42
|
-
* ```
|
43
|
-
sudo apt-get install sox libsox-fmt-all
|
44
|
-
```
|
53
|
+
* ```sudo apt-get install sox libsox-fmt-all```
|
data/agile_notifier.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.name = 'agile_notifier'
|
8
8
|
s.version = AgileNotifier::VERSION
|
9
9
|
s.license = 'MIT'
|
10
|
-
s.date = '2014-
|
10
|
+
s.date = '2014-08-25'
|
11
11
|
s.summary = %q{agile_notifier alerts you via making wonderful noises when your Continuous Integration status changes.}
|
12
12
|
s.description = %q{agile_notifier alerts you via making wonderful noises when your Continuous Integration status changes. It totally makes software development more agile and more fun.}
|
13
13
|
s.authors = ['Jing Li']
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module AgileNotifier
|
4
4
|
class Composer
|
5
|
-
|
5
|
+
SENTENCES_BLAME_COMMITTER = {
|
6
6
|
de: [
|
7
7
|
"%{committer_name} hat den Build kaputt gemacht.",
|
8
8
|
"Schießt %{committer_name} mit der Nerf Gun ab!",
|
@@ -26,7 +26,7 @@ module AgileNotifier
|
|
26
26
|
]
|
27
27
|
}
|
28
28
|
|
29
|
-
|
29
|
+
SENTENCES_WARN_COMMITTER = {
|
30
30
|
de: [
|
31
31
|
"%{committer_name} hat den Build krank gemacht.",
|
32
32
|
"%{committer_name} hat etwas nicht gut genug gemacht."
|
@@ -45,7 +45,7 @@ module AgileNotifier
|
|
45
45
|
]
|
46
46
|
}
|
47
47
|
|
48
|
-
|
48
|
+
SENTENCES_PRAISE_COMMITTER = {
|
49
49
|
de: [
|
50
50
|
"%{committer_name} hat den Build gefixt!",
|
51
51
|
"%{committer_name} ist ein Genie!",
|
@@ -69,7 +69,34 @@ module AgileNotifier
|
|
69
69
|
]
|
70
70
|
}
|
71
71
|
|
72
|
+
SENTENCES_WARN_WIP_LIMIT = {
|
73
|
+
de: [
|
74
|
+
"Kanban WIP übersteigt das Limit.",
|
75
|
+
"Kanban hat einen Flaschenhals.",
|
76
|
+
"Kanban hat zu viele Tickets, arbeitet jemand schon daran?"
|
77
|
+
],
|
78
|
+
en: [
|
79
|
+
"Kanban WIP exceeds limit.",
|
80
|
+
"Kanban has hit a bottleneck.",
|
81
|
+
"Kanban has stacked too many items, is anyone working on it?"
|
82
|
+
],
|
83
|
+
es: [
|
84
|
+
"El limite de WIP ha sido excedido.",
|
85
|
+
"El Kanban se esta llenando mucho.",
|
86
|
+
"Hay demasiados elementos Kanban, alguien esta trabajando en el?"
|
87
|
+
],
|
88
|
+
zh: [
|
89
|
+
"看板瓶颈上限超出",
|
90
|
+
"搞什么呢? 看板堆积太多工作了, 想被炒鱿鱼吗?",
|
91
|
+
"看板, 嘟嘟, 请注意. 看板, 嘟嘟, 请注意."
|
92
|
+
]
|
93
|
+
}
|
94
|
+
|
72
95
|
class << self
|
96
|
+
def warn_wip_limit(args)
|
97
|
+
random_picker(SENTENCES_WARN_WIP_LIMIT[args[:language]])
|
98
|
+
end
|
99
|
+
|
73
100
|
def blame_committer_of_a_commit(args)
|
74
101
|
committer_name = get_committer_name_of_a_commit(args)
|
75
102
|
blame_committer(committer_name, args[:language])
|
@@ -92,15 +119,15 @@ module AgileNotifier
|
|
92
119
|
end
|
93
120
|
|
94
121
|
def blame_committer(committer_name, language)
|
95
|
-
mention_committer(committer_name,
|
122
|
+
mention_committer(committer_name, SENTENCES_BLAME_COMMITTER[language])
|
96
123
|
end
|
97
124
|
|
98
125
|
def warn_committer(committer_name, language)
|
99
|
-
mention_committer(committer_name,
|
126
|
+
mention_committer(committer_name, SENTENCES_WARN_COMMITTER[language])
|
100
127
|
end
|
101
128
|
|
102
129
|
def praise_committer(committer_name, language)
|
103
|
-
mention_committer(committer_name,
|
130
|
+
mention_committer(committer_name, SENTENCES_PRAISE_COMMITTER[language])
|
104
131
|
end
|
105
132
|
|
106
133
|
def mention_committer(committer_name, sentences)
|
@@ -114,6 +141,6 @@ module AgileNotifier
|
|
114
141
|
end
|
115
142
|
end
|
116
143
|
|
117
|
-
private_class_method :get_committer_name_of_a_commit, :blame_committer, :praise_committer, :mention_committer, :random_picker
|
144
|
+
private_class_method :get_committer_name_of_a_commit, :blame_committer, :warn_committer, :praise_committer, :mention_committer, :random_picker
|
118
145
|
end
|
119
146
|
end
|
@@ -4,6 +4,7 @@ module AgileNotifier
|
|
4
4
|
class Configuration
|
5
5
|
def initialize(&blk)
|
6
6
|
@current_module = Object.const_get(self.class.to_s.split('::').first)
|
7
|
+
@its_args = Hash.new
|
7
8
|
instance_eval(&blk)
|
8
9
|
end
|
9
10
|
|
@@ -48,6 +49,22 @@ module AgileNotifier
|
|
48
49
|
return @scm
|
49
50
|
end
|
50
51
|
|
52
|
+
def its_url(url)
|
53
|
+
@its_args[:url] = url
|
54
|
+
end
|
55
|
+
|
56
|
+
def its_auth(username, password)
|
57
|
+
@its_args.merge!(:username => username, :password => password)
|
58
|
+
end
|
59
|
+
|
60
|
+
def its_get(its_type)
|
61
|
+
@its = @current_module.const_get(its_type).new(@its_args)
|
62
|
+
end
|
63
|
+
|
64
|
+
def its_set_wip(project, query, limit)
|
65
|
+
@its.set_limit(project, query, limit)
|
66
|
+
end
|
67
|
+
|
51
68
|
def speak(language)
|
52
69
|
@language = language.to_s.downcase.intern
|
53
70
|
end
|
@@ -69,18 +86,26 @@ module AgileNotifier
|
|
69
86
|
end
|
70
87
|
|
71
88
|
def alert(composer_type, judger_type)
|
72
|
-
args = Hash.new
|
73
|
-
args[:language] = @language
|
74
|
-
args[:voice] = @voice if @voice
|
75
89
|
composer_type = composer_type.to_s.downcase
|
76
90
|
judger_type = judger_type.to_s.downcase
|
77
91
|
composer_method = "#{composer_type}_committer_of_a_commit".intern
|
78
92
|
judger_method = "on_#{judger_type}".intern
|
79
93
|
text = Composer.send(composer_method, repo: @scm.repository, revision: @ci.job.last_build.revision, language: @language)
|
80
|
-
Judger.send(judger_method, @ci.job.last_build, text,
|
94
|
+
Judger.send(judger_method, @ci.job.last_build, text, organize_args)
|
95
|
+
end
|
96
|
+
|
97
|
+
def alert_on_wip
|
98
|
+
Judger.on_limit(@its, organize_args)
|
99
|
+
end
|
100
|
+
|
101
|
+
def organize_args
|
102
|
+
args = Hash.new
|
103
|
+
args[:language] = @language
|
104
|
+
args[:voice] = @voice if @voice
|
105
|
+
args
|
81
106
|
end
|
82
107
|
|
83
108
|
private_class_method :new
|
84
|
-
private :alert
|
109
|
+
private :alert, :organize_args
|
85
110
|
end
|
86
111
|
end
|
data/lib/agile_notifier/its.rb
CHANGED
@@ -1,19 +1,21 @@
|
|
1
1
|
module AgileNotifier
|
2
2
|
class ITS
|
3
|
-
|
4
|
-
|
3
|
+
include Servable
|
4
|
+
|
5
|
+
def initialize(args)
|
6
|
+
@url = args.fetch(:url)
|
7
|
+
end
|
8
|
+
|
9
|
+
def query_amount_of_tickets(query)
|
10
|
+
raise(NotImplementedError, "Abstract method [#{__method__}] is called, please implement", caller)
|
5
11
|
end
|
6
12
|
|
7
|
-
|
8
|
-
|
9
|
-
@name = name
|
10
|
-
end
|
13
|
+
def set_limit(project, query, limit)
|
14
|
+
raise(NotImplementedError, "Abstract method [#{__method__}] is called, please implement", caller)
|
11
15
|
end
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
@id = id
|
16
|
-
end
|
17
|
+
def exceeds_limit?
|
18
|
+
raise(NotImplementedError, "Abstract method [#{__method__}] is called, please implement", caller)
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
data/lib/agile_notifier/jira.rb
CHANGED
@@ -1,7 +1,49 @@
|
|
1
1
|
require_relative 'its'
|
2
|
+
require_relative 'response_helper'
|
2
3
|
|
3
4
|
module AgileNotifier
|
4
5
|
class Jira < ITS
|
5
|
-
|
6
|
+
include ResponseHelper
|
7
|
+
|
8
|
+
alias_method :original_is_available?, :is_available?
|
9
|
+
|
10
|
+
API_VERSION_URL = '/rest/api/latest/'
|
11
|
+
USERAGENT = 'AgileNotifier'
|
12
|
+
|
13
|
+
def initialize(args)
|
14
|
+
@url = args.fetch(:url).gsub(/\/$/, '') + API_VERSION_URL
|
15
|
+
@username = args.fetch(:username)
|
16
|
+
@password = args.fetch(:password)
|
17
|
+
@wip = Hash.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def is_available?
|
21
|
+
original_is_available?(@url + 'serverInfo')
|
22
|
+
end
|
23
|
+
|
24
|
+
def query_amount_of_tickets(jql)
|
25
|
+
get_value('total', jql)
|
26
|
+
end
|
27
|
+
|
28
|
+
def set_limit(project, query, limit)
|
29
|
+
@wip[project] = {:query => query, :limit => limit}
|
30
|
+
end
|
31
|
+
|
32
|
+
def exceeds_limit?
|
33
|
+
@wip.inject({}) do |result, (key, value)|
|
34
|
+
result.merge({key => query_amount_of_tickets(value[:query]) > value[:limit]})
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_value(key, jql, max = 1)
|
39
|
+
get_value_of_key(key,
|
40
|
+
@url + 'search',
|
41
|
+
:method => :post,
|
42
|
+
:headers => {'Content-Type' => 'application/json', 'User-Agent' => USERAGENT},
|
43
|
+
:basic_auth => {:username => @username, :password => @password},
|
44
|
+
:body => {'jql' => jql, 'maxResults' => max}.to_json)
|
45
|
+
end
|
46
|
+
|
47
|
+
private :get_value
|
6
48
|
end
|
7
49
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative 'tts'
|
2
|
+
require_relative 'composer'
|
2
3
|
|
3
4
|
module AgileNotifier
|
4
5
|
class Judger
|
@@ -19,6 +20,13 @@ module AgileNotifier
|
|
19
20
|
on_condition(trackable.fixed?, text, args)
|
20
21
|
end
|
21
22
|
|
23
|
+
def on_limit(its, args)
|
24
|
+
its.exceeds_limit?.each do |key, value|
|
25
|
+
on_condition(value, "#{key} #{Composer.warn_wip_limit(args)}", args)
|
26
|
+
sleep 1.5 if value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
22
30
|
def on_condition(condition, text, args)
|
23
31
|
if condition
|
24
32
|
TTS.speak(text, args)
|
@@ -8,16 +8,22 @@ module AgileNotifier
|
|
8
8
|
module ResponseHelper
|
9
9
|
def get_value_of_key(key, *args)
|
10
10
|
pm = PrivateMethods.new
|
11
|
-
pm.get_value_of_key_from_json(key, pm.
|
11
|
+
pm.get_value_of_key_from_json(key, pm.request_json_response(*args))
|
12
12
|
end
|
13
13
|
|
14
14
|
class PrivateMethods
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
def request_json_response(*args)
|
16
|
+
method = ((args[1].respond_to?(:delete) ? args[1].delete(:method) : false) || :get).to_sym
|
17
|
+
supported_methods = [:get, :post, :put, :delete, :head, :options]
|
18
|
+
unless supported_methods.include?(method)
|
19
|
+
raise(RuntimeError, "Unsupported HTTP Method: #{method.to_s}", caller)
|
19
20
|
else
|
20
|
-
|
21
|
+
response = HTTParty.send(method, *args)
|
22
|
+
if response.code.to_s.match(/^2\d{2}$/)
|
23
|
+
return JSON.parse(response.body)
|
24
|
+
else
|
25
|
+
raise(ResponseError, "HTTP Status Code: #{response.code} - #{response.parsed_response}", caller)
|
26
|
+
end
|
21
27
|
end
|
22
28
|
end
|
23
29
|
|
data/lib/agile_notifier.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: agile_notifier
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: '2.0'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jing Li
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -79,6 +79,7 @@ executables: []
|
|
79
79
|
extensions: []
|
80
80
|
extra_rdoc_files: []
|
81
81
|
files:
|
82
|
+
- .gitignore
|
82
83
|
- Gemfile
|
83
84
|
- Gemfile.lock
|
84
85
|
- README.md
|