1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
# -*- mode: ruby; coding: utf-8 -*-
#
# Copyright (C) 2012 Kouhei Sutou <kou@cozmixng.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
require "fileutils"
require "json"
require "yaml"
require "pathname"
require "racknga"
use Rack::CommonLogger
use Rack::Runtime
use Rack::ContentLength
base_dir = Pathname(__FILE__).dirname
config_file = base_dir + "config.yaml"
if config_file.exist?
options = YAML.load_file(config_file.to_s)
notifier_options = options["exception_notifier"]
notifiers = [Racknga::ExceptionMailNotifier.new(notifier_options)]
use Racknga::Middleware::ExceptionNotifier, :notifiers => notifiers
end
class GitHubPostReceiver
def initialize(env)
@request = Rack::Request.new(env)
@response = Rack::Response.new
@response.headers["Content-Type"] = "text/plain"
end
def run
process
@response.finish
end
private
def process
payload = parse_payload
return if payload.nil?
return unless rabbit_shocker_repository?(payload["repository"])
update_site if need_update_site?(payload)
update_github_post_receiver if need_update_github_post_receiver?(payload)
end
def parse_payload
payload = @request.params["payload"]
if payload.nil?
@response.status = Rack::Utils.status_code(:bad_request)
@response.write("No payload.")
return nil
end
log_payload(payload)
begin
JSON.parse(payload)
rescue JSON::ParseError
@response.status = Rack::Utils.status_code(:bad_request)
@response.write("Invalid JSON: #{$!.message}\n#{payload}")
nil
end
end
MB = 1000 * 1000
def log_payload(payload)
return if payload.bytesize > (2 * MB)
path = File.join(tmp_dir, "latest-payload.json")
File.open(path, "w") do |latest_payload_file|
latest_payload_file.print(payload)
end
end
def need_update_site?(payload)
payload["commits"].any? do |commit|
doc_directory_changed?(commit)
end
end
def need_update_github_post_receiver?(payload)
return false unless payload["repository"]["name"] == "rabbit"
payload["commits"].any? do |commit|
github_post_receiver_changed?(commit)
end
end
def rabbit_shocker_repository?(repository)
repository["owner"]["name"] == "rabbit-shocker"
end
def effected_files(commit)
files = []
files |= (commit["added"] || [])
files |= (commit["removed"] || [])
files |= (commit["modified"] || [])
files
end
def doc_directory_changed?(commit)
effected_files(commit).any? do |effected_file|
effected_file.start_with?("doc/")
end
end
def github_post_receiver_changed?(commit)
effected_files(commit).any? do |effected_file|
effected_file.start_with?("misc/github-post-receiver/")
end
end
def update_site
rake(["update", "html:publish:local"],
:log_file_name => "update-site.log")
end
def update_github_post_receiver
rake(["update", "github:post_receiver:restart"],
:log_file_name => "update-github-post-receiver.log")
end
def rake(rake_options, options={})
log_file_name = File.join(tmp_dir, options[:log_file_name] || "rake.log")
env = {
"LANG" => "ja_JP.UTF-8",
}
rake = Gem.bin_path("rake", "rake")
File.open("/dev/null") do |null|
File.open(log_file_name, "w") do |log|
options = {
:chdir => top_dir,
:in => null,
[:out, :err] => log,
}
Process.spawn(env,
"xvfb-run", Gem.ruby, rake, *rake_options,
options)
end
end
end
def top_dir
File.expand_path(File.join(File.dirname(__FILE__), "..", ".."))
end
def tmp_dir
File.expand_path(File.join(File.dirname(__FILE__), "tmp"))
end
end
receiver = lambda do |env|
receiver = GitHubPostReceiver.new(env)
receiver.run
end
run receiver
|