jirametrics 2.13 → 2.30

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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/bin/jirametrics-mcp +5 -0
  3. data/lib/jirametrics/aggregate_config.rb +10 -2
  4. data/lib/jirametrics/aging_work_bar_chart.rb +191 -133
  5. data/lib/jirametrics/aging_work_in_progress_chart.rb +43 -11
  6. data/lib/jirametrics/aging_work_table.rb +9 -7
  7. data/lib/jirametrics/anonymizer.rb +81 -6
  8. data/lib/jirametrics/atlassian_document_format.rb +101 -97
  9. data/lib/jirametrics/bar_chart_range.rb +17 -0
  10. data/lib/jirametrics/blocked_stalled_change.rb +5 -3
  11. data/lib/jirametrics/board.rb +32 -8
  12. data/lib/jirametrics/board_config.rb +4 -1
  13. data/lib/jirametrics/board_feature.rb +14 -0
  14. data/lib/jirametrics/board_movement_calculator.rb +2 -2
  15. data/lib/jirametrics/cfd_data_builder.rb +108 -0
  16. data/lib/jirametrics/change_item.rb +14 -6
  17. data/lib/jirametrics/chart_base.rb +141 -3
  18. data/lib/jirametrics/css_variable.rb +1 -1
  19. data/lib/jirametrics/cumulative_flow_diagram.rb +208 -0
  20. data/lib/jirametrics/{cycletime_config.rb → cycle_time_config.rb} +21 -4
  21. data/lib/jirametrics/cycletime_histogram.rb +15 -101
  22. data/lib/jirametrics/cycletime_scatterplot.rb +17 -83
  23. data/lib/jirametrics/daily_view.rb +85 -53
  24. data/lib/jirametrics/daily_wip_by_age_chart.rb +4 -5
  25. data/lib/jirametrics/daily_wip_by_blocked_stalled_chart.rb +14 -4
  26. data/lib/jirametrics/daily_wip_by_parent_chart.rb +4 -2
  27. data/lib/jirametrics/daily_wip_chart.rb +30 -8
  28. data/lib/jirametrics/data_quality_report.rb +43 -12
  29. data/lib/jirametrics/dependency_chart.rb +6 -3
  30. data/lib/jirametrics/download_config.rb +15 -0
  31. data/lib/jirametrics/downloader.rb +117 -100
  32. data/lib/jirametrics/downloader_for_cloud.rb +287 -0
  33. data/lib/jirametrics/downloader_for_data_center.rb +95 -0
  34. data/lib/jirametrics/estimate_accuracy_chart.rb +42 -4
  35. data/lib/jirametrics/examples/aggregated_project.rb +2 -2
  36. data/lib/jirametrics/examples/standard_project.rb +41 -28
  37. data/lib/jirametrics/expedited_chart.rb +3 -1
  38. data/lib/jirametrics/exporter.rb +26 -6
  39. data/lib/jirametrics/file_config.rb +9 -11
  40. data/lib/jirametrics/file_system.rb +59 -3
  41. data/lib/jirametrics/fix_version.rb +13 -0
  42. data/lib/jirametrics/flow_efficiency_scatterplot.rb +5 -1
  43. data/lib/jirametrics/github_gateway.rb +115 -0
  44. data/lib/jirametrics/groupable_issue_chart.rb +11 -1
  45. data/lib/jirametrics/grouping_rules.rb +26 -4
  46. data/lib/jirametrics/html/aging_work_bar_chart.erb +5 -5
  47. data/lib/jirametrics/html/aging_work_in_progress_chart.erb +3 -1
  48. data/lib/jirametrics/html/aging_work_table.erb +5 -0
  49. data/lib/jirametrics/html/collapsible_issues_panel.erb +2 -2
  50. data/lib/jirametrics/html/cumulative_flow_diagram.erb +503 -0
  51. data/lib/jirametrics/html/daily_wip_chart.erb +40 -5
  52. data/lib/jirametrics/html/estimate_accuracy_chart.erb +4 -12
  53. data/lib/jirametrics/html/expedited_chart.erb +6 -14
  54. data/lib/jirametrics/html/flow_efficiency_scatterplot.erb +4 -8
  55. data/lib/jirametrics/html/index.css +249 -69
  56. data/lib/jirametrics/html/index.erb +9 -35
  57. data/lib/jirametrics/html/index.js +164 -0
  58. data/lib/jirametrics/html/legacy_colors.css +174 -0
  59. data/lib/jirametrics/html/sprint_burndown.erb +17 -15
  60. data/lib/jirametrics/html/throughput_chart.erb +42 -11
  61. data/lib/jirametrics/html/{cycletime_histogram.erb → time_based_histogram.erb} +61 -59
  62. data/lib/jirametrics/html/{cycletime_scatterplot.erb → time_based_scatterplot.erb} +15 -11
  63. data/lib/jirametrics/html/wip_by_column_chart.erb +250 -0
  64. data/lib/jirametrics/html_generator.rb +32 -0
  65. data/lib/jirametrics/html_report_config.rb +52 -57
  66. data/lib/jirametrics/issue.rb +304 -101
  67. data/lib/jirametrics/issue_printer.rb +97 -0
  68. data/lib/jirametrics/jira_gateway.rb +77 -17
  69. data/lib/jirametrics/mcp_server.rb +531 -0
  70. data/lib/jirametrics/project_config.rb +128 -12
  71. data/lib/jirametrics/pull_request.rb +30 -0
  72. data/lib/jirametrics/pull_request_cycle_time_histogram.rb +77 -0
  73. data/lib/jirametrics/pull_request_cycle_time_scatterplot.rb +88 -0
  74. data/lib/jirametrics/pull_request_review.rb +13 -0
  75. data/lib/jirametrics/raw_javascript.rb +17 -0
  76. data/lib/jirametrics/settings.json +5 -1
  77. data/lib/jirametrics/sprint.rb +12 -0
  78. data/lib/jirametrics/sprint_burndown.rb +10 -4
  79. data/lib/jirametrics/status.rb +1 -1
  80. data/lib/jirametrics/stitcher.rb +81 -0
  81. data/lib/jirametrics/throughput_by_completed_resolution_chart.rb +22 -0
  82. data/lib/jirametrics/throughput_chart.rb +73 -23
  83. data/lib/jirametrics/time_based_histogram.rb +139 -0
  84. data/lib/jirametrics/time_based_scatterplot.rb +107 -0
  85. data/lib/jirametrics/wip_by_column_chart.rb +236 -0
  86. data/lib/jirametrics.rb +83 -69
  87. metadata +60 -6
