github-event-watcher 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fbbc0e39a43cb1d647f242f828e71aa38577e32e
4
+ data.tar.gz: 1c1d8274a79420feb01506eca2f121adad53e737
5
+ SHA512:
6
+ metadata.gz: d49f46fc9782cc848954fb4bdc80a6aa1eca0f3a82cfbfc6f9e893eef3ff019c13acb7b4e9e3d079b069105de807a32e7bd4388a5d0fba94281d49d8d25f930d
7
+ data.tar.gz: 2418a9cac647a5d83945d61298515e8447d879d39861689c1d0b40102c5bbf702a49d88904bbc2f1982711488e2cb195e1018eab633bf3d52114583750dbef9d
@@ -0,0 +1,2 @@
1
+ /config.yaml
2
+ /var/
@@ -0,0 +1,8 @@
1
+ rvm:
2
+ - 2.0.0
3
+ - 2.1
4
+ - 2.2
5
+ notifications:
6
+ email:
7
+ recipients:
8
+ - commit@clear-code.com
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,48 @@
1
+ [![Build Status](https://travis-ci.org/clear-code/github-event-watcher.svg?branch=master)](https://travis-ci.org/clear-code/github-event-watcher)
2
+
3
+ # README
4
+
5
+ ## Name
6
+
7
+ github-event-watcher
8
+
9
+ ## Description
10
+
11
+ This package is for developers who want to watch GitHub repositories
12
+ of other people. You can't set
13
+ [GitHub Webhooks](https://developer.github.com/webhooks/) for GitHub
14
+ repositories of other people.
15
+
16
+ This package pulls events from GitHub and sends GitHub compatible
17
+ (subset) POST request to your Webhooks.
18
+
19
+ You can implement commit mail by using with
20
+ [GitHub POST receiver at clear-code/git-utils](https://github.com/clear-code/git-utils/tree/master/github-post-receiver).
21
+
22
+ ## Usage
23
+
24
+ % git clone https://github.com/clear-code/git-utils.git
25
+ % cd github-event-watcher
26
+ % cp config.yaml{.example,}
27
+ % editor config.yaml
28
+ % ruby -I lib bin/github-pull-push-events --daemon
29
+
30
+ `config.yaml` uses the following format:
31
+
32
+ repositories:
33
+ - clear-code/git-utils
34
+ - ruby/ruby
35
+ - rails/rails
36
+ webhook-end-point: http://git-utils.example.com/post-receiver/
37
+
38
+ List repositories by `${owner}/${name}` format into `repositories`.
39
+
40
+ Specify your GitHub Webhook receiver URL to `webhook-end-point`.
41
+
42
+ ## Authors
43
+
44
+ * Kouhei Sutou `<kou@clear-code.com>`
45
+
46
+ ## License
47
+
48
+ GPLv3 or later.
@@ -0,0 +1,23 @@
1
+ # Copyright (C) 2012-2013 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require "bundler/gem_tasks"
17
+
18
+ task :default => :test
19
+
20
+ desc "Run test"
21
+ task :test do
22
+ ruby("test/run-test.rb")
23
+ end
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright (C) 2014 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "github-event-watcher"
19
+
20
+ command = GitHubEventWatcher::Command::GitHubPullPushEvents.new
21
+ exit(command.run)
@@ -0,0 +1,4 @@
1
+ repositories:
2
+ - clear-code/git-utils
3
+ - ruby/ruby
4
+ webhook-end-point: http://git-utils.example.com/post-receiver/
@@ -0,0 +1,25 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'github-event-watcher/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "github-event-watcher"
7
+ spec.version = GitHubEventWatcher::VERSION
8
+ spec.authors = ["Kouhei Sutou"]
9
+ spec.email = ["kou@clear-code.com"]
10
+ spec.summary = %q{GitHub event watcher}
11
+ spec.description = %q{GitHub event watcher}
12
+ spec.homepage = ""
13
+ spec.license = "GPL-3.0+"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_development_dependency "test-unit"
23
+ spec.add_development_dependency "test-unit-rr"
24
+ spec.add_development_dependency "test-unit-capybara"
25
+ end
@@ -0,0 +1,22 @@
1
+ # Copyright (C) 2014 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require "github-event-watcher/event"
17
+ require "github-event-watcher/persistent-state"
18
+ require "github-event-watcher/version"
19
+ require "github-event-watcher/watcher"
20
+ require "github-event-watcher/webhook-sender"
21
+
22
+ require "github-event-watcher/command/github-pull-push-events"
@@ -0,0 +1,179 @@
1
+ # Copyright (C) 2014 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require "optparse"
17
+ require "fileutils"
18
+ require "pathname"
19
+ require "time"
20
+ require "logger"
21
+ require "yaml"
22
+
23
+ require "github-event-watcher"
24
+
25
+ module GitHubEventWatcher
26
+ module Command
27
+ class GitHubPullPushEvents
28
+ def initialize
29
+ @state_dir = Pathname.new("var/lib")
30
+ @log_dir = Pathname.new("var/log")
31
+ @config_file = Pathname.new("config.yaml")
32
+ @pid_file = Pathname.new("var/run/github-pull-push-events.pid")
33
+ @daemonize = false
34
+ end
35
+
36
+ def run(argv=ARGV)
37
+ parse_command_line!(argv)
38
+ expand_paths
39
+ start_watcher
40
+ true
41
+ end
42
+
43
+ private
44
+ def parse_command_line!(argv)
45
+ parser = OptionParser.new
46
+ parser.version = VERSION
47
+ parser.on("--state-dir=DIR",
48
+ "The directory to store state file",
49
+ "(#{@state_dir})") do |dir|
50
+ @state_dir = Pathname.new(dir)
51
+ end
52
+ parser.on("--log-dir=DIR",
53
+ "The directory to store logs",
54
+ "(#{@log_dir})") do |dir|
55
+ @log_dir = Pathname.new(dir)
56
+ end
57
+ parser.on("--config-file=FILE",
58
+ "The config file in YAML",
59
+ "(#{@config_file})") do |file|
60
+ @config_file = Pathname.new(file)
61
+ end
62
+ parser.on("--pid-file=FILE",
63
+ "The PID file",
64
+ "(#{@pid_file})") do |file|
65
+ @pid_file = Pathname.new(file)
66
+ end
67
+ parser.on("--[no-]daemonize",
68
+ "Run as a daemon",
69
+ "(#{@daemonize})") do |boolean|
70
+ @daemonize = boolean
71
+ end
72
+ parser.parse!(argv)
73
+ end
74
+
75
+ def expand_paths
76
+ @state_dir = @state_dir.expand_path
77
+ @log_dir = @log_dir.expand_path
78
+ @config_file = @config_file.expand_path
79
+ @pid_file = @pid_file.expand_path
80
+ end
81
+
82
+ def start_watcher
83
+ state = create_state
84
+ logger = create_logger
85
+ watcher = Watcher.new(state, logger)
86
+ config = load_config
87
+ config["repositories"].each do |repository|
88
+ watcher.add_repository(repository)
89
+ end
90
+ webhook_end_point = URI.parse(config["webhook-end-point"])
91
+ webhook_sender = WebhookSender.new(webhook_end_point, logger)
92
+
93
+ setup_signals(watcher)
94
+
95
+ if @daemonize
96
+ Process.daemon
97
+ $stdout = create_io_logger("stdout")
98
+ $stderr = create_io_logger("stderr")
99
+ at_exit do
100
+ $stdout.flush
101
+ $stderr.flush
102
+ end
103
+ end
104
+ create_pid_file
105
+
106
+ begin
107
+ watcher.watch do |event|
108
+ next if event.type != "PushEvent"
109
+ webhook_sender.send_push_event(event)
110
+ end
111
+ ensure
112
+ remove_pid_file
113
+ end
114
+
115
+ logger.close
116
+ end
117
+
118
+ def create_state
119
+ FileUtils.mkdir_p(@state_dir.to_s)
120
+ PersistentState.new(@state_dir + "state.yaml")
121
+ end
122
+
123
+ def create_logger(type=nil)
124
+ FileUtils.mkdir_p(@log_dir.to_s)
125
+ components = ["github-pull-push-events", type, "log"].compact
126
+ log_file = @log_dir + components.join(".")
127
+ logger = Logger.new(log_file.to_s, 10, 1024 ** 2)
128
+ logger.level = Logger::INFO
129
+ logger.formatter = lambda do |severity, timestamp, program_name, message|
130
+ "#{timestamp.iso8601}[#{severity.downcase}] #{message}\n"
131
+ end
132
+ logger
133
+ end
134
+
135
+ def create_io_logger(type)
136
+ logger = create_logger(type)
137
+ logger.level = Logger::DEBUG
138
+ class << logger
139
+ def write(message)
140
+ message = message.strip
141
+ return if message.empty?
142
+ debug(message)
143
+ end
144
+
145
+ def flush
146
+ return if @logdev.nil?
147
+ @logdev.dev.flush
148
+ end
149
+ end
150
+ logger
151
+ end
152
+
153
+ def load_config
154
+ YAML.load(@config_file.read)
155
+ end
156
+
157
+ def setup_signals(watcher)
158
+ trap(:INT) do
159
+ watcher.stop
160
+ end
161
+ trap(:TERM) do
162
+ watcher.stop
163
+ end
164
+ end
165
+
166
+ def create_pid_file
167
+ FileUtils.mkdir_p(@pid_file.dirname.to_s)
168
+ @pid_file.open("w") do |pid_file|
169
+ pid_file.print(Process.pid)
170
+ end
171
+ end
172
+
173
+ def remove_pid_file
174
+ return unless @pid_file.exist?
175
+ FileUtils.rm_f(@pid_file.to_s)
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,55 @@
1
+ # Copyright (C) 2014 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ module GitHubEventWatcher
17
+ class Event
18
+ def initialize(data)
19
+ @data = data
20
+ @repository = @data["repo"]
21
+ end
22
+
23
+ def id
24
+ Integer(@data["id"])
25
+ end
26
+
27
+ def type
28
+ @data["type"]
29
+ end
30
+
31
+ def payload
32
+ @data["payload"]
33
+ end
34
+
35
+ def repository_url
36
+ "https://github.com/#{repository_full_name}"
37
+ end
38
+
39
+ def repository_owner
40
+ owner, name = repository_full_name.split("/", 2)
41
+ _ = name # For suppressing a warning
42
+ owner
43
+ end
44
+
45
+ def repository_name
46
+ owner, name = repository_full_name.split("/", 2)
47
+ _ = owner # For suppressing a warning
48
+ name
49
+ end
50
+
51
+ def repository_full_name
52
+ @repository["name"]
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,53 @@
1
+ # Copyright (C) 2014 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require "yaml"
17
+
18
+ module GitHubEventWatcher
19
+ class PersistentState
20
+ def initialize(path)
21
+ @path = path
22
+ load
23
+ end
24
+
25
+ def processed_event_id(repository_name)
26
+ repository(repository_name)["processed-event-id"] || 0
27
+ end
28
+
29
+ def update_processed_event_id(repository_name, id)
30
+ repository(repository_name)["processed-event-id"] = id
31
+ save
32
+ end
33
+
34
+ private
35
+ def repository(name)
36
+ @repositories[name] ||= {}
37
+ end
38
+
39
+ def load
40
+ if @path.exist?
41
+ @repositories = YAML.load(@path.read)
42
+ else
43
+ @repositories = {}
44
+ end
45
+ end
46
+
47
+ def save
48
+ @path.open("w") do |file|
49
+ file.print(@repositories.to_yaml)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,18 @@
1
+ # Copyright (C) 2014 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ module GitHubEventWatcher
17
+ VERSION = "1.0.0"
18
+ end
@@ -0,0 +1,88 @@
1
+ # Copyright (C) 2014-2015 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require "open-uri"
17
+ require "json"
18
+
19
+ require "github-event-watcher/event"
20
+
21
+ module GitHubEventWatcher
22
+ class Watcher
23
+ NOTIFY_MESSAGE = "X"
24
+
25
+ def initialize(state, logger)
26
+ @repositories = []
27
+ @state = state
28
+ @logger = logger
29
+ @running = true
30
+ @notify_pipe = IO.pipe
31
+ end
32
+
33
+ def add_repository(name)
34
+ @logger.info("[watcher][repository] add: <#{name}>")
35
+ @repositories << name
36
+ end
37
+
38
+ def watch
39
+ i = 0
40
+ while @running
41
+ name = @repositories[i]
42
+ events = fetch_events(name)
43
+ processed_event_id = @state.processed_event_id(name)
44
+ events = remove_processed_events(events, processed_event_id)
45
+ @logger.info("[watcher][watch][#{name}] target events: <#{events.size}>")
46
+ sorted_events = events.sort_by do |event|
47
+ event.id
48
+ end
49
+ sorted_events.each do |event|
50
+ yield(event)
51
+ end
52
+ latest_event = sorted_events.last
53
+ if latest_event
54
+ @logger.info("[watcher][watch][#{name}] last processed event ID: " +
55
+ "<#{latest_event.id}>")
56
+ @state.update_processed_event_id(name, latest_event.id)
57
+ end
58
+ readables, = IO.select([@notify_pipe[0]], nil, nil, 60)
59
+ readables[0].read(NOTIFY_MESSAGE.size) if readables
60
+ i = (i + 1) % @repositories.size
61
+ end
62
+ end
63
+
64
+ def stop
65
+ @running = false
66
+ @notify_pipe[1].write(NOTIFY_MESSAGE)
67
+ end
68
+
69
+ private
70
+ def fetch_events(name)
71
+ open("https://api.github.com/repos/#{name}/events") do |body|
72
+ JSON.parse(body.read).collect do |event|
73
+ Event.new(event)
74
+ end
75
+ end
76
+ rescue OpenURI::HTTPError, SystemCallError, Timeout::Error
77
+ tag = "[watcher][watch][#{name}][fetch]"
78
+ @logger.error("#{tag} Failed to fetch: #{$!.class}: #{$!.message}")
79
+ []
80
+ end
81
+
82
+ def remove_processed_events(events, processed_event_id)
83
+ events.reject do |event|
84
+ event.id <= processed_event_id
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,74 @@
1
+ # Copyright (C) 2014 Kouhei Sutou <kou@clear-code.com>
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+
16
+ require "net/http"
17
+ require "json"
18
+
19
+ module GitHubEventWatcher
20
+ class WebhookSender
21
+ def initialize(end_point, logger)
22
+ @end_point = end_point
23
+ @logger = logger
24
+ @logger.info("[webhook-sender][end-point] <#{@end_point}>")
25
+ end
26
+
27
+ def send_push_event(event)
28
+ @logger.info("[webhook-sender][send][push] " +
29
+ "<#{event.id}>:<#{event.repository_full_name}>")
30
+ options = {
31
+ :use_ssl => (@end_point.scheme == "https"),
32
+ }
33
+ begin
34
+ Net::HTTP.start(@end_point.host, @end_point.port, options) do |http|
35
+ request = Net::HTTP::Post.new(@end_point.request_uri)
36
+ request["Host"] = @end_point.hostname
37
+ request["X-GitHub-Event"] = "push"
38
+ request["Content-Type"] = "application/json"
39
+ request["User-Agent"] = "GitHub Event Watcher/1.0"
40
+ request.body = JSON.generate(convert_to_push_event_payload(event))
41
+ response = http.request(request)
42
+ log_tag = "[webhook-sender][sent][push]"
43
+ case response
44
+ when Net::HTTPSuccess
45
+ @logger.info("#{log_tag}[success]")
46
+ else
47
+ @logger.error("#{log_tag}[error] <#{response.code}>")
48
+ end
49
+ end
50
+ rescue SystemCallError, Timeout::Error
51
+ tag = "[webhook-sender][send][push][error]"
52
+ message = "#{tag} Failed to send push event: #{$!.class}: #{$!.message}"
53
+ @logger.error(message)
54
+ end
55
+ end
56
+
57
+ private
58
+ def convert_to_push_event_payload(event)
59
+ {
60
+ "ref" => event.payload["ref"],
61
+ "before" => event.payload["before"],
62
+ "after" => event.payload["head"],
63
+ "repository" => {
64
+ "url" => event.repository_url,
65
+ "name" => event.repository_name,
66
+ "full_name" => event.repository_full_name,
67
+ "owner" => {
68
+ "name" => event.repository_owner,
69
+ },
70
+ },
71
+ }
72
+ end
73
+ end
74
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: github-event-watcher
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Kouhei Sutou
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-25 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: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: test-unit
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: test-unit-rr
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
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: test-unit-capybara
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: GitHub event watcher
84
+ email:
85
+ - kou@clear-code.com
86
+ executables:
87
+ - github-pull-push-events
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - ".travis.yml"
93
+ - Gemfile
94
+ - README.md
95
+ - Rakefile
96
+ - bin/github-pull-push-events
97
+ - config.yaml.example
98
+ - github-event-watcher.gemspec
99
+ - lib/github-event-watcher.rb
100
+ - lib/github-event-watcher/command/github-pull-push-events.rb
101
+ - lib/github-event-watcher/event.rb
102
+ - lib/github-event-watcher/persistent-state.rb
103
+ - lib/github-event-watcher/version.rb
104
+ - lib/github-event-watcher/watcher.rb
105
+ - lib/github-event-watcher/webhook-sender.rb
106
+ homepage: ''
107
+ licenses:
108
+ - GPL-3.0+
109
+ metadata: {}
110
+ post_install_message:
111
+ rdoc_options: []
112
+ require_paths:
113
+ - lib
114
+ required_ruby_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ requirements: []
125
+ rubyforge_project:
126
+ rubygems_version: 2.4.5
127
+ signing_key:
128
+ specification_version: 4
129
+ summary: GitHub event watcher
130
+ test_files: []