jira_reporting 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +52 -0
- data/Rakefile +6 -0
- data/auth.yml.example +10 -0
- data/bin/jira_reporting +50 -0
- data/bin/jira_sla_update +54 -0
- data/bin/kpi_report +204 -0
- data/bin/maint_vs_enh +127 -0
- data/bin/platform_stability_kpi_report +215 -0
- data/bin/pr-report.rb +23 -0
- data/bin/quarter_report +65 -0
- data/bin/sla_update_closed_issues +38 -0
- data/bin/sla_warning +36 -0
- data/bin/time_in_dev +56 -0
- data/jira_reporting.gemspec +37 -0
- data/lib/auto_hash.rb +21 -0
- data/lib/code_climate.rb +35 -0
- data/lib/jira_issue.rb +288 -0
- data/lib/jira_reporting.rb +27 -0
- data/lib/jira_reporting/connection.rb +16 -0
- data/lib/jira_reporting/sla_report.rb +103 -0
- data/lib/jira_reporting/sla_tracker.rb +183 -0
- data/lib/jira_reporting/triage_tracker.rb +69 -0
- data/lib/jira_reporting/version.rb +3 -0
- data/lib/pull_request.rb +104 -0
- data/optoro_holidays.yaml +71 -0
- data/spec/jira_reporting_spec.rb +11 -0
- data/spec/spec_helper.rb +2 -0
- metadata +313 -0
data/bin/maint_vs_enh
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift "#{File.dirname(__FILE__)}/../lib"
|
4
|
+
require 'jira_reporting'
|
5
|
+
require 'pry-byebug'
|
6
|
+
require 'active_support'
|
7
|
+
require 'yaml'
|
8
|
+
require 'code_climate'
|
9
|
+
require 'auto_hash'
|
10
|
+
require 'pull_request'
|
11
|
+
require 'yaml/dbm'
|
12
|
+
|
13
|
+
auth = YAML.load_file('auth.yml')
|
14
|
+
|
15
|
+
jira_username = auth["jira"]["username"]
|
16
|
+
jira_password = auth["jira"]["password"]
|
17
|
+
JiraReporting.connect! jira_username, jira_password
|
18
|
+
|
19
|
+
start_date = (ARGV[0] && Date.parse(ARGV[0])) || 30.days.ago
|
20
|
+
end_date = (ARGV[1] && Date.parse(ARGV[1])) || 1.day.ago
|
21
|
+
|
22
|
+
start_date = start_date.strftime("%Y-%m-%d")
|
23
|
+
end_date = end_date.strftime("%Y-%m-%d")
|
24
|
+
|
25
|
+
puts "Start: #{start_date} END: #{end_date}"
|
26
|
+
|
27
|
+
def db
|
28
|
+
@db ||= YAML::DBM.open('maint_vs_enh_cache', DBM::WRCREAT)
|
29
|
+
end
|
30
|
+
|
31
|
+
def cache_issues(start_date, end_date)
|
32
|
+
|
33
|
+
# This takes a while
|
34
|
+
# query = %Q{
|
35
|
+
# project in (BULQ, DT, BLINQ.com, OptiTurn, "Tech Support", Tech)
|
36
|
+
# and status was "In Progress" DURING ("#{start_date}", "#{end_date}")
|
37
|
+
# }
|
38
|
+
query = %Q{
|
39
|
+
status was "In Progress" DURING ("#{start_date}", "#{end_date}")
|
40
|
+
}
|
41
|
+
|
42
|
+
puts "Searching jira: #{query}"
|
43
|
+
issues = JiraIssue.find(query)
|
44
|
+
puts "Search complete."
|
45
|
+
|
46
|
+
issue_count = issues.count
|
47
|
+
issues.each_with_index do |issue, index|
|
48
|
+
print "#{index + 1}/#{issue_count} (#{(((index+1).to_r/issue_count)*100).to_i }%) #{issue.key} "
|
49
|
+
if !db[issue.key]
|
50
|
+
issue.changelog
|
51
|
+
db[issue.key] = issue
|
52
|
+
puts "found"
|
53
|
+
else
|
54
|
+
puts "cached"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# cache_issues(start_date, end_date)
|
60
|
+
|
61
|
+
# binding.pry
|
62
|
+
# puts "yep"
|
63
|
+
|
64
|
+
# status_ages = {}
|
65
|
+
# if !db[issue.key] || !db[issue.key][:in_progress_duration]
|
66
|
+
# in_progress_duration = issue.status_duration_during("In Progress", start_date, end_date)
|
67
|
+
# db[issue.key] = {
|
68
|
+
# type: issue.type,
|
69
|
+
# in_progress_duration: in_progress_duration,
|
70
|
+
# issue: issue
|
71
|
+
# }
|
72
|
+
# end
|
73
|
+
# status_ages = db[issue.key][:status_ages]
|
74
|
+
|
75
|
+
# puts "#{issue.key} #{issue.type} (#{index + 1}/#{issue_count})"
|
76
|
+
# type_times[issue.type] += (status_ages["In Progress"] || 0)
|
77
|
+
# type_counts[issue.type] += 1
|
78
|
+
# puts type_times
|
79
|
+
# puts type_counts
|
80
|
+
|
81
|
+
# type_counts.keys.each { |type|
|
82
|
+
# puts [type, type_counts[type], type_times[type]].join(",")
|
83
|
+
# }
|
84
|
+
|
85
|
+
# binding.pry
|
86
|
+
|
87
|
+
puts "Loading issues"
|
88
|
+
issues = db.values
|
89
|
+
count = issues.count
|
90
|
+
|
91
|
+
puts "Dumping issues"
|
92
|
+
File.open("result.csv", "w") do |csv|
|
93
|
+
csv.puts("project,key,type,assignee,mover,in_progress_hours,summary,epic_key,epic_name,start,end")
|
94
|
+
issues.each_with_index do |issue, index|
|
95
|
+
puts "Processing... #{index+1}/#{count}"
|
96
|
+
|
97
|
+
epic_key = issue.orig["fields"]["customfield_10008"]
|
98
|
+
if epic_key
|
99
|
+
epic_issue = db[epic_key] || JiraIssue.find("issue = #{epic_key}").first
|
100
|
+
db[epic_key] ||= epic_issue
|
101
|
+
epic_name = epic_issue.orig["fields"]["customfield_10009"] if epic_issue
|
102
|
+
end
|
103
|
+
|
104
|
+
status_ages = issue.status_ages
|
105
|
+
out_of_in_progress_by = issue.status_changes.select{|c| c[:status] == "In Progress"}.last.andand[:author_out]
|
106
|
+
summary = issue.summary
|
107
|
+
summary.gsub!(',','')
|
108
|
+
epic_name ||= ""
|
109
|
+
epic_name.gsub!(',','')
|
110
|
+
row = [
|
111
|
+
issue.project,
|
112
|
+
issue.key,
|
113
|
+
issue.type,
|
114
|
+
(issue.orig["fields"]["assignee"].andand["name"] || ""),
|
115
|
+
out_of_in_progress_by || "",
|
116
|
+
status_ages["In Progress"] || 0,
|
117
|
+
summary,
|
118
|
+
epic_key || "",
|
119
|
+
epic_name || "",
|
120
|
+
issue.created_at,
|
121
|
+
issue.status_changes.last[:start]
|
122
|
+
].join(",")
|
123
|
+
puts row
|
124
|
+
csv.puts(row)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
@@ -0,0 +1,215 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
PROJECT_ROOT = "#{File.dirname(__FILE__)}/../"
|
3
|
+
|
4
|
+
$:.unshift "#{File.dirname(__FILE__)}/../lib"
|
5
|
+
require 'jira_reporting'
|
6
|
+
require 'active_support'
|
7
|
+
require 'yaml'
|
8
|
+
require 'code_climate'
|
9
|
+
require 'auto_hash'
|
10
|
+
require 'pull_request'
|
11
|
+
require 'os'
|
12
|
+
|
13
|
+
report = AutoHash.new
|
14
|
+
|
15
|
+
auth = YAML.load_file(File.join(PROJECT_ROOT,'auth.yml'))
|
16
|
+
jira_username = auth["jira"]["username"]
|
17
|
+
jira_password = auth["jira"]["password"]
|
18
|
+
JiraReporting.connect! jira_username, jira_password
|
19
|
+
|
20
|
+
# If run on a day to calculate stats for the previous week, do not have to enter a start or end date.
|
21
|
+
start_date = (ARGV[0] && Date.parse(ARGV[0])) || 7.day.ago
|
22
|
+
end_date = (ARGV[1] && Date.parse(ARGV[1])) || 0.day.ago
|
23
|
+
|
24
|
+
start_date = start_date.strftime("%Y-%m-%d")
|
25
|
+
end_date = end_date.strftime("%Y-%m-%d")
|
26
|
+
|
27
|
+
puts ''
|
28
|
+
puts "Report dates - START: #{start_date} END: #{end_date}"
|
29
|
+
puts ''
|
30
|
+
|
31
|
+
puts 'Beginning report data pull...'
|
32
|
+
puts ''
|
33
|
+
|
34
|
+
# Closed issues during given date range
|
35
|
+
closed_ticket_query = %Q{
|
36
|
+
project = "Tech Support"
|
37
|
+
AND "SLA: Closed at" >= "#{start_date}"
|
38
|
+
AND "SLA: Closed at" < "#{end_date}"
|
39
|
+
AND status != "Not Accepted"
|
40
|
+
AND status != "Can't Reproduce"
|
41
|
+
AND type != Epic
|
42
|
+
}
|
43
|
+
puts "The following query will be run for closed tickets: #{closed_ticket_query}"
|
44
|
+
|
45
|
+
# Created issues during given date range
|
46
|
+
created_ticket_query = %Q{
|
47
|
+
project = "Tech Support"
|
48
|
+
AND created >= "#{start_date}"
|
49
|
+
AND created < "#{end_date}"
|
50
|
+
AND status != "Not Accepted"
|
51
|
+
AND status != "Can't Reproduce"
|
52
|
+
AND type != Epic
|
53
|
+
}
|
54
|
+
puts ''
|
55
|
+
puts "The following query will be run for created tickets: #{created_ticket_query}"
|
56
|
+
|
57
|
+
ISSUE_SEGMENTS = %i{bug operational feature research affects_warehouse_users affects_customers affects_client_corporate_users affects_internal_optoro_users}
|
58
|
+
|
59
|
+
# This method creates a hash object of issue arrays divided segments as keys.
|
60
|
+
def segment_issues(issues, segments)
|
61
|
+
segmented_issues = segments.inject({}){|segments_hash, segment| segments_hash[segment] = []; segments_hash }
|
62
|
+
issues.each do |issue|
|
63
|
+
segments.each do |segment|
|
64
|
+
segmented_issues[segment] << issue if issue.send("#{segment}?")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
segmented_issues
|
68
|
+
end
|
69
|
+
|
70
|
+
created_ts_issues = JiraIssue.find(created_ticket_query)
|
71
|
+
total_created_ts_issues = created_ts_issues.count
|
72
|
+
created_segmented_issues = segment_issues(created_ts_issues, ISSUE_SEGMENTS)
|
73
|
+
created_ts_bug_count = created_segmented_issues[:bug].count
|
74
|
+
created_ts_ops_count = created_segmented_issues[:operational].count
|
75
|
+
created_ts_feature_requests = created_segmented_issues[:feature].count
|
76
|
+
created_ts_research_requests = created_segmented_issues[:research].count
|
77
|
+
created_ts_affecting_wh_users = created_segmented_issues[:affects_warehouse_users].count
|
78
|
+
created_ts_affecting_customers = created_segmented_issues[:affects_customers].count
|
79
|
+
created_ts_affecting_client_corporate_users = created_segmented_issues[:affects_client_corporate_users].count
|
80
|
+
created_ts_affecting_internal_users = created_segmented_issues[:affects_internal_optoro_users].count
|
81
|
+
created_ts_over_triage_sla = created_ts_issues.select { |issue| issue.over_triage_sla? == true }.count
|
82
|
+
created_ts_triaged_by_ed = created_ts_issues.select { |issue| issue.triager == 'ewright' }.count
|
83
|
+
created_ts_triaged_by_gabriel = created_ts_issues.select { |issue| issue.triager == 'gzurita' }.count
|
84
|
+
created_ts_triaged_by_spencer = created_ts_issues.select { |issue| issue.triager == 'sgilbert' }.count
|
85
|
+
created_ts_triaged_by_jason = created_ts_issues.select { |issue| issue.triager == 'jfogg' }.count
|
86
|
+
|
87
|
+
closed_ts_issues = JiraIssue.find(closed_ticket_query)
|
88
|
+
|
89
|
+
sla_counted_issues = closed_ts_issues.reject { |issue| issue.sla_due_time.nil? }
|
90
|
+
|
91
|
+
total_ts_cumulative_delay = sla_counted_issues.inject(0){|sum, issue| sum + issue.sum_total_time_over_sla }
|
92
|
+
total_closed_ts_issues = closed_ts_issues.count
|
93
|
+
total_sla_counted_issues = sla_counted_issues.count
|
94
|
+
total_on_time_issues = sla_counted_issues.select { |issue| issue.over_sla.nil? || issue.over_sla? == false }.count
|
95
|
+
closed_segmented_issues = segment_issues(closed_ts_issues, ISSUE_SEGMENTS)
|
96
|
+
closed_ts_bug_count = closed_segmented_issues[:bug].count
|
97
|
+
closed_ts_ops_count = closed_segmented_issues[:operational].count
|
98
|
+
closed_ts_feature_requests = closed_segmented_issues[:feature].count
|
99
|
+
closed_ts_research_requests = closed_segmented_issues[:research].count
|
100
|
+
|
101
|
+
tickets_created_to_tickets_closed = ( total_created_ts_issues.to_f / total_closed_ts_issues.to_f * 100 ).round(2)
|
102
|
+
|
103
|
+
report[:week] = {
|
104
|
+
closed_ts_cumulative_delay: total_ts_cumulative_delay,
|
105
|
+
closed_ts_count: total_closed_ts_issues,
|
106
|
+
closed_bug_count: closed_ts_bug_count,
|
107
|
+
closed_ops_count: closed_ts_ops_count,
|
108
|
+
closed_feature_requests: closed_ts_feature_requests,
|
109
|
+
closed_research_requests: closed_ts_research_requests,
|
110
|
+
created_ts_count: total_created_ts_issues,
|
111
|
+
created_bug_count: created_ts_bug_count,
|
112
|
+
created_ops_count: created_ts_ops_count,
|
113
|
+
created_feature_requests: created_ts_feature_requests,
|
114
|
+
created_research_requests: created_ts_research_requests,
|
115
|
+
created_issues_affecting_wh_users: created_ts_affecting_wh_users,
|
116
|
+
created_issues_affecting_customers: created_ts_affecting_customers,
|
117
|
+
created_issues_affecting_client_corporate_users: created_ts_affecting_client_corporate_users,
|
118
|
+
created_issues_affecting_internal_users: created_ts_affecting_internal_users,
|
119
|
+
tickets_created_to_closed_ratio: tickets_created_to_tickets_closed,
|
120
|
+
created_issues_over_triage_sla: created_ts_over_triage_sla,
|
121
|
+
created_issues_triaged_by_ed: created_ts_triaged_by_ed,
|
122
|
+
created_issues_triaged_by_gabriel: created_ts_triaged_by_gabriel,
|
123
|
+
created_issues_triaged_by_spencer: created_ts_triaged_by_spencer,
|
124
|
+
created_issues_triaged_by_jason: created_ts_triaged_by_jason
|
125
|
+
}
|
126
|
+
|
127
|
+
puts ''
|
128
|
+
|
129
|
+
priorities = closed_ts_issues.group_by(&:priority)
|
130
|
+
|
131
|
+
[:p1,:p2,:p3,:p4,:p5].each do |priority|
|
132
|
+
closed = priorities[priority] || []
|
133
|
+
trend_hit = 1.0
|
134
|
+
trend_hit = closed.select{|issue| issue.over_sla.nil? || issue.over_sla? == false }.length / closed.length.to_f if closed.any?
|
135
|
+
|
136
|
+
report[:sla][priority] = {
|
137
|
+
avg_hit_rate: (trend_hit * 100).round(2),
|
138
|
+
}
|
139
|
+
|
140
|
+
puts "Average hit rate for #{priority.to_s.upcase} tickets: #{(trend_hit * 100).round(2)}%"
|
141
|
+
puts ''
|
142
|
+
end
|
143
|
+
|
144
|
+
puts ''
|
145
|
+
puts 'The following issues went over SLA during the queried period:'
|
146
|
+
closed_ts_issues.sort_by(&:priority).each do |issue|
|
147
|
+
if issue.over_sla?
|
148
|
+
puts "#{issue.priority}\t#{issue.key}\t#{issue.assigned_team}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
puts ''
|
153
|
+
puts "These issues did not meet Platform Stability's triage goals:"
|
154
|
+
closed_ts_issues.sort_by(&:priority).each do |issue|
|
155
|
+
if issue.over_triage_sla?
|
156
|
+
puts "#{issue.priority}\t#{issue.key}\t#{issue.triager}"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
overall_hit = total_on_time_issues.to_f / total_sla_counted_issues.to_f
|
161
|
+
report[:sla][:overall][:avg_hit_rate] = (overall_hit * 100).round(2)
|
162
|
+
puts ''
|
163
|
+
puts "Overall Avg Hit Rate: #{(overall_hit * 100).round(2)}%"
|
164
|
+
|
165
|
+
def copy_paste_string(report)
|
166
|
+
[
|
167
|
+
report[:week][:closed_ts_cumulative_delay].to_s,
|
168
|
+
report[:sla][:overall][:avg_hit_rate].to_s + '%',
|
169
|
+
report[:sla][:p1][:avg_hit_rate].to_s + '%',
|
170
|
+
report[:sla][:p2][:avg_hit_rate].to_s + '%',
|
171
|
+
report[:sla][:p3][:avg_hit_rate].to_s + '%',
|
172
|
+
report[:sla][:p4][:avg_hit_rate].to_s + '%',
|
173
|
+
report[:week][:closed_ts_count],
|
174
|
+
report[:week][:closed_bug_count].to_s,
|
175
|
+
report[:week][:closed_ops_count].to_s,
|
176
|
+
report[:week][:closed_feature_requests].to_s,
|
177
|
+
report[:week][:closed_research_requests].to_s,
|
178
|
+
report[:week][" "].to_s,
|
179
|
+
report[:week][:created_ts_count].to_s,
|
180
|
+
report[:week][:created_bug_count].to_s,
|
181
|
+
report[:week][:created_ops_count].to_s,
|
182
|
+
report[:week][:created_feature_requests].to_s,
|
183
|
+
report[:week][:created_research_requests].to_s,
|
184
|
+
report[:week][:created_issues_affecting_wh_users].to_s,
|
185
|
+
report[:week][:created_issues_affecting_customers].to_s,
|
186
|
+
report[:week][:created_issues_affecting_client_corporate_users].to_s,
|
187
|
+
report[:week][:created_issues_affecting_internal_users].to_s,
|
188
|
+
report[:week][" "].to_s,
|
189
|
+
report[:week][:tickets_created_to_closed_ratio].to_s + '%',
|
190
|
+
report[:week][" "].to_s,
|
191
|
+
report[:week][:created_issues_over_triage_sla].to_s,
|
192
|
+
report[:week][:created_issues_triaged_by_ed].to_s,
|
193
|
+
report[:week][:created_issues_triaged_by_gabriel].to_s,
|
194
|
+
report[:week][:created_issues_triaged_by_spencer].to_s,
|
195
|
+
report[:week][:created_issues_triaged_by_jason].to_s
|
196
|
+
].join("\n")
|
197
|
+
end
|
198
|
+
|
199
|
+
# Copy/pasteable
|
200
|
+
puts "Copy/paste:\n----------"
|
201
|
+
puts copy_paste_string(report)
|
202
|
+
puts "-----------"
|
203
|
+
|
204
|
+
case
|
205
|
+
when OS.linux? == true
|
206
|
+
IO.popen("xclip -selection clipboard", "r+") do |xclip|
|
207
|
+
xclip.puts copy_paste_string(report)
|
208
|
+
end
|
209
|
+
when OS.mac? == true
|
210
|
+
IO.popen("pbcopy", "r+") do |pbcopy|
|
211
|
+
pbcopy.puts copy_paste_string(report)
|
212
|
+
end
|
213
|
+
else
|
214
|
+
puts "The automatic copying of the kpi report stats failed. Please manually copy and paste the output into the KPI spreadsheet"
|
215
|
+
end
|
data/bin/pr-report.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift "#{File.dirname(__FILE__)}/../lib"
|
4
|
+
require 'pull_request'
|
5
|
+
require 'pry-byebug'
|
6
|
+
|
7
|
+
auth = YAML.load_file('auth.yml')
|
8
|
+
jira_username = auth["jira"]["username"]
|
9
|
+
jira_password = auth["jira"]["password"]
|
10
|
+
JiraReporting.connect! jira_username, jira_password
|
11
|
+
|
12
|
+
github_token = auth["github"]["api_token"]
|
13
|
+
PullRequest.connect(github_token)
|
14
|
+
|
15
|
+
prs = PullRequest.get_prs('inventory')
|
16
|
+
binding.pry
|
17
|
+
|
18
|
+
keys = [:pr_number, :jira, :title, :created, :requester, :cl, :ci, :code_reviewed, :needs_testing, :project, :issue_current_sprint, :issue_status]
|
19
|
+
puts keys.to_csv
|
20
|
+
prs.each do |pr|
|
21
|
+
puts pr.to_csv
|
22
|
+
end
|
23
|
+
|
data/bin/quarter_report
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'jira_reporting'
|
3
|
+
require 'pry'
|
4
|
+
require 'byebug'
|
5
|
+
|
6
|
+
username = "hi"
|
7
|
+
password = "there"
|
8
|
+
start_date = "2014-07-01"
|
9
|
+
end_date = "2014-10-01"
|
10
|
+
|
11
|
+
JiraReporting.connect! username, password
|
12
|
+
|
13
|
+
r = JiraReporting::SLAReport.new
|
14
|
+
query = %Q{project = "Tech Support" AND status not in ("Not Accepted", "Can't Reproduce") AND "Support xt Resolved" >= #{start_date} AND "Support xt Resolved" < #{end_date}}
|
15
|
+
issues = r.find_all(query)
|
16
|
+
rept = issues.map{|i| JiraIssue.new(i) }
|
17
|
+
prios = rept.group_by(&:priority)
|
18
|
+
|
19
|
+
|
20
|
+
hour = 60 * 60.0
|
21
|
+
ideal_times = {
|
22
|
+
p1: 2 * hour,
|
23
|
+
p2: 24 * hour,
|
24
|
+
p3: (24 * hour) * 3, # 5 business days
|
25
|
+
p4: (24 * hour) * 5 # 5 business days
|
26
|
+
}
|
27
|
+
|
28
|
+
[:p1,:p2,:p3,:p4,:p5].each do |priority|
|
29
|
+
set = prios[priority] || []
|
30
|
+
open, closed = set.partition(&:open?)
|
31
|
+
trend_time = closed.inject(0){|s,t| s + t.sla_diff } / closed.length.to_f
|
32
|
+
|
33
|
+
|
34
|
+
trend_resolution_time = ""
|
35
|
+
if closed.any?
|
36
|
+
mm, ss = trend_time.divmod(60)
|
37
|
+
hh, mm = mm.divmod(60)
|
38
|
+
dd, hh = hh.divmod(24)
|
39
|
+
trend_resolution_time = "#{dd}d #{hh.to_i}h #{mm.to_i}m #{ss.to_i}s"
|
40
|
+
end
|
41
|
+
|
42
|
+
unless priority == :p4
|
43
|
+
ideal_time = ideal_times[priority]
|
44
|
+
multiple_off_ideal = trend_time.to_f / ideal_time
|
45
|
+
end
|
46
|
+
|
47
|
+
trend_hit = 0
|
48
|
+
trend_hit = closed.select{|t| t.sla_diff <= 0 }.length / closed.length.to_f if closed.any?
|
49
|
+
|
50
|
+
puts "#{priority.to_s.upcase}:"
|
51
|
+
puts "Open Tickets: #{open.count}"
|
52
|
+
puts "Closed Tickets: #{closed.count}"
|
53
|
+
puts "Avg Diff to SLA: #{trend_resolution_time}"
|
54
|
+
puts "Avg SLA Multiple: #{multiple_off_ideal.round(2)}x" unless priority == :p4
|
55
|
+
puts "Avg Hit Rate: #{(trend_hit * 100).round(2)}%"
|
56
|
+
puts ""
|
57
|
+
end
|
58
|
+
|
59
|
+
overall_hit = rept.select{|t| t.sla_diff <= 0 }.length / rept.length.to_f
|
60
|
+
puts ""
|
61
|
+
puts "Overall Avg Hit Rate: #{(overall_hit * 100).round(2)}%"
|
62
|
+
|
63
|
+
binding.pry
|
64
|
+
|
65
|
+
puts 2 + 2
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
PROJECT_ROOT = "#{File.dirname(__FILE__)}/../"
|
4
|
+
|
5
|
+
$:.unshift "#{File.dirname(__FILE__)}/../lib"
|
6
|
+
require 'jira_reporting'
|
7
|
+
require 'pry-byebug'
|
8
|
+
require 'active_support'
|
9
|
+
require 'yaml'
|
10
|
+
|
11
|
+
auth = YAML.load_file(File.join(PROJECT_ROOT,'auth.yml'))
|
12
|
+
jira_username = auth["jira"]["username"]
|
13
|
+
jira_password = auth["jira"]["password"]
|
14
|
+
JiraReporting.connect! jira_username, jira_password
|
15
|
+
|
16
|
+
# Open TS issues
|
17
|
+
query = %Q{
|
18
|
+
project = TS
|
19
|
+
AND ("Support xt Requester Review" >= startOfWeek(-1)
|
20
|
+
OR "Support xt On Production" >= startOfWeek(-1)
|
21
|
+
OR "Support xt Merged" >=startOfWeek(-1) )
|
22
|
+
AND status != "Not Accepted"
|
23
|
+
AND type != Epic
|
24
|
+
}
|
25
|
+
|
26
|
+
ts_issues = JiraIssue.find(query).sort_by(&:sla_time_ratio)
|
27
|
+
|
28
|
+
ts_issues.each do |issue|
|
29
|
+
issue.set_sla_due_time! if issue.sla_due_time.nil?
|
30
|
+
issue.set_sla_triaged_at! if issue.sla_triaged_at.nil?
|
31
|
+
issue.set_over_triage_sla! if issue.over_triage_sla.nil?
|
32
|
+
issue.set_sla_closed_at! if issue.sla_closed_at.nil?
|
33
|
+
issue.set_sla_due_warning! if issue.sla_due_warning.nil?
|
34
|
+
issue.set_over_sla! if issue.over_sla.nil?
|
35
|
+
puts "#{issue.priority} #{issue.key} #{issue.summary} has been updated."
|
36
|
+
end
|
37
|
+
|
38
|
+
puts 'SLA due time and overdue status update complete.'
|