data/lib/jirametrics.rb CHANGED
@@ -1,6 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'English'
3
4
  require 'thor'
5
+ require 'require_all'
6
+
7
+ # This one does need to be loaded early. The rest will be loaded later.
8
+ require 'jirametrics/file_system'
4
9
 
5
10
  class JiraMetrics < Thor
6
11
  def self.exit_on_failure?
@@ -43,81 +48,90 @@ class JiraMetrics < Thor
43
48
 
44
49
  option :config
45
50
  desc 'info', 'Dump information about one issue'
46
- def info keys
51
+ def info key
47
52
  load_config options[:config]
48
- Exporter.instance.info(keys, name_filter: options[:name] || '*')
53
+ Exporter.instance.info(key, name_filter: options[:name] || '*')
49
54
  end
50
55
 
51
- private
56
+ option :config
57
+ option :name
58
+ desc 'mcp', 'Start in MCP (Model Context Protocol) server mode'
59
+ def mcp
60
+ # Redirect stdout to stderr for the entire startup phase so that any
61
+ # incidental output (from config files, gem loading, etc.) does not
62
+ # corrupt the JSON-RPC channel before the MCP transport takes over.
63
+ original_stdout = $stdout.dup
64
+ $stdout.reopen($stderr)
65
+
66
+ load_config options[:config]
67
+ require 'jirametrics/mcp_server'
68
+
69
+ Exporter.instance.file_system.log_only = true
52
70
 
