fluent-plugin-github-activities 0.4.0 → 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 +4 -4
- data/README.md +5 -0
- data/fluent-plugin-github-activities.gemspec +2 -2
- data/lib/fluent/plugin/github-activities.rb +1 -0
- data/lib/fluent/plugin/github-activities/crawler.rb +38 -80
- data/lib/fluent/plugin/github-activities/users_manager.rb +103 -0
- data/lib/fluent/plugin/in_github-activities.rb +39 -17
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db6ee8ed9280b6965e10bd6ebf3248aba5a945de
|
4
|
+
data.tar.gz: 58e9f85025bcab3c4094203eb8ebca1133faed30
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3a357bc0e21a4eda4069a8eee4df00e7fe7508de55cd51f9251e529d3d54ef27d3e7613d87e6ce8069afb19d2200aee458914038a9a41dc845d32541758290b7
|
7
|
+
data.tar.gz: 0177ef399a2d19968e3628c6ad3686c2e2f1e99a581be729521c85977ca1e609136c8b5742c0bab43d985a8f984be122749fe05d31d55df6a7c9d45d1861b175
|
data/README.md
CHANGED
@@ -44,6 +44,7 @@ Notes:
|
|
44
44
|
|
45
45
|
The configuration item `access_token` is optional but strongly recommended to be configured, because there is a rate limit: 60requests/hour by default.
|
46
46
|
By an authenticated crawler, you can crawl 5000requests/hour (means about 80requests/minute).
|
47
|
+
See also [the guide to create new access token](https://help.github.com/articles/creating-an-access-token-for-command-line-use/).
|
47
48
|
|
48
49
|
A new access token for your instance can be generated by a simple BASIC authentication, like:
|
49
50
|
|
@@ -72,6 +73,7 @@ Enter host password for user 'your-account':
|
|
72
73
|
}
|
73
74
|
~~~
|
74
75
|
|
76
|
+
fluent-plugin-github-activities crawls only public activities, so you don't have to give any extra permission.
|
75
77
|
Then the value of the `token` field is the access key to be written to the configuration file.
|
76
78
|
|
77
79
|
## Configurations
|
@@ -86,6 +88,9 @@ Then the value of the `token` field is the access key to be written to the confi
|
|
86
88
|
# Interval seconds for requests. This is `1` by default.
|
87
89
|
interval 1
|
88
90
|
|
91
|
+
# Number of clients. This is `4` by default.
|
92
|
+
clients 1
|
93
|
+
|
89
94
|
# Path to a file to store timestamp of last crawled activity
|
90
95
|
# for each user. If you don't specify this option, same records
|
91
96
|
# can be forwarded after the fluentd is restarted.
|
@@ -19,11 +19,11 @@
|
|
19
19
|
|
20
20
|
Gem::Specification.new do |spec|
|
21
21
|
spec.name = "fluent-plugin-github-activities"
|
22
|
-
spec.version = "0.
|
22
|
+
spec.version = "0.5.0"
|
23
23
|
spec.authors = ["YUKI Hiroshi"]
|
24
24
|
spec.email = ["yuki@clear-code.com"]
|
25
25
|
spec.summary = "Fluentd plugin to crawl public activities on the GitHub."
|
26
|
-
spec.description = "This provides ability
|
26
|
+
spec.description = "This provides ability to crawl public " +
|
27
27
|
"activities of users."
|
28
28
|
spec.homepage = "https://github.com/groonga/fluent-plugin-groonga"
|
29
29
|
spec.license = "LGPL-3.0"
|
@@ -20,10 +20,9 @@
|
|
20
20
|
require "uri"
|
21
21
|
require "net/https"
|
22
22
|
require "json"
|
23
|
-
require "pathname"
|
24
23
|
require "time"
|
25
24
|
|
26
|
-
require "fluent/plugin/github-activities/
|
25
|
+
require "fluent/plugin/github-activities/users_manager"
|
27
26
|
|
28
27
|
module Fluent
|
29
28
|
module GithubActivities
|
@@ -34,15 +33,17 @@ module Fluent
|
|
34
33
|
NO_INTERVAL = 0
|
35
34
|
DEFAULT_INTERVAL = 1
|
36
35
|
|
37
|
-
DEFAULT_LAST_EVENT_TIMESTAMP = -1
|
38
|
-
|
39
36
|
RELATED_USER_IMAGE_KEY = "$github-activities-related-avatar"
|
40
37
|
RELATED_ORGANIZATION_IMAGE_KEY = "$github-activities-related-organization-logo"
|
38
|
+
RELATED_EVENT = "$github-activities-related-event"
|
41
39
|
|
42
40
|
attr_writer :on_emit
|
43
41
|
attr_reader :request_queue, :interval_for_next_request
|
44
42
|
|
45
43
|
def initialize(options={})
|
44
|
+
@users_manager = UsersManager.new(:users => options[:watching_users],
|
45
|
+
:pos_file => options[:pos_file])
|
46
|
+
|
46
47
|
@access_token = options[:access_token]
|
47
48
|
|
48
49
|
@watching_users = options[:watching_users] || []
|
@@ -50,25 +51,14 @@ module Fluent
|
|
50
51
|
@include_commits_from_pull_request = options[:include_commits_from_pull_request]
|
51
52
|
@include_foreign_commits = options[:include_foreign_commits]
|
52
53
|
|
53
|
-
@positions = {}
|
54
|
-
@pos_file = options[:pos_file]
|
55
|
-
@pos_file = Pathname(@pos_file) if @pos_file
|
56
|
-
load_positions
|
57
|
-
|
58
54
|
@request_queue = options[:request_queue] || []
|
59
55
|
|
60
56
|
@default_interval = options[:default_interval] || DEFAULT_INTERVAL
|
61
|
-
|
62
|
-
@watching_users.each do |user|
|
63
|
-
reserve_user_events(user)
|
64
|
-
end
|
65
57
|
end
|
66
58
|
|
67
59
|
def process_request
|
68
|
-
raise EmptyRequestQueue.new if @request_queue.empty?
|
69
|
-
|
70
60
|
request = @request_queue.shift
|
71
|
-
$log.
|
61
|
+
$log.debug("GithubActivities::Crawler: processing request: #{request.inspect}") if $log
|
72
62
|
if request[:process_after] and
|
73
63
|
Time.now.to_i < request[:process_after]
|
74
64
|
@request_queue.push(request)
|
@@ -79,34 +69,36 @@ module Fluent
|
|
79
69
|
uri = request_uri(request)
|
80
70
|
extra_headers = extra_request_headers(request)
|
81
71
|
|
82
|
-
$log.
|
72
|
+
$log.debug("GithubActivities::Crawler: requesting to #{uri.inspect}") if $log
|
83
73
|
response = http_get(uri, extra_headers)
|
84
|
-
$log.
|
74
|
+
$log.debug("GithubActivities::Crawler: response: #{response.inspect}") if $log
|
85
75
|
|
86
76
|
case response
|
87
77
|
when Net::HTTPSuccess
|
78
|
+
$log.trace("GithubActivities::Crawler: Net::HTTPSuccess / request type: #{request[:type]}") if $log
|
88
79
|
body = JSON.parse(response.body)
|
89
|
-
$log.info("GithubActivities::Crawler: request type: #{request[:type]}") if $log
|
90
80
|
case request[:type]
|
91
81
|
when TYPE_EVENTS
|
92
82
|
events = body
|
93
|
-
$log.
|
83
|
+
$log.trace("GithubActivities::Crawler: events size: #{events.size}") if $log
|
94
84
|
process_user_events(request[:user], events)
|
95
85
|
reserve_user_events(request[:user], :previous_response => response)
|
96
|
-
|
86
|
+
@users_manager.save_position_for(request[:user], :entity_tag => response["ETag"])
|
97
87
|
when TYPE_COMMIT
|
98
88
|
process_commit(body, request[:push])
|
99
89
|
end
|
100
90
|
when Net::HTTPNotModified
|
91
|
+
$log.trace("GithubActivities::Crawler: Net::HTTPNotModified / request type: #{request[:type]}") if $log
|
101
92
|
case request[:type]
|
102
93
|
when TYPE_EVENTS
|
103
94
|
reserve_user_events(request[:user],
|
104
95
|
:previous_response => response,
|
105
96
|
:previous_entity_tag => extra_headers["If-None-Match"])
|
106
97
|
end
|
107
|
-
@interval_for_next_request =
|
98
|
+
@interval_for_next_request = @default_interval
|
108
99
|
return true
|
109
|
-
|
100
|
+
else
|
101
|
+
$log.trace("GithubActivities::Crawler: UnknownType / request type: #{request[:type]}") if $log
|
110
102
|
case request[:type]
|
111
103
|
when TYPE_COMMIT
|
112
104
|
fake_body = {
|
@@ -118,6 +110,8 @@ module Fluent
|
|
118
110
|
end
|
119
111
|
@interval_for_next_request = @default_interval
|
120
112
|
return true
|
113
|
+
rescue StandardError => error
|
114
|
+
$log.error(error.inspect)
|
121
115
|
end
|
122
116
|
|
123
117
|
def request_uri(request)
|
@@ -134,35 +128,28 @@ module Fluent
|
|
134
128
|
headers = {}
|
135
129
|
if request[:previous_entity_tag]
|
136
130
|
headers["If-None-Match"] = request[:previous_entity_tag]
|
137
|
-
elsif request[:type] == TYPE_EVENTS
|
138
|
-
|
139
|
-
|
131
|
+
elsif request[:type] == TYPE_EVENTS
|
132
|
+
position = @users_manager.position_for(request[:user])
|
133
|
+
if position
|
134
|
+
entity_tag = position["entity_tag"]
|
135
|
+
headers["If-None-Match"] = entity_tag if entity_tag
|
136
|
+
end
|
140
137
|
end
|
141
138
|
headers
|
142
139
|
end
|
143
140
|
|
144
141
|
def reserve_user_events(user, options={})
|
145
|
-
request =
|
146
|
-
:type => TYPE_EVENTS,
|
147
|
-
:user => user,
|
148
|
-
}
|
149
|
-
response = options[:previous_response]
|
150
|
-
if response
|
151
|
-
now = options[:now] || Time.now
|
152
|
-
interval = response["X-Poll-Interval"].to_i
|
153
|
-
time_to_process = now.to_i + interval
|
154
|
-
request[:previous_entity_tag] = response["ETag"] ||
|
155
|
-
options[:previous_entity_tag]
|
156
|
-
request[:process_after] = time_to_process
|
157
|
-
end
|
142
|
+
request = @users_manager.new_events_request(user, options)
|
158
143
|
@request_queue.push(request)
|
159
144
|
end
|
160
145
|
|
161
146
|
def process_user_events(user, events)
|
162
|
-
last_event_timestamp = DEFAULT_LAST_EVENT_TIMESTAMP
|
163
|
-
|
164
|
-
|
147
|
+
last_event_timestamp = UsersManager::DEFAULT_LAST_EVENT_TIMESTAMP
|
148
|
+
position = @users_manager.position_for(user)
|
149
|
+
if position and position["last_event_timestamp"]
|
150
|
+
last_event_timestamp = position["last_event_timestamp"]
|
165
151
|
end
|
152
|
+
|
166
153
|
events = events.sort do |a, b|
|
167
154
|
b["created_at"] <=> a["created_at"]
|
168
155
|
end
|
@@ -170,7 +157,7 @@ module Fluent
|
|
170
157
|
timestamp = Time.parse(event["created_at"]).to_i
|
171
158
|
next if timestamp <= last_event_timestamp
|
172
159
|
process_user_event(user, event)
|
173
|
-
|
160
|
+
@users_manager.save_position_for(user, :last_event_timestamp => timestamp)
|
174
161
|
end
|
175
162
|
end
|
176
163
|
|
@@ -198,6 +185,8 @@ module Fluent
|
|
198
185
|
else
|
199
186
|
emit(event["type"], event)
|
200
187
|
end
|
188
|
+
rescue StandardError => error
|
189
|
+
$log.exception(error)
|
201
190
|
end
|
202
191
|
|
203
192
|
def process_push_event(event)
|
@@ -208,16 +197,16 @@ module Fluent
|
|
208
197
|
return
|
209
198
|
end
|
210
199
|
commit_refs.reverse.each do |commit_ref|
|
211
|
-
@request_queue.
|
212
|
-
|
213
|
-
|
214
|
-
|
200
|
+
@request_queue.push(:type => TYPE_COMMIT,
|
201
|
+
:uri => commit_ref["url"],
|
202
|
+
:sha => commit_ref["sha"],
|
203
|
+
:push => event)
|
215
204
|
end
|
216
205
|
# emit("push", event)
|
217
206
|
end
|
218
207
|
|
219
208
|
def process_commit(commit, push_event)
|
220
|
-
$log.
|
209
|
+
$log.debug("GithubActivities::Crawler: processing commit #{commit["sha"]}") if $log
|
221
210
|
user = commit["author"]["login"]
|
222
211
|
|
223
212
|
if user and (@include_foreign_commits or watching_user?(user))
|
@@ -225,6 +214,7 @@ module Fluent
|
|
225
214
|
if push_event["org"]
|
226
215
|
commit[RELATED_ORGANIZATION_IMAGE_KEY] = push_event["org"]["avatar_url"]
|
227
216
|
end
|
217
|
+
commit[RELATED_EVENT] = push_event
|
228
218
|
emit("commit", commit)
|
229
219
|
end
|
230
220
|
|
@@ -341,38 +331,6 @@ module Fluent
|
|
341
331
|
end
|
342
332
|
response
|
343
333
|
end
|
344
|
-
|
345
|
-
def load_positions
|
346
|
-
return unless @pos_file
|
347
|
-
return unless @pos_file.exist?
|
348
|
-
|
349
|
-
@positions = JSON.parse(@pos_file.read)
|
350
|
-
rescue
|
351
|
-
@positions = {}
|
352
|
-
end
|
353
|
-
|
354
|
-
def save_positions
|
355
|
-
return unless @pos_file
|
356
|
-
SafeFileWriter.write(@pos_file, JSON.pretty_generate(@positions))
|
357
|
-
end
|
358
|
-
|
359
|
-
def save_user_position(user, params)
|
360
|
-
@positions[user] ||= {}
|
361
|
-
|
362
|
-
if params[:entity_tag]
|
363
|
-
@positions[user]["entity_tag"] = params[:entity_tag]
|
364
|
-
end
|
365
|
-
|
366
|
-
if params[:last_event_timestamp] and
|
367
|
-
params[:last_event_timestamp] != DEFAULT_LAST_EVENT_TIMESTAMP
|
368
|
-
old_timestamp = @positions[user]["last_event_timestamp"]
|
369
|
-
if old_timestamp.nil? or old_timestamp < params[:last_event_timestamp]
|
370
|
-
@positions[user]["last_event_timestamp"] = params[:last_event_timestamp]
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
save_positions
|
375
|
-
end
|
376
334
|
end
|
377
335
|
end
|
378
336
|
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# This file is part of fluent-plugin-github-activities.
|
4
|
+
#
|
5
|
+
# fluent-plugin-github-activities is free software: you can
|
6
|
+
# redistribute it and/or modify it under the terms of the GNU Lesser
|
7
|
+
# General Public License as published by the Free Software
|
8
|
+
# Foundation, either version 3 of the License, or (at your option)
|
9
|
+
# any later version.
|
10
|
+
#
|
11
|
+
# fluent-plugin-github-activities is distributed in the hope that
|
12
|
+
# it will be useful, but WITHOUT ANY WARRANTY; without even the
|
13
|
+
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
14
|
+
# PURPOSE. See the GNU Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public
|
17
|
+
# License along with fluent-plugin-github-activities. If not, see
|
18
|
+
# <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require "pathname"
|
21
|
+
require "json"
|
22
|
+
|
23
|
+
require "fluent/plugin/github-activities/safe_file_writer"
|
24
|
+
|
25
|
+
module Fluent
|
26
|
+
module GithubActivities
|
27
|
+
class UsersManager
|
28
|
+
DEFAULT_LAST_EVENT_TIMESTAMP = -1
|
29
|
+
|
30
|
+
def initialize(params={})
|
31
|
+
@users = params[:users]
|
32
|
+
|
33
|
+
@positions = {}
|
34
|
+
@pos_file = params[:pos_file]
|
35
|
+
@pos_file = Pathname(@pos_file) if @pos_file
|
36
|
+
end
|
37
|
+
|
38
|
+
def generate_initial_requests
|
39
|
+
@users.collect do |user|
|
40
|
+
new_events_request(user)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def new_events_request(user, options={})
|
45
|
+
request = {
|
46
|
+
:type => TYPE_EVENTS,
|
47
|
+
:user => user,
|
48
|
+
}
|
49
|
+
response = options[:previous_response]
|
50
|
+
if response
|
51
|
+
now = options[:now] || Time.now
|
52
|
+
interval = response["X-Poll-Interval"].to_i
|
53
|
+
time_to_process = now.to_i + interval
|
54
|
+
request[:previous_entity_tag] = response["ETag"] ||
|
55
|
+
options[:previous_entity_tag]
|
56
|
+
request[:process_after] = time_to_process
|
57
|
+
else
|
58
|
+
request[:previous_entity_tag] = options[:previous_entity_tag]
|
59
|
+
end
|
60
|
+
request
|
61
|
+
end
|
62
|
+
|
63
|
+
def position_for(user)
|
64
|
+
load_positions
|
65
|
+
@positions[user]
|
66
|
+
end
|
67
|
+
|
68
|
+
def save_position_for(user, params)
|
69
|
+
load_positions
|
70
|
+
@positions[user] ||= {}
|
71
|
+
|
72
|
+
if params[:entity_tag]
|
73
|
+
@positions[user]["entity_tag"] = params[:entity_tag]
|
74
|
+
end
|
75
|
+
|
76
|
+
if params[:last_event_timestamp] and
|
77
|
+
params[:last_event_timestamp] != DEFAULT_LAST_EVENT_TIMESTAMP
|
78
|
+
old_timestamp = @positions[user]["last_event_timestamp"]
|
79
|
+
if old_timestamp.nil? or old_timestamp < params[:last_event_timestamp]
|
80
|
+
@positions[user]["last_event_timestamp"] = params[:last_event_timestamp]
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
save_positions
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
def load_positions
|
89
|
+
return unless @pos_file
|
90
|
+
return unless @pos_file.exist?
|
91
|
+
|
92
|
+
@positions = JSON.parse(@pos_file.read)
|
93
|
+
rescue
|
94
|
+
@positions = {}
|
95
|
+
end
|
96
|
+
|
97
|
+
def save_positions
|
98
|
+
return unless @pos_file
|
99
|
+
SafeFileWriter.write(@pos_file, JSON.pretty_generate(@positions))
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -20,6 +20,7 @@
|
|
20
20
|
module Fluent
|
21
21
|
class GithubActivitiesInput < Input
|
22
22
|
DEFAULT_BASE_TAG = "github-activity"
|
23
|
+
DEFAULT_CLIENTS = 4
|
23
24
|
|
24
25
|
Plugin.register_input("github-activities", self)
|
25
26
|
|
@@ -30,6 +31,7 @@ module Fluent
|
|
30
31
|
config_param :include_foreign_commits, :bool, :default => false
|
31
32
|
config_param :base_tag, :string, :default => DEFAULT_BASE_TAG
|
32
33
|
config_param :pos_file, :string, :default => nil
|
34
|
+
config_param :clients, :integer, :default => DEFAULT_CLIENTS
|
33
35
|
config_param :interval, :integer, :default => 1
|
34
36
|
|
35
37
|
def initialize
|
@@ -42,29 +44,49 @@ module Fluent
|
|
42
44
|
|
43
45
|
def start
|
44
46
|
@base_tag = @base_tag.sub(/\.\z/, "")
|
45
|
-
@thread = Thread.new do
|
46
|
-
crawler_options = {
|
47
|
-
:access_token => @access_token,
|
48
|
-
:watching_users => prepare_users_list,
|
49
|
-
:include_commits_from_pull_request => @include_commits_from_pull_request,
|
50
|
-
:include_foreign_commits => @include_foreign_commits,
|
51
|
-
:pos_file => @pos_file,
|
52
|
-
:default_interval => @interval,
|
53
|
-
}
|
54
|
-
@crawler = ::Fluent::GithubActivities::Crawler.new(crawler_options)
|
55
|
-
@crawler.on_emit = lambda do |tag, record|
|
56
|
-
Engine.emit("#{@base_tag}.#{tag}", Engine.now, record)
|
57
|
-
end
|
58
47
|
|
59
|
-
|
60
|
-
|
61
|
-
|
48
|
+
users = prepare_users_list
|
49
|
+
n_clients = [@clients, users.size].min
|
50
|
+
@interval = @interval * n_clients
|
51
|
+
|
52
|
+
@client_threads = []
|
53
|
+
@request_queue = Queue.new
|
54
|
+
|
55
|
+
users_manager_params = {
|
56
|
+
:users => users,
|
57
|
+
:pos_file => @pos_file,
|
58
|
+
}
|
59
|
+
users_manager = ::Fluent::GithubActivities::UsersManager.new(users_manager_params)
|
60
|
+
users_manager.generate_initial_requests.each do |request|
|
61
|
+
@request_queue.push(request)
|
62
|
+
end
|
63
|
+
|
64
|
+
n_clients.times do
|
65
|
+
@client_threads << Thread.new do
|
66
|
+
crawler_options = {
|
67
|
+
:access_token => @access_token,
|
68
|
+
:watching_users => users,
|
69
|
+
:include_commits_from_pull_request => @include_commits_from_pull_request,
|
70
|
+
:include_foreign_commits => @include_foreign_commits,
|
71
|
+
:pos_file => @pos_file,
|
72
|
+
:request_queue => @request_queue,
|
73
|
+
:default_interval => @interval,
|
74
|
+
}
|
75
|
+
crawler = ::Fluent::GithubActivities::Crawler.new(crawler_options)
|
76
|
+
crawler.on_emit = lambda do |tag, record|
|
77
|
+
Engine.emit("#{@base_tag}.#{tag}", Engine.now, record)
|
78
|
+
end
|
79
|
+
|
80
|
+
loop do
|
81
|
+
crawler.process_request
|
82
|
+
sleep(crawler.interval_for_next_request)
|
83
|
+
end
|
62
84
|
end
|
63
85
|
end
|
64
86
|
end
|
65
87
|
|
66
88
|
def shutdown
|
67
|
-
@
|
89
|
+
@client_threads.each(&:exit)
|
68
90
|
end
|
69
91
|
|
70
92
|
private
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluent-plugin-github-activities
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- YUKI Hiroshi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: fluentd
|
@@ -94,7 +94,7 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
|
-
description: This provides ability
|
97
|
+
description: This provides ability to crawl public activities of users.
|
98
98
|
email:
|
99
99
|
- yuki@clear-code.com
|
100
100
|
executables: []
|
@@ -107,6 +107,7 @@ files:
|
|
107
107
|
- lib/fluent/plugin/github-activities.rb
|
108
108
|
- lib/fluent/plugin/github-activities/crawler.rb
|
109
109
|
- lib/fluent/plugin/github-activities/safe_file_writer.rb
|
110
|
+
- lib/fluent/plugin/github-activities/users_manager.rb
|
110
111
|
- lib/fluent/plugin/in_github-activities.rb
|
111
112
|
- test/fixture.rb
|
112
113
|
- test/fixture/accept-pull-request-event.json
|