we-github-stats 0.1.0
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 +7 -0
- data/.ruby-version +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +64 -0
- data/bin/github_stats +8 -0
- data/lib/we/github_stats.rb +4 -0
- data/lib/we/github_stats/cli.rb +152 -0
- data/lib/we/github_stats/organization.rb +22 -0
- data/lib/we/github_stats/repository.rb +66 -0
- data/lib/we/github_stats/version.rb +5 -0
- data/we-github-stats.gemspec +27 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8128f46c7ff0afc6df17f658a42d1fb8bceb26fc
|
4
|
+
data.tar.gz: cdfc79c21477edc2b9e32d745d87fa3253d91adb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 831c440c12cb77d1f0b281aca0bd7291d18396f148e7f0e8ea924b0580d95e87b3222fb7de520b9c816a8d66aa98d8ce912491e03958f96192052d053f662a4f
|
7
|
+
data.tar.gz: 792975e154c901fc8b44897539831f61c85cf376ccd15173a6060626ed116755ca7a0580bf630d5c5729ce22428bbe0f58ca48947b7e53d44f65510db3ab3508
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.3.1
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
we-github-stats (0.1.0)
|
5
|
+
faraday-http-cache
|
6
|
+
octokit (~> 4.0)
|
7
|
+
terminal-table
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
addressable (2.5.0)
|
13
|
+
public_suffix (~> 2.0, >= 2.0.2)
|
14
|
+
byebug (9.0.5)
|
15
|
+
coderay (1.1.1)
|
16
|
+
diff-lcs (1.2.5)
|
17
|
+
faraday (0.10.0)
|
18
|
+
multipart-post (>= 1.2, < 3)
|
19
|
+
faraday-http-cache (2.0.0)
|
20
|
+
faraday (~> 0.8)
|
21
|
+
method_source (0.8.2)
|
22
|
+
multipart-post (2.0.0)
|
23
|
+
octokit (4.6.2)
|
24
|
+
sawyer (~> 0.8.0, >= 0.5.3)
|
25
|
+
pry (0.10.4)
|
26
|
+
coderay (~> 1.1.0)
|
27
|
+
method_source (~> 0.8.1)
|
28
|
+
slop (~> 3.4)
|
29
|
+
pry-byebug (3.4.0)
|
30
|
+
byebug (~> 9.0)
|
31
|
+
pry (~> 0.10)
|
32
|
+
public_suffix (2.0.4)
|
33
|
+
rspec (3.5.0)
|
34
|
+
rspec-core (~> 3.5.0)
|
35
|
+
rspec-expectations (~> 3.5.0)
|
36
|
+
rspec-mocks (~> 3.5.0)
|
37
|
+
rspec-core (3.5.4)
|
38
|
+
rspec-support (~> 3.5.0)
|
39
|
+
rspec-expectations (3.5.0)
|
40
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
41
|
+
rspec-support (~> 3.5.0)
|
42
|
+
rspec-mocks (3.5.0)
|
43
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
44
|
+
rspec-support (~> 3.5.0)
|
45
|
+
rspec-support (3.5.0)
|
46
|
+
sawyer (0.8.1)
|
47
|
+
addressable (>= 2.3.5, < 2.6)
|
48
|
+
faraday (~> 0.8, < 1.0)
|
49
|
+
slop (3.6.0)
|
50
|
+
terminal-table (1.7.3)
|
51
|
+
unicode-display_width (~> 1.1.1)
|
52
|
+
unicode-display_width (1.1.2)
|
53
|
+
|
54
|
+
PLATFORMS
|
55
|
+
ruby
|
56
|
+
|
57
|
+
DEPENDENCIES
|
58
|
+
bundler (~> 1.12)
|
59
|
+
pry-byebug
|
60
|
+
rspec (~> 3.0)
|
61
|
+
we-github-stats!
|
62
|
+
|
63
|
+
BUNDLED WITH
|
64
|
+
1.13.6
|
data/bin/github_stats
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'optparse'
|
3
|
+
require 'octokit'
|
4
|
+
require 'faraday-http-cache'
|
5
|
+
require 'terminal-table'
|
6
|
+
|
7
|
+
module We
|
8
|
+
module GitHubStats
|
9
|
+
class Cli
|
10
|
+
OK = 1
|
11
|
+
NOPE = 0
|
12
|
+
|
13
|
+
class ScriptOptions
|
14
|
+
attr_accessor :access_token, :organization, :format
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@format = 'console'
|
18
|
+
end
|
19
|
+
|
20
|
+
def define_options(parser)
|
21
|
+
parser.banner = "Usage: github_stats [options]"
|
22
|
+
parser.separator ""
|
23
|
+
parser.separator "Specific options:"
|
24
|
+
|
25
|
+
parser.on(
|
26
|
+
"-o", "--organization wework",
|
27
|
+
"GitHub organization to troll for stats"
|
28
|
+
) do |o|
|
29
|
+
@organization = o
|
30
|
+
end
|
31
|
+
|
32
|
+
parser.on(
|
33
|
+
"-t", "--token ABC123",
|
34
|
+
"GitHub Access Token with read permissions for the organization"
|
35
|
+
) do |t|
|
36
|
+
@access_token = t
|
37
|
+
end
|
38
|
+
|
39
|
+
parser.on(
|
40
|
+
"-f", "--format console",
|
41
|
+
"How should it be output? Supported: console,csv"
|
42
|
+
) do |f|
|
43
|
+
@format = f
|
44
|
+
end
|
45
|
+
|
46
|
+
parser.on_tail("-h", "--help", "Show this message") do
|
47
|
+
puts parser
|
48
|
+
exit
|
49
|
+
end
|
50
|
+
|
51
|
+
parser.on_tail("--version", "Show version") do
|
52
|
+
puts VERSION
|
53
|
+
exit
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
attr_reader :parser, :options
|
58
|
+
end
|
59
|
+
|
60
|
+
def client(access_token)
|
61
|
+
Octokit.auto_paginate = true
|
62
|
+
stack = Faraday::RackBuilder.new do |builder|
|
63
|
+
builder.use Faraday::HttpCache, serializer: Marshal, shared_cache: false
|
64
|
+
builder.use Octokit::Response::RaiseError
|
65
|
+
builder.adapter Faraday.default_adapter
|
66
|
+
end
|
67
|
+
Octokit.middleware = stack
|
68
|
+
|
69
|
+
Octokit::Client.new(access_token: access_token)
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Return a structure describing the options.
|
74
|
+
#
|
75
|
+
def parse(args)
|
76
|
+
@options = ScriptOptions.new
|
77
|
+
@args = OptionParser.new do |parser|
|
78
|
+
@options.define_options(parser)
|
79
|
+
parser.parse!(args)
|
80
|
+
end
|
81
|
+
@options
|
82
|
+
end
|
83
|
+
|
84
|
+
def error(msg)
|
85
|
+
puts msg
|
86
|
+
return NOPE
|
87
|
+
end
|
88
|
+
|
89
|
+
def run
|
90
|
+
return error("Missing --token option") if @options.access_token.nil?
|
91
|
+
return error("Missing --organization option") if @options.organization.nil?
|
92
|
+
|
93
|
+
organization = Organization.new(
|
94
|
+
name: @options.organization,
|
95
|
+
client: client(@options.access_token)
|
96
|
+
)
|
97
|
+
|
98
|
+
incomplete = []
|
99
|
+
|
100
|
+
subtotals = organization.repos.map do |repo|
|
101
|
+
begin
|
102
|
+
repo_stats = {
|
103
|
+
name: repo.name,
|
104
|
+
num_commits: repo.num_commits,
|
105
|
+
num_lines_added: repo.num_lines_added,
|
106
|
+
num_lines_removed: repo.num_lines_removed,
|
107
|
+
}
|
108
|
+
|
109
|
+
rescue Repository::InProgressError
|
110
|
+
incomplete << repo.name
|
111
|
+
end
|
112
|
+
repo_stats
|
113
|
+
end.compact
|
114
|
+
|
115
|
+
if incomplete != []
|
116
|
+
puts "ERROR! The following stats are not ready on the GitHub API:"
|
117
|
+
incomplete.each { |repo_name| puts "\t- #{repo_name}" }
|
118
|
+
puts "Please wait a few minutes and try again. In the meantime, the stats for other repos is..."
|
119
|
+
end
|
120
|
+
|
121
|
+
if @options.format == 'console'
|
122
|
+
|
123
|
+
puts "==== Repositories ===="
|
124
|
+
|
125
|
+
rows = subtotals.map { |r| [r[:name], r[:num_commits].to_i, r[:num_lines_added].to_i, r[:num_lines_removed].to_i] }
|
126
|
+
|
127
|
+
puts Terminal::Table.new(
|
128
|
+
headings: ['Name', 'Commits', 'Lines Added', 'Lines Removed'],
|
129
|
+
rows: rows
|
130
|
+
)
|
131
|
+
|
132
|
+
total_commits = subtotals.map { |r| r[:num_commits].to_i }.reduce(:+)
|
133
|
+
total_lines_added = subtotals.map { |r| r[:num_lines_added].to_i }.reduce(:+)
|
134
|
+
total_lines_removed = subtotals.map { |r| r[:num_lines_removed].to_i }.reduce(:+)
|
135
|
+
|
136
|
+
puts "==== Total ===="
|
137
|
+
puts "Commits: #{total_commits}"
|
138
|
+
puts "Lines Added: #{total_lines_added}"
|
139
|
+
puts "Lines Removed: #{total_lines_removed}"
|
140
|
+
return OK
|
141
|
+
|
142
|
+
elsif @options.format == 'csv'
|
143
|
+
puts 'Name, Commits, Lines Added, Lines Removed'
|
144
|
+
subtotals.each { |s| puts "#{s[:name]},#{s[:num_commits]},#{s[:num_lines_added]},#{s[:num_lines_removed]}" }
|
145
|
+
return OK
|
146
|
+
end
|
147
|
+
|
148
|
+
return error("Unknown output format selected")
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module We
|
2
|
+
module GitHubStats
|
3
|
+
class Organization
|
4
|
+
def initialize(client:, name:)
|
5
|
+
@client = client
|
6
|
+
@name = name
|
7
|
+
end
|
8
|
+
|
9
|
+
def repos
|
10
|
+
@repos ||= begin
|
11
|
+
client.org_repos(name).compact.reject(&:fork).map do |repo|
|
12
|
+
Repository.new(client: client, name: repo.name, full_name: repo.full_name)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :client, :name
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module We
|
2
|
+
module GitHubStats
|
3
|
+
class Repository
|
4
|
+
class InProgressError < StandardError; end
|
5
|
+
|
6
|
+
def initialize(client:, name:, full_name:)
|
7
|
+
@client = client
|
8
|
+
@full_name = full_name
|
9
|
+
@name = name
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :name, :full_name
|
13
|
+
|
14
|
+
def num_commits
|
15
|
+
fetch_commit_activity && fetch_commit_activity.map(&:total).inject(:+)
|
16
|
+
end
|
17
|
+
|
18
|
+
def num_lines_added
|
19
|
+
fetch_code_frequency && fetch_code_frequency.map { |week| week[1] }.inject(:+)
|
20
|
+
end
|
21
|
+
|
22
|
+
def num_lines_removed
|
23
|
+
fetch_code_frequency && fetch_code_frequency.map { |week| week[2] }.inject(:+)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :client
|
29
|
+
|
30
|
+
def fetch_commit_activity
|
31
|
+
@fetch_commit_activity ||= begin
|
32
|
+
client.commit_activity_stats(full_name).tap do
|
33
|
+
raise InProgressError if stats_building?
|
34
|
+
raise "PANIC!" if error?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def fetch_code_frequency
|
40
|
+
@fetch_code_frequency ||= begin
|
41
|
+
data = client.code_frequency_stats(full_name)
|
42
|
+
|
43
|
+
raise InProgressError if stats_building?
|
44
|
+
raise "PANIC!" if error?
|
45
|
+
|
46
|
+
return nil if data.nil?
|
47
|
+
|
48
|
+
current_date = DateTime.now
|
49
|
+
|
50
|
+
data.reject do |week|
|
51
|
+
days_ago = (current_date - Time.at(week[0]).to_datetime).to_i
|
52
|
+
days_ago > 365
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def stats_building?
|
58
|
+
client.last_response.status == 202
|
59
|
+
end
|
60
|
+
|
61
|
+
def error?
|
62
|
+
client.last_response.status >= 400
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
# coding: utf-8
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'we/github_stats/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = 'we-github-stats'
|
9
|
+
spec.version = We::GitHubStats::VERSION
|
10
|
+
spec.authors = ['Phil Sturgeon']
|
11
|
+
spec.email = ['phil.sturgeon@wework.com']
|
12
|
+
spec.summary = %q{What did your organization get up to this year}
|
13
|
+
spec.description = %q{Pull basic statistics on the last years worth of commits}
|
14
|
+
spec.homepage = 'https://github.com/wework/we-github-stats'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = 'bin'
|
18
|
+
spec.executables = ['github_stats']
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.12'
|
22
|
+
# spec.add_development_dependency 'rspec', '~> 3.0'
|
23
|
+
spec.add_development_dependency 'pry-byebug'
|
24
|
+
spec.add_runtime_dependency 'octokit', '~> 4.0'
|
25
|
+
spec.add_runtime_dependency 'terminal-table'
|
26
|
+
spec.add_runtime_dependency 'faraday-http-cache'
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: we-github-stats
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Phil Sturgeon
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-12-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.12'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry-byebug
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: octokit
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '4.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '4.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: terminal-table
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: faraday-http-cache
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Pull basic statistics on the last years worth of commits
|
84
|
+
email:
|
85
|
+
- phil.sturgeon@wework.com
|
86
|
+
executables:
|
87
|
+
- github_stats
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".ruby-version"
|
92
|
+
- Gemfile
|
93
|
+
- Gemfile.lock
|
94
|
+
- bin/github_stats
|
95
|
+
- lib/we/github_stats.rb
|
96
|
+
- lib/we/github_stats/cli.rb
|
97
|
+
- lib/we/github_stats/organization.rb
|
98
|
+
- lib/we/github_stats/repository.rb
|
99
|
+
- lib/we/github_stats/version.rb
|
100
|
+
- we-github-stats.gemspec
|
101
|
+
homepage: https://github.com/wework/we-github-stats
|
102
|
+
licenses: []
|
103
|
+
metadata: {}
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options: []
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
requirements: []
|
119
|
+
rubyforge_project:
|
120
|
+
rubygems_version: 2.5.1
|
121
|
+
signing_key:
|
122
|
+
specification_version: 4
|
123
|
+
summary: What did your organization get up to this year
|
124
|
+
test_files: []
|