jirametrics 2.20.1 → 2.20.2pre6

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.

Potentially problematic release.


This version of jirametrics might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cbe1101b082615d38939850c0adc688aedefe02a74537503bcd390cdf11d0d4e
4
- data.tar.gz: eeffbda7c7ba8280273e0d749ede1ed3c1caa33d06a1f50a2c47b2331035d5af
3
+ metadata.gz: 63b99b8edec3e017c9ef1be6ad6d7e9c4fa94038126a4fb84cf8d90face9ed9e
4
+ data.tar.gz: c2df48cad225aa8c270dfd3c8f04dc049d3c48642eaa971b885258d58f230a61
5
5
  SHA512:
6
- metadata.gz: b73533c90e457c2c5f7a7f2d1759ccd44d218ebe984052fcb581d8ab88225abf43b5612923217b4fa7467ed11e82ba5b4fe2cc656a324f269b71c2497bf67659
7
- data.tar.gz: 57cbc54fe6c739d0c85f68cc0efcfbc6005975af0b40174ed9ee35790a83dac9b5e524601b770dffc6a3fefbd10f0d577d19b840560b3acfb63b0b542728d5fc
6
+ metadata.gz: 50dcdb60c3626a3faa6260313fed8a015f24eb757b9f7f338218f7e789b5d0be242e390d9e56b51b2f2f7289eebe6d64df2e195af04a1ecec8acd2fff782772b
7
+ data.tar.gz: 6608ebbefbd28943fed9ab39fa8611a0948e523f76f9f3b37777fdef0a7f0d001df8db2ef4d7d936c588077ba45f27639e8273af279e74291fdbfa638941a9e9
@@ -116,4 +116,8 @@ class Board
116
116
  def estimation_configuration
117
117
  EstimationConfiguration.new raw: raw['estimation']
118
118
  end
119
+
120
+ def inspect
121
+ "Board(id:#{id}, name:#{name.inspect}, board_type:#{board_type.inspect})"
122
+ end
119
123
  end
@@ -24,7 +24,8 @@ class BoardConfig
24
24
  end
25
25
 
26
26
  @board.cycletime = CycleTimeConfig.new(
27
- parent_config: self, label: label, block: block, file_system: project_config.file_system,
27
+ possible_statuses: project_config.possible_statuses,
28
+ label: label, block: block, file_system: project_config.file_system,
28
29
  settings: project_config.settings
29
30
  )
30
31
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ChangeItem
4
- attr_reader :field, :value_id, :old_value_id, :raw, :author_raw
4
+ attr_reader :field, :value_id, :old_value_id, :raw, :author_raw, :field_id
5
5
  attr_accessor :value, :old_value, :time
6
6
 
7
7
  def initialize raw:, author_raw:, time:, artificial: false
@@ -13,9 +13,15 @@ class ChangeItem
13
13
 
14
14
  @field = @raw['field']
15
15
  @value = @raw['toString']
16
- @value_id = @raw['to'].to_i
17
16
  @old_value = @raw['fromString']
18
- @old_value_id = @raw['from']&.to_i
17
+ if sprint?
18
+ @value_id = @raw['to'].split(', ').collect(&:to_i)
19
+ @old_value_id = (@raw['from'] || '').split(', ').collect(&:to_i)
20
+ else
21
+ @value_id = @raw['to'].to_i
22
+ @old_value_id = @raw['from']&.to_i
23
+ end
24
+ @field_id = @raw['fieldId']
19
25
  @artificial = artificial
20
26
  end
21
27
 
@@ -22,6 +22,14 @@ class ChartBase
22
22
  @canvas_responsive = true
23
23
  end
24
24
 
25
+ def call_before_run &proc
26
+ (@call_before_run_procs ||= []) << proc
27
+ end
28
+
29
+ def before_run
30
+ @call_before_run_procs&.each { |proc| proc.call }
31
+ end
32
+
25
33
  def aggregated_project?
26
34
  @aggregated_project
27
35
  end
@@ -279,4 +287,19 @@ class ChartBase
279
287
  </div>
280
288
  TEXT
281
289
  end
