I decided to use cruisecontrol.rb for continuous integration of an application that I’m working on at Bezurk. So I downloaded the 1.2.1 release from RubyForge and proceeded to add the project repository to the local installation of cruisecontrol.rb.
douglas@macbookpro:~$ ./cruise add MyProject --url http://path.to/repository --username 'douglas' --password 'guessable'
douglas@macbookpro:~$ ./cruise build MyProject
Builder for project 'MyProject' started
Logging to: /Users/douglas/Development/Ruby/cruisecontrolrb-1.2.1/log/MyProject_builder.log
Build loop failed
BuilderError: svn: PROPFIND request failed on '/svn/my_project/trunk'
./script/../config/../app/models/subversion.rb:98:in `execute_in_local_copy'
./script/../config/../lib/command_line.rb:86:in `call'
./script/../config/../lib/command_line.rb:86:in `e'
./script/../config/../lib/command_line.rb:84:in `popen'
./script/../config/../lib/command_line.rb:84:in `e'
./script/../config/../lib/command_line.rb:71:in `execute'
./script/../config/../lib/command_line.rb:70:in `chdir'
./script/../config/../lib/command_line.rb:70:in `execute'
./script/../config/../app/models/subversion.rb:89:in `execute_in_local_copy'
./script/../config/../app/models/subversion.rb:85:in `chdir'
./script/../config/../app/models/subversion.rb:85:in `execute_in_local_copy'
./script/../config/../app/models/subversion.rb:44:in `latest_revision'
./script/../config/../app/models/project.rb:228:in `new_revisions'
./script/../config/../app/models/change_in_source_control_trigger.rb:8:in `revisions_to_build'
./script/../config/../vendor/rails/actionpack/lib/../../activesupport/lib/active_support/core_ext/symbol.rb:10:in `__send__'
./script/../config/../vendor/rails/actionpack/lib/../../activesupport/lib/active_support/core_ext/symbol.rb:10:in `to_proc'
./script/../config/../app/models/project.rb:223:in `collect'
./script/../config/../app/models/project.rb:223:in `revisions_to_build'
./script/../config/../app/models/project.rb:202:in `build_if_necessary'
./script/../config/../app/models/polling_scheduler.rb:13:in `run'
./script/builder:79
./script/builder:78:in `catch'
./script/builder:78
./cruise:14:in `load'
./cruise:14:in `builder'
./cruise:68:in `send'
./cruise:68
/opt/local/lib/ruby/1.8/fileutils.rb:121:in `chdir'
/opt/local/lib/ruby/1.8/fileutils.rb:121:in `cd'
./cruise:67
Hmm, what’s with the svn: PROPFIND error? Looking at the stracktrace doesn’t tell me alot about what’s going wrong here, let’s try logging errors to the console.
--SNIP--
douglas$ svn --non-interactive info --xml
douglas$ svn --non-interactive log --revision HEAD:20 --verbose --xml
svn: PROPFIND request failed on '/repository/trunk'
svn: PROPFIND of '/repository/trunk': authorization failed (http://svnhost.com)
--SNIP--
It happens that my repository does not have anonymous access and requires a subversion user account to do anything useful. So it should be obvious that cruisecontrol.rb is trying to get log info from the repository but subversion is quitting with authentication errors because no user credentials are being supplied.
I need to have cruisecontrol.rb make use of the –username and –password options when making queries to the repository when I give it the credentials for access.
My first stop is the app/models/subversion.rb. Only the checkout method uses the username and password instance variables. Subversion should only include the –username and –password options when executing svn commands when both the username and password instance variables are present.
[ruby]
test/unit/subversion_test.rb
def test_svn_command_uses_user_password_when_provided
svn = Subversion.new(:username => 'jer', :password => "crap")
svn.expects(:info).with(dummy_project).returns(Subversion::Info.new(10, 10))
svn.expects(:execute).with(["svn", "--non-interactive", "log", "--revision", "HEAD:10", "--verbose", "--xml",
"--username", "jer", "--password", "crap"],
{:stderr => './svn.err'}).yields(StringIO.new(LOG_ENTRY))
svn.latest_revision(dummy_project)
end
app/models/subversion.rb
def checkout(target_directory, revision = nil, stdout = $stdout)
@url or raise 'URL not specified'
options = [@url, target_directory]
options < < "--revision" << revision_number(revision) if revision
# need to read from command output, because otherwise tests break
execute(svn('co', options)) do |io|
begin
while line = io.gets
stdout.puts line
end
rescue EOFError
end
end
end
def svn(operation, *options)
command = ["svn"]
command << "--non-interactive" unless @interactive
command << operation
command += options.compact.flatten
command += ['--username', @username, '--password', @password] if @username and @password
command
end
[/ruby]
The username and password would then be injected into the project's Subversion instance in the cruise_config.rb file for each project.
[ruby]
Project.configure do |project|
project.source_control.username = 'douglas'
project.source_control.password = 'guessable'
end
[/ruby]
I’ve submitted a ticket along with a patch for this on cruisecontrol.rb’s tracker. Keep a lookout for it if you happen to encounter the same problem.