jirametrics 2.7 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 73e2f2e8408a55ccecb221ba0c6d241c77f19de18d2100a9b05213a6470ed65f
4
- data.tar.gz: d0f9056615c44e783c824ca1c6566c95bf68f16a26f81a596475c1d458fee9f1
3
+ metadata.gz: b747372b77be9d3ec514c09b57f479741a47688dd6e634e6823aa9feefe3154e
4
+ data.tar.gz: df7b9bdc06211d7d2fd89df18af5aa8ab4b780aa58f798c29c45ca8033c1986f
5
5
  SHA512:
6
- metadata.gz: e58594175d798269e0e4b8ec1fd4c0f8b693767670222bc6144be19646b04f83e5edb508e4f933f8466865018e8802f789ecb348db368c3f626318df7774c0e0
7
- data.tar.gz: 4555628c33a398cd3aaedd6e36a074b54d89f5a431f47d8617344e4af45e389e529ba54dd9cbd7d9e7d8ad7f673a68f664d00b951451b433d47f90c6feb439a5
6
+ metadata.gz: 7f4873e816019b7b2903b7b2a5c905484a6e1ef5d2601f9bb8dd0cec78a306646a4d145a6bb76981a4bd3ce46d884e5e7b8e8e3ccef4f179a2a7067e26b58a43
7
+ data.tar.gz: 40790878004dd12d1aa362cbe72988a2c6ed13152066b48ab1f38855a74bf89f8aae926d13d3e721990ca568c20f5adbd1c99d0ce5b81aaece19d04701b8eddd
@@ -25,6 +25,14 @@ class ChartBase
25
25
  @aggregated_project
26
26
  end
27
27
 
28
+ def html_directory
29
+ pathname = Pathname.new(File.realpath(__FILE__))
30
+ # basename = pathname.basename.to_s
31
+ # raise "Unexpected filename #{basename.inspect}" unless basename.match?(/^(.+)\.rb$/)
32
+
33
+ "#{pathname.dirname}/html"
34
+ end
35
+
28
36
  def render caller_binding, file
29
37
  pathname = Pathname.new(File.realpath(file))
30
38
  basename = pathname.basename.to_s
@@ -33,8 +41,8 @@ class ChartBase
33
41
  # Insert a incrementing chart_id so that all the chart names on the page are unique
34
42
  caller_binding.eval "chart_id='chart#{next_id}'" # chart_id=chart3
35
43
 
36
- @html_directory = "#{pathname.dirname}/html"
37
- erb = ERB.new file_system.load "#{@html_directory}/#{$1}.erb"
44
+ # @html_directory = "#{pathname.dirname}/html"
45
+ erb = ERB.new file_system.load "#{html_directory}/#{$1}.erb"
38
46
  erb.result(caller_binding)
39
47
  end
40
48
 
@@ -100,7 +108,7 @@ class ChartBase
100
108
  issues_id = next_id
101
109
 
102
110
  issue_descriptions.sort! { |a, b| a[0].key_as_i <=> b[0].key_as_i }
103
- erb = ERB.new file_system.load "#{@html_directory}/collapsible_issues_panel.erb"
111
+ erb = ERB.new file_system.load File.join(html_directory, 'collapsible_issues_panel.erb')
104
112
  erb.result(binding)
105
113
  end
106
114
 
@@ -57,7 +57,25 @@ class DataQualityReport < ChartBase
57
57
  entries_with_problems = entries_with_problems()
58
58
  return '' if entries_with_problems.empty?
59
59
 
60
- wrap_and_render(binding, __FILE__)
60
+ caller_binding = binding
61
+ result = +''
62
+ result << render_top_text(caller_binding)
63
+
64
+ result << '<ul class="quality_report">'
65
+ result << render_problem_type(:discarded_changes)
66
+ result << render_problem_type(:completed_but_not_started)
67
+ result << render_problem_type(:status_changes_after_done)
68
+ result << render_problem_type(:backwards_through_status_categories)
69
+ result << render_problem_type(:backwords_through_statuses)
70
+ result << render_problem_type(:status_not_on_board)
71
+ result << render_problem_type(:created_in_wrong_status)
72
+ result << render_problem_type(:stopped_before_started)
73
+ result << render_problem_type(:issue_not_started_but_subtasks_have)
74
+ result << render_problem_type(:incomplete_subtasks_when_issue_done)
75
+ result << render_problem_type(:issue_on_multiple_boards)
76
+ result << '</ul>'
77
+
78
+ result
61
79
  end