53
- def load_config config_file
54
- config_file = './config.rb' if config_file.nil?
71
+ projects = {}
72
+ aggregates = {}
73
+ Exporter.instance.each_project_config(name_filter: options[:name] || '*') do |project|
74
+ project.evaluate_next_level
75
+ project.run load_only: true
76
+ projects[project.name || 'default'] = {
77
+ issues: project.issues,
78
+ today: project.time_range.end.to_date,
79
+ end_time: project.time_range.end
80
+ }
81
+ rescue StandardError => e
82
+ if e.message.start_with? 'This is an aggregated project'
83
+ names = project.aggregate_project_names
84
+ aggregates[project.name] = names if names.any?
85
+ next
86
+ end
87
+ next if e.message.start_with? 'No data found'
55
88
 
56
- if File.exist? config_file
57
- # The fact that File.exist can see the file does not mean that require will be
58
- # able to load it. Convert this to an absolute pathname now for require.
59
- config_file = File.absolute_path(config_file).to_s
60
- else
61
- puts "Cannot find configuration file #{config_file.inspect}"
62
- exit 1
89
+ raise
63
90
  end
64
91
 
65
- require 'jirametrics/value_equality'
66
- require 'jirametrics/chart_base'
67
- require 'jirametrics/rules'
68
- require 'jirametrics/grouping_rules'
69
- require 'jirametrics/daily_wip_chart'
70
- require 'jirametrics/groupable_issue_chart'
71
- require 'jirametrics/css_variable'
72
- require 'jirametrics/issue_collection'
73
-
74
- require 'jirametrics/aggregate_config'
75
- require 'jirametrics/expedited_chart'
76
- require 'jirametrics/board_config'
77
- require 'jirametrics/file_config'
78
- require 'jirametrics/jira_gateway'
79
- require 'jirametrics/trend_line_calculator'
80
- require 'jirametrics/status'
81
- require 'jirametrics/issue_link'
82
- require 'jirametrics/estimate_accuracy_chart'
83
- require 'jirametrics/status_collection'
84
- require 'jirametrics/sprint'
85
- require 'jirametrics/issue'
86
- require 'jirametrics/daily_wip_by_age_chart'
87
- require 'jirametrics/daily_wip_by_parent_chart'
88
- require 'jirametrics/aging_work_in_progress_chart'
89
- require 'jirametrics/cycletime_scatterplot'
90
- require 'jirametrics/flow_efficiency_scatterplot'
91
- require 'jirametrics/sprint_issue_change_data'
92
- require 'jirametrics/cycletime_histogram'
93
- require 'jirametrics/daily_wip_by_blocked_stalled_chart'
94
- require 'jirametrics/html_report_config'
95
- require 'jirametrics/data_quality_report'
96
- require 'jirametrics/aging_work_bar_chart'
97
- require 'jirametrics/change_item'
98
- require 'jirametrics/project_config'
99
- require 'jirametrics/dependency_chart'
100
- require 'jirametrics/cycletime_config'
101
- require 'jirametrics/tree_organizer'
102
- require 'jirametrics/aging_work_table'
103
- require 'jirametrics/sprint_burndown'
104
- require 'jirametrics/self_or_issue_dispatcher'
105
- require 'jirametrics/throughput_chart'
106
- require 'jirametrics/exporter'
107
- require 'jirametrics/file_system'
108
- require 'jirametrics/blocked_stalled_change'
109
- require 'jirametrics/board_column'
110
- require 'jirametrics/anonymizer'
111
- require 'jirametrics/downloader'
112
- require 'jirametrics/fix_version'
113
- require 'jirametrics/download_config'
114
- require 'jirametrics/columns_config'
115
- require 'jirametrics/hierarchy_table'
116
- require 'jirametrics/estimation_configuration'
117
- require 'jirametrics/board'
118
- require 'jirametrics/daily_view'
119
- require 'jirametrics/user'
120
- require 'jirametrics/atlassian_document_format'
121
- load config_file
92
+ $stdout.reopen(original_stdout)
93
+ original_stdout.close
94
+ McpServer.new(projects: projects, aggregates: aggregates, timezone_offset: Exporter.instance.timezone_offset).run
95
+ end
96
+
97
+ option :config
98
+ desc 'stitch', 'Dump information about one issue'
99
+ def stitch stitch_file = 'stitcher.erb'
100
+ load_config options[:config]
101
+ Exporter.instance.stitch stitch_file
102
+ end
103
+
104
+ def self.log_uncaught_exception exception, file_system: nil
105
+ return unless exception && !exception.is_a?(SystemExit)
106
+
107
+ begin
108
+ file_system ||= Exporter.instance.file_system
109
+ return if file_system.logfile == $stdout
110
+
111
+ file_system.logfile.puts "#{exception.class}: #{exception.message}"
112
+ exception.backtrace&.each { |line| file_system.logfile.puts "\t#{line}" }
113
+ rescue StandardError
114
+ # Exporter may not be initialized, or the logfile may already be closed
115
+ end
116
+ end
117
+
118
+ at_exit { JiraMetrics.log_uncaught_exception $ERROR_INFO }
119
+
120
+ no_commands do
121
+ def load_config config_file, file_system: FileSystem.new
122
+ config_file = './config.rb' if config_file.nil?
123
+
124
+ if file_system.file_exist? config_file
125
+ # The fact that File.exist can see the file does not mean that require will be
126
+ # able to load it. Convert this to an absolute pathname now for require.
127
+ config_file = File.absolute_path(config_file).to_s
128
+ else
129
+ file_system.error "Cannot find configuration file #{config_file.inspect}"
130
+ exit 1
131
+ end
132
+
133
+ require_rel 'jirametrics'
134
+ load config_file
135
+ end
122
136
  end
