foca-integrity 0.1.8 → 0.1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +7 -0
- data/Rakefile +89 -81
- data/config/config.sample.ru +11 -21
- data/config/config.sample.yml +15 -12
- data/lib/integrity.rb +21 -23
- data/lib/integrity/app.rb +138 -0
- data/lib/integrity/author.rb +39 -0
- data/lib/integrity/build.rb +54 -31
- data/lib/integrity/commit.rb +71 -0
- data/lib/integrity/helpers.rb +3 -3
- data/lib/integrity/helpers/authorization.rb +2 -2
- data/lib/integrity/helpers/forms.rb +3 -3
- data/lib/integrity/helpers/pretty_output.rb +1 -1
- data/lib/integrity/helpers/rendering.rb +6 -1
- data/lib/integrity/helpers/resources.rb +9 -3
- data/lib/integrity/helpers/urls.rb +15 -13
- data/lib/integrity/installer.rb +43 -60
- data/lib/integrity/migrations.rb +31 -48
- data/lib/integrity/notifier.rb +14 -16
- data/lib/integrity/notifier/base.rb +29 -19
- data/lib/integrity/notifier/test_helpers.rb +100 -0
- data/lib/integrity/project.rb +69 -33
- data/lib/integrity/project_builder.rb +23 -14
- data/lib/integrity/scm/git.rb +15 -14
- data/lib/integrity/scm/git/uri.rb +9 -9
- data/test/acceptance/api_test.rb +97 -0
- data/test/acceptance/browse_project_builds_test.rb +65 -0
- data/test/acceptance/browse_project_test.rb +95 -0
- data/test/acceptance/build_notifications_test.rb +42 -0
- data/test/acceptance/create_project_test.rb +97 -0
- data/test/acceptance/delete_project_test.rb +53 -0
- data/test/acceptance/edit_project_test.rb +117 -0
- data/test/acceptance/error_page_test.rb +18 -0
- data/test/acceptance/helpers.rb +2 -0
- data/test/acceptance/installer_test.rb +62 -0
- data/test/acceptance/manual_build_project_test.rb +82 -0
- data/test/acceptance/notifier_test.rb +109 -0
- data/test/acceptance/project_syndication_test.rb +30 -0
- data/test/acceptance/stylesheet_test.rb +18 -0
- data/test/helpers.rb +59 -27
- data/test/helpers/acceptance.rb +19 -64
- data/test/helpers/acceptance/email_notifier.rb +55 -0
- data/test/helpers/acceptance/git_helper.rb +15 -15
- data/test/helpers/acceptance/textfile_notifier.rb +3 -3
- data/test/helpers/expectations.rb +0 -1
- data/test/helpers/expectations/be_a.rb +4 -4
- data/test/helpers/expectations/change.rb +5 -5
- data/test/helpers/expectations/have.rb +4 -4
- data/test/helpers/expectations/predicates.rb +4 -4
- data/test/helpers/fixtures.rb +44 -18
- data/test/helpers/initial_migration_fixture.sql +44 -0
- data/test/unit/build_test.rb +51 -0
- data/test/unit/commit_test.rb +83 -0
- data/test/unit/helpers_test.rb +56 -0
- data/test/unit/integrity_test.rb +18 -0
- data/test/unit/migrations_test.rb +56 -0
- data/test/unit/notifier_test.rb +123 -0
- data/test/unit/project_builder_test.rb +108 -0
- data/test/unit/project_test.rb +282 -0
- data/test/unit/scm_test.rb +54 -0
- data/views/_commit_info.haml +24 -0
- data/views/build.haml +2 -2
- data/views/error.haml +4 -3
- data/views/home.haml +3 -5
- data/views/integrity.sass +19 -6
- data/views/new.haml +6 -6
- data/views/project.builder +9 -9
- data/views/project.haml +14 -12
- metadata +98 -116
- data/VERSION.yml +0 -4
- data/app.rb +0 -137
- data/integrity.gemspec +0 -76
- data/lib/integrity/core_ext/string.rb +0 -5
- data/test/helpers/expectations/have_tag.rb +0 -128
- data/views/_build_info.haml +0 -18
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/helpers"
|
2
|
+
|
3
|
+
class ProjectSyndicationTest < Test::Unit::AcceptanceTestCase
|
4
|
+
story <<-EOS
|
5
|
+
As a user,
|
6
|
+
I want to subscribe to a public project's Atom feed
|
7
|
+
So I can know the status of my favorite projects while having my morning coffee
|
8
|
+
EOS
|
9
|
+
|
10
|
+
scenario "a public project's page includes an autodiscovery link tag for the feed" do
|
11
|
+
Project.gen(:integrity, :public => true)
|
12
|
+
visit "/integrity"
|
13
|
+
|
14
|
+
assert_have_tag("link[@href='/integrity.atom']")
|
15
|
+
end
|
16
|
+
|
17
|
+
scenario "a public project's feed should include the latest builds" do
|
18
|
+
commits = 10.of { Commit.gen(:successful) } + 1.of { Commit.gen(:failed) }
|
19
|
+
Project.gen(:integrity, :public => true, :commits => commits)
|
20
|
+
|
21
|
+
visit "/integrity.atom"
|
22
|
+
|
23
|
+
# TODO: check for content-type
|
24
|
+
|
25
|
+
assert_have_tag("feed title", :content => "Build history for Integrity")
|
26
|
+
assert_have_tag("feed entry", :count => 11)
|
27
|
+
assert_have_tag("feed entry:first title", :content => "success")
|
28
|
+
assert_have_tag("feed entry:last title", :content => "failed")
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/helpers"
|
2
|
+
|
3
|
+
class IntegrityStylesheetTest < Test::Unit::AcceptanceTestCase
|
4
|
+
story <<-EOS
|
5
|
+
As a user,
|
6
|
+
I want the stylesheet to work (even with Sinatra 0.9.1)
|
7
|
+
So that Integrity isn't a PITA to use
|
8
|
+
EOS
|
9
|
+
|
10
|
+
scenario "browsing on some Integrity install" do
|
11
|
+
visit "/integrity.css"
|
12
|
+
|
13
|
+
assert_contain("body {")
|
14
|
+
# TODO: better test
|
15
|
+
assert_equal %Q{"2465c472aacf302259dde5146a841e45"},
|
16
|
+
webrat_session.send(:response).headers["ETag"]
|
17
|
+
end
|
18
|
+
end
|
data/test/helpers.rb
CHANGED
@@ -1,38 +1,43 @@
|
|
1
|
-
|
1
|
+
$:.unshift File.dirname(__FILE__) + "/../lib", File.dirname(__FILE__),
|
2
|
+
File.dirname(__FILE__) + "/../vendor/webrat/lib"
|
3
|
+
|
4
|
+
%w(test/unit
|
5
|
+
context
|
6
|
+
pending
|
7
|
+
matchy
|
8
|
+
storyteller
|
9
|
+
webrat/sinatra
|
10
|
+
rr
|
11
|
+
mocha
|
12
|
+
test/zentest_assertions
|
13
|
+
dm-sweatshop).each { |dependency|
|
14
|
+
begin
|
15
|
+
require dependency
|
16
|
+
rescue LoadError
|
17
|
+
puts "You're missing some gems required to run the tests."
|
18
|
+
puts "Please run `rake test:install_dependencies`"
|
19
|
+
puts "You'll probably need to run that command as root or with sudo."
|
20
|
+
|
21
|
+
puts "Thanks :)"
|
22
|
+
puts
|
23
|
+
|
24
|
+
exit 1
|
25
|
+
end
|
26
|
+
}
|
2
27
|
|
3
28
|
begin
|
4
|
-
require "test/unit"
|
5
|
-
require "redgreen"
|
6
|
-
require "context"
|
7
|
-
require "storyteller"
|
8
|
-
require "pending"
|
9
|
-
require "matchy"
|
10
|
-
require "rr"
|
11
|
-
require "mocha"
|
12
29
|
require "ruby-debug"
|
30
|
+
require "redgreen"
|
13
31
|
rescue LoadError
|
14
|
-
puts "You're missing some gems required to run the tests."
|
15
|
-
puts "Please run `rake test:install_dependencies`"
|
16
|
-
puts "You'll probably need to run that command as root or with sudo."
|
17
|
-
puts
|
18
|
-
puts "Thanks :)"
|
19
|
-
puts
|
20
|
-
|
21
|
-
exit 1
|
22
32
|
end
|
23
33
|
|
24
|
-
require
|
25
|
-
require
|
26
|
-
require
|
34
|
+
require "integrity"
|
35
|
+
require "helpers/expectations"
|
36
|
+
require "helpers/fixtures"
|
27
37
|
|
28
38
|
module TestHelper
|
29
|
-
def setup_and_reset_database!
|
30
|
-
DataMapper.setup(:default, "sqlite3::memory:")
|
31
|
-
DataMapper.auto_migrate!
|
32
|
-
end
|
33
|
-
|
34
39
|
def ignore_logs!
|
35
|
-
|
40
|
+
Integrity.config[:log] = "/tmp/integrity.test.log"
|
36
41
|
end
|
37
42
|
end
|
38
43
|
|
@@ -44,5 +49,32 @@ class Test::Unit::TestCase
|
|
44
49
|
include RR::Adapters::TestUnit
|
45
50
|
include Integrity
|
46
51
|
include TestHelper
|
47
|
-
end
|
48
52
|
|
53
|
+
before(:all) do
|
54
|
+
DataMapper.setup(:default, "sqlite3::memory:")
|
55
|
+
end
|
56
|
+
|
57
|
+
before(:each) do
|
58
|
+
RR.reset
|
59
|
+
DataMapper.auto_migrate!
|
60
|
+
Integrity.instance_variable_set(:@config, nil)
|
61
|
+
Notifier.available.each { |n|
|
62
|
+
Notifier.send(:remove_const, n.to_s.split(":").last.to_sym)
|
63
|
+
}
|
64
|
+
|
65
|
+
repository(:default) do
|
66
|
+
transaction = DataMapper::Transaction.new(repository)
|
67
|
+
transaction.begin
|
68
|
+
repository.adapter.push_transaction(transaction)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
after(:each) do
|
73
|
+
repository(:default) do
|
74
|
+
while repository.adapter.current_transaction
|
75
|
+
repository.adapter.current_transaction.rollback
|
76
|
+
repository.adapter.pop_transaction
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/test/helpers/acceptance.rb
CHANGED
@@ -1,66 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require 'sinatra'
|
3
|
-
require 'sinatra/test'
|
4
|
-
|
5
|
-
disable :run
|
6
|
-
disable :reload
|
7
|
-
|
8
|
-
Webrat.configuration.instance_variable_set("@mode", :sinatra)
|
9
|
-
|
10
|
-
module Webrat
|
11
|
-
class SinatraSession < Session
|
12
|
-
DEFAULT_DOMAIN = "integrity.example.org"
|
13
|
-
|
14
|
-
def initialize(context = nil)
|
15
|
-
super(context)
|
16
|
-
@sinatra_test = Sinatra::TestHarness.new
|
17
|
-
end
|
18
|
-
|
19
|
-
%w(get head post put delete).each do |verb|
|
20
|
-
class_eval <<-METHOD
|
21
|
-
def #{verb}(path, data, headers = {})
|
22
|
-
params = data.inject({}) do |data, (key,value)|
|
23
|
-
data[key] = Rack::Utils.unescape(value)
|
24
|
-
data
|
25
|
-
end
|
26
|
-
headers['HTTP_HOST'] = DEFAULT_DOMAIN
|
27
|
-
@sinatra_test.#{verb}(path, params, headers)
|
28
|
-
end
|
29
|
-
METHOD
|
30
|
-
end
|
31
|
-
|
32
|
-
def response_body
|
33
|
-
@sinatra_test.body
|
34
|
-
end
|
35
|
-
|
36
|
-
def response_code
|
37
|
-
@sinatra_test.status
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def response
|
43
|
-
@sinatra_test.response
|
44
|
-
end
|
45
|
-
|
46
|
-
def current_host
|
47
|
-
URI.parse(current_url).host || DEFAULT_DOMAIN
|
48
|
-
end
|
49
|
-
|
50
|
-
def response_location_host
|
51
|
-
URI.parse(response_location).host || DEFAULT_DOMAIN
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
require Integrity.root / "app"
|
57
|
-
require File.dirname(__FILE__) / "acceptance/git_helper"
|
1
|
+
require "helpers/acceptance/git_helper"
|
58
2
|
|
59
3
|
module AcceptanceHelper
|
60
4
|
include FileUtils
|
61
5
|
|
62
6
|
def export_directory
|
63
|
-
|
7
|
+
File.dirname(__FILE__) + "/../../exports"
|
64
8
|
end
|
65
9
|
|
66
10
|
def enable_auth!
|
@@ -74,7 +18,7 @@ module AcceptanceHelper
|
|
74
18
|
def AcceptanceHelper.logged_in; true; end
|
75
19
|
basic_auth user, password
|
76
20
|
visit "/login"
|
77
|
-
|
21
|
+
Integrity::App.before { login_required if AcceptanceHelper.logged_in }
|
78
22
|
end
|
79
23
|
|
80
24
|
def log_out
|
@@ -93,9 +37,9 @@ module AcceptanceHelper
|
|
93
37
|
end
|
94
38
|
|
95
39
|
def setup_log!
|
96
|
-
|
97
|
-
|
98
|
-
Integrity.config[:log] =
|
40
|
+
log_file = Pathname(File.dirname(__FILE__) + "/../../integrity.log")
|
41
|
+
log_file.delete if log_file.exist?
|
42
|
+
Integrity.config[:log] = log_file
|
99
43
|
end
|
100
44
|
end
|
101
45
|
|
@@ -104,15 +48,25 @@ class Test::Unit::AcceptanceTestCase < Test::Unit::TestCase
|
|
104
48
|
include Test::Storyteller
|
105
49
|
include GitHelper
|
106
50
|
include Webrat::Methods
|
51
|
+
include Webrat::Matchers
|
52
|
+
include Webrat::HaveTagMatcher
|
53
|
+
|
54
|
+
# TODO: does this belongs in Webrat::SinatraSession?
|
107
55
|
Webrat::Methods.delegate_to_session :response_code
|
108
56
|
|
57
|
+
def app
|
58
|
+
Integrity::App.tap { |app|
|
59
|
+
app.set :environment, :test
|
60
|
+
app.disable :raise_errors, :run, :reload
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
109
64
|
before(:all) do
|
110
|
-
Integrity.config[:base_uri] = "http
|
65
|
+
Integrity.config[:base_uri] = "http://www.example.com"
|
111
66
|
end
|
112
67
|
|
113
68
|
before(:each) do
|
114
69
|
# ensure each scenario is run in a clean sandbox
|
115
|
-
setup_and_reset_database!
|
116
70
|
enable_auth!
|
117
71
|
setup_log!
|
118
72
|
set_and_create_export_directory!
|
@@ -123,4 +77,5 @@ class Test::Unit::AcceptanceTestCase < Test::Unit::TestCase
|
|
123
77
|
destroy_all_git_repos
|
124
78
|
rm_r export_directory if File.directory?(export_directory)
|
125
79
|
end
|
80
|
+
|
126
81
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'integrity'
|
3
|
+
|
4
|
+
module Integrity
|
5
|
+
class Notifier
|
6
|
+
class Email < Notifier::Base
|
7
|
+
attr_reader :to, :from
|
8
|
+
|
9
|
+
def self.to_haml
|
10
|
+
<<-EOF
|
11
|
+
%p.normal
|
12
|
+
%label{ :for => "email_notifier_to" } Send to
|
13
|
+
%input.text#email_notifier_to{ :name => "notifiers[Email][to]", :type => "text", :value => config["to"] }
|
14
|
+
|
15
|
+
%p.normal
|
16
|
+
%label{ :for => "email_notifier_from" } Send from
|
17
|
+
%input.text#email_notifier_from{ :name => "notifiers[Email][from]", :type => "text", :value => config["from"] }
|
18
|
+
|
19
|
+
%h3 SMTP Server Configuration
|
20
|
+
|
21
|
+
%p.normal
|
22
|
+
%label{ :for => "email_notifier_host" } Host : Port
|
23
|
+
= succeed " : " do
|
24
|
+
%input.text#email_notifier_host{ :name => "notifiers[Email][host]", :value => config["host"], :style => "width: 24.5em;", :type => "text" }
|
25
|
+
%input.text#email_notifier_port{ :name => "notifiers[Email][port]", :value => config["port"], :style => "width: 3.5em;", :type => "text" }
|
26
|
+
|
27
|
+
%p.normal
|
28
|
+
%label{ :for => "email_notifier_user" } User
|
29
|
+
%input.text#email_notifier_user{ :name => "notifiers[Email][user]", :value => config["user"], :type => "text" }
|
30
|
+
|
31
|
+
%p.normal
|
32
|
+
%label{ :for => "email_notifier_pass" } Password
|
33
|
+
%input.text#email_notifier_pass{ :name => "notifiers[Email][pass]", :value => config["pass"], :type => "text" }
|
34
|
+
|
35
|
+
%p.normal
|
36
|
+
%label{ :for => "email_notifier_auth" } Auth type
|
37
|
+
%input.text#email_notifier_auth{ :name => "notifiers[Email][auth]", :value => (config["auth"] || "plain"), :type => "text" }
|
38
|
+
|
39
|
+
%p.normal
|
40
|
+
%label{ :for => "email_notifier_domain" } Domain
|
41
|
+
%input.text#email_notifier_domain{ :name => "notifiers[Email][domain]", :value => config["domain"], :type => "text" }
|
42
|
+
EOF
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize(build, config={})
|
46
|
+
@to = config.delete("to")
|
47
|
+
@from = config.delete("from")
|
48
|
+
super
|
49
|
+
end
|
50
|
+
|
51
|
+
def deliver!
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -1,32 +1,32 @@
|
|
1
1
|
module GitHelper
|
2
2
|
@@_git_repositories = Hash.new {|h,k| h[k] = Repo.new(k) }
|
3
|
-
|
3
|
+
|
4
4
|
def git_repo(name)
|
5
5
|
@@_git_repositories[name]
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
def destroy_all_git_repos
|
9
9
|
@@_git_repositories.each {|n,r| r.destroy }
|
10
10
|
@@_git_repositories.clear
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
class Repo
|
14
14
|
attr_reader :path
|
15
|
-
|
15
|
+
|
16
16
|
def initialize(name)
|
17
17
|
@name = name
|
18
18
|
@path = "/tmp" / @name.to_s
|
19
19
|
create
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def path
|
23
23
|
@path / ".git"
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def create
|
27
27
|
destroy
|
28
28
|
FileUtils.mkdir_p @path
|
29
|
-
|
29
|
+
|
30
30
|
Dir.chdir(@path) do
|
31
31
|
system 'git init &>/dev/null'
|
32
32
|
system 'git config user.name "John Doe"'
|
@@ -35,7 +35,7 @@ module GitHelper
|
|
35
35
|
system 'git add README &>/dev/null'
|
36
36
|
system 'git commit -m "First commit" &>/dev/null'
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
add_successful_commit
|
40
40
|
end
|
41
41
|
|
@@ -43,7 +43,7 @@ module GitHelper
|
|
43
43
|
Dir.chdir(@path) do
|
44
44
|
commits = `git log --pretty=oneline`.collect { |line| line.split(" ").first }
|
45
45
|
commits.inject([]) do |commits, sha1|
|
46
|
-
format = %Q(---%n:message: >-%n %s%n:timestamp: %ci%n:id:
|
46
|
+
format = %Q(---%n:message: >-%n %s%n:timestamp: %ci%n:id: %H%n:author: %n :name: %an%n :email: %ae%n)
|
47
47
|
commits << YAML.load(`git show -s --pretty=format:"#{format}" #{sha1}`)
|
48
48
|
end
|
49
49
|
end
|
@@ -55,7 +55,7 @@ module GitHelper
|
|
55
55
|
system %Q(git commit -m "#{message}" &>/dev/null)
|
56
56
|
end
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
def add_failing_commit
|
60
60
|
add_commit "This commit will fail" do
|
61
61
|
system %Q(echo '#{build_script(false)}' > test)
|
@@ -71,23 +71,23 @@ module GitHelper
|
|
71
71
|
system %Q(git add test &>/dev/null)
|
72
72
|
end
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
def head
|
76
76
|
Dir.chdir(@path) do
|
77
77
|
`git log --pretty=format:%H | head -1`.chomp
|
78
78
|
end
|
79
79
|
end
|
80
|
-
|
80
|
+
|
81
81
|
def short_head
|
82
82
|
head[0..6]
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
def destroy
|
86
86
|
FileUtils.rm_rf @path if File.directory?(@path)
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
protected
|
90
|
-
|
90
|
+
|
91
91
|
def build_script(successful=true)
|
92
92
|
<<-script
|
93
93
|
#!/bin/sh
|
@@ -8,12 +8,12 @@ module Integrity
|
|
8
8
|
%input.text#textfile_notifier_file{ :name => "notifiers[Textfile][file]", :type => "text", :value => config["file"] }
|
9
9
|
haml
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def initialize(build, config={})
|
13
13
|
super
|
14
14
|
@file = @config["file"]
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
def deliver!
|
18
18
|
File.open(@file, "a") do |f|
|
19
19
|
f.puts "=== #{short_message} ==="
|
@@ -23,4 +23,4 @@ module Integrity
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
26
|
-
end
|
26
|
+
end
|