62
80
 
63
81
  def problems_for key
@@ -70,6 +88,18 @@ class DataQualityReport < ChartBase
70
88
  result
71
89
  end
72
90
 
91
+ def render_problem_type problem_key
92
+ problems = problems_for problem_key
93
+ return '' if problems.empty?
94
+
95
+ <<-HTML
96
+ <li>
97
+ #{__send__ :"render_#{problem_key}", problems}
98
+ #{collapsible_issues_panel problems}
99
+ </li>
100
+ HTML
101
+ end
102
+
73
103
  # Return a format that's easier to assert against
74
104
  def testable_entries
75
105
  format = '%Y-%m-%d %H:%M:%S %z'
@@ -317,4 +347,94 @@ class DataQualityReport < ChartBase
317
347
  )
318
348
  end
319
349
  end
350
+
351
+ def render_discarded_changes problems
352
+ <<-HTML
353
+ #{label_issues problems.size} have had information discarded. This configuration is set
354
+ to "reset the clock" if an item is moved back to the backlog after it's been started. This hides important
355
+ information and makes the data less accurate. <b>Moving items back to the backlog is strongly discouraged.</b> HTML
356
+ HTML
357
+ end
358
+
359
+ def render_completed_but_not_started problems
360
+ percentage_work_included = ((issues.size - problems.size).to_f / issues.size * 100).to_i
361
+ html = <<-HTML
362
+ #{label_issues problems.size} were discarded from all charts using cycletime (scatterplot, histogram, etc)
363
+ as we couldn't determine when they started.
364
+ HTML
365
+ if percentage_work_included < 85
366
+ html << <<-HTML
367
+ Consider whether looking at only #{percentage_work_included}% of the total data points is enough
368
+ to come to any reasonable conclusions. See <a href="https://en.wikipedia.org/wiki/Survivorship_bias">
369
+ Survivorship Bias</a>.
370
+ HTML
371
+ end
372
+ html
373
+ end
374
+
375
+ def render_status_changes_after_done problems
376
+ <<-HTML
377
+ #{label_issues problems.size} had a status change after being identified as done. We should question
378
+ whether they were really done at that point or if we stopped the clock too early.
379
+ HTML
380
+ end
381
+
382
+ def render_backwards_through_status_categories problems
383
+ <<-HTML
384
+ #{label_issues problems.size} moved backwards across the board, <b>crossing status categories</b>.
385
+ This will almost certainly have impacted timings as the end times are often taken at status category
386
+ boundaries. You should assume that any timing measurements for this item are wrong.
387
+ HTML
388
+ end
389
+
390
+ def render_backwords_through_statuses problems
391
+ <<-HTML
392
+ #{label_issues problems.size} moved backwards across the board. Depending where we have set the
393
+ start and end points, this may give us incorrect timing data. Note that these items did not cross
394
+ a status category and may not have affected metrics.
395
+ HTML
396
+ end
397
+
398
+ def render_status_not_on_board problems
399
+ <<-HTML
400
+ #{label_issues problems.size} were not visible on the board for some period of time. This may impact
401
+ timings as the work was likely to have been forgotten if it wasn't visible.
402
+ HTML
403
+ end
404
+
405
+ def render_created_in_wrong_status problems
406
+ <<-HTML
407
+ #{label_issues problems.size} were created in a status not designated as Backlog. This will impact
408
+ the measurement of start times and will therefore impact whether it's shown as in progress or not.
409
+ HTML
410
+ end
411
+
412
+ def render_stopped_before_started problems
413
+ <<-HTML
414
+ #{label_issues problems.size} were stopped before they were started and this will play havoc with
415
+ any cycletime or WIP calculations. The most common case for this is when an item gets closed and
416
+ then moved back into an in-progress status.
417
+ HTML
418
+ end
419
+
420
+ def render_issue_not_started_but_subtasks_have problems
421
+ <<-HTML
422
+ #{label_issues problems.size} still showing 'not started' while sub-tasks underneath them have
423
+ started. This is almost always a mistake; if we're working on subtasks, the top level item should
424
+ also have started.
425
+ HTML
426
+ end
427
+
428
+ def render_incomplete_subtasks_when_issue_done problems
429
+ <<-HTML
430
+ #{label_issues problems.size} issues were marked as done while subtasks were still not done.
431
+ HTML
432
+ end
433
+
434
+ def render_issue_on_multiple_boards problems
435
+ <<-HTML
436
+ For #{label_issues problems.size}, we have an issue that shows up on more than one board. This
437
+ could result in more data points showing up on a chart then there really should be.
438
+ HTML
439
+ end
320
440
  end