123
137
  end
metadata CHANGED
@@ -1,14 +1,42 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jirametrics
3
3
  version: !ruby/object:Gem::Version
4
- version: '2.13'
4
+ version: '2.30'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Bowler
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-07-25 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: mutant-rspec
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :development
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: mcp
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
12
40
  - !ruby/object:Gem::Dependency
13
41
  name: random-word
14
42
  requirement: !ruby/object:Gem::Requirement
@@ -55,10 +83,12 @@ description: Extract metrics from Jira and export to either a report or to CSV f
55
83
  email: mbowler@gargoylesoftware.com
56
84
  executables:
57
85
  - jirametrics
86
+ - jirametrics-mcp
58
87
  extensions: []
59
88
  extra_rdoc_files: []
60
89
  files:
61
90
  - bin/jirametrics
91
+ - bin/jirametrics-mcp
62
92
  - lib/jirametrics.rb
63
93
  - lib/jirametrics/aggregate_config.rb
64
94
  - lib/jirametrics/aging_work_bar_chart.rb
@@ -66,16 +96,20 @@ files:
66
96
  - lib/jirametrics/aging_work_table.rb
67
97
  - lib/jirametrics/anonymizer.rb
68
98
  - lib/jirametrics/atlassian_document_format.rb
99
+ - lib/jirametrics/bar_chart_range.rb
69
100
  - lib/jirametrics/blocked_stalled_change.rb
70
101
  - lib/jirametrics/board.rb
71
102
  - lib/jirametrics/board_column.rb
72
103
  - lib/jirametrics/board_config.rb
104
+ - lib/jirametrics/board_feature.rb
73
105
  - lib/jirametrics/board_movement_calculator.rb
106
+ - lib/jirametrics/cfd_data_builder.rb
74
107
  - lib/jirametrics/change_item.rb
75
108
  - lib/jirametrics/chart_base.rb
76
109
  - lib/jirametrics/columns_config.rb
77
110
  - lib/jirametrics/css_variable.rb
78
- - lib/jirametrics/cycletime_config.rb
111
+ - lib/jirametrics/cumulative_flow_diagram.rb
112
+ - lib/jirametrics/cycle_time_config.rb
79
113
  - lib/jirametrics/cycletime_histogram.rb
80
114
  - lib/jirametrics/cycletime_scatterplot.rb
81
115
  - lib/jirametrics/daily_view.rb
@@ -87,6 +121,8 @@ files:
87
121
  - lib/jirametrics/dependency_chart.rb
88
122
  - lib/jirametrics/download_config.rb
89
123
  - lib/jirametrics/downloader.rb
124
+ - lib/jirametrics/downloader_for_cloud.rb
125
+ - lib/jirametrics/downloader_for_data_center.rb
90
126
  - lib/jirametrics/estimate_accuracy_chart.rb
91
127
  - lib/jirametrics/estimation_configuration.rb
92
128
  - lib/jirametrics/examples/aggregated_project.rb
