foca-integrity 0.1.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 +139 -0
- data/Rakefile +87 -0
- data/app.rb +247 -0
- data/bin/integrity +60 -0
- data/config/config.sample.ru +30 -0
- data/config/config.sample.yml +8 -0
- data/config/thin.sample.yml +14 -0
- data/integrity.gemspec +65 -0
- data/lib/integrity.rb +47 -0
- data/lib/integrity/build.rb +56 -0
- data/lib/integrity/builder.rb +42 -0
- data/lib/integrity/core_ext/object.rb +6 -0
- data/lib/integrity/core_ext/string.rb +5 -0
- data/lib/integrity/core_ext/time.rb +13 -0
- data/lib/integrity/notifier.rb +49 -0
- data/lib/integrity/notifier/base.rb +56 -0
- data/lib/integrity/project.rb +83 -0
- data/lib/integrity/scm.rb +22 -0
- data/lib/integrity/scm/git.rb +72 -0
- data/lib/integrity/scm/git/uri.rb +57 -0
- data/lib/integrity/version.rb +3 -0
- data/public/buttons.css +82 -0
- data/public/reset.css +7 -0
- data/public/spinner.gif +0 -0
- data/spec/form_field_matchers.rb +91 -0
- data/spec/spec_helper.rb +131 -0
- data/vendor/sinatra-hacks/lib/hacks.rb +49 -0
- data/views/build.haml +2 -0
- data/views/build_info.haml +22 -0
- data/views/home.haml +14 -0
- data/views/integrity.sass +361 -0
- data/views/layout.haml +25 -0
- data/views/new.haml +53 -0
- data/views/not_found.haml +31 -0
- data/views/notifier.haml +7 -0
- data/views/project.haml +32 -0
- data/views/unauthorized.haml +38 -0
- metadata +197 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
module Integrity
|
2
|
+
class Project
|
3
|
+
include DataMapper::Resource
|
4
|
+
|
5
|
+
property :id, Integer, :serial => true
|
6
|
+
property :name, String, :nullable => false
|
7
|
+
property :permalink, String
|
8
|
+
property :uri, URI, :nullable => false, :length => 255
|
9
|
+
property :branch, String, :nullable => false, :default => "master"
|
10
|
+
property :command, String, :nullable => false, :length => 255, :default => "rake"
|
11
|
+
property :public, Boolean, :default => true
|
12
|
+
property :building, Boolean, :default => false
|
13
|
+
property :created_at, DateTime
|
14
|
+
property :updated_at, DateTime
|
15
|
+
|
16
|
+
has n, :builds, :class_name => "Integrity::Build"
|
17
|
+
has n, :notifiers, :class_name => "Integrity::Notifier"
|
18
|
+
|
19
|
+
before :save, :set_permalink
|
20
|
+
before :destroy, :delete_code
|
21
|
+
|
22
|
+
validates_is_unique :name
|
23
|
+
|
24
|
+
def build(commit_identifier="HEAD")
|
25
|
+
return if building?
|
26
|
+
update_attributes(:building => true)
|
27
|
+
Builder.new(self).build(commit_identifier)
|
28
|
+
ensure
|
29
|
+
update_attributes(:building => false)
|
30
|
+
send_notifications
|
31
|
+
end
|
32
|
+
|
33
|
+
def last_build
|
34
|
+
builds.last
|
35
|
+
end
|
36
|
+
|
37
|
+
def previous_builds
|
38
|
+
return [] if builds.count <= 1
|
39
|
+
builds.all(:order => [:created_at.desc], :offset => 1, :limit => builds.count - 1)
|
40
|
+
end
|
41
|
+
|
42
|
+
def status
|
43
|
+
last_build && last_build.status
|
44
|
+
end
|
45
|
+
|
46
|
+
def public=(flag)
|
47
|
+
attribute_set(:public, !!flag)
|
48
|
+
end
|
49
|
+
|
50
|
+
def config_for(notifier)
|
51
|
+
notifier = notifiers.first(:name => notifier.to_s.split(/::/).last)
|
52
|
+
notifier.blank? ? {} : notifier.config
|
53
|
+
end
|
54
|
+
|
55
|
+
def notifies?(notifier)
|
56
|
+
!notifiers.first(:name => notifier.to_s.split(/::/).last).blank?
|
57
|
+
end
|
58
|
+
|
59
|
+
def enable_notifiers(*args)
|
60
|
+
Notifier.enable_notifiers(id, *args)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def set_permalink
|
65
|
+
self.permalink = (name || "").downcase.
|
66
|
+
gsub(/'s/, "s").
|
67
|
+
gsub(/&/, "and").
|
68
|
+
gsub(/[^a-z0-9]+/, "-").
|
69
|
+
gsub(/-*$/, "")
|
70
|
+
end
|
71
|
+
|
72
|
+
def delete_code
|
73
|
+
builds.destroy!
|
74
|
+
Builder.new(self).delete_code
|
75
|
+
end
|
76
|
+
|
77
|
+
def send_notifications
|
78
|
+
notifiers.each do |notifier|
|
79
|
+
notifier.notify_of_build last_build
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Integrity
|
2
|
+
module SCM
|
3
|
+
class SCMUnknownError < StandardError; end
|
4
|
+
|
5
|
+
def self.new(uri, *args)
|
6
|
+
scm_class_for(uri).new(uri, *args)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.working_tree_path(uri)
|
10
|
+
scm_class_for(uri).working_tree_path(uri)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def self.scm_class_for(string)
|
16
|
+
case string.to_s
|
17
|
+
when /\.git\/?/ then Git
|
18
|
+
else raise SCMUnknownError, "could not find any SCM based on string '#{string}'"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Integrity
|
2
|
+
module SCM
|
3
|
+
class Git
|
4
|
+
require File.dirname(__FILE__) / "git/uri"
|
5
|
+
|
6
|
+
attr_reader :uri, :branch, :working_directory
|
7
|
+
|
8
|
+
def self.working_tree_path(uri)
|
9
|
+
Git::URI.new(uri).working_tree_path
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(uri, branch, working_directory)
|
13
|
+
@uri = uri.to_s
|
14
|
+
@branch = branch.to_s
|
15
|
+
@working_directory = working_directory
|
16
|
+
end
|
17
|
+
|
18
|
+
def with_revision(revision)
|
19
|
+
fetch_code
|
20
|
+
checkout(revision)
|
21
|
+
yield
|
22
|
+
end
|
23
|
+
|
24
|
+
def commit_identifier(sha1)
|
25
|
+
`cd #{working_directory} && git show -s --pretty=format:%H #{sha1}`.chomp
|
26
|
+
end
|
27
|
+
|
28
|
+
def commit_metadata(sha1)
|
29
|
+
format = %Q(---%n:author: %an <%ae>%n:message: >-%n %s%n:date: %ci%n)
|
30
|
+
YAML.load(`cd #{working_directory} && git show -s --pretty=format:"#{format}" #{sha1}`)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def fetch_code
|
36
|
+
clone unless cloned?
|
37
|
+
checkout unless on_branch?
|
38
|
+
pull
|
39
|
+
end
|
40
|
+
|
41
|
+
def clone
|
42
|
+
`git clone #{uri} #{working_directory}`
|
43
|
+
end
|
44
|
+
|
45
|
+
def checkout(treeish=nil)
|
46
|
+
strategy = case
|
47
|
+
when treeish then treeish
|
48
|
+
when local_branches.include?(branch) then branch
|
49
|
+
else "-b #{branch} origin/#{branch}"
|
50
|
+
end
|
51
|
+
|
52
|
+
`cd #{working_directory} && git checkout #{strategy}`
|
53
|
+
end
|
54
|
+
|
55
|
+
def pull
|
56
|
+
`cd #{working_directory} && git pull`
|
57
|
+
end
|
58
|
+
|
59
|
+
def local_branches
|
60
|
+
`cd #{working_directory} && git branch`.split("\n").map {|b| b.delete("*").strip }
|
61
|
+
end
|
62
|
+
|
63
|
+
def cloned?
|
64
|
+
File.directory?(working_directory / ".git")
|
65
|
+
end
|
66
|
+
|
67
|
+
def on_branch?
|
68
|
+
File.basename(`cd #{working_directory} && git symbolic-ref HEAD`).chomp == branch
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Integrity
|
2
|
+
module SCM
|
3
|
+
class Git
|
4
|
+
# From the git-pull man page:
|
5
|
+
#
|
6
|
+
# GIT URLS
|
7
|
+
# One of the following notations can be used to name the remote repository:
|
8
|
+
#
|
9
|
+
# rsync://host.xz/path/to/repo.git/
|
10
|
+
# http://host.xz/path/to/repo.git/
|
11
|
+
# git://host.xz/~user/path/to/repo.git/
|
12
|
+
# ssh://[user@]host.xz[:port]/path/to/repo.git/
|
13
|
+
# ssh://[user@]host.xz/path/to/repo.git/
|
14
|
+
# ssh://[user@]host.xz/~user/path/to/repo.git/
|
15
|
+
# ssh://[user@]host.xz/~/path/to/repo.git
|
16
|
+
#
|
17
|
+
# SSH is the default transport protocol over the network. You can optionally
|
18
|
+
# specify which user to log-in as, and an alternate, scp-like syntax is also
|
19
|
+
# supported
|
20
|
+
#
|
21
|
+
# Both syntaxes support username expansion, as does the native git protocol,
|
22
|
+
# but only the former supports port specification. The following three are
|
23
|
+
# identical to the last three above, respectively:
|
24
|
+
#
|
25
|
+
# [user@]host.xz:/path/to/repo.git/
|
26
|
+
# [user@]host.xz:~user/path/to/repo.git/
|
27
|
+
# [user@]host.xz:path/to/repo.git
|
28
|
+
#
|
29
|
+
class URI
|
30
|
+
def initialize(uri_string)
|
31
|
+
@uri = Addressable::URI.parse(uri_string)
|
32
|
+
end
|
33
|
+
|
34
|
+
def working_tree_path
|
35
|
+
strip_extension(path).gsub("/", "-")
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def strip_extension(string)
|
41
|
+
uri = Pathname.new(string)
|
42
|
+
if uri.extname.any?
|
43
|
+
uri = Pathname.new(string)
|
44
|
+
string.gsub(Regexp.new("#{uri.extname}\/?"), "")
|
45
|
+
else
|
46
|
+
string
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def path
|
51
|
+
path = @uri.path
|
52
|
+
path.gsub(/\~[a-zA-Z0-9]*\//, "").gsub(/^\//, "")
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/public/buttons.css
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
/* --------------------------------------------------------------
|
2
|
+
|
3
|
+
buttons.css
|
4
|
+
* Gives you some great CSS-only buttons.
|
5
|
+
|
6
|
+
Created by Kevin Hale [particletree.com]
|
7
|
+
* particletree.com/features/rediscovering-the-button-element
|
8
|
+
|
9
|
+
See Readme.txt in this folder for instructions.
|
10
|
+
|
11
|
+
-------------------------------------------------------------- */
|
12
|
+
|
13
|
+
button {
|
14
|
+
display:block;
|
15
|
+
float:left;
|
16
|
+
margin:0 0.583em 0.667em 0;
|
17
|
+
padding:5px 10px 5px 7px; /* Links */
|
18
|
+
|
19
|
+
border:1px solid #dedede;
|
20
|
+
border-top:1px solid #eee;
|
21
|
+
border-left:1px solid #eee;
|
22
|
+
|
23
|
+
background-color:#f5f5f5;
|
24
|
+
font-family:"Lucida Grande", Tahoma, Arial, Verdana, sans-serif;
|
25
|
+
font-size:100%;
|
26
|
+
line-height:130%;
|
27
|
+
text-decoration:none;
|
28
|
+
font-weight:bold;
|
29
|
+
color:#565656;
|
30
|
+
cursor:pointer;
|
31
|
+
}
|
32
|
+
button {
|
33
|
+
width:auto;
|
34
|
+
overflow:visible;
|
35
|
+
padding:4px 10px 3px 7px; /* IE6 */
|
36
|
+
}
|
37
|
+
button[type] {
|
38
|
+
padding:4px 10px 4px 7px; /* Firefox */
|
39
|
+
line-height:17px; /* Safari */
|
40
|
+
}
|
41
|
+
*:first-child+html button[type] {
|
42
|
+
padding:4px 10px 3px 7px; /* IE7 */
|
43
|
+
}
|
44
|
+
button img {
|
45
|
+
margin:0 3px -3px 0 !important;
|
46
|
+
padding:0;
|
47
|
+
border:none;
|
48
|
+
width:16px;
|
49
|
+
height:16px;
|
50
|
+
float:none;
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
/* Button colors
|
55
|
+
-------------------------------------------------------------- */
|
56
|
+
|
57
|
+
/* Standard */
|
58
|
+
button:hover {
|
59
|
+
background-color:#dff4ff;
|
60
|
+
border:1px solid #c2e1ef;
|
61
|
+
color:#336699;
|
62
|
+
}
|
63
|
+
|
64
|
+
/* Positive */
|
65
|
+
body .positive {
|
66
|
+
color:#529214;
|
67
|
+
}
|
68
|
+
button.positive:hover {
|
69
|
+
background-color:#E6EFC2;
|
70
|
+
border:1px solid #C6D880;
|
71
|
+
color:#529214;
|
72
|
+
}
|
73
|
+
|
74
|
+
/* Negative */
|
75
|
+
body .negative {
|
76
|
+
color:#d12f19;
|
77
|
+
}
|
78
|
+
button.negative:hover {
|
79
|
+
background:#fbe3e4;
|
80
|
+
border:1px solid #fbc2c4;
|
81
|
+
color:#d12f19;
|
82
|
+
}
|
data/public/reset.css
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
/*
|
2
|
+
Copyright (c) 2008, Yahoo! Inc. All rights reserved.
|
3
|
+
Code licensed under the BSD License:
|
4
|
+
http://developer.yahoo.net/yui/license.txt
|
5
|
+
version: 2.5.2
|
6
|
+
*/
|
7
|
+
html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym {border:0;font-variant:normal;}sup {vertical-align:text-top;}sub {vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}
|
data/public/spinner.gif
ADDED
Binary file
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module FormFieldHpricotMatchers
|
2
|
+
# TODO: Add support for selects
|
3
|
+
class HaveField
|
4
|
+
include RspecHpricotMatchers
|
5
|
+
|
6
|
+
def initialize(id, type, tagname)
|
7
|
+
@tagname = tagname
|
8
|
+
@type = type
|
9
|
+
@id = id
|
10
|
+
@tag_matcher = have_tag("#{@tagname}##{@id}", @tagname == "textarea" ? @value : nil)
|
11
|
+
@label_set = true # always check for a label, unless explicitly told not to
|
12
|
+
end
|
13
|
+
|
14
|
+
def named(name)
|
15
|
+
@name_set = true
|
16
|
+
@name = name
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def with_label(label)
|
21
|
+
@label = label
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def without_label
|
26
|
+
@label_set = false
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def with_value(value)
|
31
|
+
@value_set = true
|
32
|
+
@value = value
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def checked
|
37
|
+
@checked = "checked"
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def unchecked
|
42
|
+
@checked = ""
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
def matches?(actual)
|
47
|
+
(@label_set ? have_tag("label[@for=#{@id}]", @label).matches?(actual) : true) &&
|
48
|
+
@tag_matcher.matches?(actual) do |field|
|
49
|
+
field["type"].should == @type if @type
|
50
|
+
field["name"].should == @name if @name_set
|
51
|
+
field["value"].should == @value if @value_set && @tagname == "input"
|
52
|
+
field["checked"].should == @checked if @checked
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def failure_message
|
57
|
+
attrs = [
|
58
|
+
"id ##{@id}",
|
59
|
+
@name && "name '#{@name}'",
|
60
|
+
@type && "type '#{@type}'",
|
61
|
+
@label && "labelled '#{@label}'",
|
62
|
+
@value && "value '#{@value}'"
|
63
|
+
].compact.join(", ")
|
64
|
+
"You expected a #{@tagname}#{@type ? " (#{@type})" : ""} with #{attrs} but found none.\n\n#{@tag_matcher.failure_message}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def have_field(id, type="text", tagname="input")
|
69
|
+
HaveField.new(id, type, tagname)
|
70
|
+
end
|
71
|
+
|
72
|
+
def have_textfield(id)
|
73
|
+
have_field(id)
|
74
|
+
end
|
75
|
+
|
76
|
+
def have_password(id)
|
77
|
+
have_field(id, "password")
|
78
|
+
end
|
79
|
+
|
80
|
+
def have_checkbox(id)
|
81
|
+
have_field(id, "checkbox")
|
82
|
+
end
|
83
|
+
|
84
|
+
def have_radio(id)
|
85
|
+
have_field(id, "radio")
|
86
|
+
end
|
87
|
+
|
88
|
+
def have_textarea(id)
|
89
|
+
have_field(id, nil, "textarea")
|
90
|
+
end
|
91
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../lib/integrity'
|
2
|
+
require 'spec'
|
3
|
+
|
4
|
+
module NotifierSpecHelper
|
5
|
+
def self.included(mod)
|
6
|
+
mod.before(:each) { Integrity.stub!(:config).and_return(:base_uri => "http://localhost:4567") }
|
7
|
+
end
|
8
|
+
|
9
|
+
class Integrity::Notifier::Stub < Integrity::Notifier::Base
|
10
|
+
def self.to_haml
|
11
|
+
""
|
12
|
+
end
|
13
|
+
|
14
|
+
def deliver!
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def mock_build(messages={})
|
20
|
+
messages = {
|
21
|
+
:project => stub("project", :name => "Integrity", :permalink => "integrity"),
|
22
|
+
:commit_identifier => "e7e02bc669d07064cdbc7e7508a21a41e040e70d",
|
23
|
+
:short_commit_identifier => "e7e02b",
|
24
|
+
:status => :success,
|
25
|
+
:successful? => true,
|
26
|
+
:commit_message => "the commit message",
|
27
|
+
:commit_author => stub("author", :name => "Nicolás Sanguinetti"),
|
28
|
+
:commited_at => Time.mktime(2008, 07, 25, 18, 44),
|
29
|
+
:output => "the output \e[31mwith color coding\e[0m"
|
30
|
+
}.merge(messages)
|
31
|
+
@build ||= stub("build", messages)
|
32
|
+
end
|
33
|
+
|
34
|
+
def notifier_config(overrides={})
|
35
|
+
@config ||= overrides
|
36
|
+
end
|
37
|
+
|
38
|
+
def notifier
|
39
|
+
@notifier ||= stub("notifier", :method_missing => nil)
|
40
|
+
end
|
41
|
+
|
42
|
+
def the_form(locals = {})
|
43
|
+
locals = { :config => {} }.merge(locals)
|
44
|
+
require 'haml'
|
45
|
+
@form ||= Haml::Engine.new(klass.to_haml).render(self, locals)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "A notifier", :shared => true do
|
50
|
+
it "should have a `notify_of_build' class method" do
|
51
|
+
klass.should respond_to(:notify_of_build)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should have a `to_haml' class method" do
|
55
|
+
klass.should respond_to(:to_haml)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
module DatabaseSpecHelper
|
60
|
+
def self.included(mod)
|
61
|
+
mod.before(:each) { setup_database! }
|
62
|
+
end
|
63
|
+
|
64
|
+
def setup_database!
|
65
|
+
DataMapper.setup(:default, 'sqlite3::memory:')
|
66
|
+
Integrity::Project.auto_migrate!
|
67
|
+
Integrity::Build.auto_migrate!
|
68
|
+
Integrity::Notifier.auto_migrate!
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
module AppSpecHelper
|
73
|
+
def self.included(mod)
|
74
|
+
require 'rspec_hpricot_matchers'
|
75
|
+
require Integrity.root / 'spec/form_field_matchers'
|
76
|
+
|
77
|
+
mod.send(:include, DatabaseSpecHelper)
|
78
|
+
mod.send(:include, RspecHpricotMatchers)
|
79
|
+
mod.send(:include, FormFieldHpricotMatchers)
|
80
|
+
end
|
81
|
+
|
82
|
+
def mock_project(messages={})
|
83
|
+
messages = {
|
84
|
+
:name => "Integrity",
|
85
|
+
:permalink => "integrity",
|
86
|
+
:new_record? => false,
|
87
|
+
:uri => "git://github.com/foca/integrity.git",
|
88
|
+
:branch => "master",
|
89
|
+
:command => "rake",
|
90
|
+
:public? => true,
|
91
|
+
:builds => [],
|
92
|
+
:config_for => {},
|
93
|
+
:build => nil,
|
94
|
+
:update_attributes => true,
|
95
|
+
:save => true,
|
96
|
+
:destroy => nil,
|
97
|
+
:errors => stub("errors", :on => nil),
|
98
|
+
:notifies? => false,
|
99
|
+
:enable_notifiers => nil
|
100
|
+
}.merge(messages)
|
101
|
+
|
102
|
+
@project ||= stub("project", messages)
|
103
|
+
end
|
104
|
+
|
105
|
+
def mock_build(messages={})
|
106
|
+
messages = {
|
107
|
+
:status => :success,
|
108
|
+
:successful? => true,
|
109
|
+
:output => 'output',
|
110
|
+
:project => @project,
|
111
|
+
:commit_identifier => '9f6302002d2259c05a64767e0dedb15d280a4848',
|
112
|
+
:commit_author => mock("author",
|
113
|
+
:name => 'Nicolás Sanguinetti',
|
114
|
+
:email => 'contacto@nicolassanguinetti.info',
|
115
|
+
:full =>'Nicolás Sanguinetti <contacto@nicolassanguinetti.info>'
|
116
|
+
),
|
117
|
+
:commited_at => Time.mktime(2008, 7, 24, 17, 15),
|
118
|
+
:commit_message => "Add Object#tap for versions of ruby that don't have it"
|
119
|
+
}.merge(messages)
|
120
|
+
messages[:short_commit_identifier] = messages[:commit_identifier][0..5]
|
121
|
+
mock('build', messages)
|
122
|
+
end
|
123
|
+
|
124
|
+
def disable_basic_auth!
|
125
|
+
Integrity.stub!(:config).and_return(:use_basic_auth => false)
|
126
|
+
end
|
127
|
+
|
128
|
+
def enable_basic_auth!
|
129
|
+
Integrity.stub!(:config).and_return(:use_basic_auth => true, :admin_username => 'user', :admin_password => 'pass')
|
130
|
+
end
|
131
|
+
end
|