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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 41aec86572fd574612c90eeaff7b250a38747428
4
- data.tar.gz: ff763fd1bfaddd9ec1e846edcd8d33b1bc8f1822
3
+ metadata.gz: 381bca60d1cdcef7b0e28496244aa7213c097821
4
+ data.tar.gz: 7dc6ba3581331d1287e11ef0591d81f74d3e1a72
5
5
  SHA512:
6
- metadata.gz: a4edb8f07f0afcac32d63b945472b2706db8716a2aa4995c77d7082961a5cc4457d0832dc7fc56e7993bb8c4e80b20870071d5d1aec61e839a420546570441a4
7
- data.tar.gz: 2f63fb2a3d1a039de45045b93ba6d75b2d6294785185158d148ac8407bf39bff8006e126e56487316fc7cec031aafc6cc5164830ed62d63b3adf9e4885aed564
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```
@@ -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-05-06'
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
- SENTENCES_BLAME = {
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
- SENTENCES_WARN = {
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
- SENTENCES_PRAISE = {
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, SENTENCES_BLAME[language])
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, SENTENCES_WARN[language])
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, SENTENCES_PRAISE[language])
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, args)
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
@@ -1,19 +1,21 @@
1
1
  module AgileNotifier
2
2
  class ITS
3
- def initialize(url)
4
- @url = url
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
- class Project
8
- def initialize(name)
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
- class Issue
14
- def initialize(id)
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
@@ -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.get_json_response(*args))
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 get_json_response(*args)
16
- response = HTTParty.get(*args)
17
- if response.code == 200
18
- return JSON.parse(response.body)
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
- raise(ResponseError, "HTTP Status Code: #{response.code} - #{response.parsed_response}", caller)
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
 
@@ -1,5 +1,5 @@
1
1
  Dir[(File.expand_path(File.dirname(__FILE__)) + "/agile_notifier/*.rb")].each { |file| require file }
2
2
 
3
3
  module AgileNotifier
4
- VERSION = '1.1.1'
4
+ VERSION = '2.0'
5
5
  end
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: 1.1.1
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-05-06 00:00:00.000000000 Z
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