290
+
291
+ # Set a cycletime for just this one chart, overriding the one for the report.
292
+ def cycletime &block
293
+ call_before_run do
294
+ @cycletime = CycleTimeConfig.new(
295
+ possible_statuses: possible_statuses, label: nil, block: block, file_system: file_system,
296
+ settings: settings
297
+ )
298
+ end
299
+ end
300
+
301
+ # Returns the cycletime in use right now, which may be specific to the chart or across the report.
302
+ def cycletime_for_issue issue
303
+ @cycletime || issue.board.cycletime
304
+ end
282
305
  end
@@ -6,15 +6,14 @@ require 'date'
6
6
  class CycleTimeConfig
7
7
  include SelfOrIssueDispatcher
8
8
 
9
- attr_reader :label, :parent_config, :settings, :file_system
9
+ attr_reader :label, :possible_statuses, :settings, :file_system
10
10
 
11
- def initialize parent_config:, label:, block:, settings:, file_system: nil, today: Date.today
11
+ def initialize possible_statuses:, label:, block:, settings:, file_system: nil, today: Date.today
12
12
 
13
- @parent_config = parent_config
13
+ @possible_statuses = possible_statuses
14
14
  @label = label
15
15
  @today = today
16
16
  @settings = settings
17
- @cache_cycletime_calculations = settings['cache_cycletime_calculations']
18
17
 
19
18
  # If we hit something deprecated and this is nil then we'll blow up. Although it's ugly, this
20
19
  # may make it easier to find problems in the test code ;-)
@@ -68,7 +67,7 @@ class CycleTimeConfig
68
67
  def started_stopped_changes issue
69
68
  cache_key = "#{issue.key}:#{issue.board.id}"
70
69
  last_result = (@cache ||= {})[cache_key]
71
- return *last_result if last_result && @cache_cycletime_calculations
70
+ return *last_result if last_result && settings['cache_cycletime_calculations']
72
71
 
73
72
  started = @start_at.call(issue)
74
73
  stopped = @stop_at.call(issue)
@@ -66,7 +66,7 @@ class DailyWipChart < ChartBase
66
66
  hash = {}
67
67
 
68
68
  @issues.each do |issue|
69
- start, stop = issue.board.cycletime.started_stopped_dates(issue)
69
+ start, stop = cycletime_for_issue(issue).started_stopped_dates(issue)
70
70
  next if start.nil? && stop.nil?
71
71
 
72
72
  # If it stopped but never started then assume it started at creation so the data points
@@ -266,6 +266,8 @@ class DataQualityReport < ChartBase
266
266
 
267
267
  def scan_for_items_blocked_on_closed_tickets entry:
268
268
  entry.issue.issue_links.each do |link|
269
+ next unless settings['blocked_link_text'].include?(link.label)
270
+
269
271
  this_active = !entry.stopped
270
272
  other_active = !link.other_issue.board.cycletime.started_stopped_times(link.other_issue).last
271
273
  next unless this_active && !other_active
@@ -11,11 +11,24 @@ class FixVersion
11
11
  @raw['name']
12
12
  end
13
13
 
14
+ def description
15
+ @raw['description']
16
+ end
17
+
14
18
  def id
15
19
  @raw['id'].to_i
16
20
  end
17
21
 
22
+ def release_date
23
+ text = @raw['releaseDate']
24
+ text.nil? ? nil : Date.parse(text)
25
+ end
26
+
18
27
  def released?
19
28
  @raw['released']
20
29
  end
30
+
31
+ def archived?
32
+ @raw['archived']
33
+ end
21
34
  end
@@ -52,7 +52,8 @@ class HtmlReportConfig
52
52
  raise 'Multiple cycletimes not supported' if board.cycletime
53
53
 
54
54
  board.cycletime = CycleTimeConfig.new(
55
- parent_config: self, label: label, block: block, file_system: file_system, settings: settings
55
+ possible_statuses: file_config.project_config, label: label, block: block,
56
+ file_system: file_system, settings: settings
56
57
  )
57
58
  end
58
59
  end
@@ -175,6 +176,7 @@ class HtmlReportConfig
175
176
  after_init_block&.call chart
176
177
 
177
178
  @charts << chart
