github_repo_statistics 2.2.15 → 2.2.17
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 +4 -4
- data/Gemfile.lock +1 -1
- data/bin/release_merge_report +57 -0
- data/lib/github_repo_statistics/force_merge_report.rb +1 -0
- data/lib/github_repo_statistics/github_repo_statistics.rb +24 -9
- data/lib/github_repo_statistics/release_merge_report.rb +112 -0
- data/lib/github_repo_statistics/review_report.rb +1 -0
- data/lib/github_repo_statistics/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8169d892f1d72c50d184868f6857ca0025b01cd15331e686f7df54b6f202aee
|
4
|
+
data.tar.gz: 9e459684119ab981629054fe8f4c3896f9f4d3dad3901af315ba2bcb4582191c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1564877229312ef1fee2c1fac355fe4e1c6df216523e368665c626f768e5215acf02a934a3785dce7971862d803f5835dc3d0fdc58e670d004eea109d27e9c30
|
7
|
+
data.tar.gz: 40949fa763572d6c16a12af50019a7c4eb29d4a273808c114bbf451abf5d4c61b2e64df488202bb191069cb18ce941665d3d697fcae60e83070e3f075433298c
|
data/Gemfile.lock
CHANGED
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'date'
|
5
|
+
require 'optparse'
|
6
|
+
require 'pry'
|
7
|
+
require_relative '../lib/github_repo_statistics/version'
|
8
|
+
require_relative '../lib/github_repo_statistics/release_merge_report'
|
9
|
+
|
10
|
+
|
11
|
+
options = {}
|
12
|
+
OptionParser.new do |opts|
|
13
|
+
opts.banner = 'Usage: github_repo_statistics [options]'
|
14
|
+
|
15
|
+
opts.on('--duration-in-days STRING',
|
16
|
+
'Number of days to aggregate the changes for [default: 90]') do |duration_in_days|
|
17
|
+
options[:duration_in_days] = duration_in_days.to_i
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on('--default-branch STRING',
|
21
|
+
'The default branch to pull and run metrics for [default: master]') do |default_branch|
|
22
|
+
options[:default_branch] = default_branch
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on('--github-token STRING',
|
26
|
+
'GitHub API token [default: ""]') do |github_token|
|
27
|
+
options[:github_token] = github_token
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on('--github-repo STRING',
|
31
|
+
'GitHub repository name and owner (e.g. octokit/octokit) [default: ""]') do |github_repo|
|
32
|
+
options[:github_repo] = github_repo
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on('-v', '--version', 'Display the version of the gem') do
|
36
|
+
puts "github_repo_statistics version #{GithubRepoStatistics::VERSION}"
|
37
|
+
exit
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on('-h', '--help', 'Display this help message') do
|
41
|
+
puts opts
|
42
|
+
puts <<~EXAMPLES
|
43
|
+
|
44
|
+
Examples:
|
45
|
+
review_report --github-token ghp_bKasj29ndkfdksf3rjt2ngi43j --github-repo octokit/octokit
|
46
|
+
EXAMPLES
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
end.parse!
|
50
|
+
|
51
|
+
DEFAULT_BRANCH = options[:default_branch] || 'master'
|
52
|
+
|
53
|
+
raise 'Please provide GitHub token using --github-token flag' if options[:github_token].nil?
|
54
|
+
raise 'Please provide GitHub repo name using --github-repo flag' if options[:github_repo].nil?
|
55
|
+
raise 'Please provide default GitHub branch using --default-branch flag' if DEFAULT_BRANCH.nil?
|
56
|
+
|
57
|
+
ReleaseMergeReport.new(token: options[:github_token], repo: options[:github_repo], branch_prefix: "release/").report
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'pry'
|
4
4
|
require 'date'
|
5
|
+
require 'csv'
|
5
6
|
|
6
7
|
class GithubRepoStatistics
|
7
8
|
def initialize(directory_path:, duration_in_days:, begin_time:, debug: nil, steps: 1)
|
@@ -145,6 +146,10 @@ class GithubRepoStatistics
|
|
145
146
|
count
|
146
147
|
end
|
147
148
|
|
149
|
+
def count_lines_of_code(file)
|
150
|
+
File.foreach(file).reject { |line| line.match(%r{^\s*(//|/\*.*\*/|\s*$)}) }.count
|
151
|
+
end
|
152
|
+
|
148
153
|
def filter_existing_code_files(files)
|
149
154
|
files.select do |f|
|
150
155
|
next unless File.exist?(f)
|
@@ -243,6 +248,7 @@ class GithubRepoStatistics
|
|
243
248
|
hotspot_lines = count_hotspot_lines(filtered_files.keys)
|
244
249
|
big_files_count = count_big_files(@directory_path)
|
245
250
|
|
251
|
+
# ENV['BQ_CREDENTIALS'] = `cat /Users/serghei.moret/.config/gcloud/application_default_credentials.json`
|
246
252
|
|
247
253
|
if ENV['BQ_CREDENTIALS']
|
248
254
|
require "google/cloud/bigquery"
|
@@ -308,23 +314,32 @@ class GithubRepoStatistics
|
|
308
314
|
puts " *Contributors:* #{contributors}"
|
309
315
|
|
310
316
|
if HOTSPOT
|
311
|
-
hotspot_output =
|
317
|
+
hotspot_output = []
|
312
318
|
|
313
319
|
filtered_top_touched_files.each do |line|
|
314
|
-
hotspot_output += "\n"
|
315
320
|
file = line.first
|
316
321
|
contributors = line.last.first
|
322
|
+
lines_of_code = count_lines_of_code(file)
|
317
323
|
commits = line.last.last
|
318
|
-
|
319
|
-
|
324
|
+
owner = find_owner(file:)
|
325
|
+
|
326
|
+
hotspot_output << [file.gsub(@directory_path, ''), contributors, lines_of_code, commits, owner]
|
320
327
|
end
|
321
328
|
|
329
|
+
hotspot_output.sort_by! { |row| row[2] }
|
330
|
+
|
322
331
|
if FILE_OUTPUT
|
323
|
-
|
324
|
-
|
332
|
+
CSV.open('hotspot.csv', 'w') do |csv|
|
333
|
+
csv << ['File', 'Contributors', 'Lines', 'Commits', 'Owner']
|
334
|
+
hotspot_output.each do |row|
|
335
|
+
csv << row
|
336
|
+
end
|
325
337
|
end
|
326
338
|
else
|
327
|
-
puts
|
339
|
+
puts "\n *Hotspot files(#{filtered_top_touched_files.count}):*\n"
|
340
|
+
hotspot_output.each do |row|
|
341
|
+
puts " #{row[0]} Contributors: #{row[1]} Lines: #{row[2]} Commits: #{row[3]} Owner: #{row[4]}"
|
342
|
+
end
|
328
343
|
end
|
329
344
|
end
|
330
345
|
|
@@ -334,9 +349,9 @@ class GithubRepoStatistics
|
|
334
349
|
|
335
350
|
return unless @steps.positive?
|
336
351
|
|
337
|
-
system("git checkout `git rev-list -1 --before='#{(@begin_time -
|
352
|
+
system("git checkout `git rev-list -1 --before='#{(@begin_time - duration_in_days).strftime('%B %d %Y')}' HEAD`",
|
338
353
|
%i[out err] => File::NULL)
|
339
|
-
@begin_time -=
|
354
|
+
@begin_time -= duration_in_days
|
340
355
|
contribution_message
|
341
356
|
end
|
342
357
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'octokit'
|
2
|
+
require 'json'
|
3
|
+
require 'google/cloud/bigquery'
|
4
|
+
|
5
|
+
class ReleaseMergeReport
|
6
|
+
def initialize(token:, repo:, branch_prefix:)
|
7
|
+
@token = token
|
8
|
+
@repo = repo
|
9
|
+
@branch_prefix = branch_prefix
|
10
|
+
end
|
11
|
+
|
12
|
+
def report
|
13
|
+
branch_counts = count_merged_pull_requests_per_branch
|
14
|
+
grouped_branch_counts = group_branch_counts(branch_counts)
|
15
|
+
require 'pry'
|
16
|
+
binding.pry
|
17
|
+
|
18
|
+
# Print the grouped branch counts
|
19
|
+
puts 'Branches with Merged Pull Requests:'
|
20
|
+
grouped_branch_counts.each do |branch, count|
|
21
|
+
puts "#{branch}: #{count}"
|
22
|
+
end
|
23
|
+
|
24
|
+
ENV['BQ_CREDENTIALS'] = `cat /Users/serghei.moret/.config/gcloud/application_default_credentials.json`
|
25
|
+
|
26
|
+
export_to_bigquery(grouped_branch_counts) if ENV['BQ_CREDENTIALS']
|
27
|
+
|
28
|
+
grouped_branch_counts
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def count_merged_pull_requests_per_branch
|
34
|
+
client = Octokit::Client.new(access_token: @token)
|
35
|
+
client.auto_paginate = true
|
36
|
+
|
37
|
+
tags = client.tags(@repo)
|
38
|
+
branch_counts = Hash.new(0)
|
39
|
+
|
40
|
+
tags.each do |tag|
|
41
|
+
next if !tag.name.match?(/^(v23|v24)\./) && !tag.name.match?(/^(23|24)\./)
|
42
|
+
|
43
|
+
# Extract release version from the tag name
|
44
|
+
release_version = tag.name.gsub('v', '')
|
45
|
+
|
46
|
+
# Construct branch name with the specified prefix
|
47
|
+
branch_name = "#{@branch_prefix}#{release_version}"
|
48
|
+
|
49
|
+
# Count merged pull requests associated with the branch
|
50
|
+
pull_requests = client.pull_requests(@repo, state: 'closed', sort: 'updated', direction: 'desc', base: branch_name)
|
51
|
+
.select { |pr| pr.merged_at }
|
52
|
+
|
53
|
+
branch_counts[branch_name] = pull_requests.size
|
54
|
+
end
|
55
|
+
|
56
|
+
branch_counts
|
57
|
+
end
|
58
|
+
|
59
|
+
def group_branch_counts(branch_counts)
|
60
|
+
patch_counts = Hash.new(0)
|
61
|
+
hotfix_counts = Hash.new { |hash, key| hash[key] = Hash.new(0) }
|
62
|
+
|
63
|
+
branch_counts.each do |branch, count|
|
64
|
+
major_minor_version, patch_version = branch.match(/^#{@branch_prefix}(\d+\.\d+)(?:\.(\d+))?/)&.captures
|
65
|
+
|
66
|
+
if patch_version.nil?
|
67
|
+
# Branch is a patch version
|
68
|
+
patch_counts[major_minor_version] += count
|
69
|
+
elsif count > 0
|
70
|
+
# Branch is a hotfix version
|
71
|
+
hotfix_counts[major_minor_version][patch_version] += count
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Sum up the counts for hotfix versions within the same major and minor version
|
76
|
+
hotfix_counts.each do |major_minor_version, hotfixes|
|
77
|
+
hotfix_counts[major_minor_version] = hotfixes.values.sum
|
78
|
+
end
|
79
|
+
|
80
|
+
{ patch_versions: patch_counts, hotfix_versions: hotfix_counts }
|
81
|
+
end
|
82
|
+
|
83
|
+
def export_to_bigquery(branch_counts)
|
84
|
+
require "google/cloud/bigquery"
|
85
|
+
require "json"
|
86
|
+
creds = JSON.parse(ENV['BQ_CREDENTIALS'])
|
87
|
+
bigquery = Google::Cloud::Bigquery.new(
|
88
|
+
project_id: "hellofresh-android",
|
89
|
+
credentials: creds
|
90
|
+
)
|
91
|
+
dataset = bigquery.dataset "github_data"
|
92
|
+
|
93
|
+
date = DateTime.now
|
94
|
+
|
95
|
+
branch_counts.each do |branch, count|
|
96
|
+
query = <<~SQL
|
97
|
+
MERGE INTO release_merges AS target
|
98
|
+
USING (SELECT '#{branch}' AS release, '#{@repo}' AS platform) AS source
|
99
|
+
ON target.release = source.release AND target.platform = source.platform
|
100
|
+
WHEN MATCHED THEN
|
101
|
+
UPDATE SET
|
102
|
+
target.merge_count = #{count},
|
103
|
+
target.timestamp = '#{date}'
|
104
|
+
WHEN NOT MATCHED THEN
|
105
|
+
INSERT (release, merge_count, platform, timestamp)
|
106
|
+
VALUES ('#{branch}', #{count}, '#{@repo}', '#{date}');
|
107
|
+
SQL
|
108
|
+
date -= 7
|
109
|
+
dataset.query(query)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -87,6 +87,7 @@ class ReviewReport
|
|
87
87
|
puts " Reviews with comments: #{reviews_with_comments}"
|
88
88
|
puts " Change requested reviews: #{change_requested_reviews}"
|
89
89
|
|
90
|
+
# ENV['BQ_CREDENTIALS'] = `cat /Users/serghei.moret/.config/gcloud/application_default_credentials.json`
|
90
91
|
|
91
92
|
if ENV['BQ_CREDENTIALS']
|
92
93
|
require "google/cloud/bigquery"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: github_repo_statistics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Serghei Moret
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: date
|
@@ -87,6 +87,7 @@ executables:
|
|
87
87
|
- console
|
88
88
|
- force_merge_report
|
89
89
|
- github_repo_statistics
|
90
|
+
- release_merge_report
|
90
91
|
- review_report
|
91
92
|
- setup
|
92
93
|
extensions: []
|
@@ -108,12 +109,14 @@ files:
|
|
108
109
|
- bin/console
|
109
110
|
- bin/force_merge_report
|
110
111
|
- bin/github_repo_statistics
|
112
|
+
- bin/release_merge_report
|
111
113
|
- bin/review_report
|
112
114
|
- bin/setup
|
113
115
|
- github_repo_statistics.gemspec
|
114
116
|
- lib/github_repo_statistics.rb
|
115
117
|
- lib/github_repo_statistics/force_merge_report.rb
|
116
118
|
- lib/github_repo_statistics/github_repo_statistics.rb
|
119
|
+
- lib/github_repo_statistics/release_merge_report.rb
|
117
120
|
- lib/github_repo_statistics/review_report.rb
|
118
121
|
- lib/github_repo_statistics/version.rb
|
119
122
|
- sig/github_repo_statistics.rbs
|