lib/tutter.rb in tutter-0.0.5 vs lib/tutter.rb in tutter-0.0.6

- old
+ new

@@ -1,16 +1,18 @@ -require 'rubygems' +require 'json' require 'octokit' -require 'yaml' require 'sinatra' +require 'thin' require 'tutter/action' -require 'json' +require 'yaml' +# Modular sinatra app Tutter class Tutter < Sinatra::Base + enable :logging configure do - set :config_path, ENV['TUTTER_CONFIG_PATH'] || "conf/tutter.yaml" + set :config_path, ENV['TUTTER_CONFIG_PATH'] || 'conf/tutter.yaml' set :config, YAML.load_file(settings.config_path) end configure :development do require 'sinatra/reloader' @@ -20,80 +22,93 @@ configure :test do set :bind, '0.0.0.0' end + def verify_signature(payload_body, secret_token) + signature = 'sha1=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), secret_token, payload_body) + return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_HUB_SIGNATURE']) + end + # Return project settings from config - def get_project_settings project + def project_settings(project) settings.config['projects'].each do |p| return p if p['name'] == project end - false + error(404, 'Project does not exist in tutter.conf') end - def try_action event, data - project = data['repository']['full_name'] || error(400, 'Bad request') + # Return actions for event from config + def actions_for_event(event, config) + config['actions'][event] || error(404, + "No Actions for #{event} in tutter.conf" + ) + end - conf = get_project_settings(project) || error(404, 'Project does not exist in tutter.conf') - - # Setup octokit endpoints + def octokit_client(config) Octokit.configure do |c| - c.api_endpoint = conf['github_api_endpoint'] - c.web_endpoint = conf['github_site'] + c.api_endpoint = config['github_api_endpoint'] + c.web_endpoint = config['github_site'] + c.auto_paginate = config['github_api_auto_paginate'] or false end - if conf['access_token_env_var'] - access_token = ENV[conf['access_token_env_var']] || '' + if config['access_token_env_var'] + access_token = ENV[config['access_token_env_var']] || '' else - access_token = conf['access_token'] || '' + access_token = config['access_token'] || '' end - client = Octokit::Client.new :access_token => access_token + Octokit::Client.new access_token: access_token + end - # Load action - action = Action.create(conf['action'], - conf['action_settings'], - client, - project, - event, - data) + def prepare_actions(project, event, data, config) + client = octokit_client(config) + actions_for_event(event, config).each do |a| + yield Action.create(a, + config['action_settings'], + client, + project, + event, + data), a + end + end - status_code, message = action.run - - return status_code, message + def try_actions(event, data, project, config) + responses = { event: event, responses: {} } + prepare_actions(project, event, data, config) do |action, name| + status_code, message = action.run + responses[:responses][name] = { status_code: status_code, + message: message + } + break if status_code != 200 + end + [responses[:responses].values.last[:status_code], responses.to_json] end post '/' do - event = env['HTTP_X_GITHUB_EVENT'] + event = env['HTTP_X_GITHUB_EVENT'] || error(500, 'Invalid request') - unless event - error(500, "Invalid request") - end - # Get a 200 OK message in the Github webhook history # Previously this showed an error. - if event == "ping" - return 200, "Tutter likes this hook!" - end + return 200, 'Tutter likes this hook!' if event == 'ping' # Github send data in JSON format, parse it! + request_body = request.body.read begin - data = JSON.parse request.body.read + data = JSON.parse request_body rescue JSON::ParserError error(400, 'POST data is not JSON') end - # Check actions with repo + project = data['repository']['full_name'] || error(400, 'Bad request') + config = project_settings(project) + verify_signature(request_body, config['hook_secret']) if config['hook_secret'] - if data['repository'] - return try_action(event, data) - end - - error(400, "Unsupported request: #{event}") + return try_actions(event, data, project, config) if data['repository'] end get '/' do 'Source code and documentation at https://github.com/jhaals/tutter' end - run! if app_file == $0 + run! if app_file == $PROGRAM_NAME end