Class: JiraIssue
- Inherits:
-
Object
- Object
- JiraIssue
- Includes:
- SLATracker, TriageTracker
- Defined in:
- lib/jira_issue.rb,
lib/jira_reporting/sla_tracker.rb,
lib/jira_reporting/triage_tracker.rb
Defined Under Namespace
Modules: SLATracker, TriageTracker
Constant Summary collapse
- FIVE_P_DATE =
The FIVE_P_DATE variable exists for tickets created before 2015-03-06 15:55:16 -0500. Not used for any tickets after that. Tickets created after above date use differnt SLA measurements.
Time.at(142_567_531_6).freeze
- STORY_POINTS_FIELD =
'customfield_10007'.freeze
- TRIAGER_FIELD =
'customfield_14100'.freeze
- SLA_TRIAGED_AT_FIELD =
'customfield_14400'.freeze
- OVER_TRIAGE_SLA_FIELD =
'customfield_14200'.freeze
- OVER_TRIAGE_SLA_FIELD_YES =
'12500'.freeze
- OVER_TRIAGE_SLA_FIELD_NO =
'12501'.freeze
- API_OVER_TRIAGE_SLA_FIELD_YES =
{"self"=>"https://optoro.atlassian.net/rest/api/2/customFieldOption/12500", "value"=>"Yes", "id"=>"12500"}.freeze
- API_OVER_TRIAGE_SLA_FIELD_NO =
{"self"=>"https://optoro.atlassian.net/rest/api/2/customFieldOption/12501", "value"=>"No", "id"=>"12501"}.freeze
- SLA_DUE_TIME_FIELD =
'customfield_12900'.freeze
- SLA_DUE_WARNING_FIELD =
'customfield_13401'.freeze
- SLA_DUE_WARNING_FIELD_SET =
'12100'.freeze
- SLA_CLOSED_AT_FIELD =
'customfield_14000'.freeze
- OVER_SLA_FIELD =
'customfield_12901'.freeze
- OVER_SLA_FIELD_YES =
'11901'.freeze
- OVER_SLA_FIELD_NO =
'11900'.freeze
- TOTAL_TIME_OVER_SLA_FIELD =
'customfield_14201'.freeze
- API_OVER_SLA_FIELD_YES =
{"self"=>"https://optoro.atlassian.net/rest/api/2/customFieldOption/11901", "value"=>"Yes", "id"=>"11901"}.freeze
- API_OVER_SLA_FIELD_NO =
{"self"=>"https://optoro.atlassian.net/rest/api/2/customFieldOption/11900", "value"=>"No", "id"=>"11900"}.freeze
- AFFECTED_USER_GROUP_FIELD =
'customfield_13602'.freeze
Instance Attribute Summary collapse
-
#affected_user_group ⇒ Object
Returns the value of attribute affected_user_group.
-
#assigned_team ⇒ Object
Returns the value of attribute assigned_team.
-
#cant_reproduce ⇒ Object
Returns the value of attribute cant_reproduce.
-
#changelog ⇒ Object
Returns the value of attribute changelog.
-
#completed ⇒ Object
Returns the value of attribute completed.
-
#created_at ⇒ Object
Returns the value of attribute created_at.
-
#deploy ⇒ Object
Returns the value of attribute deploy.
-
#description ⇒ Object
Returns the value of attribute description.
-
#in_progress ⇒ Object
Returns the value of attribute in_progress.
-
#key ⇒ Object
Returns the value of attribute key.
-
#labels ⇒ Object
Returns the value of attribute labels.
-
#merged ⇒ Object
Returns the value of attribute merged.
-
#merged_st ⇒ Object
Returns the value of attribute merged_st.
-
#not_accepted ⇒ Object
Returns the value of attribute not_accepted.
-
#on_production ⇒ Object
Returns the value of attribute on_production.
-
#orig ⇒ Object
Returns the value of attribute orig.
-
#over_sla ⇒ Object
Returns the value of attribute over_sla.
-
#over_triage_sla ⇒ Object
Returns the value of attribute over_triage_sla.
-
#pr_review ⇒ Object
Returns the value of attribute pr_review.
-
#priority_name ⇒ Object
Returns the value of attribute priority_name.
-
#project ⇒ Object
Returns the value of attribute project.
-
#raw_sprints ⇒ Object
Returns the value of attribute raw_sprints.
-
#requester_denied ⇒ Object
Returns the value of attribute requester_denied.
-
#requester_review ⇒ Object
Returns the value of attribute requester_review.
-
#resolved ⇒ Object
Returns the value of attribute resolved.
-
#reverify ⇒ Object
Returns the value of attribute reverify.
-
#sla_closed_at ⇒ Object
Returns the value of attribute sla_closed_at.
-
#sla_due_time ⇒ Object
Returns the value of attribute sla_due_time.
-
#sla_due_warning ⇒ Object
Returns the value of attribute sla_due_warning.
-
#sla_triaged_at ⇒ Object
Returns the value of attribute sla_triaged_at.
-
#status ⇒ Object
Returns the value of attribute status.
-
#story_points ⇒ Object
Returns the value of attribute story_points.
-
#summary ⇒ Object
Returns the value of attribute summary.
-
#total_time_over_sla ⇒ Object
Returns the value of attribute total_time_over_sla.
-
#triaged ⇒ Object
Returns the value of attribute triaged.
-
#triager ⇒ Object
Returns the value of attribute triager.
-
#type ⇒ Object
Returns the value of attribute type.
-
#url ⇒ Object
Returns the value of attribute url.
-
#verified ⇒ Object
Returns the value of attribute verified.
Class Method Summary collapse
Instance Method Summary collapse
- #affected_user_groups ⇒ Object
- #affects_client_corporate_users? ⇒ Boolean
- #affects_customers? ⇒ Boolean
- #affects_internal_optoro_users? ⇒ Boolean
- #affects_warehouse_users? ⇒ Boolean
- #bug? ⇒ Boolean
- #changelog_simple ⇒ Object
- #closed? ⇒ Boolean
- #closed_at ⇒ Object
- #feature? ⇒ Boolean
-
#initialize(issue) ⇒ JiraIssue
constructor
A new instance of JiraIssue.
- #jiralicious_issue ⇒ Object
- #open? ⇒ Boolean
- #operational? ⇒ Boolean
- #priority ⇒ Object
- #research? ⇒ Boolean
- #sprints ⇒ Object
- #status_ages ⇒ Object
- #status_changes ⇒ Object
- #status_duration_during(status, start_date, end_date) ⇒ Object
- #time_to_qa ⇒ Object
Methods included from TriageTracker
#over_triage_sla?, #set_over_triage_sla!, #set_sla_triaged_at!, #time_to_triage, #triage_sla_remaining_time, #triage_sla_target, #triage_sla_total_available_time
Methods included from SLATracker
#approaching_sla_due_time?, #over_sla?, #resolution_base, #set_over_sla!, #set_sla_closed_at!, #set_sla_due_time!, #set_sla_due_warning!, #set_total_time_over_sla!, #sla_base, #sla_diff, #sla_remaining_time, #sla_target, #sla_time_ratio, #sla_total_available_time, #sla_warning_time, #sum_total_time_over_sla, #time_to_finish_work, #time_to_start_work, #total_time_to_resolution
Constructor Details
#initialize(issue) ⇒ JiraIssue
Returns a new instance of JiraIssue.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/jira_issue.rb', line 40 def initialize(issue) issue.extend(DotNotation) self.key = issue.dot 'key' self.created_at = Time.parse(issue.dot('fields.created')) self.type = issue.dot 'fields.issuetype.name' self.priority_name = issue.dot 'fields.priority.name' self.status = issue.dot('fields.status.name').downcase self.project = issue.dot 'fields.project.key' self.description = issue.dot 'fields.description' self.summary = issue.dot 'fields.summary' self.labels = issue.dot 'fields.labels' self.assigned_team = issue.dot 'fields.customfield_12601.value' self.story_points = issue.dot "fields.#{STORY_POINTS_FIELD}" self.orig = issue self.url = "https://optoro.atlassian.net/browse/#{key}" self.raw_sprints = issue.dot 'fields.customfield_10007' self.sla_triaged_at = Time.parse(issue.dot("fields.#{SLA_TRIAGED_AT_FIELD}")) if issue.dot("fields.#{SLA_TRIAGED_AT_FIELD}").present? self.over_triage_sla = issue.dot "fields.#{OVER_TRIAGE_SLA_FIELD}" self.triager = issue.dot "fields.#{TRIAGER_FIELD}.name" self.sla_due_time = Time.parse(issue.dot("fields.#{SLA_DUE_TIME_FIELD}")) if issue.dot("fields.#{SLA_DUE_TIME_FIELD}").present? self.sla_due_warning = issue.dot "fields.#{SLA_DUE_WARNING_FIELD}" self.sla_closed_at = Time.parse(issue.dot("fields.#{SLA_CLOSED_AT_FIELD}")) if issue.dot("fields.#{SLA_CLOSED_AT_FIELD}").present? self.over_sla = issue.dot "fields.#{OVER_SLA_FIELD}" self.total_time_over_sla = issue.dot "fields.#{TOTAL_TIME_OVER_SLA_FIELD}" self.affected_user_group = issue.dot "fields.#{AFFECTED_USER_GROUP_FIELD}" inv = self.class.custom_time_fields.invert inv.each do |name, key| x = name.gsub(/'/,'').gsub(/ +/, '_').downcase.gsub(/support_xt_/,'') v = issue.dot "fields.#{key}" v = Time.parse(v) if v x = "pr_review" if x == "review" # rename send("#{x}=", v) end end |
Instance Attribute Details
#affected_user_group ⇒ Object
Returns the value of attribute affected_user_group.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def affected_user_group @affected_user_group end |
#assigned_team ⇒ Object
Returns the value of attribute assigned_team.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def assigned_team @assigned_team end |
#cant_reproduce ⇒ Object
Returns the value of attribute cant_reproduce.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def cant_reproduce @cant_reproduce end |
#changelog ⇒ Object
Returns the value of attribute changelog.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def changelog @changelog end |
#completed ⇒ Object
Returns the value of attribute completed.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def completed @completed end |
#created_at ⇒ Object
Returns the value of attribute created_at.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def created_at @created_at end |
#deploy ⇒ Object
Returns the value of attribute deploy.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def deploy @deploy end |
#description ⇒ Object
Returns the value of attribute description.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def description @description end |
#in_progress ⇒ Object
Returns the value of attribute in_progress.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def in_progress @in_progress end |
#key ⇒ Object
Returns the value of attribute key.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def key @key end |
#labels ⇒ Object
Returns the value of attribute labels.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def labels @labels end |
#merged ⇒ Object
Returns the value of attribute merged.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def merged @merged end |
#merged_st ⇒ Object
Returns the value of attribute merged_st.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def merged_st @merged_st end |
#not_accepted ⇒ Object
Returns the value of attribute not_accepted.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def not_accepted @not_accepted end |
#on_production ⇒ Object
Returns the value of attribute on_production.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def on_production @on_production end |
#orig ⇒ Object
Returns the value of attribute orig.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def orig @orig end |
#over_sla ⇒ Object
Returns the value of attribute over_sla.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def over_sla @over_sla end |
#over_triage_sla ⇒ Object
Returns the value of attribute over_triage_sla.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def over_triage_sla @over_triage_sla end |
#pr_review ⇒ Object
Returns the value of attribute pr_review.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def pr_review @pr_review end |
#priority_name ⇒ Object
Returns the value of attribute priority_name.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def priority_name @priority_name end |
#project ⇒ Object
Returns the value of attribute project.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def project @project end |
#raw_sprints ⇒ Object
Returns the value of attribute raw_sprints.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def raw_sprints @raw_sprints end |
#requester_denied ⇒ Object
Returns the value of attribute requester_denied.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def requester_denied @requester_denied end |
#requester_review ⇒ Object
Returns the value of attribute requester_review.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def requester_review @requester_review end |
#resolved ⇒ Object
Returns the value of attribute resolved.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def resolved @resolved end |
#reverify ⇒ Object
Returns the value of attribute reverify.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def reverify @reverify end |
#sla_closed_at ⇒ Object
Returns the value of attribute sla_closed_at.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def sla_closed_at @sla_closed_at end |
#sla_due_time ⇒ Object
Returns the value of attribute sla_due_time.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def sla_due_time @sla_due_time end |
#sla_due_warning ⇒ Object
Returns the value of attribute sla_due_warning.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def sla_due_warning @sla_due_warning end |
#sla_triaged_at ⇒ Object
Returns the value of attribute sla_triaged_at.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def sla_triaged_at @sla_triaged_at end |
#status ⇒ Object
Returns the value of attribute status.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def status @status end |
#story_points ⇒ Object
Returns the value of attribute story_points.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def story_points @story_points end |
#summary ⇒ Object
Returns the value of attribute summary.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def summary @summary end |
#total_time_over_sla ⇒ Object
Returns the value of attribute total_time_over_sla.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def total_time_over_sla @total_time_over_sla end |
#triaged ⇒ Object
Returns the value of attribute triaged.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def triaged @triaged end |
#triager ⇒ Object
Returns the value of attribute triager.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def triager @triager end |
#type ⇒ Object
Returns the value of attribute type.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def type @type end |
#url ⇒ Object
Returns the value of attribute url.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def url @url end |
#verified ⇒ Object
Returns the value of attribute verified.
30 31 32 |
# File 'lib/jira_issue.rb', line 30 def verified @verified end |
Class Method Details
.custom_time_fields ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/jira_issue.rb', line 94 def self.custom_time_fields Hash[[ [10812, "Support xt Can't Reproduce"], [10808, 'Support xt In Progress'], [10809, 'Support xt Not Accepted'], [10817, 'Support xt Requester Denied'], [10814, 'Support xt Requester Review'], [13101, 'Support xt Merged'], [13102, 'Support xt On Production'], [10816, 'Support xt Resolved'], [10815, 'Support xt Reverify'], [10813, 'Support xt Review'], [10810, 'Support xt Triaged'], [10811, 'Support xt Verified'] ].map{|k,v| ["customfield_#{k}", v]}] end |
.find(query, offset = 0) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/jira_issue.rb', line 80 def self.find(query, offset = 0) ask = 100 result = Jiralicious.search(query, start_at: offset, max_results: ask) issues = result.issues_raw issues.map! { |i| new(i) } if issues.count == ask && result.num_results > offset + ask issues += find(query, offset + ask) end issues rescue Jiralicious::JqlError => e $stderr.puts "Error: #{e}" [] end |
Instance Method Details
#affected_user_groups ⇒ Object
159 160 161 |
# File 'lib/jira_issue.rb', line 159 def affected_user_groups affected_user_group.map {|user_group| user_group["value"]} unless affected_user_group.nil? end |
#affects_client_corporate_users? ⇒ Boolean
173 174 175 176 |
# File 'lib/jira_issue.rb', line 173 def affects_client_corporate_users? return false if affected_user_groups.nil? affected_user_groups.include?("Client Corporate Users") end |
#affects_customers? ⇒ Boolean
168 169 170 171 |
# File 'lib/jira_issue.rb', line 168 def affects_customers? return false if affected_user_groups.nil? affected_user_groups.include?("Customers") end |
#affects_internal_optoro_users? ⇒ Boolean
178 179 180 181 |
# File 'lib/jira_issue.rb', line 178 def affects_internal_optoro_users? return false if affected_user_groups.nil? affected_user_groups.include?("Internal Optoro Users") end |
#affects_warehouse_users? ⇒ Boolean
163 164 165 166 |
# File 'lib/jira_issue.rb', line 163 def affects_warehouse_users? return false if affected_user_groups.nil? affected_user_groups.include?("WH Users") end |
#bug? ⇒ Boolean
143 144 145 |
# File 'lib/jira_issue.rb', line 143 def bug? type == "Bug / Outage" end |
#changelog_simple ⇒ Object
228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/jira_issue.rb', line 228 def changelog_simple changelog.map { |c| c["items"].map { |i| i.slice("field", "fromString","toString") .merge({ "created" => c["created"], "author_out" => c["author"]["name"] || "" }) } }.flatten end |
#closed? ⇒ Boolean
117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/jira_issue.rb', line 117 def closed? [ "requester review", "merged", "merged_st", "on production", "resolved", "not accepted", "can't reproduce", "deploy", "completed" ].include? status end |
#closed_at ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/jira_issue.rb', line 130 def closed_at [ requester_review, merged, merged_st, on_production, resolved, not_accepted, cant_reproduce, deploy, completed ].compact.min end |
#feature? ⇒ Boolean
151 152 153 |
# File 'lib/jira_issue.rb', line 151 def feature? type == "Feature Enhancement" end |
#jiralicious_issue ⇒ Object
76 77 78 |
# File 'lib/jira_issue.rb', line 76 def jiralicious_issue Jiralicious::Issue.find(key) end |
#open? ⇒ Boolean
111 112 113 114 115 |
# File 'lib/jira_issue.rb', line 111 def open? !closed? # ["unverified", "triaged", "verified", # "in progress", "pr_review", "pr review"].include? status end |
#operational? ⇒ Boolean
147 148 149 |
# File 'lib/jira_issue.rb', line 147 def operational? type == "Operational Request" end |
#priority ⇒ Object
183 184 185 186 187 188 189 190 191 192 193 194 195 196 |
# File 'lib/jira_issue.rb', line 183 def priority case priority_name when /P1/ :p1 when /P2/ :p2 when /P3/ :p3 when /P4/ :p4 else :p5 end end |
#research? ⇒ Boolean
155 156 157 |
# File 'lib/jira_issue.rb', line 155 def research? type == "Research" end |
#sprints ⇒ Object
214 215 216 217 218 219 220 |
# File 'lib/jira_issue.rb', line 214 def sprints if raw_sprints raw_sprints.map {|s| Hash[s.match(/\[(.*)\]/)[1].split(',').map{|f|f.split('=')}]} else [] end end |
#status_ages ⇒ Object
270 271 272 273 274 |
# File 'lib/jira_issue.rb', line 270 def status_ages ages = {} status_changes.each{|c| ages[c[:status]] = ages.fetch(c[:status], 0) + c[:age_hours].to_r.round(2).to_f} ages end |
#status_changes ⇒ Object
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/jira_issue.rb', line 240 def status_changes status_changes = changelog_simple.select{|c| c["field"] == "status"} start = created_at = orig["fields"]["reporter"].andand["name"] || "" status_changes.each { |c| c["age_hours"] = (Time.parse(c["created"]).to_i - start.to_i)/60.0/60 c["started"] = start start = Time.parse(c["created"]) = = c["author_out"] c["author_in"] = } statuses = status_changes.map { |s| { status: s["fromString"], start: s["started"], end: Time.parse(s["created"]), author_in: s["author_in"], author_out: s["author_out"], age_hours: s["age_hours"] } } statuses << { status: status, start: start, author_in: } end |
#status_duration_during(status, start_date, end_date) ⇒ Object
276 277 278 279 280 281 282 283 284 285 286 287 |
# File 'lib/jira_issue.rb', line 276 def status_duration_during(status, start_date, end_date) ages = {} status_changes.each{|c| ages[c["fromString"]] = ages.fetch(c["fromString"],0) + c["age_hours"]} status_changes.each{|c| ages[c[:status]] = ages.fetch(c[:status], 0) + c[:age_hours].to_r.round(2).to_f} last_status = status_changes.last if last_status ages[last_status["toString"]] = ages.fetch(last_status["toString"], 0) + ((Time.now.to_f - Time.parse(last_status["created"]).to_f)/60.0/60) end ages end |
#time_to_qa ⇒ Object
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 |
# File 'lib/jira_issue.rb', line 198 def time_to_qa if triaged && (verified || cant_reproduce || in_progress) if verified verified - triaged elsif cant_reproduce cant_reproduce - triaged else in_progress - triaged end elsif triaged Time.now - triaged else nil end end |