@@ -3,8 +3,6 @@
3
3
  # This file is really intended to give you ideas about how you might configure your own reports, not
4
4
  # as a complete setup that will work in every case.
5
5
  #
6
- # See https://github.com/mikebowler/jirametrics/wiki/Examples-folder for more details
7
- #
8
6
  # The point of an AGGREGATED report is that we're now looking at a higher level. We might use this in a
9
7
  # S2 meeting (Scrum of Scrums) to talk about the things that are happening across teams, not within a
10
8
  # single team. For that reason, we look at slightly different things that we would on a single team board.
@@ -2,8 +2,6 @@
2
2
 
3
3
  # This file is really intended to give you ideas about how you might configure your own reports, not
4
4
  # as a complete setup that will work in every case.
5
- #
6
- # See https://github.com/mikebowler/jirametrics/wiki/Examples-folder for more
7
5
  class Exporter
8
6
  def standard_project name:, file_prefix:, ignore_issues: nil, starting_status: nil, boards: {},
9
7
  default_board: nil, anonymize: false, settings: {}, status_category_mappings: {},
@@ -19,14 +19,12 @@ class FlowEfficiencyScatterplot < ChartBase
19
19
  </div>
20
20
  <div class="p">
21
21
  <math>
22
- <mn>Flow efficiency</mn>
22
+ <mn>Flow efficiency (%)</mn>
23
23
  <mo>=</mo>
24
24
  <mfrac>
25
25
  <mrow><mn>Time adding value</mn></mrow>
26
26
  <mrow><mn>Total time</mn></mrow>
27
27
  </mfrac>
28
- <mo>x</mo>
29
- <mn>100%</mn>
30
28
  </math>
31
29
  </div>
32
30
  <div style="background: yellow">Note that for this calculation to be accurate, we must be moving items into a
@@ -99,9 +99,6 @@ table.standard {
99
99
  background-color: #eee;
100
100
  }
101
101
  }
102
- .quality_note_bullet {
103
- color: red;
104
- }
105
102
 