@@ -97,6 +133,7 @@ files:
97
133
  - lib/jirametrics/file_system.rb
98
134
  - lib/jirametrics/fix_version.rb
99
135
  - lib/jirametrics/flow_efficiency_scatterplot.rb
136
+ - lib/jirametrics/github_gateway.rb
100
137
  - lib/jirametrics/groupable_issue_chart.rb
101
138
  - lib/jirametrics/grouping_rules.rb
102
139
  - lib/jirametrics/hierarchy_table.rb
@@ -104,8 +141,7 @@ files:
104
141
  - lib/jirametrics/html/aging_work_in_progress_chart.erb
105
142
  - lib/jirametrics/html/aging_work_table.erb
106
143
  - lib/jirametrics/html/collapsible_issues_panel.erb
107
- - lib/jirametrics/html/cycletime_histogram.erb
108
- - lib/jirametrics/html/cycletime_scatterplot.erb
144
+ - lib/jirametrics/html/cumulative_flow_diagram.erb
109
145
  - lib/jirametrics/html/daily_wip_chart.erb
110
146
  - lib/jirametrics/html/estimate_accuracy_chart.erb
111
147
  - lib/jirametrics/html/expedited_chart.erb
@@ -113,14 +149,27 @@ files:
113
149
  - lib/jirametrics/html/hierarchy_table.erb
114
150
  - lib/jirametrics/html/index.css
115
151
  - lib/jirametrics/html/index.erb
152
+ - lib/jirametrics/html/index.js
153
+ - lib/jirametrics/html/legacy_colors.css
116
154
  - lib/jirametrics/html/sprint_burndown.erb
117
155
  - lib/jirametrics/html/throughput_chart.erb
156
+ - lib/jirametrics/html/time_based_histogram.erb
157
+ - lib/jirametrics/html/time_based_scatterplot.erb
158
+ - lib/jirametrics/html/wip_by_column_chart.erb
159
+ - lib/jirametrics/html_generator.rb
118
160
  - lib/jirametrics/html_report_config.rb
119
161
  - lib/jirametrics/issue.rb
120
162
  - lib/jirametrics/issue_collection.rb
121
163
  - lib/jirametrics/issue_link.rb
164
+ - lib/jirametrics/issue_printer.rb
122
165
  - lib/jirametrics/jira_gateway.rb
166
+ - lib/jirametrics/mcp_server.rb
123
167
  - lib/jirametrics/project_config.rb
168
+ - lib/jirametrics/pull_request.rb
169
+ - lib/jirametrics/pull_request_cycle_time_histogram.rb
170
+ - lib/jirametrics/pull_request_cycle_time_scatterplot.rb
171
+ - lib/jirametrics/pull_request_review.rb
172
+ - lib/jirametrics/raw_javascript.rb
124
173
  - lib/jirametrics/rules.rb
125
174
  - lib/jirametrics/self_or_issue_dispatcher.rb
126
175
  - lib/jirametrics/settings.json
@@ -129,11 +178,16 @@ files:
129
178
  - lib/jirametrics/sprint_issue_change_data.rb
130
179
  - lib/jirametrics/status.rb
131
180
  - lib/jirametrics/status_collection.rb
181
+ - lib/jirametrics/stitcher.rb
182
+ - lib/jirametrics/throughput_by_completed_resolution_chart.rb
132
183
  - lib/jirametrics/throughput_chart.rb
184
+ - lib/jirametrics/time_based_histogram.rb
185
+ - lib/jirametrics/time_based_scatterplot.rb
133
186
  - lib/jirametrics/tree_organizer.rb
134
187
  - lib/jirametrics/trend_line_calculator.rb
135
188
  - lib/jirametrics/user.rb
136
189
  - lib/jirametrics/value_equality.rb
190
+ - lib/jirametrics/wip_by_column_chart.rb
137
191
  homepage: https://jirametrics.org
138
192
  licenses:
139
193
  - Apache-2.0
@@ -156,7 +210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
156
210
  - !ruby/object:Gem::Version
157
211
  version: '0'
158
212
  requirements: []
159
- rubygems_version: 3.6.2
213
+ rubygems_version: 4.0.10
160
214
  specification_version: 4
161
215
  summary: Extract Jira metrics
162
216
  test_files: []