cobench 0.0.17 → 0.0.20

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b84694d76fb95dc4c62d1c4ba42d4d4bee5c8c193c33c241b02964d44816e91
4
- data.tar.gz: a56793bef0c5d3bdda384ddd553a47cf135c51cead18e73ed984a7a5f4922077
3
+ metadata.gz: 944037515588754a9074051087759954ea921346dbf852b234a9507836e4ad4d
4
+ data.tar.gz: e718f120d970ae6f60cd83c748d4f33b6570fc4befa9ec7801316700951b56bb
5
5
  SHA512:
6
- metadata.gz: 4fee03b92b8a370f39bc207012bf777b54f459c903b08e25e75e469d98f458d599c85f2bccb51892c165b837192a3450da23d545f84c33263c07bf7469ed6261
7
- data.tar.gz: 71bb57a42b734c46f865beda63815ad1984964bf96a690a4c94c9e67ca6eb32199a59c7efb12e0c5fa99423cd54f7087aa72c2443864ea96ad091fb2e7124bc3
6
+ metadata.gz: 9bed4c1f78e45b2d7185e0c2bb67b928bb4b642cc70ac49851ed81de577817ce54da6fdd2f85f836fb26c30d27814b68c4d6e6164907e69157be0cd209227751
7
+ data.tar.gz: 9768224ff1925aef1a9cfa7656c930ae3782e6f5488aa7aa502f5a8032974925da8f64916147609cc0a2f801afd466d1b6b707ba1a6343a9a063fdf49ff9aed8
data/.rultor.yml CHANGED
@@ -1,3 +1,5 @@
1
+ docker:
2
+ image: yegor256/rultor-image:1.9.1
1
3
  assets:
2
4
  rubygems.yml: yegor256/home#assets/rubygems.yml
3
5
  install: |
@@ -16,7 +18,3 @@ release:
16
18
  merge:
17
19
  script: |-
18
20
  bundle exec rake
19
- deploy:
20
- script: |-
21
- echo "There is nothing to deploy"
22
- exit -1
data/README.md CHANGED
@@ -26,6 +26,8 @@ Then, run it locally and read its output:
26
26
  $ cobench --coder yegor256 --verbose
