foca-integrity 0.1.8 → 0.1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|