From 12826e26065e9e2f2348ae52eb538d23a4aa1d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicol=C3=A1s=20Sanguinetti?= Date: Fri, 25 Jul 2008 22:02:27 -0300 Subject: [PATCH] Move GitHub's post-receive script to the web UI [#19 state:resolved] --- lib/integrity.rb | 1 + lib/integrity/github.rb | 34 -------------- lib/integrity/ui.rb | 16 +++++++ spec/github_spec.rb | 100 ---------------------------------------- spec/ui_spec.rb | 99 ++++++++++++++++++++++++++++++++++++++- 5 files changed, 114 insertions(+), 136 deletions(-) delete mode 100644 lib/integrity/github.rb delete mode 100644 spec/github_spec.rb diff --git a/lib/integrity.rb b/lib/integrity.rb index b1f3ca72..9c9cd1b2 100644 --- a/lib/integrity.rb +++ b/lib/integrity.rb @@ -2,6 +2,7 @@ $:.unshift "#{__DIR__}/integrity", "#{__DIR__}integrity/scm", *Dir["#{__DIR__}/../vendor/**/lib"].to_a require "rubygems" +require 'json' require 'dm-core' require 'dm-validations' require 'dm-types' diff --git a/lib/integrity/github.rb b/lib/integrity/github.rb deleted file mode 100644 index 2abf6ea7..00000000 --- a/lib/integrity/github.rb +++ /dev/null @@ -1,34 +0,0 @@ -require File.dirname(__FILE__) + '/../integrity' -require 'sinatra' -require 'json' - -configure do - Integrity.new -end - -include Integrity - -post '/:project' do - content_type 'text/plain' - - project = Project.first(:permalink => params[:project]) - unknown_project! if project.nil? - - begin - payload = JSON.parse(params[:payload] || "") - payload['commits'].each_key { |commit| project.build(commit) } - 'Thanks, build started.' - rescue JSON::ParserError => exception - invalid_payload!(exception.to_s) - end -end - -helpers do - def unknown_project! - throw :halt, [404, "Unknown project `#{params[:project]}'"] - end - - def invalid_payload!(msg=nil) - throw :halt, [422, msg || 'No payload given'] - end -end \ No newline at end of file diff --git a/lib/integrity/ui.rb b/lib/integrity/ui.rb index bc9c4a24..804317fe 100644 --- a/lib/integrity/ui.rb +++ b/lib/integrity/ui.rb @@ -81,6 +81,18 @@ show :new, :title => ["projects", current_project.permalink, "edit"] end +post "/:project/push" do + content_type 'text/plain' + + begin + payload = JSON.parse(params[:payload] || "") + payload['commits'].each_key { |commit| current_project.build(commit) } + 'Thanks, build started.' + rescue JSON::ParserError => exception + invalid_payload!(exception.to_s) + end +end + post "/:project/builds" do login_required @@ -121,6 +133,10 @@ def unauthorized!(realm=authorization_realm) throw :halt, [401, show(:unauthorized, :title => "incorrect credentials")] end + def invalid_payload!(msg=nil) + throw :halt, [422, msg || 'No payload given'] + end + def current_project @project ||= Project.first(:permalink => params[:project]) or raise Sinatra::NotFound end diff --git a/spec/github_spec.rb b/spec/github_spec.rb deleted file mode 100644 index 33465d8c..00000000 --- a/spec/github_spec.rb +++ /dev/null @@ -1,100 +0,0 @@ -require File.dirname(__FILE__) + '/spec_helper' - -describe "Sinatra app to handle GitHub's post-receive hooks" do - def payload - <<-EOS - { "before": "5aef35982fb2d34e9d9d4502f6ede1072793222d", - "repository": { - "url": "http://github.com/defunkt/github", - "name": "github", - "owner": { - "email": "chris@ozmm.org", - "name": "defunkt" - } - }, - "commits": { - "41a212ee83ca127e3c8cf465891ab7216a705f59": { - "url": "http://github.com/defunkt/github/commit/41a212ee83ca127e3c8cf465891ab7216a705f59", - "author": { - "email": "chris@ozmm.org", - "name": "Chris Wanstrath" - }, - "message": "okay i give in", - "timestamp": "2008-02-15T14:57:17-08:00" - }, - "de8251ff97ee194a289832576287d6f8ad74e3d0": { - "url": "http://github.com/defunkt/github/commit/de8251ff97ee194a289832576287d6f8ad74e3d0", - "author": { - "email": "chris@ozmm.org", - "name": "Chris Wanstrath" - }, - "message": "update pricing a tad", - "timestamp": "2008-02-15T14:36:34-08:00" - } - }, - "after": "de8251ff97ee194a289832576287d6f8ad74e3d0", - "ref": "refs/heads/master" } - EOS - end - - before(:each) do - Integrity.stub!(:new) - @project = mock('project', :build => true) - Integrity::Project.stub!(:first).and_return(@project) - require Integrity.root / "lib" / "integrity" / "github" - end - - it 'should be successful' do - post_it '/github', :payload => payload - status.should == 200 - end - - it 'should return a confirmation message' do - post_it '/github', :payload => payload - body.should == 'Thanks, build started.' - end - - it 'should be 422 without payload' do - post_it '/github' - status.should == 422 - end - - it 'should find the Project by its name' do - Integrity::Project.should_receive(:first).with(:permalink => 'github').and_return(@project) - post_it '/github', :payload => payload - end - - it 'should be 404 if unknown project' do - Integrity::Project.stub!(:first).and_return(nil) - post_it '/github', :payload => payload - status.should == 404 - body.should == "Unknown project `github'" - end - - it 'should make a new build for each commit' do - @project.should_receive(:build).with('41a212ee83ca127e3c8cf465891ab7216a705f59') - @project.should_receive(:build).with('de8251ff97ee194a289832576287d6f8ad74e3d0') - post_it '/github', :payload => payload - end - - describe 'With invalid payload' do - before(:each) do - JSON.stub!(:parse).and_raise(JSON::ParserError.new('error message')) - end - - it 'should rescue any JSON parse error and return a 422 status code' do - post_it '/github' - @response.status.should == 422 - end - - it 'should rescue any JSON parse error and return the error' do - post_it '/github' - @response.body.should == 'error message' - end - - it 'should return error in plain/text' do - post_it '/github' - @response['Content-Type'].should == 'text/plain' - end - end -end diff --git a/spec/ui_spec.rb b/spec/ui_spec.rb index 0d53064e..3e3c816d 100644 --- a/spec/ui_spec.rb +++ b/spec/ui_spec.rb @@ -1,6 +1,6 @@ require File.dirname(__FILE__) + '/spec_helper' -describe 'Web UI using Sinatra' do +describe 'Web UI' do def mock_project(messages={}) messages = { :name => "Integrity", @@ -48,7 +48,7 @@ def provide_valid_credentials! before(:each) do Integrity.stub!(:new) - require File.dirname(__FILE__) + '/../lib/integrity/ui' + require Integrity.root / "lib" / "integrity" / "ui" end after(:each) { @project = nil } @@ -428,6 +428,101 @@ def provide_valid_credentials! end end + describe "POST /:project/push" do + def payload + <<-EOS + { "before": "5aef35982fb2d34e9d9d4502f6ede1072793222d", + "repository": { + "url": "http://github.com/defunkt/github", + "name": "github", + "owner": { + "email": "chris@ozmm.org", + "name": "defunkt" + } + }, + "commits": { + "41a212ee83ca127e3c8cf465891ab7216a705f59": { + "url": "http://github.com/defunkt/github/commit/41a212ee83ca127e3c8cf465891ab7216a705f59", + "author": { + "email": "chris@ozmm.org", + "name": "Chris Wanstrath" + }, + "message": "okay i give in", + "timestamp": "2008-02-15T14:57:17-08:00" + }, + "de8251ff97ee194a289832576287d6f8ad74e3d0": { + "url": "http://github.com/defunkt/github/commit/de8251ff97ee194a289832576287d6f8ad74e3d0", + "author": { + "email": "chris@ozmm.org", + "name": "Chris Wanstrath" + }, + "message": "update pricing a tad", + "timestamp": "2008-02-15T14:36:34-08:00" + } + }, + "after": "de8251ff97ee194a289832576287d6f8ad74e3d0", + "ref": "refs/heads/master" } + EOS + end + + before do + Project.stub!(:first).with(:permalink => "github").and_return mock_project + end + + it 'should be successful' do + post_it '/github/push', :payload => payload + status.should == 200 + end + + it 'should return a confirmation message' do + post_it '/github/push', :payload => payload + body.should == 'Thanks, build started.' + end + + it 'should be 422 without payload' do + post_it '/github/push' + status.should == 422 + end + + it 'should find the Project by its name' do + Integrity::Project.should_receive(:first).with(:permalink => 'github').and_return(@project) + post_it '/github/push', :payload => payload + end + + it 'should be 404 if unknown project' do + Integrity::Project.stub!(:first).and_return(nil) + post_it '/github/push', :payload => payload + status.should == 404 + end + + it 'should make a new build for each commit' do + @project.should_receive(:build).with('41a212ee83ca127e3c8cf465891ab7216a705f59') + @project.should_receive(:build).with('de8251ff97ee194a289832576287d6f8ad74e3d0') + post_it '/github/push', :payload => payload + end + + describe 'With invalid payload' do + before(:each) do + JSON.stub!(:parse).and_raise(JSON::ParserError.new('error message')) + end + + it 'should rescue any JSON parse error and return a 422 status code' do + post_it '/github/push' + @response.status.should == 422 + end + + it 'should rescue any JSON parse error and return the error' do + post_it '/github/push' + @response.body.should == 'error message' + end + + it 'should return error in plain/text' do + post_it '/github/push' + @response['Content-Type'].should == 'text/plain' + end + end + end + describe "POST /:project/builds" do it "should build the project" do Project.stub!(:first).with(:permalink => "integrity").and_return mock_project