opsask 2.0.0 → 2.0.1
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/Gemfile.lock +6 -6
- data/VERSION +1 -1
- data/lib/opsask/app.rb +101 -15
- data/opsask.gemspec +1 -1
- data/public/css/style.css +38 -0
- data/views/stats.erb +42 -0
- metadata +12 -16
- data/.yardoc/checksums +0 -4
- data/.yardoc/object_types +0 -0
- data/.yardoc/objects/root.dat +0 -0
- data/.yardoc/proxy_types +0 -0
- data/views/agile.erb +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cbff03a2754db23e2c4924d402c479430b57eae0
|
4
|
+
data.tar.gz: 34b9c28797098d3329167157effee3421fde796e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67de8c2f12b86598b6a6d1c6f3a33033bcbcf945710d4b09a456d4bd953dc99a7aabeacc1017a706668e337a51220d6ec9ca94ad0f80d2caf76e852b6db1e3fc
|
7
|
+
data.tar.gz: 9a3d53f75530f62ecdf57d64e6ed6bf578d9fe57c43dea8d5b742b1d84a608037e73e54b09a7710524d9ed172c99e9c07b9d2663005b5aecca9fa018000f2ef0
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -3,9 +3,9 @@ PATH
|
|
3
3
|
specs:
|
4
4
|
opsask (2.0.0)
|
5
5
|
curb (~> 0.8)
|
6
|
-
jira-ruby (~> 0.1)
|
7
6
|
rack (~> 1)
|
8
7
|
rack-flash3 (~> 1)
|
8
|
+
sclemmer-jira-ruby (~> 0.1)
|
9
9
|
sinatra (~> 1.4)
|
10
10
|
sinatra-partial (~> 0.4)
|
11
11
|
thin (~> 1)
|
@@ -14,7 +14,7 @@ PATH
|
|
14
14
|
GEM
|
15
15
|
remote: https://rubygems.org/
|
16
16
|
specs:
|
17
|
-
activesupport (4.1.
|
17
|
+
activesupport (4.1.8)
|
18
18
|
i18n (~> 0.6, >= 0.6.9)
|
19
19
|
json (~> 1.7, >= 1.7.7)
|
20
20
|
minitest (~> 5.1)
|
@@ -25,9 +25,6 @@ GEM
|
|
25
25
|
daemons (1.1.9)
|
26
26
|
eventmachine (1.0.3)
|
27
27
|
i18n (0.6.11)
|
28
|
-
jira-ruby (0.1.11)
|
29
|
-
activesupport (~> 4.1.4)
|
30
|
-
oauth (~> 0.4.7)
|
31
28
|
json (1.8.1)
|
32
29
|
method_source (0.8.2)
|
33
30
|
minitest (5.4.3)
|
@@ -43,6 +40,9 @@ GEM
|
|
43
40
|
rack
|
44
41
|
rake (10.3.2)
|
45
42
|
rubygems-tasks (0.2.4)
|
43
|
+
sclemmer-jira-ruby (0.1.12)
|
44
|
+
activesupport (~> 4.1.4)
|
45
|
+
oauth (~> 0.4.7)
|
46
46
|
sinatra (1.4.5)
|
47
47
|
rack (~> 1.4)
|
48
48
|
rack-protection (~> 1.4)
|
@@ -60,7 +60,7 @@ GEM
|
|
60
60
|
tzinfo (1.2.2)
|
61
61
|
thread_safe (~> 0.1)
|
62
62
|
version (1.0.0)
|
63
|
-
yard (0.8.7.
|
63
|
+
yard (0.8.7.6)
|
64
64
|
|
65
65
|
PLATFORMS
|
66
66
|
ruby
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0.
|
1
|
+
2.0.1
|
data/lib/opsask/app.rb
CHANGED
@@ -55,18 +55,41 @@ module OpsAsk
|
|
55
55
|
end
|
56
56
|
|
57
57
|
get '/sprint/:sprint_num' do
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
num = params[:sprint_num]
|
59
|
+
sprint = get_sprint(num)
|
60
|
+
id = sprint['id']
|
61
|
+
erb :stats, locals: {
|
62
|
+
sprint: sprint,
|
63
|
+
ask_stats: stats_for(
|
64
|
+
asks_in_sprint(num),
|
65
|
+
"#{settings.config[:jira_url]}/issues/?jql=#{URI::escape "labels in (Sprint#{num}) AND resolution is not EMPTY"}",
|
66
|
+
"#{settings.config[:jira_url]}/issues/?jql=#{URI::escape "labels in (Sprint#{num}) AND resolution is EMPTY"}"
|
67
|
+
),
|
68
|
+
sprint_stats: stats_for(
|
69
|
+
items_in_sprint(num),
|
70
|
+
"#{settings.config[:jira_url]}/issues/?jql=#{URI::escape "sprint = #{id} AND resolution is not EMPTY"}",
|
71
|
+
"#{settings.config[:jira_url]}/issues/?jql=#{URI::escape "sprint = #{id} AND resolution is EMPTY"}"
|
72
|
+
),
|
61
73
|
untracked_jiras: untracked_issues,
|
62
74
|
stragglers: straggling_issues
|
63
75
|
}
|
64
76
|
end
|
65
77
|
|
66
|
-
get '/
|
67
|
-
|
68
|
-
|
69
|
-
|
78
|
+
get '/sprint' do
|
79
|
+
num = current_sprint_num
|
80
|
+
id = current_sprint_id
|
81
|
+
erb :stats, locals: {
|
82
|
+
sprint: current_sprint,
|
83
|
+
ask_stats: stats_for(
|
84
|
+
asks_in_current_sprint,
|
85
|
+
"#{settings.config[:jira_url]}/issues/?jql=#{URI::escape "labels in (Sprint#{num}) AND resolution is not EMPTY"}",
|
86
|
+
"#{settings.config[:jira_url]}/issues/?jql=#{URI::escape "labels in (Sprint#{num}) AND resolution is EMPTY"}"
|
87
|
+
),
|
88
|
+
sprint_stats: stats_for(
|
89
|
+
items_in_current_sprint,
|
90
|
+
"#{settings.config[:jira_url]}/issues/?jql=#{URI::escape "sprint = #{id} AND resolution is not EMPTY"}",
|
91
|
+
"#{settings.config[:jira_url]}/issues/?jql=#{URI::escape "sprint = #{id} AND resolution is EMPTY"}"
|
92
|
+
),
|
70
93
|
untracked_jiras: untracked_issues,
|
71
94
|
stragglers: straggling_issues
|
72
95
|
}
|
@@ -216,14 +239,68 @@ module OpsAsk
|
|
216
239
|
return date
|
217
240
|
end
|
218
241
|
|
242
|
+
def stats_for issues, resolved_link, unresolved_link
|
243
|
+
return {} unless logged_in?
|
244
|
+
return {} unless issues
|
245
|
+
|
246
|
+
resolved_issues, unresolved_issues = [], []
|
247
|
+
|
248
|
+
issues.map! do |i|
|
249
|
+
key = i['key']
|
250
|
+
status = i['fields']['status']['name']
|
251
|
+
resolution = i['fields']['resolution']['name'] rescue nil
|
252
|
+
points = i['fields']['customfield_10002'].to_i
|
253
|
+
|
254
|
+
issue = {
|
255
|
+
key: key,
|
256
|
+
status: status,
|
257
|
+
resolution: resolution,
|
258
|
+
points: points
|
259
|
+
}
|
260
|
+
|
261
|
+
if resolution.nil?
|
262
|
+
unresolved_issues << issue
|
263
|
+
else
|
264
|
+
resolved_issues << issue
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
{
|
269
|
+
resolved: {
|
270
|
+
number: resolved_issues.size,
|
271
|
+
points: resolved_issues.map { |i| i[:points] }.reduce(0, :+),
|
272
|
+
link: resolved_link
|
273
|
+
},
|
274
|
+
unresolved: {
|
275
|
+
number: unresolved_issues.size,
|
276
|
+
points: unresolved_issues.map { |i| i[:points] }.reduce(0, :+),
|
277
|
+
link: unresolved_link
|
278
|
+
}
|
279
|
+
}
|
280
|
+
end
|
281
|
+
|
282
|
+
def items_in_current_sprint
|
283
|
+
items_in_sprint current_sprint_num
|
284
|
+
end
|
285
|
+
|
286
|
+
def items_in_sprint num
|
287
|
+
return [] unless logged_in?
|
288
|
+
issues = []
|
289
|
+
id = get_sprint(num)['id']
|
290
|
+
@jira_client.Issue.jql("sprint = #{id}", max_results: 500).each do |i|
|
291
|
+
issues << i.attrs
|
292
|
+
end
|
293
|
+
return issues
|
294
|
+
end
|
295
|
+
|
219
296
|
def asks_in_current_sprint
|
220
|
-
|
297
|
+
asks_in_sprint current_sprint_num
|
221
298
|
end
|
222
299
|
|
223
300
|
def asks_in_sprint num
|
224
301
|
return [] unless logged_in?
|
225
302
|
issues = []
|
226
|
-
@jira_client.Issue.jql("
|
303
|
+
@jira_client.Issue.jql("labels in (Sprint#{num})", max_results: 500).each do |i|
|
227
304
|
issues << i.attrs
|
228
305
|
end
|
229
306
|
return issues
|
@@ -279,6 +356,14 @@ module OpsAsk
|
|
279
356
|
sprint.nil? ? nil : sprint['name'].gsub(/\s+/, '')
|
280
357
|
end
|
281
358
|
|
359
|
+
def current_sprint_num sprint=current_sprint
|
360
|
+
sprint.nil? ? nil : sprint['name'].gsub(/\D+/, '')
|
361
|
+
end
|
362
|
+
|
363
|
+
def current_sprint_id sprint=current_sprint
|
364
|
+
sprint.nil? ? nil : sprint['id']
|
365
|
+
end
|
366
|
+
|
282
367
|
def current_sprint keys=[ 'sprintsData', 'sprints', 0 ]
|
283
368
|
url = "#{settings.config[:jira_url]}/rest/greenhopper/1.0/xboard/work/allData.json?rapidViewId=#{settings.config[:agile_board]}"
|
284
369
|
curl_request = Curl::Easy.http_get(url) do |curl|
|
@@ -294,11 +379,12 @@ module OpsAsk
|
|
294
379
|
begin
|
295
380
|
data = JSON::parse(raw_response)
|
296
381
|
keys.each { |k| data = data[k] }
|
297
|
-
return data
|
382
|
+
return data unless data.nil?
|
298
383
|
rescue
|
299
384
|
$stderr.puts "Failed to parse response from JIRA: #{raw_response}"
|
300
385
|
end
|
301
|
-
|
386
|
+
|
387
|
+
return sprints.last
|
302
388
|
end
|
303
389
|
|
304
390
|
def today offset=0
|
@@ -324,9 +410,9 @@ module OpsAsk
|
|
324
410
|
def jiras_for date
|
325
411
|
return [] unless logged_in?
|
326
412
|
unless ops?
|
327
|
-
return @jira_client.Issue.jql("due = #{date} AND project = #{settings.config[:project_name]} AND type != Change AND labels not in (OpsOnly)")
|
413
|
+
return @jira_client.Issue.jql("due = #{date} AND project = #{settings.config[:project_name]} AND type != Change AND labels not in (OpsOnly)", max_results: 100)
|
328
414
|
end
|
329
|
-
return @jira_client.Issue.jql("due = #{date} AND project = #{settings.config[:project_name]} AND type != Change")
|
415
|
+
return @jira_client.Issue.jql("due = #{date} AND project = #{settings.config[:project_name]} AND type != Change", max_results: 100)
|
330
416
|
end
|
331
417
|
|
332
418
|
def jira_count_for date
|
@@ -462,7 +548,7 @@ module OpsAsk
|
|
462
548
|
"resolution = unresolved",
|
463
549
|
"assignee = denimcores"
|
464
550
|
].join(' AND ')
|
465
|
-
@jira_client.Issue.jql(constraints).sort_by do |jira|
|
551
|
+
@jira_client.Issue.jql(constraints, max_results: 100).sort_by do |jira|
|
466
552
|
sorting_key_for(jira)
|
467
553
|
end.reverse
|
468
554
|
end
|
@@ -476,7 +562,7 @@ module OpsAsk
|
|
476
562
|
"resolution = unresolved",
|
477
563
|
"assignee != denimcores"
|
478
564
|
].join(' AND ')
|
479
|
-
@jira_client.Issue.jql(constraints).sort_by do |jira|
|
565
|
+
@jira_client.Issue.jql(constraints, max_results: 100).sort_by do |jira|
|
480
566
|
sorting_key_for(jira)
|
481
567
|
end.reverse
|
482
568
|
end
|
data/opsask.gemspec
CHANGED
@@ -18,9 +18,9 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.add_runtime_dependency 'curb', '~> 0.8'
|
19
19
|
s.add_runtime_dependency 'rack', '~> 1'
|
20
20
|
s.add_runtime_dependency 'sinatra', '~> 1.4'
|
21
|
-
s.add_runtime_dependency 'jira-ruby', '~> 0.1'
|
22
21
|
s.add_runtime_dependency 'rack-flash3', '~> 1'
|
23
22
|
s.add_runtime_dependency 'sinatra-partial', '~> 0.4'
|
23
|
+
s.add_runtime_dependency 'sclemmer-jira-ruby', '~> 0.1'
|
24
24
|
|
25
25
|
s.files = `git ls-files`.split("\n")
|
26
26
|
s.test_files = `git ls-files -- test/*`.split("\n")
|
data/public/css/style.css
CHANGED
@@ -149,4 +149,42 @@ p.ops-queues-are-full {
|
|
149
149
|
input[type="checkbox"] + label {
|
150
150
|
color: #bbb;
|
151
151
|
margin-left: 0.2em;
|
152
|
+
}
|
153
|
+
|
154
|
+
#stats h2 {
|
155
|
+
text-align: center;
|
156
|
+
}
|
157
|
+
|
158
|
+
.stats .stat {
|
159
|
+
padding-top: 2em;
|
160
|
+
padding-bottom: 2em;
|
161
|
+
background-color: #333;
|
162
|
+
text-align: center;
|
163
|
+
}
|
164
|
+
|
165
|
+
.stat.resolved {
|
166
|
+
color: #fff;
|
167
|
+
background-color: #5da423;
|
168
|
+
margin-top: 0.75em;
|
169
|
+
}
|
170
|
+
|
171
|
+
.stat.unresolved {
|
172
|
+
color: #000;
|
173
|
+
background-color: #ff005c;
|
174
|
+
margin-top: 2em;
|
175
|
+
}
|
176
|
+
|
177
|
+
.stat .number {
|
178
|
+
font-size: 1.25em;
|
179
|
+
font-weight: bold;
|
180
|
+
}
|
181
|
+
|
182
|
+
.stat .points {
|
183
|
+
padding-top: 0.5em;
|
184
|
+
}
|
185
|
+
|
186
|
+
.stat .about {
|
187
|
+
font-size: 1.5em;
|
188
|
+
padding-top: 0.75em;
|
189
|
+
font-weight: bold;
|
152
190
|
}
|
data/views/stats.erb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
<div class="row" id="stats">
|
2
|
+
<div class="small-10 columns">
|
3
|
+
<div class="small-5 small-offset-2 columns">
|
4
|
+
<h2>OpsAsk</h2>
|
5
|
+
<div class="stats">
|
6
|
+
<a href="<%= ask_stats[:resolved][:link] rescue '#' %>" target="_blank">
|
7
|
+
<div class="stat resolved">
|
8
|
+
<div class="issues"><span class="number"><%= ask_stats[:resolved][:number] rescue 0 %></span> issues</div>
|
9
|
+
<div class="points"><span class="number"><%= ask_stats[:resolved][:points] rescue 0 %></span> points</div>
|
10
|
+
<div class="about">Resolved</div>
|
11
|
+
</div>
|
12
|
+
</a>
|
13
|
+
<a href="<%= ask_stats[:unresolved][:link] rescue '#' %>" target="_blank">
|
14
|
+
<div class="stat unresolved">
|
15
|
+
<div class="issues"><span class="number"><%= ask_stats[:unresolved][:number] rescue 0 %></span> issues</div>
|
16
|
+
<div class="points"><span class="number"><%= ask_stats[:unresolved][:points] rescue 0 %></span> points</div>
|
17
|
+
<div class="about">Unresolved</div>
|
18
|
+
</div>
|
19
|
+
</a>
|
20
|
+
</div>
|
21
|
+
</div>
|
22
|
+
<div class="small-5 columns">
|
23
|
+
<h2><%= sprint['name'] %></h2>
|
24
|
+
<div class="stats">
|
25
|
+
<a href="<%= sprint_stats[:resolved][:link] rescue '#' %>" target="_blank">
|
26
|
+
<div class="stat resolved">
|
27
|
+
<div class="issues"><span class="number"><%= sprint_stats[:resolved][:number] rescue 0 %></span> issues</div>
|
28
|
+
<div class="points"><span class="number"><%= sprint_stats[:resolved][:points] rescue 0 %></span> points</div>
|
29
|
+
<div class="about">Resolved</div>
|
30
|
+
</div>
|
31
|
+
</a>
|
32
|
+
<a href="<%= sprint_stats[:unresolved][:link] rescue '#' %>" target="_blank">
|
33
|
+
<div class="stat unresolved">
|
34
|
+
<div class="issues"><span class="number"><%= sprint_stats[:unresolved][:number] rescue 0 %></span> issues</div>
|
35
|
+
<div class="points"><span class="number"><%= sprint_stats[:unresolved][:points] rescue 0 %></span> points</div>
|
36
|
+
<div class="about">Unresolved</div>
|
37
|
+
</div>
|
38
|
+
</a>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
</div>
|
42
|
+
</div>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opsask
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sean Clemmer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -81,47 +81,47 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '1.4'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rack-flash3
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '1'
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '
|
96
|
+
version: '1'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: sinatra-partial
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
103
|
+
version: '0.4'
|
104
104
|
type: :runtime
|
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: '
|
110
|
+
version: '0.4'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: sclemmer-jira-ruby
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '0.
|
117
|
+
version: '0.1'
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '0.
|
124
|
+
version: '0.1'
|
125
125
|
description: Ask Ops for stuff.
|
126
126
|
email: sczizzo@gmail.com
|
127
127
|
executables:
|
@@ -130,10 +130,6 @@ extensions: []
|
|
130
130
|
extra_rdoc_files: []
|
131
131
|
files:
|
132
132
|
- ".gitignore"
|
133
|
-
- ".yardoc/checksums"
|
134
|
-
- ".yardoc/object_types"
|
135
|
-
- ".yardoc/objects/root.dat"
|
136
|
-
- ".yardoc/proxy_types"
|
137
133
|
- Gemfile
|
138
134
|
- Gemfile.lock
|
139
135
|
- LICENSE
|
@@ -184,10 +180,10 @@ files:
|
|
184
180
|
- views/_flash.erb
|
185
181
|
- views/_form.erb
|
186
182
|
- views/_queue.erb
|
187
|
-
- views/agile.erb
|
188
183
|
- views/glance.erb
|
189
184
|
- views/index.erb
|
190
185
|
- views/layout.erb
|
186
|
+
- views/stats.erb
|
191
187
|
- views/stragglers.erb
|
192
188
|
- views/untracked.erb
|
193
189
|
homepage: http://git.ops.bluejeans.com/inf/opsask
|
data/.yardoc/checksums
DELETED
data/.yardoc/object_types
DELETED
Binary file
|
data/.yardoc/objects/root.dat
DELETED
Binary file
|
data/.yardoc/proxy_types
DELETED
Binary file
|