106
103
  .chart {
107
104
  background-color: white;
@@ -119,6 +116,16 @@ div.color_block {
119
116
  border: 1px solid black;
120
117
  }
121
118
 
119
+ ul.quality_report {
120
+ list-style-type: '⮕';
121
+ ::marker {
122
+ color: red;
123
+ }
124
+ li {
125
+ padding: 0.2em;
126
+ }
127
+ }
128
+
122
129
  @media screen and (prefers-color-scheme: dark) {
123
130
  :root {
124
131
  --non-working-days-color: #2f2f2f;
@@ -141,7 +141,7 @@ class Issue
141
141
  @board.project_config.file_system.log(
142
142
  "Warning: Status name #{name.inspect} for issue #{key} not found in" \
143
143
  " #{board.possible_statuses.collect(&:name).inspect}" \
144
- "\n See Q1 in the FAQ for more details: https://github.com/mikebowler/jirametrics/wiki/FAQ\n",
144
+ "\n See https://jirametrics.org/faq/#q1\n",
145
145
  also_write_to_stderr: true
146
146
  )
147
147
  status = Status.new(name: name, category_name: 'In Progress')
@@ -31,6 +31,10 @@ class ProjectConfig
31
31
  instance_eval(&@block) if @block
32
32
  end
33
33
 
34
+ def data_downloaded?
35
+ File.exist? File.join(@target_path, "#{file_prefix}_meta.json")
36
+ end
37
+
34
38
  def load_data
35
39
  return if @has_loaded_data
36
40
 
@@ -43,6 +47,8 @@ class ProjectConfig
43
47
  end
44
48
 
45
49
  def run load_only: false
50
+ return if @exporter.downloading?
51
+
46
52
  load_data unless aggregated_project?
47
53
  anonymize_data if @anonymizer_needed
48
54
 
@@ -304,6 +310,10 @@ class ProjectConfig
304
310
  raise 'This is an aggregated project and issues should have been included with the include_issues_from ' \
305
311
  'declaration but none are here. Check your config.'
306
312
  end
313
+
314
+ return @issues = [] if @exporter.downloading?
315
+ raise 'No data found. Must do a download before an export' unless data_downloaded?
316
+
307
317
  load_data if all_boards.empty?
308
318
 
309
319
  timezone_offset = exporter.timezone_offset
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jirametrics
3
3
  version: !ruby/object:Gem::Version
4
- version: '2.7'
4
+ version: 2.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Bowler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-27 00:00:00.000000000 Z
11
+ date: 2024-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: random-word
@@ -106,7 +106,6 @@ files:
106
106
  - lib/jirametrics/html/cycletime_histogram.erb
107
107
  - lib/jirametrics/html/cycletime_scatterplot.erb
108
108
  - lib/jirametrics/html/daily_wip_chart.erb
109
- - lib/jirametrics/html/data_quality_report.erb
110
109
  - lib/jirametrics/html/estimate_accuracy_chart.erb
111
110
  - lib/jirametrics/html/expedited_chart.erb
112
111
  - lib/jirametrics/html/flow_efficiency_scatterplot.erb
@@ -132,14 +131,14 @@ files:
132
131
  - lib/jirametrics/tree_organizer.rb
133
132
  - lib/jirametrics/trend_line_calculator.rb
134
133
  - lib/jirametrics/value_equality.rb
135
- homepage: https://github.com/mikebowler/jirametrics
134
+ homepage: https://jirametrics.org
136
135
  licenses:
137
136
  - Apache-2.0
138
137
  metadata:
139
138
  rubygems_mfa_required: 'true'
140
139
  bug_tracker_uri: https://github.com/mikebowler/jirametrics/issues
141
- changelog_uri: https://github.com/mikebowler/jirametrics/wiki/Changes
142
- documentation_uri: https://github.com/mikebowler/jirametrics/wiki
140
+ changelog_uri: https://jirametrics.org/changes
141
+ documentation_uri: https://jirametrics.org
143
142
  post_install_message:
144
143
  rdoc_options: []
145
144
  require_paths:
@@ -1,138 +0,0 @@
1
- <%
2
- problems = problems_for :discarded_changes
3
- unless problems.empty?
4
- %>
5
- <p>
6
- <span class="quality_note_bullet">⮕</span> <%= label_issues problems.size %> have had information discarded. This configuration is set
7
- to "reset the clock" if an item is moved back to the backlog after it's been started. This hides important
8
- information and makes the data less accurate. <b>Moving items back to the backlog is strongly discouraged.</b>
9
- <%= collapsible_issues_panel problems %>
10
- </p>
11
- <%
12
- end
13
- %>
14
-
15
- <%
16
- problems = problems_for :completed_but_not_started
17
- unless problems.empty?
18
- percentage_work_included = ((issues.size - problems.size).to_f / issues.size * 100).to_i
19
- %>
20
- <p>
21
- <span class="quality_note_bullet">⮕</span> <%= label_issues problems.size %> were discarded from all charts using cycletime (scatterplot, histogram, etc) as we couldn't determine when they started.
22
- <% if percentage_work_included < 85 %>
23
- Consider whether looking at only <%= percentage_work_included %>% of the total data points is enough to come to any reasonable conclusions. See <a href="https://en.wikipedia.org/wiki/Survivorship_bias">Survivorship Bias</a>.
24
- <% end %>
25
- <%= collapsible_issues_panel problems %>
26
- </p>
27
- <%
28
- end
29
- %>
30
-
31
- <%
32
- problems = problems_for :status_changes_after_done
33
- unless problems.empty?
34
- %>
35
- <p>
36
- <span class="quality_note_bullet">⮕</span> <%= label_issues problems.size %> had a status change after being identified as done. We should question whether they were really done at that point or if we stopped the clock too early.
37
- <%= collapsible_issues_panel problems %>
38
- </p>
39
- <%
40
- end
41
- %>
42
-
43
- <%
44
- problems = problems_for :backwards_through_status_categories
45
- unless problems.empty?
46
- %>
47
- <p>
48
- <span class="quality_note_bullet">⮕</span> <%= label_issues problems.size %> moved backwards across the board, <b>crossing status categories</b>. This will almost certainly have impacted timings as the end times are often taken at status category boundaries. You should assume that any timing measurements for this item are wrong.
49
- <%= collapsible_issues_panel problems %>
50
- </p>
51
- <%
52
- end
53
- %>
54
-
55
- <%
56
- problems = problems_for :backwords_through_statuses
57
- unless problems.empty?
58
- %>
59
- <p>
60
- <span class="quality_note_bullet">⮕</span> <%= label_issues problems.size %> moved backwards across the board. Depending where we have set the start and end points, this may give us incorrect timing data. Note that these items did not cross a status category and may not have affected metrics.
61
- <%= collapsible_issues_panel problems %>
62
- </p>
63
- <%
64
- end
65
- %>
66
-
67
- <%
68
- problems = problems_for :status_not_on_board
69
- unless problems.empty?
70
- %>
71
- <p>
72
- <span class="quality_note_bullet">⮕</span> <%= label_issues problems.size %> were not visible on the board for some period of time. This may impact timings as the work was likely to have been forgotten if it wasn't visible.
73
- <%= collapsible_issues_panel problems %>
74
- </p>
75
- <%
76
- end
77
- %>
78
-
79
- <%
80
- problems = problems_for :created_in_wrong_status
81
- unless problems.empty?
82
- %>
83
- <p>
84
- <span class="quality_note_bullet">⮕</span> <%= label_issues problems.size %> were created in a status not designated as Backlog. This will impact the measurement of start times and will therefore impact whether it's shown as in progress or not.
85
- <%= collapsible_issues_panel problems %>
86
- </p>
87
- <%
88
- end
89
- %>
90
-
91
- <%
92
- problems = problems_for :stopped_before_started
93
- unless problems.empty?
94
- %>
95
- <p>
96
- <span class="quality_note_bullet">⮕</span> <%= label_issues problems.size %> were stopped before they were started and this will play havoc with any cycletime or WIP calculations. The most common case for this is when an item gets closed and then moved back into an in-progress status.
97
- <%= collapsible_issues_panel problems %>
98
- </p>
99
- <%
100
- end
101
- %>
102
-
103
- <%
104
- problems = problems_for :issue_not_started_but_subtasks_have
105
- unless problems.empty?
106
- %>
107
- <p>
108
- <span class="quality_note_bullet">⮕</span> <%= label_issues problems.size %> still showing 'not started' while sub-tasks underneath them have started. This is almost always a mistake; if we're working on subtasks, the top level
109
- item should also have started.
110
- <%= collapsible_issues_panel problems %>
111
- </p>
112
- <%
113
- end
114
- %>
115
-
116
- <%
117
- problems = problems_for :incomplete_subtasks_when_issue_done
118
- unless problems.empty?
119
- %>
120
- <p>
121
- <span class="quality_note_bullet">⮕</span> <%= label_issues problems.size %> issues were marked as done while subtasks were still not done.
122
- <%= collapsible_issues_panel problems %>
123
- </p>
124
- <%
125
- end
126
- %>
127
-
128
- <%
129
- problems = problems_for :issue_on_multiple_boards
130
- unless problems.empty?
131
- %>
132
- <p>
133
- <span class="quality_note_bullet">⮕</span> For <%= label_issues problems.size %>, we have an issue that shows up on more than one board. This could result in more data points showing up on a chart then there really should be.
134
- <%= collapsible_issues_panel problems, :hide_board_column %>
135
- </p>
136
- <%
137
- end
138
- %>