jetmeter 0.5.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/bin/jetmeter +5 -0
- data/lib/jetmeter/cli.rb +117 -0
- data/lib/jetmeter/close_accumulator.rb +25 -0
- data/lib/jetmeter/collection.rb +7 -0
- data/lib/jetmeter/config/client_middleware.rb +17 -0
- data/lib/jetmeter/config/file_cache_store.rb +39 -0
- data/lib/jetmeter/config/flow.rb +37 -0
- data/lib/jetmeter/config.rb +37 -0
- data/lib/jetmeter/csv_formatter.rb +46 -0
- data/lib/jetmeter/date_filter.rb +7 -0
- data/lib/jetmeter/flow_reducer.rb +43 -0
- data/lib/jetmeter/issue_adapter.rb +17 -0
- data/lib/jetmeter/issue_event_adapter.rb +17 -0
- data/lib/jetmeter/label_accumulator.rb +64 -0
- data/lib/jetmeter/merge_accumulator.rb +23 -0
- data/lib/jetmeter/open_accumulator.rb +27 -0
- data/lib/jetmeter/open_filter.rb +14 -0
- data/lib/jetmeter/repository_issue_events_loader.rb +13 -0
- data/lib/jetmeter/repository_issues_loader.rb +13 -0
- data/lib/jetmeter/resource_adapter.rb +19 -0
- data/lib/jetmeter/version.rb +3 -0
- data/lib/jetmeter.rb +28 -0
- metadata +129 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 552f4e1368015da59b856cf64cb93ad98b571ffd
|
4
|
+
data.tar.gz: f1ed9aa5f81412a7581337c010a0d5ddddb69d0c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 144711bf099df07a7dc65e781bacd1436344428f5aa51f293fda266d8735f360174cc61f5048f63cf95f407fa6ace14f40cb6edc056ffe7c9ef6b6f0efbbbc31
|
7
|
+
data.tar.gz: '02394680fcb5c414938af6bab035f028c924fd6c9d39a7af0897ec3e8d55974e28183bf2479f541ae741a2ac769ce42a98f08ae37c314963393ae3ef522d487b'
|
data/bin/jetmeter
ADDED
data/lib/jetmeter/cli.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class CLI
|
3
|
+
CREDENTIAL_PATH = File.expand_path('~/.jetmeter/token').freeze
|
4
|
+
CACHE_PATH = File.expand_path('~/.jetmeter/cache').freeze
|
5
|
+
|
6
|
+
def initialize(config_path)
|
7
|
+
@config = eval(File.read(config_path))
|
8
|
+
prepare_cache
|
9
|
+
authenticate_user
|
10
|
+
end
|
11
|
+
|
12
|
+
def run
|
13
|
+
puts "Receiving issue events..."
|
14
|
+
repository_issue_events = Jetmeter::Collection.new(
|
15
|
+
Jetmeter::RepositoryIssueEventsLoader.new(@config).load,
|
16
|
+
Jetmeter::IssueEventAdapter
|
17
|
+
)
|
18
|
+
|
19
|
+
puts "Receiving issues..."
|
20
|
+
repository_issues = Jetmeter::Collection.new(
|
21
|
+
Jetmeter::RepositoryIssuesLoader.new(@config).load,
|
22
|
+
Jetmeter::IssueAdapter
|
23
|
+
)
|
24
|
+
|
25
|
+
accums = [
|
26
|
+
Jetmeter::OpenAccumulator.new,
|
27
|
+
Jetmeter::LabelAccumulator.new,
|
28
|
+
Jetmeter::LabelAccumulator.new(additive: false),
|
29
|
+
Jetmeter::CloseAccumulator.new,
|
30
|
+
Jetmeter::CloseAccumulator.new(additive: false),
|
31
|
+
Jetmeter::MergeAccumulator.new
|
32
|
+
]
|
33
|
+
filters = [
|
34
|
+
Jetmeter::DateFilter.new,
|
35
|
+
Jetmeter::OpenFilter.new
|
36
|
+
]
|
37
|
+
|
38
|
+
reducer = Jetmeter::FlowReducer.new(
|
39
|
+
[repository_issues, repository_issue_events],
|
40
|
+
@config
|
41
|
+
)
|
42
|
+
|
43
|
+
puts "Analyzing received data..."
|
44
|
+
reducer.reduce(accums, filters)
|
45
|
+
|
46
|
+
puts "Initializing CSV formatter..."
|
47
|
+
formatter = Jetmeter::CsvFormatter.new(@config, reducer)
|
48
|
+
|
49
|
+
puts "Saving CSV file..."
|
50
|
+
File.open(@config.output_path, 'wb') do |file|
|
51
|
+
formatter.save(file)
|
52
|
+
puts "Created CSV: #{@config.output_path}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def authenticate_user
|
59
|
+
if access_token_stored? && access_token_readable?
|
60
|
+
@config.github_credentials = { access_token: File.read(CREDENTIAL_PATH) }
|
61
|
+
else
|
62
|
+
login, password = ask_credentials
|
63
|
+
@config.github_credentials = { login: login, password: password }
|
64
|
+
|
65
|
+
authorization = create_authorization
|
66
|
+
save_access_token(authorization.token)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def prepare_cache
|
71
|
+
FileUtils.mkdir_p CACHE_PATH
|
72
|
+
@config.cache_path = CACHE_PATH
|
73
|
+
end
|
74
|
+
|
75
|
+
def ask_credentials
|
76
|
+
puts "Your github login:"
|
77
|
+
login = STDIN.gets.chomp
|
78
|
+
|
79
|
+
puts "Your github password:"
|
80
|
+
password = STDIN.noecho(&:gets).chomp
|
81
|
+
|
82
|
+
[login, password]
|
83
|
+
end
|
84
|
+
|
85
|
+
def ask_two_factor
|
86
|
+
puts 'Enter 2-factor authentication token:'
|
87
|
+
STDIN.gets.chomp
|
88
|
+
end
|
89
|
+
|
90
|
+
def create_authorization
|
91
|
+
auth_note = "jetmeter for #{ENV['USER']}@#{ENV['HOSTNAME']}"
|
92
|
+
@config.client.create_authorization(
|
93
|
+
scopes: [:repo],
|
94
|
+
note: auth_note
|
95
|
+
)
|
96
|
+
rescue Octokit::OneTimePasswordRequired
|
97
|
+
@config.client.create_authorization(
|
98
|
+
scopes: [:repo],
|
99
|
+
note: auth_note,
|
100
|
+
headers: { 'X-GitHub-OTP' => ask_two_factor }
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
def save_access_token(token)
|
105
|
+
File.write(CREDENTIAL_PATH, token)
|
106
|
+
@config.github_credentials = { access_token: token }
|
107
|
+
end
|
108
|
+
|
109
|
+
def access_token_stored?
|
110
|
+
File.exist?(CREDENTIAL_PATH)
|
111
|
+
end
|
112
|
+
|
113
|
+
def access_token_readable?
|
114
|
+
File.readable?(CREDENTIAL_PATH)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class CloseAccumulator
|
3
|
+
CLOSED_EVENT = 'closed'.freeze
|
4
|
+
|
5
|
+
attr_reader :additive
|
6
|
+
|
7
|
+
def initialize(additive: true)
|
8
|
+
@additive = additive
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid?(event, flow)
|
12
|
+
event.issue_event? &&
|
13
|
+
event.event == CLOSED_EVENT &&
|
14
|
+
closing_transition?(flow)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def closing_transition?(flow)
|
20
|
+
flow.transitions(additive).any? do |from, to|
|
21
|
+
from.nil? && to.include?(:closed)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class Config
|
3
|
+
class ClientMiddleware
|
4
|
+
def self.build(cache_path)
|
5
|
+
raise ArgumentError unless cache_path
|
6
|
+
|
7
|
+
store = Jetmeter::Config::FileCacheStore.new(cache_path)
|
8
|
+
|
9
|
+
Faraday::RackBuilder.new do |builder|
|
10
|
+
builder.use Faraday::HttpCache, store: store, serializer: Marshal, shared_cache: false
|
11
|
+
builder.use Octokit::Response::RaiseError
|
12
|
+
builder.adapter Faraday.default_adapter
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class Config
|
3
|
+
class FileCacheStore
|
4
|
+
def initialize(root_path)
|
5
|
+
raise ArgumentError unless File.exist?(root_path)
|
6
|
+
raise ArgumentError unless File.directory?(root_path)
|
7
|
+
raise ArgumentError unless File.writable?(root_path)
|
8
|
+
|
9
|
+
@root_path = root_path
|
10
|
+
end
|
11
|
+
|
12
|
+
def read(key)
|
13
|
+
if readable?(key)
|
14
|
+
File.open(path(key)) { |f| Marshal.load(f) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def write(key, value)
|
19
|
+
File.open(path(key), 'wb') { |f| Marshal.dump(value, f) }
|
20
|
+
end
|
21
|
+
|
22
|
+
def delete(key)
|
23
|
+
if File.exist?(path(key))
|
24
|
+
File.delete(path(key))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def path(key)
|
31
|
+
File.join(@root_path, Digest::MD5.hexdigest(key))
|
32
|
+
end
|
33
|
+
|
34
|
+
def readable?(key)
|
35
|
+
File.exist?(path(key)) && File.readable?(path(key))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class Config
|
3
|
+
class Flow
|
4
|
+
attr_reader :additions
|
5
|
+
attr_reader :substractions
|
6
|
+
attr_accessor :filters
|
7
|
+
attr_writer :accumulative
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@additions = Hash.new { |hash, key| hash[key] = [] }
|
11
|
+
@substractions = Hash.new { |hash, key| hash[key] = [] }
|
12
|
+
@filters = {}
|
13
|
+
@accumulative = true
|
14
|
+
end
|
15
|
+
|
16
|
+
def register_addition(hash)
|
17
|
+
hash.each_pair do |key, value|
|
18
|
+
@additions[key] << value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def register_substraction(hash)
|
23
|
+
hash.each_pair do |key, value|
|
24
|
+
@substractions[key] << value
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def transitions(additive)
|
29
|
+
additive ? additions : substractions
|
30
|
+
end
|
31
|
+
|
32
|
+
def accumulative?
|
33
|
+
!!@accumulative
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class Config
|
3
|
+
attr_accessor :repository_name
|
4
|
+
attr_accessor :output_path
|
5
|
+
attr_reader :flows
|
6
|
+
attr_writer :cache_path
|
7
|
+
|
8
|
+
def initialize(api: Octokit::Client, middleware: Jetmeter::Config::ClientMiddleware)
|
9
|
+
raise ArgumentError unless block_given?
|
10
|
+
|
11
|
+
@api = api
|
12
|
+
@middleware = middleware
|
13
|
+
@flows = {}
|
14
|
+
@cache_path = nil
|
15
|
+
|
16
|
+
yield self
|
17
|
+
end
|
18
|
+
|
19
|
+
def github_credentials=(credentials)
|
20
|
+
@github_credentials = credentials
|
21
|
+
@_client = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def client
|
25
|
+
@_client ||= begin
|
26
|
+
client = @api.new(@github_credentials)
|
27
|
+
client.auto_paginate = true
|
28
|
+
client.middleware = @middleware.build(@cache_path) if @cache_path
|
29
|
+
client
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def register_flow(flow_name, &block)
|
34
|
+
@flows[flow_name] = Jetmeter::Config::Flow.new.tap(&block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class CsvFormatter
|
3
|
+
def initialize(config, reducer)
|
4
|
+
@config = config
|
5
|
+
@reducer = reducer
|
6
|
+
@commulative = Hash.new { |hash, flow| hash[flow] = Set.new }
|
7
|
+
@dates = @reducer.flows.values.map(&:keys).flatten
|
8
|
+
end
|
9
|
+
|
10
|
+
def save(io)
|
11
|
+
csv = CSV.new(io)
|
12
|
+
render_header(csv)
|
13
|
+
render_rows(csv)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def render_header(csv)
|
19
|
+
csv << ['Date'] + @config.flows.keys
|
20
|
+
end
|
21
|
+
|
22
|
+
def render_rows(csv)
|
23
|
+
return if @dates.empty?
|
24
|
+
|
25
|
+
(@dates.min..@dates.max).each do |date|
|
26
|
+
accumulative_flow_names = []
|
27
|
+
|
28
|
+
@config.flows.each_pair do |flow_name, flow_config|
|
29
|
+
issues = Set.new(@reducer.flows[flow_name][date])
|
30
|
+
|
31
|
+
@commulative[flow_name] |= issues
|
32
|
+
|
33
|
+
accumulative_flow_names.each do |accumulative_flow_name|
|
34
|
+
@commulative[accumulative_flow_name] |= issues
|
35
|
+
end
|
36
|
+
|
37
|
+
if flow_config.accumulative?
|
38
|
+
accumulative_flow_names.push(flow_name)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
csv << [date.iso8601] + @commulative.values.map(&:size)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class FlowReducer
|
3
|
+
attr_reader :flows
|
4
|
+
|
5
|
+
def initialize(resource_collections, config)
|
6
|
+
@resource_collections = resource_collections
|
7
|
+
@config_flows = config.flows
|
8
|
+
@flows = Hash.new do |hash, flow_name|
|
9
|
+
hash[flow_name] = Hash.new { |flow, date| flow[date] = [] }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def reduce(accumulators, filters)
|
14
|
+
@resource_collections.each do |resource_collection|
|
15
|
+
resource_collection.each do |resource|
|
16
|
+
reduce_resource(resource, accumulators, filters)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def reduce_resource(resource, accumulators, filters)
|
24
|
+
@config_flows.each_pair do |flow_name, flow_config|
|
25
|
+
next if filters.any? { |filter| filter.apply?(resource, flow_config) }
|
26
|
+
|
27
|
+
accumulators.each do |accumulator|
|
28
|
+
if accumulator.valid?(resource, flow_config)
|
29
|
+
apply_accumulator(resource, accumulator, flow_name)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def apply_accumulator(resource, accumulator, flow_name)
|
36
|
+
if accumulator.additive
|
37
|
+
@flows[flow_name][resource.flow_date].push(resource.issue_number)
|
38
|
+
else
|
39
|
+
@flows[flow_name][resource.flow_date].delete(resource.issue_number)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class LabelAccumulator
|
3
|
+
LABELED_EVENT = 'labeled'.freeze
|
4
|
+
UNLABELED_EVENT = 'unlabeled'.freeze
|
5
|
+
CORRESPONDING_EVENTS_LIMIT = 15
|
6
|
+
MAX_LABEL_CHANGE_TIME = 60
|
7
|
+
|
8
|
+
attr_reader :additive
|
9
|
+
|
10
|
+
def initialize(additive: true)
|
11
|
+
@corresponding_events = { LABELED_EVENT => [], UNLABELED_EVENT => [] }
|
12
|
+
@additive = additive
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid?(event, flow)
|
16
|
+
return false unless event.issue_event?
|
17
|
+
|
18
|
+
store_corresponding_event(event)
|
19
|
+
labeling_transition?(flow, event) || unlabeling_transition?(flow, event)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def labeling_transition?(flow, event)
|
25
|
+
if event.event == LABELED_EVENT
|
26
|
+
flow.transitions(additive).any? do |from, to|
|
27
|
+
to.include?(event.label[:name]) && from.nil? || corresponding_event?(event, from)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def unlabeling_transition?(flow, event)
|
33
|
+
if event.event == UNLABELED_EVENT
|
34
|
+
flow.transitions(additive).any? do |from, to|
|
35
|
+
from == event.label[:name] && to.any? { |label| label.nil? || corresponding_event?(event, label) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def store_corresponding_event(event)
|
41
|
+
return unless [LABELED_EVENT, UNLABELED_EVENT].include?(event.event)
|
42
|
+
|
43
|
+
@corresponding_events[event.event].push(event)
|
44
|
+
if @corresponding_events[event.event].length > CORRESPONDING_EVENTS_LIMIT
|
45
|
+
@corresponding_events[event.event].shift
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def corresponding_event?(event, label)
|
50
|
+
corresponding_type = event.event == LABELED_EVENT ? UNLABELED_EVENT : LABELED_EVENT
|
51
|
+
|
52
|
+
@corresponding_events[corresponding_type].any? do |corresponding|
|
53
|
+
corresponding.label[:name] == label &&
|
54
|
+
corresponding.issue[:number] == event.issue[:number] &&
|
55
|
+
near?(corresponding, event)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def near?(first, second)
|
60
|
+
diff = (first.created_at.to_time - second.created_at.to_time).abs
|
61
|
+
diff < MAX_LABEL_CHANGE_TIME
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class MergeAccumulator
|
3
|
+
MERGED_EVENT = 'merged'.freeze
|
4
|
+
|
5
|
+
def valid?(event, flow)
|
6
|
+
event.issue_event? &&
|
7
|
+
event.event == MERGED_EVENT &&
|
8
|
+
merging_transition?(flow)
|
9
|
+
end
|
10
|
+
|
11
|
+
def additive
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def merging_transition?(flow)
|
18
|
+
flow.transitions(additive).any? do |from, to|
|
19
|
+
from.nil? && to.include?(:merged)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class OpenAccumulator
|
3
|
+
def valid?(resource, flow)
|
4
|
+
resource.issue? &&
|
5
|
+
opening_transition?(flow) &&
|
6
|
+
open_or_finished?(resource)
|
7
|
+
end
|
8
|
+
|
9
|
+
def additive
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def opening_transition?(flow)
|
16
|
+
if flow
|
17
|
+
flow.transitions(additive).any? do |from, to|
|
18
|
+
from.nil? && to.include?(:opened)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def open_or_finished?(issue)
|
24
|
+
issue[:closed_at].nil? || issue.key?(:pull_request)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class OpenFilter
|
3
|
+
def apply?(resource, flow)
|
4
|
+
resource.issue? && flow.filters.key?(:open_at) && closed_at?(resource, flow)
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def closed_at?(resource, flow)
|
10
|
+
resource.closed_at && resource.closed_at < flow.filters[:open_at]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class RepositoryIssueEventsLoader
|
3
|
+
def initialize(config)
|
4
|
+
@repository_name = config.repository_name
|
5
|
+
@client = config.client
|
6
|
+
end
|
7
|
+
|
8
|
+
def load
|
9
|
+
return @events if defined?(@events)
|
10
|
+
@events = @client.repository_issue_events(@repository_name)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class RepositoryIssuesLoader
|
3
|
+
def initialize(config)
|
4
|
+
@repository_name = config.repository_name
|
5
|
+
@client = config.client
|
6
|
+
end
|
7
|
+
|
8
|
+
def load
|
9
|
+
return @issues if defined?(@issues)
|
10
|
+
@issues = @client.list_issues(@repository_name, state: 'all')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Jetmeter
|
2
|
+
class ResourceAdapter < SimpleDelegator
|
3
|
+
def issue?
|
4
|
+
false
|
5
|
+
end
|
6
|
+
|
7
|
+
def issue_event?
|
8
|
+
false
|
9
|
+
end
|
10
|
+
|
11
|
+
def flow_date
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
def issue_number
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/jetmeter.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Jetmeter; end
|
2
|
+
|
3
|
+
require 'octokit'
|
4
|
+
require 'faraday-http-cache'
|
5
|
+
|
6
|
+
require 'csv'
|
7
|
+
require 'delegate'
|
8
|
+
require 'io/console'
|
9
|
+
require 'fileutils'
|
10
|
+
|
11
|
+
require 'jetmeter/config'
|
12
|
+
require 'jetmeter/config/flow'
|
13
|
+
require 'jetmeter/config/client_middleware'
|
14
|
+
require 'jetmeter/config/file_cache_store'
|
15
|
+
require 'jetmeter/collection'
|
16
|
+
require 'jetmeter/repository_issues_loader'
|
17
|
+
require 'jetmeter/repository_issue_events_loader'
|
18
|
+
require 'jetmeter/issue_adapter'
|
19
|
+
require 'jetmeter/issue_event_adapter'
|
20
|
+
require 'jetmeter/flow_reducer'
|
21
|
+
require 'jetmeter/label_accumulator'
|
22
|
+
require 'jetmeter/close_accumulator'
|
23
|
+
require 'jetmeter/open_accumulator'
|
24
|
+
require 'jetmeter/merge_accumulator'
|
25
|
+
require 'jetmeter/date_filter'
|
26
|
+
require 'jetmeter/open_filter'
|
27
|
+
require 'jetmeter/csv_formatter'
|
28
|
+
require 'jetmeter/cli'
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jetmeter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mark Volosiuk
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-05-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: octokit
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday-http-cache
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '12.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '12.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.10'
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 5.10.2
|
65
|
+
type: :development
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - "~>"
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '5.10'
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 5.10.2
|
75
|
+
description: Jetmeter is a tool to analyze github repo activity
|
76
|
+
email:
|
77
|
+
- marchi.martius@gmail.com
|
78
|
+
executables:
|
79
|
+
- jetmeter
|
80
|
+
extensions: []
|
81
|
+
extra_rdoc_files: []
|
82
|
+
files:
|
83
|
+
- bin/jetmeter
|
84
|
+
- lib/jetmeter.rb
|
85
|
+
- lib/jetmeter/cli.rb
|
86
|
+
- lib/jetmeter/close_accumulator.rb
|
87
|
+
- lib/jetmeter/collection.rb
|
88
|
+
- lib/jetmeter/config.rb
|
89
|
+
- lib/jetmeter/config/client_middleware.rb
|
90
|
+
- lib/jetmeter/config/file_cache_store.rb
|
91
|
+
- lib/jetmeter/config/flow.rb
|
92
|
+
- lib/jetmeter/csv_formatter.rb
|
93
|
+
- lib/jetmeter/date_filter.rb
|
94
|
+
- lib/jetmeter/flow_reducer.rb
|
95
|
+
- lib/jetmeter/issue_adapter.rb
|
96
|
+
- lib/jetmeter/issue_event_adapter.rb
|
97
|
+
- lib/jetmeter/label_accumulator.rb
|
98
|
+
- lib/jetmeter/merge_accumulator.rb
|
99
|
+
- lib/jetmeter/open_accumulator.rb
|
100
|
+
- lib/jetmeter/open_filter.rb
|
101
|
+
- lib/jetmeter/repository_issue_events_loader.rb
|
102
|
+
- lib/jetmeter/repository_issues_loader.rb
|
103
|
+
- lib/jetmeter/resource_adapter.rb
|
104
|
+
- lib/jetmeter/version.rb
|
105
|
+
homepage:
|
106
|
+
licenses:
|
107
|
+
- BSD-2-Clause
|
108
|
+
metadata: {}
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options: []
|
111
|
+
require_paths:
|
112
|
+
- lib
|
113
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
requirements: []
|
124
|
+
rubyforge_project:
|
125
|
+
rubygems_version: 2.6.11
|
126
|
+
signing_key:
|
127
|
+
specification_version: 4
|
128
|
+
summary: Analyze github repo - JT way
|
129
|
+
test_files: []
|