From c5c775e38d9e145d580cf4f7cebacf605bd7ffea Mon Sep 17 00:00:00 2001 From: winton Date: Sat, 5 Dec 2009 23:39:00 -0800 Subject: [PATCH] Specs passing with newly modularized structure and config system --- lib/lilypad.rb | 50 +++++++ lib/lilypad/adapters/rails.rb | 23 ++++ lib/lilypad/adapters/sinatra.rb | 10 ++ lib/lilypad/config.rb | 63 +++++++++ lib/lilypad/config/request.rb | 24 ++++ lib/lilypad/hoptoad/deploy.rb | 42 ++++++ lib/lilypad/hoptoad/notify.rb | 83 ++++++++++++ lib/lilypad/hoptoad/xml.rb | 61 +++++++++ lib/lilypad/log.rb | 46 +++++++ lib/rack/lilypad.rb | 152 ++-------------------- lib/rack/lilypad/rails.rb | 27 ---- spec/fixtures/rails/config/environment.rb | 4 +- spec/fixtures/sinatra.rb | 9 +- spec/{rack => }/lilypad_spec.rb | 49 ++++--- spec/spec_helper.rb | 4 +- 15 files changed, 454 insertions(+), 193 deletions(-) create mode 100644 lib/lilypad.rb create mode 100644 lib/lilypad/adapters/rails.rb create mode 100644 lib/lilypad/adapters/sinatra.rb create mode 100644 lib/lilypad/config.rb create mode 100644 lib/lilypad/config/request.rb create mode 100644 lib/lilypad/hoptoad/deploy.rb create mode 100644 lib/lilypad/hoptoad/notify.rb create mode 100644 lib/lilypad/hoptoad/xml.rb create mode 100644 lib/lilypad/log.rb delete mode 100644 lib/rack/lilypad/rails.rb rename spec/{rack => }/lilypad_spec.rb (72%) diff --git a/lib/lilypad.rb b/lib/lilypad.rb new file mode 100644 index 0000000..aac5c7e --- /dev/null +++ b/lib/lilypad.rb @@ -0,0 +1,50 @@ +require 'builder' +require 'net/http' +require 'rack' + +lib = File.dirname(__FILE__) +require "#{lib}/lilypad/config" +require "#{lib}/lilypad/config/request" +require "#{lib}/lilypad/log" +require "#{lib}/lilypad/hoptoad/deploy" +require "#{lib}/lilypad/hoptoad/notify" +require "#{lib}/lilypad/hoptoad/xml" +require "#{lib}/rack/lilypad" + +class Lilypad + class < e + end + + log :debug, @response + success? + end + + private + + def params + { + 'api_key' => api_key, + 'deploy[local_username]' => @options[:username], + 'deploy[rails_env]' => @options[:environment], + 'deploy[scm_revision]' => @options[:revision], + 'deploy[scm_repository]' => @options[:repository] + } + end + + def post + url = URI.parse Config.deploy_url + @response = Net::HTTP.post_form url, params + end + + def success? + @response.class.superclass == Net::HTTPSuccess + end + end + end +end \ No newline at end of file diff --git a/lib/lilypad/hoptoad/notify.rb b/lib/lilypad/hoptoad/notify.rb new file mode 100644 index 0000000..238d17d --- /dev/null +++ b/lib/lilypad/hoptoad/notify.rb @@ -0,0 +1,83 @@ +class Lilypad + class Hoptoad + class Notify + + include Log::Methods + + def initialize(env, exception) + @exception = exception + @env = env + + http_start do |http| + begin + xml = XML.build *parse + http.post @uri.path, xml, headers + rescue Exception => e + end + end + + if env && success? + env['hoptoad.notified'] = true + end + + Config::Request.reset! + log :notify, @response + success? + end + + private + + def backtrace + regex = %r{^([^:]+):(\d+)(?::in `([^']+)')?$} + @exception.backtrace.map do |line| + _, file, number, method = line.match(regex).to_a + Backtrace.new file, number, method + end + end + + def filter(hash) + return unless Config.filters + hash.inject({}) do |acc, (key, val)| + match = Config.filters.any? { |f| key.to_s =~ Regexp.new(f) } + acc[key] = match ? "[FILTERED]" : val + acc + end + end + + def headers + { + 'Content-type' => 'text/xml', + 'Accept' => 'text/xml, application/xml' + } + end + + def http_start(&block) + @uri = URI.parse Config.notify_url + Net::HTTP.start @uri.host, @uri.port do |http| + http.read_timeout = 5 # seconds + http.open_timeout = 2 # seconds + @response = yield http + end + end + + def parse + env = filter ENV.to_hash.merge(@env || {}) + if @env + request = Rack::Request.new @env + request_path = request.script_name + request.path_info + else + request = nil + request_path = 'Internal' + end + [ backtrace, env, @exception, request, request_path ] + end + + def success? + @response.class.superclass == Net::HTTPSuccess + end + + class Backtrace < Struct.new(:file, :number, :method) + end + end + end +end \ No newline at end of file diff --git a/lib/lilypad/hoptoad/xml.rb b/lib/lilypad/hoptoad/xml.rb new file mode 100644 index 0000000..8e97b43 --- /dev/null +++ b/lib/lilypad/hoptoad/xml.rb @@ -0,0 +1,61 @@ +class Lilypad + class Hoptoad + class XML + class < "1.0", :encoding => "UTF-8" + xml.notice :version => '2.0.0' do |n| + n.tag! 'api-key', api_key + n.notifier do |n| + n.name 'Lilypad' + n.url 'http://github.com/winton/lilypad' + n.version '0.2.4' + end + n.error do |e| + e.tag! 'class', exception.class.name + e.message exception.message + e.backtrace do |b| + backtrace.each do |line| + b.line :method => line.method, :file => line.file, :number => line.number + end + end + end + n.request do |r| + r.action Config::Request.action + r.component Config::Request.component || request_path + r.url request_path + if request && request.params.any? + r.params do |p| + request.params.each do |key, value| + p.var value.to_s, :key => key + end + end + end + if env.any? + r.tag! 'cgi-data' do |c| + env.each do |key, value| + c.var value.to_s, :key => key + end + end + end + end + n.tag! 'server-environment' do |s| + s.tag! 'project-root', Dir.pwd + s.tag! 'environment-name', ENV['RACK_ENV'] || 'development' + end + end + @@last_request = xml.target! + end + + def last_request + @@last_request + end + end + end + end +end \ No newline at end of file diff --git a/lib/lilypad/log.rb b/lib/lilypad/log.rb new file mode 100644 index 0000000..0fa36b6 --- /dev/null +++ b/lib/lilypad/log.rb @@ -0,0 +1,46 @@ +class Lilypad + class Log + + def initialize(type, response) + @response = response + @type = type + self.class.log title, xml_request, response_body + end + + class < e - @hoptoad.post(e, env) + ::Lilypad.notify e, env raise end - @hoptoad.post(env['rack.exception'], env) if env['rack.exception'] - [ status, headers, body ] - end - - class < 'text/xml', - 'Accept' => 'text/xml, application/xml' - } - http.read_timeout = 5 # seconds - http.open_timeout = 2 # seconds - response = begin - http.post uri.path, xml(exception, env), headers - rescue TimeoutError => e - end - case response - when Net::HTTPSuccess - env['hoptoad.notified'] = true if env - log "Hoptoad Success: #{response.class}" - else - log "Hoptoad Failure:", (response.body rescue nil), @@last_request - end - end - end - def xml(exception, env) - environment = filter(ENV.to_hash.merge(env || {})) - if env - request = Rack::Request.new(env) - request_path = request.script_name + request.path_info - else - request = nil - request_path = 'internal' - end - - xml = ::Builder::XmlMarkup.new - xml.instruct! :xml, :version => "1.0", :encoding => "UTF-8" - xml.notice(:version => '2.0.0') do |n| - n.tag! 'api-key', @api_key - n.notifier do |n| - n.name 'Lilypad' - n.url 'http://github.com/winton/lilypad' - n.version '0.1.7' - end - n.error do |e| - e.tag! 'class', exception.class.name - e.message exception.message - e.backtrace do |b| - backtrace(exception).each do |line| - b.line(:method => line.method, :file => line.file, :number => line.number) - end - end - end - n.request do |r| - r.action environment['rack.lilypad.action'] - r.component environment['rack.lilypad.component'] || request_path - r.url request_path - if request && request.params.any? - r.params do |p| - request.params.each do |key, value| - p.var(value.to_s, :key => key) - end - end - end - if environment.any? - r.tag!('cgi-data') do |c| - environment.each do |key, value| - c.var(value.to_s, :key => key) - end - end - end - end - n.tag!('server-environment') do |s| - s.tag! 'project-root', Dir.pwd - s.tag! 'environment-name', ENV['RACK_ENV'] || 'development' - end - end - @@last_request = xml.target! + if env['rack.exception'] + ::Lilypad.notify env['rack.exception'], env end - class < e - Rack::Lilypad.notify(e) + Lilypad.notify(e) end validate_xml end + it "should provide a deploy method" do + Net::HTTP.should_receive(:post_form).and_return(Net::HTTPOK.new(nil, nil, nil)) + Lilypad.deploy( + :username => 't1', + :environment => 't2', + :revision => 't3', + :repository => 't4' + ) + end + describe 'Rails' do def app diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 419a225..e3d1923 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,7 +2,7 @@ SPEC = File.dirname(__FILE__) $:.unshift File.expand_path("#{SPEC}/../lib") -require 'rack/lilypad' +require 'lilypad' require 'pp' require 'rubygems' @@ -29,7 +29,7 @@ def debug(object) def validate_xml xsd = Nokogiri::XML::Schema(File.read(SPEC + '/fixtures/hoptoad_2_0.xsd')) - doc = Nokogiri::XML(Rack::Lilypad::Hoptoad.last_request) + doc = Nokogiri::XML(Lilypad::Hoptoad::XML.last_request) errors = xsd.validate(doc) errors.each do |error|