shiftzilla 0.2.26 → 0.2.31
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/shiftzilla +1 -0
- data/lib/shiftzilla/bug.rb +28 -28
- data/lib/shiftzilla/config.rb +18 -0
- data/lib/shiftzilla/engine.rb +1 -1
- data/lib/shiftzilla/group.rb +10 -4
- data/lib/shiftzilla/helpers.rb +7 -1
- data/lib/shiftzilla/milestone.rb +43 -1
- data/lib/shiftzilla/org_data.rb +111 -32
- data/lib/shiftzilla/source.rb +25 -1
- data/lib/shiftzilla/version.rb +1 -1
- data/shiftzilla.gemspec +2 -2
- data/{shiftzilla_cfg.yml.tmpl → shiftzilla_cfg.yaml.tmpl} +0 -0
- data/template.haml +32 -9
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31c2e44b571b53ef99faa54d3c5e6b54e4557143fe9f40f70bc45b4124872892
|
4
|
+
data.tar.gz: 9354388b6fc4a651aa283db031af0c29073b2e78094982c0e08a9f2f7ce6f672
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 213b09d6780afa354c2d7e020ac369432c01a20fdeab2229c87f542084df504204a7410732edd1b49325e82b997fa54852991fabff391adac5eb39eca69997b3
|
7
|
+
data.tar.gz: b4fdff84e4f84291a1c832777ba872a52a88479bbdc427c8c7122490f8b6d5f8bfe837e053fe5dd44ffa981e4ce3b00d5cd69082d861c8d3a91f9d1e3ae05daf
|
data/bin/shiftzilla
CHANGED
@@ -66,6 +66,7 @@ EOF
|
|
66
66
|
opt :quiet, "For cron use; don't print anything to STDOUT.", :default => false
|
67
67
|
opt :cfgpath, "Specify a config file for shiftzilla to use.", :default => "#{DEFAULT_DIR}/shiftzilla_cfg.yaml"
|
68
68
|
opt :dbpath, "Specify a database file location for shiftzilla to use.", :default => "#{DEFAULT_DIR}/shiftzilla.sqlite"
|
69
|
+
opt :groups, "Enable group aggregation table on main page", :default => false
|
69
70
|
end
|
70
71
|
when 'purge'
|
71
72
|
Optimist::options do
|
data/lib/shiftzilla/bug.rb
CHANGED
@@ -1,37 +1,37 @@
|
|
1
1
|
module Shiftzilla
|
2
2
|
class Bug
|
3
|
-
attr_reader :id, :first_seen, :last_seen, :
|
3
|
+
attr_reader :id, :first_seen, :last_seen, :blocker_plus, :blocker_unknown, :test_blocker, :ops_blocker, :owner, :component, :pm_score, :cust_cases, :tgt_release, :summary, :status
|
4
4
|
|
5
5
|
def initialize(bzid,binfo)
|
6
|
-
@id
|
7
|
-
@first_seen
|
8
|
-
@last_seen
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@owner
|
14
|
-
@summary
|
15
|
-
@status
|
16
|
-
@component
|
17
|
-
@pm_score
|
18
|
-
@cust_cases
|
19
|
-
@tgt_release
|
6
|
+
@id = bzid
|
7
|
+
@first_seen = binfo[:snapdate]
|
8
|
+
@last_seen = binfo[:snapdate]
|
9
|
+
@blocker_plus = binfo[:blocker_plus]
|
10
|
+
@blocker_unknown = binfo[:blocker_unknown]
|
11
|
+
@test_blocker = binfo[:test_blocker]
|
12
|
+
@ops_blocker = binfo[:ops_blocker]
|
13
|
+
@owner = binfo[:owner]
|
14
|
+
@summary = binfo[:summary]
|
15
|
+
@status = binfo[:status]
|
16
|
+
@component = binfo[:component]
|
17
|
+
@pm_score = binfo[:pm_score]
|
18
|
+
@cust_cases = binfo[:cust_cases]
|
19
|
+
@tgt_release = binfo[:tgt_release]
|
20
20
|
end
|
21
21
|
|
22
22
|
def update(binfo)
|
23
|
-
@last_seen
|
24
|
-
@
|
25
|
-
@
|
26
|
-
@
|
27
|
-
@
|
28
|
-
@owner
|
29
|
-
@summary
|
30
|
-
@status
|
31
|
-
@component
|
32
|
-
@pm_score
|
33
|
-
@cust_cases
|
34
|
-
@tgt_release
|
23
|
+
@last_seen = binfo[:snapdate]
|
24
|
+
@blocker_plus = binfo[:blocker_plus]
|
25
|
+
@blocker_unknown = binfo[:blocker_unknown]
|
26
|
+
@test_blocker = binfo[:test_blocker]
|
27
|
+
@ops_blocker = binfo[:ops_blocker]
|
28
|
+
@owner = binfo[:owner]
|
29
|
+
@summary = binfo[:summary]
|
30
|
+
@status = binfo[:status]
|
31
|
+
@component = binfo[:component]
|
32
|
+
@pm_score = binfo[:pm_score]
|
33
|
+
@cust_cases = binfo[:cust_cases]
|
34
|
+
@tgt_release = binfo[:tgt_release]
|
35
35
|
end
|
36
36
|
|
37
37
|
def age
|
@@ -66,4 +66,4 @@ module Shiftzilla
|
|
66
66
|
val.to_f.to_s == val.to_s || val.to_i.to_s == val.to_s
|
67
67
|
end
|
68
68
|
end
|
69
|
-
end
|
69
|
+
end
|
data/lib/shiftzilla/config.rb
CHANGED
@@ -22,6 +22,7 @@ module Shiftzilla
|
|
22
22
|
cfg_file['Teams'].each do |team|
|
23
23
|
@teams << Shiftzilla::Team.new(team,group_map)
|
24
24
|
end
|
25
|
+
set_group_components
|
25
26
|
cfg_file['Sources'].each do |sid,sinfo|
|
26
27
|
@sources << Shiftzilla::Source.new(sid,sinfo)
|
27
28
|
end
|
@@ -50,6 +51,10 @@ module Shiftzilla
|
|
50
51
|
@teams.select{ |t| t.name == tname }[0]
|
51
52
|
end
|
52
53
|
|
54
|
+
def group(gname)
|
55
|
+
@groups.select{ |g| g.id == gname[0] }[0]
|
56
|
+
end
|
57
|
+
|
53
58
|
def add_ad_hoc_team(tinfo)
|
54
59
|
@teams << Shiftzilla::Team.new(tinfo,{},true)
|
55
60
|
end
|
@@ -95,5 +100,18 @@ module Shiftzilla
|
|
95
100
|
boundaries
|
96
101
|
end
|
97
102
|
end
|
103
|
+
|
104
|
+
def set_group_components
|
105
|
+
@groups.each do |g|
|
106
|
+
components = []
|
107
|
+
@teams.each do |t|
|
108
|
+
if t.group and (t.group.id == g.id)
|
109
|
+
components += t.components
|
110
|
+
end
|
111
|
+
end
|
112
|
+
g.set_components(components)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
98
116
|
end
|
99
117
|
end
|
data/lib/shiftzilla/engine.rb
CHANGED
@@ -113,7 +113,7 @@ module Shiftzilla
|
|
113
113
|
org_data = Shiftzilla::OrgData.new(shiftzilla_config)
|
114
114
|
org_data.populate_releases
|
115
115
|
org_data.build_series
|
116
|
-
org_data.generate_reports
|
116
|
+
org_data.generate_reports(options[:groups])
|
117
117
|
if options[:local_preview]
|
118
118
|
org_data.show_local_reports
|
119
119
|
else
|
data/lib/shiftzilla/group.rb
CHANGED
@@ -1,10 +1,16 @@
|
|
1
1
|
module Shiftzilla
|
2
2
|
class Group
|
3
|
-
attr_reader :id, :lead
|
3
|
+
attr_reader :name, :id, :lead, :components
|
4
4
|
|
5
5
|
def initialize(ginfo)
|
6
|
-
@
|
7
|
-
@
|
6
|
+
@name = "Group " + ginfo['id']
|
7
|
+
@id = ginfo['id']
|
8
|
+
@lead = ginfo['lead']
|
8
9
|
end
|
10
|
+
|
11
|
+
def set_components(component_list)
|
12
|
+
@components ||= component_list
|
13
|
+
end
|
14
|
+
|
9
15
|
end
|
10
|
-
end
|
16
|
+
end
|
data/lib/shiftzilla/helpers.rb
CHANGED
@@ -249,6 +249,8 @@ module Shiftzilla
|
|
249
249
|
errors << "Team at index #{list_idx} is missing the 'name' key."
|
250
250
|
elsif not valid_config_string?(team['name'])
|
251
251
|
errors << "Team at index #{list_idx} has a nil or zero-length 'name'."
|
252
|
+
elsif team['name'].start_with?("Group")
|
253
|
+
errors << "Team at index #{list_idx} begins with the string 'Group'."
|
252
254
|
else
|
253
255
|
tnm = team['name']
|
254
256
|
if seen_tnms.has_key?(tnm)
|
@@ -329,10 +331,14 @@ module Shiftzilla
|
|
329
331
|
if not milestones.has_key?(ms)
|
330
332
|
errors << "Release at index #{list_idx} is missing the '#{ms}' milestone."
|
331
333
|
else
|
334
|
+
if milestones[ms] == 'today' or !!(milestones[ms] =~ /today[+-]\d+[dwms]/)
|
335
|
+
# Matches the variable date format
|
336
|
+
next
|
337
|
+
end
|
332
338
|
ms_date = milestones[ms].split('-')
|
333
339
|
if ms_date.length == 3 and ms_date[0].length == 4 and ms_date[1].length == 2 and ms_date[2].length == 2
|
334
340
|
else
|
335
|
-
errors << "Release at index #{list_idx}: milestone '#{ms}' is not formatted correctly (YYYY-MM-DD)."
|
341
|
+
errors << "Release at index #{list_idx}: milestone '#{ms}' is not formatted correctly - (YYYY-MM-DD) or (today[+-]X[dwms])."
|
336
342
|
end
|
337
343
|
end
|
338
344
|
end
|
data/lib/shiftzilla/milestone.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
1
3
|
module Shiftzilla
|
2
4
|
class Milestone
|
3
5
|
def initialize(mtxt)
|
4
6
|
@date = nil
|
5
7
|
@stamp = ''
|
6
|
-
|
8
|
+
if mtxt.start_with?('today')
|
9
|
+
@date = variable_date(mtxt)
|
10
|
+
@stamp = @date.strftime('%Y-%m-%d')
|
11
|
+
elsif not (mtxt.nil? or mtxt == '')
|
7
12
|
@date = Date.parse(mtxt)
|
8
13
|
@stamp = mtxt
|
9
14
|
end
|
@@ -16,5 +21,42 @@ module Shiftzilla
|
|
16
21
|
def stamp
|
17
22
|
@stamp
|
18
23
|
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def variable_date(d)
|
28
|
+
# Takes a variable date string and returns the appropriate date object
|
29
|
+
# Variable dates of the form today[+,-]#[d,w,m,s]
|
30
|
+
today = Date.today
|
31
|
+
|
32
|
+
if d.length < 8
|
33
|
+
return today
|
34
|
+
end
|
35
|
+
|
36
|
+
operation = d[5]
|
37
|
+
val = d[6..-2].to_i
|
38
|
+
unit = d[-1]
|
39
|
+
days = 0
|
40
|
+
|
41
|
+
# Convert to days for simple addition
|
42
|
+
case unit
|
43
|
+
when 'd'
|
44
|
+
days = val
|
45
|
+
when 'w'
|
46
|
+
days = 7*val
|
47
|
+
when 'm'
|
48
|
+
days = 30*val
|
49
|
+
when 's' # Sprints
|
50
|
+
days = 21*val
|
51
|
+
else
|
52
|
+
days = val
|
53
|
+
end
|
54
|
+
|
55
|
+
if operation == '-'
|
56
|
+
days = days * -1
|
57
|
+
end
|
58
|
+
|
59
|
+
return today+days
|
60
|
+
end
|
19
61
|
end
|
20
62
|
end
|
data/lib/shiftzilla/org_data.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'json'
|
3
|
+
require 'uri'
|
3
4
|
require 'shiftzilla/bug'
|
4
5
|
require 'shiftzilla/helpers'
|
5
6
|
require 'shiftzilla/team_data'
|
@@ -13,6 +14,8 @@ module Shiftzilla
|
|
13
14
|
def initialize(config)
|
14
15
|
@config = config
|
15
16
|
@teams = config.teams
|
17
|
+
@groups = config.groups
|
18
|
+
@group_teams = []
|
16
19
|
@releases = config.releases
|
17
20
|
@tmp_dir = Shiftzilla::Helpers.tmp_dir
|
18
21
|
@org_data = { '_overall' => Shiftzilla::TeamData.new('_overall',config) }
|
@@ -38,57 +41,71 @@ module Shiftzilla
|
|
38
41
|
|
39
42
|
# TODO: REMOVE BUSINESS LOGIC EMBEDDED IN CODE
|
40
43
|
if comp == 'Security' and keyw.include?('Unconfirmed')
|
41
|
-
|
44
|
+
# This report has a hardcoded exclusion of 'Security' component bugs with the 'Unconfirmed' keyword."
|
42
45
|
next
|
43
46
|
end
|
44
47
|
|
45
48
|
# Package up bug data
|
46
49
|
binfo = {
|
47
|
-
:snapdate
|
48
|
-
:
|
49
|
-
:
|
50
|
-
:
|
51
|
-
:
|
52
|
-
:owner
|
53
|
-
:summary
|
54
|
-
:status
|
55
|
-
:component
|
56
|
-
:pm_score
|
57
|
-
:cust_cases
|
58
|
-
:tgt_release
|
50
|
+
:snapdate => snapdate,
|
51
|
+
:blocker_plus => keyw.include?('blocker+'),
|
52
|
+
:blocker_unknown => keyw.include?('blocker?'),
|
53
|
+
:test_blocker => keyw.include?('TestBlocker'),
|
54
|
+
:ops_blocker => keyw.include?('ServiceDeliveryBlocker'),
|
55
|
+
:owner => owns,
|
56
|
+
:summary => summ,
|
57
|
+
:status => stat,
|
58
|
+
:component => comp,
|
59
|
+
:pm_score => pmsc,
|
60
|
+
:cust_cases => (cust == 1),
|
61
|
+
:tgt_release => tgtr,
|
59
62
|
}
|
60
63
|
|
61
64
|
tgt_release = @config.release_by_target(tgtr)
|
62
65
|
all_release = @config.release('All')
|
63
66
|
|
64
67
|
# If this component isn't mapped to a team, stub out a fake team.
|
65
|
-
tname =
|
68
|
+
tname = team_comp_map.has_key?(comp) ? team_comp_map[comp] : "(?) #{comp}"
|
66
69
|
unless @org_data.has_key?(tname)
|
67
70
|
@config.add_ad_hoc_team({ 'name' => tname, 'components' => [comp] })
|
68
71
|
@org_data[tname] = Shiftzilla::TeamData.new(tname)
|
69
72
|
end
|
70
73
|
|
74
|
+
# Generate TeamData objects for each group
|
75
|
+
gname = group_comp_map.has_key?(comp) ? group_comp_map[comp] : nil
|
76
|
+
if not gname.nil? and not @org_data.has_key?(gname)
|
77
|
+
@org_data[gname] = Shiftzilla::TeamData.new(gname)
|
78
|
+
end
|
79
|
+
|
71
80
|
team_rdata = tgt_release.nil? ? nil : @org_data[tname].get_release_data(tgt_release)
|
72
81
|
team_adata = @org_data[tname].get_release_data(all_release)
|
73
82
|
over_rdata = tgt_release.nil? ? nil : @org_data['_overall'].get_release_data(tgt_release)
|
74
83
|
over_adata = @org_data['_overall'].get_release_data(all_release)
|
84
|
+
unless gname.nil?
|
85
|
+
group_rdata = tgt_release.nil? ? nil : @org_data[gname].get_release_data(tgt_release)
|
86
|
+
group_adata = @org_data[gname].get_release_data(all_release)
|
87
|
+
else
|
88
|
+
group_rdata = nil
|
89
|
+
group_adata = nil
|
90
|
+
end
|
75
91
|
|
76
92
|
# Do some bean counting
|
77
|
-
[over_rdata,team_rdata,over_adata,team_adata].each do |
|
78
|
-
next if
|
79
|
-
snapdata =
|
80
|
-
if
|
81
|
-
|
82
|
-
|
93
|
+
[over_rdata,team_rdata,over_adata,team_adata,group_rdata,group_adata].each do |grouping|
|
94
|
+
next if grouping.nil?
|
95
|
+
snapdata = grouping.get_snapdata(snapshot)
|
96
|
+
if grouping.first_snap.nil?
|
97
|
+
grouping.first_snap = snapshot
|
98
|
+
grouping.first_snapdate = snapdate
|
83
99
|
end
|
84
|
-
|
85
|
-
|
100
|
+
grouping.latest_snap = snapshot
|
101
|
+
grouping.latest_snapdate = snapdate
|
86
102
|
|
87
|
-
bug =
|
103
|
+
bug = grouping.add_or_update_bug(bzid,binfo)
|
88
104
|
|
89
105
|
# Add info to the snapshot
|
90
106
|
snapdata.bug_ids << bzid
|
91
|
-
|
107
|
+
# Only the blocker+ flag counts as a blocker for snapshots
|
108
|
+
if bug.blocker_plus
|
92
109
|
snapdata.tb_ids << bzid
|
93
110
|
end
|
94
111
|
if bug.cust_cases
|
@@ -131,6 +148,18 @@ module Shiftzilla
|
|
131
148
|
end
|
132
149
|
end
|
133
150
|
end
|
151
|
+
|
152
|
+
# Create a "team" for each group here
|
153
|
+
@groups.each do |g|
|
154
|
+
ginfo = {
|
155
|
+
'name' => g.name,
|
156
|
+
'lead' => g.lead,
|
157
|
+
'group' => g.id,
|
158
|
+
'components' => g.components,
|
159
|
+
}
|
160
|
+
@group_teams << Shiftzilla::Team.new(ginfo, {g.id => g})
|
161
|
+
end
|
162
|
+
|
134
163
|
@all_teams = @teams.map{ |t| t.name }.concat(@org_data.keys).uniq
|
135
164
|
@ordered_teams = ['_overall'].concat(@all_teams.select{ |t| t != '_overall'}.sort)
|
136
165
|
end
|
@@ -159,6 +188,7 @@ module Shiftzilla
|
|
159
188
|
:tname => tdata.title,
|
160
189
|
:file => tdata.file,
|
161
190
|
:releases => {},
|
191
|
+
:is_group => (not @group_teams.detect{|g| g.name == tdata.title}.nil?),
|
162
192
|
}
|
163
193
|
|
164
194
|
@releases.each do |release|
|
@@ -182,9 +212,11 @@ module Shiftzilla
|
|
182
212
|
end
|
183
213
|
end
|
184
214
|
|
185
|
-
def generate_reports
|
215
|
+
def generate_reports(include_groups)
|
186
216
|
build_time = timestamp
|
187
217
|
all_release = @config.release('All')
|
218
|
+
redirects = {}
|
219
|
+
|
188
220
|
@ordered_teams.each do |tname|
|
189
221
|
tinfo = @config.team(tname)
|
190
222
|
tdata = @org_data[tname]
|
@@ -200,8 +232,22 @@ module Shiftzilla
|
|
200
232
|
:releases => [],
|
201
233
|
:latest_snapshot => latest_snapshot,
|
202
234
|
:all_bugs => [],
|
235
|
+
:include_groups => include_groups,
|
236
|
+
:is_group => false,
|
203
237
|
}
|
204
238
|
|
239
|
+
# Check if this is actually a group "team"
|
240
|
+
group_match = @group_teams.detect{|g| g.name == tname}
|
241
|
+
if not group_match.nil?
|
242
|
+
team_pinfo[:tinfo] = group_match
|
243
|
+
team_pinfo[:is_group] = true
|
244
|
+
elsif not tinfo.nil?
|
245
|
+
# Generate component -> team redirects
|
246
|
+
tinfo.components.each do |component|
|
247
|
+
redirects[component] = tdata.file
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
205
251
|
@releases.each do |release|
|
206
252
|
rname = release.name
|
207
253
|
rdata = tdata.has_release_data?(release) ? tdata.get_release_data(release) : nil
|
@@ -245,7 +291,7 @@ module Shiftzilla
|
|
245
291
|
:data => rdata.series[:closed_bugs],
|
246
292
|
},
|
247
293
|
]),
|
248
|
-
:blockers => chartify('
|
294
|
+
:blockers => chartify('Blockers',rdata.series[:date],[
|
249
295
|
{
|
250
296
|
:label => 'Total',
|
251
297
|
:data => rdata.series[:total_tb],
|
@@ -270,6 +316,24 @@ module Shiftzilla
|
|
270
316
|
team_page = haml_engine.render(Object.new,team_pinfo)
|
271
317
|
File.write(File.join(@tmp_dir,tdata.file), team_page)
|
272
318
|
end
|
319
|
+
|
320
|
+
# Create component->team redirects
|
321
|
+
redirects.each do |component, team_file|
|
322
|
+
redirect_html = <<-HTML
|
323
|
+
<!DOCTYPE html>
|
324
|
+
<html>
|
325
|
+
<head>
|
326
|
+
<meta http-equiv="Refresh" content="0; url=#{team_file}" />
|
327
|
+
</head>
|
328
|
+
<body>
|
329
|
+
<p>Redirecting to <a href="#{team_file}">team page</a>...</p>
|
330
|
+
</body>
|
331
|
+
</html>
|
332
|
+
HTML
|
333
|
+
File.write(File.join(@tmp_dir, "component_#{component}.html"), redirect_html)
|
334
|
+
end
|
335
|
+
|
336
|
+
|
273
337
|
# Copy flot library to build area
|
274
338
|
jsdir = File.join(@tmp_dir,'js')
|
275
339
|
Dir.mkdir(jsdir)
|
@@ -294,18 +358,33 @@ module Shiftzilla
|
|
294
358
|
|
295
359
|
private
|
296
360
|
|
297
|
-
def
|
298
|
-
@
|
299
|
-
|
361
|
+
def team_comp_map
|
362
|
+
@team_comp_map ||= begin
|
363
|
+
team_comp_map = {}
|
300
364
|
@teams.each do |team|
|
301
365
|
team.components.each do |comp|
|
302
|
-
|
366
|
+
team_comp_map[comp] = team.name
|
303
367
|
end
|
304
368
|
end
|
305
|
-
|
369
|
+
team_comp_map
|
306
370
|
end
|
307
371
|
end
|
308
372
|
|
373
|
+
# Creates group component mapping
|
374
|
+
def group_comp_map
|
375
|
+
@group_comp_map ||= begin
|
376
|
+
group_comp_map = {}
|
377
|
+
@groups.each do |group|
|
378
|
+
group.components.each do |comp|
|
379
|
+
group_comp_map[comp] = group.name
|
380
|
+
end
|
381
|
+
end
|
382
|
+
group_comp_map
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
|
387
|
+
|
309
388
|
def chartify(title,dates,series)
|
310
389
|
modulo = label_modulo(dates.length)
|
311
390
|
tlist = []
|
@@ -349,4 +428,4 @@ module Shiftzilla
|
|
349
428
|
end
|
350
429
|
end
|
351
430
|
end
|
352
|
-
end
|
431
|
+
end
|
data/lib/shiftzilla/source.rb
CHANGED
@@ -25,7 +25,9 @@ module Shiftzilla
|
|
25
25
|
output_format = @fields.map{ |fld| "%{#{fld.to_s}}" }.join("\x1F")
|
26
26
|
table_fields = @fields.map{ |fld| "\"#{field_map[fld]}\"" }.join(',')
|
27
27
|
insert_frame = @fields.map{ |fld| '?' }.join(', ')
|
28
|
-
|
28
|
+
# Also grabs the flags to check for the blocker flag, this is dropped before inserting into the db
|
29
|
+
bz_command = "bugzilla query --savedsearch #{@search} --savedsearch-sharer-id=#{@sharer} --outputformat='#{output_format}\x1F%{flags}flags||EOR'"
|
30
|
+
|
29
31
|
bz_csv = `#{bz_command}`
|
30
32
|
retrieved = []
|
31
33
|
bz_csv.split("||EOR\n").each do |row|
|
@@ -47,6 +49,28 @@ module Shiftzilla
|
|
47
49
|
values[@external_bugs_idx] = 0
|
48
50
|
end
|
49
51
|
end
|
52
|
+
|
53
|
+
# Check for blocker+ flag and stub it as a keyword
|
54
|
+
if not values[-1].nil? and values[-1].include?("blocker+")
|
55
|
+
keyword_idx = @fields.index(:keywords)
|
56
|
+
if not values[keyword_idx]
|
57
|
+
values[keyword_idx] = "blocker+"
|
58
|
+
else
|
59
|
+
values[keyword_idx] = values[keyword_idx] + ",blocker+"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
# Check for blocker? flag and stub it as a keyword
|
63
|
+
if not values[-1].nil? and values[-1].include?("blocker?")
|
64
|
+
keyword_idx = @fields.index(:keywords)
|
65
|
+
if not values[keyword_idx]
|
66
|
+
values[keyword_idx] = "blocker?"
|
67
|
+
else
|
68
|
+
values[keyword_idx] = values[keyword_idx] + ",blocker?"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Remove flags, which is always the final value
|
73
|
+
values = values[0...-2]
|
50
74
|
retrieved << values
|
51
75
|
end
|
52
76
|
puts "Retrieved #{retrieved.length} rows"
|
data/lib/shiftzilla/version.rb
CHANGED
data/shiftzilla.gemspec
CHANGED
@@ -6,8 +6,8 @@ require 'shiftzilla/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "shiftzilla"
|
8
8
|
spec.version = Shiftzilla::VERSION
|
9
|
-
spec.authors = ["N. Harrison Ripps"]
|
10
|
-
spec.email = ["nhr@redhat.com"]
|
9
|
+
spec.authors = ["N. Harrison Ripps","Rory Thrasher"]
|
10
|
+
spec.email = ["nhr@redhat.com","rthrashe@redhat.com"]
|
11
11
|
spec.summary = %q{Shiftzilla is a tool for providing historical reports based on Bugzilla data}
|
12
12
|
spec.description = spec.summary
|
13
13
|
spec.homepage = "http://github.com/nhr/shiftzilla"
|
File without changes
|
data/template.haml
CHANGED
@@ -45,11 +45,12 @@
|
|
45
45
|
- if tname != '_overall' and not tinfo.nil? and not tinfo.ad_hoc?
|
46
46
|
%h5 Team Info
|
47
47
|
%ul
|
48
|
-
|
48
|
+
- unless is_group
|
49
|
+
%li= "Team Lead: #{tinfo.lead}"
|
49
50
|
- if not tinfo.group.nil? and not tinfo.group.lead.nil?
|
50
51
|
%li= "Group Lead: #{tinfo.group.lead}"
|
51
52
|
- if tinfo.components.length > 0
|
52
|
-
%li= "BZ Component(s):
|
53
|
+
%li= "BZ Component(s): " + tinfo.components.map{ |c| "<a href='component_#{c}.html'>#{c}</a>"}.join(', ')
|
53
54
|
%h5= "#{tdisp} Summary"
|
54
55
|
%table.table.table-hover.table-sm
|
55
56
|
%tr
|
@@ -69,7 +70,7 @@
|
|
69
70
|
- releases.each do |r|
|
70
71
|
%td.text-right= r[:bug_avg_age]
|
71
72
|
%tr
|
72
|
-
%td Avg.
|
73
|
+
%td Avg. Blocker Age
|
73
74
|
- releases.each do |r|
|
74
75
|
%td.text-right= r[:tb_avg_age]
|
75
76
|
%tr
|
@@ -81,7 +82,7 @@
|
|
81
82
|
- releases.each do |r|
|
82
83
|
%td.text-right= r[:snapdata].closed_bugs
|
83
84
|
%tr
|
84
|
-
%td
|
85
|
+
%td Blockers
|
85
86
|
- releases.each do |r|
|
86
87
|
%td.text-right= r[:snapdata].total_tb
|
87
88
|
%tr
|
@@ -92,6 +93,26 @@
|
|
92
93
|
%td Closed Blockers Yesterday
|
93
94
|
- releases.each do |r|
|
94
95
|
%td.text-right= r[:snapdata].closed_tb
|
96
|
+
|
97
|
+
- if tname == '_overall' and include_groups
|
98
|
+
%h5 Totals By Group
|
99
|
+
%table.table.table-hover.table-sm
|
100
|
+
%tr
|
101
|
+
%td Group
|
102
|
+
- releases.each do |r|
|
103
|
+
%td.text-right= r[:release].name
|
104
|
+
- team_files.each do |tm|
|
105
|
+
- unless tm[:is_group]
|
106
|
+
- next
|
107
|
+
%tr
|
108
|
+
%td
|
109
|
+
- if tm[:tname] == tdisp
|
110
|
+
= tdisp
|
111
|
+
- else
|
112
|
+
%a{ :href => tm[:file] }= tm[:tname]
|
113
|
+
- releases.each do |r|
|
114
|
+
%td.text-right= tm[:releases][r[:release].name]
|
115
|
+
|
95
116
|
- if tname == '_overall'
|
96
117
|
%h5 Totals By Team
|
97
118
|
%table.table.table-hover.table-sm
|
@@ -100,6 +121,8 @@
|
|
100
121
|
- releases.each do |r|
|
101
122
|
%td.text-right= r[:release].name
|
102
123
|
- team_files.each do |tm|
|
124
|
+
- if tm[:is_group]
|
125
|
+
- next
|
103
126
|
%tr
|
104
127
|
%td
|
105
128
|
- if tm[:tname] == tdisp
|
@@ -130,7 +153,7 @@
|
|
130
153
|
%thead
|
131
154
|
%tr
|
132
155
|
%th
|
133
|
-
%abbr{ :title => '
|
156
|
+
%abbr{ :title => 'Blocker flags and keywords' } Blocker
|
134
157
|
%th
|
135
158
|
%abbr{ :title => 'See https://mojo.redhat.com/docs/DOC-1159309' } PM
|
136
159
|
%th
|
@@ -146,10 +169,10 @@
|
|
146
169
|
- all_bugs.each do |b|
|
147
170
|
%tr
|
148
171
|
%td
|
149
|
-
= b.
|
150
|
-
= b.
|
151
|
-
= b.
|
152
|
-
= b.
|
172
|
+
= b.blocker_plus ? "<span class='badge badge-danger'>Βlocker+</span>" : ''
|
173
|
+
= b.blocker_unknown ? "<span class='badge badge-info'>blocker?</span>" : ''
|
174
|
+
= b.test_blocker ? "<span class='badge badge-warning'>Test</span>" : ''
|
175
|
+
= b.ops_blocker ? "<span class='badge badge-dark'>SD</span>" : ''
|
153
176
|
%td= b.pm_score
|
154
177
|
%td= b.cust_cases ? "<span class='badge badge-warning'>CC</span>" : ''
|
155
178
|
%td(data-order="#{b.semver}")= b.tgt_release
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shiftzilla
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.31
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- N. Harrison Ripps
|
8
|
+
- Rory Thrasher
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2020-11-02 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|
@@ -156,6 +157,7 @@ description: Shiftzilla is a tool for providing historical reports based on Bugz
|
|
156
157
|
data
|
157
158
|
email:
|
158
159
|
- nhr@redhat.com
|
160
|
+
- rthrashe@redhat.com
|
159
161
|
executables:
|
160
162
|
- shiftzilla
|
161
163
|
extensions: []
|
@@ -182,7 +184,7 @@ files:
|
|
182
184
|
- lib/shiftzilla/version.rb
|
183
185
|
- shiftzilla.gemspec
|
184
186
|
- shiftzilla.sql.tmpl
|
185
|
-
- shiftzilla_cfg.
|
187
|
+
- shiftzilla_cfg.yaml.tmpl
|
186
188
|
- template.haml
|
187
189
|
- vendor/flot/jquery.flot.min.js
|
188
190
|
homepage: http://github.com/nhr/shiftzilla
|
@@ -204,7 +206,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
204
206
|
- !ruby/object:Gem::Version
|
205
207
|
version: '0'
|
206
208
|
requirements: []
|
207
|
-
|
209
|
+
rubyforge_project:
|
210
|
+
rubygems_version: 2.7.7
|
208
211
|
signing_key:
|
209
212
|
specification_version: 4
|
210
213
|
summary: Shiftzilla is a tool for providing historical reports based on Bugzilla data
|