quality_meter 0.0.2

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.
@@ -0,0 +1,35 @@
1
+ require 'fileutils'
2
+
3
+ module QaulityMeter
4
+ class ReportController < ::ApplicationController
5
+
6
+ # GET::report#index
7
+ # localhost:3000/qmeter
8
+ def index
9
+ thresholds = {}
10
+ thresholds['security_warnings_min'] = 1
11
+ thresholds['security_warnings_max'] = 100
12
+
13
+ thresholds['rails_best_practices_min'] = 30
14
+ thresholds['rails_best_practices_max'] = 100
15
+
16
+ thresholds['flog_complexity_min'] = 3
17
+ thresholds['flog_complexity_max'] = 25
18
+
19
+ thresholds['stats_ratio_min'] = 0.0
20
+ thresholds['stats_ratio_max'] = 5.0
21
+
22
+ extend QaulityMeter
23
+ # Call methods from lib/qmeter.rb
24
+ self.initialize_thresholds(thresholds)
25
+ self.generate_final_report
26
+ self.choose_color
27
+
28
+ # move report.html from root to the /public folder
29
+ FileUtils.cp('report.html', 'public/') if File.file?("#{Rails.root}/report.html")
30
+
31
+ render layout: false
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,276 @@
1
+ <!DOCTYPE HTML SYSTEM>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
+ <title>Quality Report</title>
6
+ <%= stylesheet_link_tag 'quality_meter/quality_meter' %>
7
+ <%= javascript_include_tag 'quality_meter/jquery-v1.11.2' %>
8
+ <%= javascript_include_tag 'quality_meter/quality_meter' %>
9
+ <script type="text/javascript">
10
+ // Custom JS
11
+ // Get previous report data
12
+ var data = <%= raw @previous_reports.to_json %>;
13
+
14
+ // Transpose array
15
+ var newArray = data[0].map(function(col, i) {
16
+ return data.map(function(row) {
17
+ return row[i]
18
+ })
19
+ });
20
+
21
+
22
+ // Get time intervals
23
+ time = newArray[newArray.length-1]
24
+
25
+ // Get data of each modules
26
+ arr_flog = newArray[newArray.length-5]
27
+ arr_stats = newArray[newArray.length-4]
28
+ arr_best_practise = newArray[newArray.length-3]
29
+ arr_security_warnings = newArray[newArray.length-2]
30
+
31
+ // Parse flog & stats data into float
32
+ arr_flog_hash = [];
33
+ for( var i = 0, len = arr_flog.length; i < len; i++ ) {
34
+ arr_flog_hash[i] = {X: time[i] , Y: parseFloat( arr_flog[i] ) };
35
+ }
36
+ arr_stats_hash = [];
37
+ for( var i = 0, len = arr_stats.length; i < len; i++ ) {
38
+ arr_stats_hash[i] = {X: time[i], Y: parseFloat( arr_stats[i] )};
39
+ }
40
+ arr_best_practise_hash = [];
41
+ for( var i = 0, len = arr_best_practise.length; i < len; i++ ) {
42
+ arr_best_practise_hash[i] ={X: time[i], Y: parseInt( arr_best_practise[i] )};
43
+ }
44
+ arr_security_warnings_hash = [];
45
+ for( var i = 0, len = arr_security_warnings.length; i < len; i++ ) {
46
+ arr_security_warnings_hash[i] ={X: time[i], Y: parseInt( arr_security_warnings[i] )};
47
+ }
48
+
49
+ var graphdata1 = {
50
+ linecolor: "Random",
51
+ values: arr_flog_hash
52
+ };
53
+
54
+ var graphdata2 = {
55
+ linecolor: "Random",
56
+ values: arr_stats_hash
57
+ };
58
+
59
+ var graphdata3 = {
60
+ linecolor: "Random",
61
+ values: arr_security_warnings_hash
62
+ };
63
+
64
+ var graphdata4 = {
65
+ linecolor: "Random",
66
+ title: 'rails practise',
67
+ values: arr_best_practise_hash
68
+ };
69
+
70
+ $(function () {
71
+ $("#Linegraph").SimpleChart({
72
+ toolwidth: "150",
73
+ toolheight: "25",
74
+ axiscolor: "#E6E6E6",
75
+ textcolor: "#6E6E6E",
76
+ title: 'flog',
77
+ data: [graphdata1],
78
+ });
79
+
80
+ $("#Linegraph1").SimpleChart({
81
+ toolwidth: "150",
82
+ toolheight: "25",
83
+ axiscolor: "#E6E6E6",
84
+ textcolor: "#6E6E6E",
85
+ title: 'stats',
86
+ data: [graphdata2],
87
+ });
88
+
89
+ $("#Linegraph2").SimpleChart({
90
+ toolwidth: "150",
91
+ toolheight: "25",
92
+ axiscolor: "#E6E6E6",
93
+ textcolor: "#6E6E6E",
94
+ title: 'security warnings',
95
+ data: [graphdata3],
96
+ });
97
+
98
+ $("#Linegraph3").SimpleChart({
99
+ toolwidth: "150",
100
+ toolheight: "25",
101
+ axiscolor: "#E6E6E6",
102
+ textcolor: "#6E6E6E",
103
+ title: 'rails practise',
104
+ data: [graphdata4],
105
+ });
106
+ });
107
+ </script>
108
+ </head>
109
+ <body class="quality_meter">
110
+ <h2 class="tophead"> Q-meter Dashboard</h2>
111
+ <%if @app_data.present?%>
112
+ <fieldset>
113
+ <legend>App Info</legend>
114
+ <table>
115
+
116
+ <%#@app_data.each do |k,v|%>
117
+ <tr>
118
+ <td><%=@app_data.keys[0].to_s.humanize%> : </td>
119
+ <td colspan="1"> <%=@app_data.values[0]%></td>
120
+ <td><%=@app_data.keys[1].to_s.humanize%> : </td>
121
+ <td colspan="1"> <%=@app_data.values[1]%></td>
122
+ </tr>
123
+ <tr>
124
+ <td><%=@app_data.keys[2].to_s.humanize%> : </td>
125
+ <td colspan="1"> <%=@app_data.values[2]%></td>
126
+ <td><%=@app_data.keys[3].to_s.humanize%> : </td>
127
+ <td colspan="1"> <%=@app_data.values[3]%></td>
128
+ </tr>
129
+ <tr>
130
+ <td><%=@app_data.keys[4].to_s.humanize%> : </td>
131
+ <td colspan="1"> <%=@app_data.values[4]%></td>
132
+ <td><%=@app_data.keys[5].to_s.humanize%> : </td>
133
+ <td colspan="1"> <%=@app_data.values[5]%></td>
134
+ </tr>
135
+ <%#end%>
136
+ </table>
137
+ </fieldset>
138
+ <%end%>
139
+ <fieldset>
140
+ <legend>Quick View</legend>
141
+ <table class="headings" align="left">
142
+ <tr>
143
+ <th>Stat</th>
144
+ <th >Rails Best Practise</th>
145
+ <th>Code Complexity</th>
146
+ <th>Security Warnings</th>
147
+ </tr>
148
+
149
+ <tr >
150
+ <th>
151
+ <a href="/metric_fu/stats.html" target="_blank">
152
+ <div class="pie" style="<%= @stats_rgy %>">
153
+ <div class="title"></div>
154
+ <div class="outer-right mask" id= "10deg">
155
+ <div class="inner-right"></div>
156
+ </div>
157
+
158
+ <div class="outer-left mask">
159
+ <div class="inner-left"></div>
160
+ </div>
161
+ <div class="content">
162
+ <span><%= @stats_code_to_test_ratio %></span>
163
+ </div>
164
+ </div>
165
+ </a>
166
+ <p></p>
167
+ <a href="/metric_fu/stats.html" target="_blank">Details</a>
168
+ </th>
169
+ <th>
170
+ <a href="/metric_fu/rails_best_practices.html" target="_blank">
171
+ <div class="pie" style="<%= @rails_best_practices_rgy %>">
172
+ <div class="title"></div>
173
+ <div class="outer-right mask" id= "10deg">
174
+ </div>
175
+
176
+ <div class="outer-left mask">
177
+ <div class="inner-left"></div>
178
+ </div>
179
+ <div class="content">
180
+ <span><%= @rails_best_practices_total %></span>
181
+ </div>
182
+ </div>
183
+ </a>
184
+ <p></p>
185
+ <a href="/metric_fu/rails_best_practices.html" target="_blank">Details</a>
186
+ </th>
187
+ <th>
188
+ <a href="/metric_fu/flog.html" target="_blank">
189
+ <div class="pie" style="<%= @flog_rgy %>">
190
+ <div class="title"></div>
191
+ <div class="outer-right mask" id= "10deg">
192
+ <div class="inner-right"></div>
193
+ </div>
194
+
195
+ <div class="outer-left mask">
196
+ <div class="inner-left"></div>
197
+ </div>
198
+ <div class="content">
199
+ <span><%= @flog_average_complexity %></span>
200
+ </div>
201
+ </div>
202
+ </a>
203
+ <p></p>
204
+ <a href="/metric_fu/flog.html" target="_blank">Details</a>
205
+ </th>
206
+ <th>
207
+ <a href="report.html" target="_blank">
208
+ <div class="pie" style="<%= @brakeman_warnings_rgy %>">
209
+ <div class="title"></div>
210
+ <div class="outer-right mask" id= "10deg"></div>
211
+ <div class="inner-right"></div>
212
+
213
+ <div class="outer-left mask">
214
+ <div class="inner-left"></div>
215
+ </div>
216
+ <div class="content">
217
+ <span><%= @warnings_count %></span>
218
+ </div>
219
+ </div>
220
+ </a>
221
+ <p></p>
222
+ <a href="report.html" target="_blank">Details</a>
223
+ </th>
224
+ </tr>
225
+ <tr><td colspan="4"></td></tr>
226
+ <tr>
227
+ <td colspan="4">
228
+ <div class="small-box green-box"></div><span class="small_span">Nice</span>
229
+ <div class="small-box yellow-box"></div><span class="small_span">Good</span>
230
+ <div class="small-box orange-box"></div><span class="small_span">Medium</span>
231
+ <div class="small-box red-box"></div><span class="small_span">Needs Improvement (Low)</span>
232
+ </td>
233
+ </tr>
234
+ </table>
235
+
236
+ </fieldset>
237
+ <fieldset>
238
+ <legend> Security Warning in Detail </legend>
239
+ <table align="right">
240
+ <% unless @brakeman_warnings.blank? %>
241
+ <% @brakeman_warnings.each do |warning| %>
242
+ <tr>
243
+ <td><%= warning[0] %></td>
244
+ <td align="right" style="font-weight:700"><%= warning[1] %></td>
245
+ </tr>
246
+ <% end %>
247
+ <% else %>
248
+ <tr><td>No Security Warnings</td></tr>
249
+ <% end %>
250
+ </table>
251
+ </fieldset>
252
+ <fieldset>
253
+ <legend> Commit Wise Reports (History) </legend>
254
+ <table align="center">
255
+ <tr>
256
+ <% unless @previous_reports.blank? %>
257
+ <tr>
258
+ <th><div id="Linegraph2" style=" height: 200px"></div></th>
259
+ <tr><th> <div id="Linegraph3" style=" height: 200px"></div></th>
260
+ </tr>
261
+ <tr>
262
+ <th><div id="Linegraph" style="height: 200px"></div></th>
263
+ </tr>
264
+ <tr><th><div id="Linegraph1" style="height: 200px"></div></th></tr>
265
+ <!-- tr bgcolor="#A5FF88">
266
+ <td colspan="2" align="center" style="font-size: 9pt;"><%#= "Generated on #{Time.now}" %></td>
267
+ </tr> -->
268
+ <% else %>
269
+ <div class='git-commit'>No commits with quality_meter yet</div>
270
+ <% end %>
271
+ </table> <!-- -->
272
+ </fieldset>
273
+
274
+ <body>
275
+ </html>
276
+
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ QualityMeter::Engine.routes.draw do
2
+ get 'qmeter' => 'quality_meter/report#index'
3
+ get 'qmeter/js_cs' => 'quality_meter/report#js_cs'
4
+ end
@@ -0,0 +1,170 @@
1
+ require "qmeter/version"
2
+ require 'qmeter/railtie' if defined?(Rails)
3
+ require "csv"
4
+ require "qmeter/engine"
5
+
6
+ module QualityMeter
7
+ def initialize_thresholds(thresholds)
8
+ # Initialize threshold values
9
+ @security_warnings_min = thresholds['security_warnings_min']
10
+ @security_warnings_max = thresholds['security_warnings_max']
11
+
12
+ @rails_best_practices_min = thresholds['rails_best_practices_min']
13
+ @rails_best_practices_max = thresholds['rails_best_practices_max']
14
+
15
+ @flog_complexity_min = thresholds['flog_complexity_min']
16
+ @flog_complexity_max = thresholds['flog_complexity_max']
17
+
18
+ @stats_ratio_min = thresholds['stats_ratio_min']
19
+ @stats_ratio_max = thresholds['stats_ratio_max']
20
+
21
+ @app_data = []
22
+ end
23
+
24
+ def collect_brakeman_details
25
+ # Breakman source file
26
+ file = check_and_assign_file_path('report.json')
27
+ if file
28
+ data_hash = JSON.parse(file)
29
+ ### change array to hash and check it contain warnings or not
30
+ if data_hash.present? && data_hash.class == Hash ? data_hash.has_key?('warnings') : data_hash[0].has_key?('warnings')
31
+ warning_type = data_hash['warnings'].map {|a| a = a['warning_type'] }
32
+ assign_warnings(warning_type, data_hash['warnings'].count)
33
+ elsif data_hash[0].has_key?('warning_type')
34
+ assign_warnings([data_hash[0]['warning_type']])
35
+ end
36
+ end
37
+ end
38
+
39
+ def collect_app_data
40
+ @app_data = {app_path: "/home/arpit/applications/G8way/g8way",rails_version: "3.2.11",security_warnings: 84}
41
+ # Breakman source file
42
+ file = check_and_assign_file_path('report.json')
43
+ if file
44
+ data_hash = JSON.parse(file)
45
+ # change array to hash and check it contain warnings or not
46
+ if data_hash.present? && data_hash.has_key?('scan_info')
47
+ @app_data = {application: data_hash['scan_info']['app_path'].split("/").last, ruby_version: data_hash['scan_info']['ruby_version'], rails_version: data_hash['scan_info']['rails_version'], number_of_models: data_hash['scan_info']['number_of_models'], number_of_controllers: data_hash['scan_info']['number_of_controllers'], number_of_templates: data_hash['scan_info']['number_of_templates']}
48
+ end
49
+ end
50
+ end
51
+
52
+ ### Assign warnings to @breakeman_warnings ###
53
+ def assign_warnings(warning_type, warnings_count=1)
54
+ @brakeman_warnings = Hash.new(0)
55
+ # warning_type = data_hash[0]['warning_type']
56
+ @warnings_count = warnings_count
57
+ warning_type.each do |v|
58
+ @brakeman_warnings[v] += 1
59
+ end
60
+ end
61
+
62
+ def collect_metric_fu_details
63
+ # parsing metric_fu report from .yml file
64
+ file = check_and_assign_file_path('tmp/metric_fu/report.yml')
65
+ if file
66
+ @surveys = YAML.load(ERB.new(file).result)
67
+ @surveys.each do |survey|
68
+ assign_status(survey) if survey.present?
69
+ end
70
+ end
71
+ end
72
+
73
+ ### assing ration ,complexity and bestpractice of code ###
74
+ def assign_status(survey)
75
+ case survey[0]
76
+ when :flog
77
+ @flog_average_complexity = survey[1][:average].round(1)
78
+ when :stats
79
+ @stats_code_to_test_ratio = survey[1][:code_to_test_ratio]
80
+ when :rails_best_practices
81
+ @rails_best_practices_total = survey[1][:total].first.gsub(/[^\d]/, '').to_i
82
+ end
83
+ end
84
+
85
+ def generate_final_report
86
+ collect_app_data
87
+ collect_metric_fu_details
88
+ collect_brakeman_details
89
+ @app_root = Rails.root
90
+ get_previour_result
91
+ end
92
+
93
+ def save_report
94
+ # Save report data into the CSV
95
+ ### Hide this because we are not using this currently
96
+ #flag = false
97
+ #flag = File.file?("#{Rails.root}/qmeter.csv")
98
+ CSV.open("#{Rails.root}/qmeter.csv", "a") do |csv|
99
+ #csv << ['flog','stats','rails_best_practices','warnings', 'timestamp'] if flag == false
100
+ sha = `git rev-parse HEAD`
101
+ csv << [@flog_average_complexity, @stats_code_to_test_ratio, @rails_best_practices_total, @warnings_count, sha]
102
+ end
103
+ end
104
+
105
+ def get_previour_result
106
+ # Get previous report data
107
+ @previous_reports = CSV.read("#{Rails.root}/qmeter.csv").last(4) if File.file?("#{Rails.root}/qmeter.csv")
108
+ end
109
+
110
+ def choose_color
111
+ # Check threashhold
112
+ ### set color to the variables ###
113
+ @brakeman_warnings_rgy = set_color(@warnings_count, @security_warnings_max, @security_warnings_min)
114
+ @rails_best_practices_rgy = set_color(@rails_best_practices_total, @rails_best_practices_max, @rails_best_practices_min)
115
+ @flog_rgy = set_color(@flog_average_complexity, @flog_complexity_max, @flog_complexity_min)
116
+ @stats_rgy = set_stat_color(@stats_code_to_test_ratio, @stats_ratio_max, @stats_ratio_min )
117
+ end
118
+
119
+ ### method to check file is exist or not ###
120
+ def check_and_assign_file_path(path)
121
+ file = "#{Rails.root}/#{path}"
122
+ File.exist?(file) ? File.read(path) : nil
123
+ end
124
+
125
+ ### send proper color according to data ###
126
+ def set_color(count, max, min)
127
+ if count.present? && count > max
128
+ 'background-color:#D00000;'
129
+ elsif count.present? && count > min && count < max
130
+ avg = max.to_f / 2.to_f
131
+ low_avg = avg / 2.to_f
132
+ high_avg = avg + low_avg
133
+ if count >= high_avg
134
+ 'background-color:#D00000;'
135
+ elsif count >= avg && count < high_avg
136
+ 'background-color:orange;'
137
+ elsif count <= low_avg
138
+ 'background-color:green;'
139
+ elsif count >= low_avg
140
+ 'background-color:yellow;'
141
+ else
142
+ 'background-color:#D00000;'
143
+ end
144
+ else
145
+ 'background-color:#006633;'
146
+ end
147
+ end
148
+
149
+ ### @arpit: send proper color according to data ###
150
+ def set_stat_color(count, max, min)
151
+ if count.present? && count > max
152
+ 'background-color:#D00000;'
153
+ elsif count.present? && count > min && count < max
154
+ avg = max.to_f / 2.to_f
155
+ low_avg = avg / 2.to_f
156
+ if count > avg
157
+ 'background-color:green;'
158
+ elsif count < avg && count < low_avg
159
+ 'background-color:#D00000;'
160
+ elsif count < avg && count > low_avg
161
+ 'background-color:orange;'
162
+ else
163
+ 'background-color:#D00000;'
164
+ end
165
+ else
166
+ 'background-color:#006633;'
167
+ end
168
+
169
+ end
170
+ end