179
+ chart.before_run
178
180
  html chart.run
179
181
  end
180
182
 
@@ -212,8 +212,79 @@ class Issue
212
212
  first_time_in_status(*board.visible_columns.collect(&:status_ids).flatten)
213
213
  end
214
214
 
215
+ # If this issue will ever be in an active sprint then return the time that it
216
+ # was first added to that sprint, whether or not the sprint was active at that
217
+ # time. Although it seems like an odd thing to calculate, it's a reasonable proxy
218
+ # for 'ready' in cases where the team doesn't have an explicit 'ready' status.
219
+ # You'd be better off with an explicit 'ready' but sometimes that's not an option.
220
+ def first_time_added_to_active_sprint
221
+ unless board.scrum?
222
+ raise 'first_time_added_to_active_sprint() can only be used with Scrum boards: ' \
223
+ "issue=#{key}, board=#{board.inspect}"
224
+ end
225
+ data_clazz = Struct.new(:sprint_id, :sprint_start, :sprint_stop, :change)
226
+
227
+ matching_changes = []
228
+ all_datas = []
229
+
230
+ @changes.each do |change|
231
+ next unless change.sprint?
232
+
233
+ added_sprint_ids = change.value_id - change.old_value_id
234
+ added_sprint_ids.each do |id|
235
+ data = data_clazz.new
236
+ data.sprint_id = id
237
+ data.change = change
238
+ data.sprint_start, data.sprint_stop = find_sprint_start_end(sprint_id: id, change: change)
239
+ all_datas << data
240
+ end
241
+
242
+ removed_sprint_ids = change.old_value_id - change.value_id
243
+ removed_sprint_ids.each do |id|
244
+ data = all_datas.find { |d| d.sprint_id == id }
245
+
246
+ all_datas.delete(data)
247
+
248
+ next if data.sprint_start.nil? || data.sprint_start >= change.time
249
+
250
+ matching_changes << data.change
251
+ end
252
+ end
253
+
254
+ # There can't be any more removes so whatever is left is a valid option
255
+ # Now all we care about is if the sprint has started.
256
+ all_datas.each do |data|
257
+ matching_changes << data.change if data.sprint_start
258
+ end
259
+
260
+ matching_changes.min_by(&:time)
261
+ end
262
+
263
+ def find_sprint_start_end sprint_id:, change:
264
+ start = nil
265
+ stop = nil
266
+
267
+ sprint = board.sprints.find { |s| s.id == sprint_id }
268
+ if sprint
269
+ start = sprint.start_time
270
+ stop = sprint.completed_time
271
+ puts "#{key}: Found sprint. values: #{start}/#{stop} from sprints file"
272
+ end
273
+
274
+ sprint_data = raw['fields'][change.field_id].find { |sd| sd['id'].to_i == sprint_id }
275
+ if sprint_data
276
+ start = parse_time(sprint_data['startDate'])
277
+ stop = parse_time(sprint_data['completeDate'])
278
+ puts "#{key}: Found sprint. values: #{start}/#{stop} from field: #{change.field_id}"
279
+ end
280
+
281
+ [start, stop]
282
+ end
283
+
215
284
  def parse_time text
216
- if text.is_a? String
285
+ if text.nil?
286
+ nil
287
+ elsif text.is_a? String
217
288
  Time.parse(text).getlocal(@timezone_offset)
218
289
  else
219
290
  Time.at(text / 1000).getlocal(@timezone_offset)
@@ -225,6 +296,10 @@ class Issue
225
296
  parse_time @raw['fields']['created'] if @raw['fields']['created']
226
297
  end
227
298
 
299
+ def time_created
300
+ @changes.first
301
+ end
302
+
228
303
  def updated
229
304
  parse_time @raw['fields']['updated']
230
305
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jirametrics
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.20.1
4
+ version: 2.20.2pre6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Bowler
@@ -159,7 +159,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
159
159
  - !ruby/object:Gem::Version
160
160
  version: '0'
161
161
  requirements: []
162
- rubygems_version: 3.6.9
162
+ rubygems_version: 4.0.3
163
163
  specification_version: 4
164
164
  summary: Extract Jira metrics
165
165
  test_files: []