Using cruisecontrol.rb with repositories without anonymous access

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:
  1. test/unit/subversion_test.rb
  2.  
  3. def test_svn_command_uses_user_password_when_provided
  4.     svn = Subversion.new(:username => 'jer', :password => "crap")
  5.  
  6.     svn.expects(:info).with(dummy_project).returns(Subversion::Info.new(10, 10))
  7.     svn.expects(:execute).with(["svn", "--non-interactive", "log", "--revision", "HEAD:10", "--verbose", "--xml",
  8.                                 "--username", "jer", "--password", "crap"],
  9.                                 {:stderr => './svn.err'}).yields(StringIO.new(LOG_ENTRY))
  10.  
  11.     svn.latest_revision(dummy_project)
  12. end
  13.  
  14. app/models/subversion.rb
  15.  
  16. def checkout(target_directory, revision = nil, stdout = $stdout)
  17.     @url or raise 'URL not specified'
  18.  
  19.     options = [@url, target_directory]
  20.     options <<"--revision" <<revision_number(revision) if revision
  21.  
  22.     # need to read from command output, because otherwise tests break
  23.     execute(svn('co', options)) do |io|
  24.     begin
  25.         while line = io.gets
  26.             stdout.puts line
  27.         end
  28.         rescue EOFError
  29.         end
  30.     end
  31. end
  32.  
  33. def svn(operation, *options)
  34.     command = ["svn"]
  35.     command <<"--non-interactive" unless @interactive
  36.     command <<operation
  37.     command += options.compact.flatten
  38.     command += ['--username', @username, '--password', @password] if @username and @password
  39.     command
  40. end

The username and password would then be injected into the project's Subversion instance in the cruise_config.rb file for each project.


RUBY:
  1. Project.configure do |project|
  2.     project.source_control.username = 'douglas'
  3.     project.source_control.password = 'guessable'
  4. end

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.

2 Comments