27
27
  ```
28
28
 
29
+ This is how our report [looks like](https://github.com/cqfn/bench).
30
+
29
31
  ## How to contribute
30
32
 
31
33
  Read [these guidelines](https://www.yegor256.com/2014/04/15/github-guidelines.html).
data/assets/index.xsl CHANGED
@@ -82,11 +82,11 @@ SOFTWARE.
82
82
  <xsl:text> on </xsl:text>
83
83
  <xsl:value-of select="cobench/@time"/>
84
84
  <xsl:text>. </xsl:text>
85
- <xsl:text>"Commits" is the total number of </xsl:text>
85
+ <xsl:text>"Commits" is the total number of non-merge </xsl:text>
86
86
  <a href="https://github.com/git-guides/git-commit">
87
87
  <xsl:text>Git commits</xsl:text>
88
88
  </a>
89
- <xsl:text> authored by the user. </xsl:text>
89
+ <xsl:text> to the default branch, authored by the user. </xsl:text>
90
90
  <xsl:text>"HoC" is the total number of user's </xsl:text>
91
91
  <a href="https://www.yegor256.com/2014/11/14/hits-of-code.html">
92
92
  <xsl:text>hits of code</xsl:text>
@@ -104,11 +104,34 @@ SOFTWARE.
104
104
  <xsl:text> created by the user and already merged. </xsl:text>
105
105
  <xsl:text>"Reviews" is the total number of merged pull requests that were reviewed by the user. </xsl:text>
106
106
  <xsl:text>"Score" is an arithmetic summary of all metrics with multipliers: </xsl:text>
107
- <xsl:text>one Pull costs 100 points, </xsl:text>
108
- <xsl:text>one Issue 50 points, </xsl:text>
109
- <xsl:text>one Review — 40 points, </xsl:text>
110
- <xsl:text>one Commit — 5 points, </xsl:text>
111
- <xsl:text>one HoC — just 1 point.</xsl:text>
107
+ <xsl:for-each select="cobench/weights/w">
108
+ <xsl:if test="position() &gt; 1">
109
+ <xsl:text>, </xsl:text>
110
+ </xsl:if>
111
+ <xsl:text>one </xsl:text>
112
+ <xsl:choose>
113
+ <xsl:when test="substring(@id, string-length(@id)) = 's'">
114
+ <xsl:value-of select="substring(@id, 0, string-length(@id))"/>
115
+ </xsl:when>
116
+ <xsl:otherwise>
117
+ <xsl:value-of select="@id"/>
118
+ </xsl:otherwise>
119
+ </xsl:choose>
120
+ <xsl:choose>
121
+ <xsl:when test="position() = 1">
122
+ <xsl:text> costs </xsl:text>
123
+ </xsl:when>
124
+ <xsl:otherwise>
125
+ <xsl:text> — </xsl:text>
126
+ </xsl:otherwise>
127
+ </xsl:choose>
128
+ <xsl:value-of select="text()"/>
129
+ <xsl:text> point</xsl:text>
130
+ <xsl:if test="text() != '1'">
131
+ <xsl:text>s</xsl:text>
132
+ </xsl:if>
133
+ </xsl:for-each>
134
+ <xsl:text>.</xsl:text>
112
135
  </p>
113
136
  <p>
114
137
  <xsl:text>The numbers you see reflect the activity of the last </xsl:text>
@@ -164,7 +187,7 @@ SOFTWARE.
164
187
  </tr>
165
188
  </xsl:template>
166
189
  <xsl:template match="m">
167
- <td class="num">
190
+ <xsl:variable name="body">
168
191
  <xsl:choose>
169
192
  <xsl:when test="@href = ''">
170
193
  <xsl:value-of select="."/>
@@ -175,6 +198,24 @@ SOFTWARE.
175
198
  </a>
176
199
  </xsl:otherwise>
177
200
  </xsl:choose>
201
+ </xsl:variable>
202
+ <td class="num">
203
+ <xsl:if test="@actual">
204
+ <xsl:choose>
205
+ <xsl:when test="@actual">
206
+ <span class="firebrick">
207
+ <xsl:value-of select="$body"/>
208
+ </span>
209
+ </xsl:when>
210
+ <xsl:otherwise>
211
+ <xsl:value-of select="$body"/>
212
+ </xsl:otherwise>
213
+ </xsl:choose>
214
+ <br/>
215
+ <span class="subtitle" title="The actual value of the metric was capped">
216
+ <xsl:value-of select="@actual"/>
217
+ </span>
218
+ </xsl:if>
178
219
  </td>
179
220
  </xsl:template>
180
221
  <xsl:template match="node()|@*">
data/bin/cobench CHANGED
@@ -35,7 +35,7 @@ loog = Loog::REGULAR
35
35
  def config(path)
36
36
  f = File.expand_path(path)
37
37
  args = []
38
- args += File.readlines(f).map(&:strip) if File.exist?(f)
38
+ args += File.readlines(f).map(&:strip).reject { |a| a.empty? } if File.exist?(f)
39
39
  args
40
40
  end
41
41
 
@@ -47,6 +47,7 @@ opts = Slop.parse(args, strict: true, help: true) do |o|
47
47
  o.bool '--version', 'Show current version'
48
48
  o.bool '--verbose', 'Print as much log messages as possible'
49
49
  o.bool '--dry', 'Make no real round trips to GitHub'
50
+ o.bool '--reuse', 'Don\'t fetch from GitHub, reuse the existing XML file'
50
51
  o.integer '--days', 'How many days to measure', default: 7
51
52
  o.string '--to', 'Directory where to save all files to', default: './cobench'
52
53
  o.string '--token', 'GitHub authentication token'
@@ -73,17 +74,7 @@ end
73
74
  Encoding.default_external = Encoding::UTF_8
74
75
  Encoding.default_internal = Encoding::UTF_8
75
76
 
76
- data = {}
77
-
78
- begin
79
- home = File.absolute_path(opts[:to])
80
- loog.debug("All files generated will be saved to #{home}")
81
- if File.exist?(home)
82
- loog.debug("Directory #{home} exists")
83
- else
84
- FileUtils.mkdir_p(home)
85
- loog.debug("Directory #{home} created")
86
- end
77
+ def build_xml(opts, loog)
87
78
  if opts.token?
88
79
  api = Octokit::Client.new(:access_token => opts[:token])
89
80
  else
@@ -94,6 +85,7 @@ begin
94
85
  api = Obk.new(api, pause: 2000)
95
86
  loog.info("Reading GitHub data for the last #{opts[:days]} days")
96
87
  titles = {}
88
+ data = {}
97
89
  opts[:coder].each do |u|
98
90
  user = u.downcase
99
91
  loog.info("Scanning #{user}...")
@@ -111,9 +103,10 @@ begin
111
103
  if opts.dry?
112
104
  measures = [
113
105
  { title: 'Issues', total: Random.new.rand(100), href: 'https://github.com/' },
114
- { title: 'Pulls', total: Random.new.rand(100), href: '' },
115
- { title: 'HoC', total: Random.new.rand(100), href: '' },
116
- { title: 'HoC', total: Random.new.rand(100), href: '' }
106
+ { title: 'Pulls', total: Random.new.rand(100) },
107
+ { title: 'Commits', total: Random.new.rand(100) },
108
+ { title: 'HoC', total: Random.new.rand(100) },
109
+ { title: 'HoC', total: Random.new.rand(100) }
117
110
  ]
118
111
  else
119
112
  measures = m.take(loog)
@@ -127,21 +120,31 @@ begin
127
120
  end
128
121
  end
129
122
  end
123
+ caps = {
124
+ 'HoC' => lambda { |ms| ms['Commits'][:total] * 512 },
125
+ }
130
126
  data.each do |u, ms|
131
- score = ms.map do |t, h|
132
- h[:total] * if t == 'HoC'
133
- 1
134
- elsif t == 'Pulls'
135
- 100
136
- elsif t == 'Issues'
137
- 50
138
- elsif t == 'Commits'
139
- 5
140
- elsif t == 'Reviews'
141
- 40
142
- else
143
- raise "Unknown title '#{t}'"
127
+ ms.map do |t, h|
128
+ next unless caps.key?(t)
129
+ cap = caps[t].call(ms)
130
+ if h[:total] > cap
131
+ data[u][t][:actual] = h[:total]
132
+ data[u][t][:total] = cap
144
133
  end
134
+ end
135
+ data[u] = ms
136
+ end
137
+ weights = {
138
+ 'HoC' => 1,
139
+ 'Pulls' => 200,
140
+ 'Issues' => 50,
141
+ 'Commits' => 5,
142
+ 'Reviews' => 75
143
+ }
144
+ data.each do |u, ms|
145
+ score = ms.map do |t, h|
146
+ raise "Unknown title '#{t}'" unless weights.key?(t)
147
+ h[:total] * weights[t]
145
148
  end.inject(0, :+)
146
149
  data[u]['Score'] = { total: score, href: '' }
147
150
  end
@@ -152,12 +155,22 @@ begin
152
155
  xml.title t
153
156
  end
154
157
  end
158
+ xml.weights do
159
+ weights.each do |t, w|
160
+ xml.w(id: t) do
161
+ xml.text w
162
+ end
163
+ end
164
+ end
155
165
  xml.coders do
156
166
  data.each do |u, ms|
157
- xml.coder(id: u, details: api.user(u).name) do
167
+ xml.coder(id: u) do
168
+ xml.parent.set_attribute('details', api.user(u).name)
158
169
  xml.metrics do
159
170
  ms.each do |k, v|
160
171
  xml.m(id: k, href: v[:href]) do
172
+ xml.parent.set_attribute('actual', v[:actual]) unless v[:actual].nil?
173
+ xml.parent.set_attribute('href', v[:href]) unless v[:href].nil?
161
174
  xml.text v[:total]
162
175
  end
163
176
  end
@@ -167,11 +180,27 @@ begin
167
180
  end
168
181
  end
169
182
  end
170
- index = File.join(home, 'index.xml')
171
183
  xml = builder.to_xml
172
184
  loog.debug(xml)
173
- File.write(index, xml)
174
- loog.debug("XML saved to #{index} (#{File.size(index)} bytes)")
185
+ xml
186
+ end
187
+ begin
188
+ home = File.absolute_path(opts[:to])
189
+ loog.debug("All files generated will be saved to #{home}")
190
+ if File.exist?(home)
191
+ loog.debug("Directory #{home} exists")
192
+ else
193
+ FileUtils.mkdir_p(home)
194
+ loog.debug("Directory #{home} created")
195
+ end
196
+ index = File.join(home, 'index.xml')
197
+ if opts[:reuse]
198
+ xml = File.read(index)
199
+ else
200
+ xml = build_xml(opts, loog)
201
+ File.write(index, xml)
202
+ loog.debug("XML saved to #{index} (#{File.size(index)} bytes)")
203
+ end
175
204
  xslt = Nokogiri::XSLT(File.read(File.join(__dir__, '../assets/index.xsl')))
176
205
  html = xslt.transform(Nokogiri::XML(xml), 'version' => "'#{Cobench::VERSION}'")
177
206
  loog.debug(html)
data/features/cli.feature CHANGED
@@ -11,7 +11,7 @@ Feature: Simple Reporting
11
11
  Then Exit code is zero
12
12
 
13
13
  Scenario: Simple report
14
- When I run bin/cobench with "--coder yegor256 --coder John --verbose --dry --to foo"
14
+ When I run bin/cobench with "--coder yegor256 --coder Jeff --verbose --dry --to foo"
15
15
  Then Stdout contains "XML saved to"
16
16
  And Exit code is zero
17
17
 
@@ -34,7 +34,7 @@ class Cobench::Commits
34
34
 
35
35
  def take(loog)
36
36
  from = (Time.now - (60 * 60 * 24 * @opts[:days])).strftime('%Y-%m-%d')
37
- q = "author:#{@user} author-date:>#{from}"
37
+ q = "author:#{@user} author-date:>#{from} is:public merge:false"
38
38
  json = @api.search_commits(q)
39
39
  loog.debug("Found #{json.total_count} commits")
40
40
  hoc = 0
@@ -44,6 +44,7 @@ class Cobench::Commits
44
44
  next unless Cobench::Match.new(@opts, loog).matches?(repo)
45
45
  loog.debug("Including #{sha} in #{repo}")
46
46
  json = @api.commit(repo, sha)
47
+ next unless json
47
48
  hocs = json.stats.total
48
49
  loog.debug("Found #{hocs} HoC in #{sha}")
49
50
  hoc += hocs
@@ -23,5 +23,5 @@
23
23
  # Copyright:: Copyright (c) 2022 Yegor Bugayenko
24
24
  # License:: MIT
25
25
  module Cobench
26
- VERSION = '0.0.17'.freeze
26
+ VERSION = '0.0.20'.freeze
27
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cobench
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.17
4
+ version: 0.0.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-16 00:00:00.000000000 Z
11
+ date: 2022-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: backtrace