hudson 0.2.4 → 0.2.5.pre2
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.md +85 -0
- data/Rakefile +120 -0
- data/bin/hudson +4 -55
- data/features/create_jobs.feature +22 -0
- data/features/development.feature +14 -0
- data/features/fixtures/projects/ruby/Rakefile +4 -0
- data/features/managing_remote_servers.feature +31 -0
- data/features/server.feature +16 -0
- data/features/step_definitions/common_steps.rb +181 -0
- data/features/step_definitions/fixture_project_steps.rb +8 -0
- data/features/step_definitions/hudson_steps.rb +71 -0
- data/features/step_definitions/scm_steps.rb +10 -0
- data/features/support/common.rb +29 -0
- data/features/support/env.rb +16 -0
- data/features/support/hooks.rb +16 -0
- data/features/support/matchers.rb +12 -0
- data/hudson.gemspec +57 -0
- data/lib/hudson/api.rb +43 -0
- data/lib/hudson/cli/formatting.rb +53 -0
- data/lib/hudson/cli.rb +141 -0
- data/lib/hudson/hudson.war +0 -0
- data/lib/hudson/job_config_builder.rb +161 -0
- data/lib/hudson/project_scm.rb +22 -0
- data/lib/hudson.rb +9 -5
- data/spec/fixtures/ec2_global.config.xml +103 -0
- data/spec/fixtures/rails.multi.config.xml +88 -0
- data/spec/fixtures/rails.single.config.xml +82 -0
- data/spec/fixtures/rubygem.config.xml +60 -0
- data/spec/fixtures/therubyracer.config.xml +77 -0
- data/spec/job_config_builder_spec.rb +30 -0
- data/spec/spec_helper.rb +19 -0
- metadata +190 -15
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
Hudson
|
2
|
+
======
|
3
|
+
|
4
|
+
Hudson is a sweet CI server. Hudson.rb makes it easy
|
5
|
+
to run ruby builds by bundling all the ruby-centric plugins
|
6
|
+
(ruby, rake, git, github) and wrapping them in a super simple
|
7
|
+
executeable.
|
8
|
+
|
9
|
+
Install
|
10
|
+
=======
|
11
|
+
|
12
|
+
gem install hudson
|
13
|
+
gem install hudson --pre (bleeding edge)
|
14
|
+
|
15
|
+
Example
|
16
|
+
=======
|
17
|
+
|
18
|
+
Hudson.rb is continuously tested using Hudson at [http://hudson.thefrontside.net/job/hudson.rb/](http://hudson.thefrontside.net/job/hudson.rb/).
|
19
|
+
|
20
|
+
The `hudson` application allows you to see the projects/jobs and their statuses:
|
21
|
+
|
22
|
+
$ hudson list --host hudson.thefrontside.net --port 80
|
23
|
+
hudson.rb - http://hudson.thefrontside.net/job/hudson.rb/
|
24
|
+
TheRubyRacer - http://hudson.thefrontside.net/job/TheRubyRacer/
|
25
|
+
|
26
|
+
# alternately use environment variables
|
27
|
+
$ HUDSON_HOST=hudson.thefrontside.net HUDSON_PORT=80 hudson list
|
28
|
+
|
29
|
+
Usage
|
30
|
+
=====
|
31
|
+
|
32
|
+
To run Hudson server:
|
33
|
+
|
34
|
+
Usage: hudson server [HUDSON_HOME] [options]
|
35
|
+
-d, --daemon fork into background and run as daemon
|
36
|
+
-p, --port [3001] run hudson on specified port
|
37
|
+
-c, --control-port [3002] set the shutdown/control port
|
38
|
+
-k, --kill send shutdown signal to control port
|
39
|
+
-v, --version show version information
|
40
|
+
-h, --help
|
41
|
+
|
42
|
+
Note: HUDSON_HOME defaults to ~/.hudson
|
43
|
+
|
44
|
+
To list Jobs/Projects on a Hudson server:
|
45
|
+
|
46
|
+
Usage: hudson list [project_path] [options]
|
47
|
+
-p, --port [3001] find hudson on specified port
|
48
|
+
--host [localhost] find hudson on specified host
|
49
|
+
-h, --help
|
50
|
+
|
51
|
+
To add Project (create a Job) on a Hudson server:
|
52
|
+
|
53
|
+
Usage: hudson create [project_path] [options]
|
54
|
+
-n, --name [dir_name] name of hudson job
|
55
|
+
-p, --port [3001] find hudson on specified port
|
56
|
+
--host [localhost] find hudson on specified host
|
57
|
+
-h, --help
|
58
|
+
|
59
|
+
For all commands, if flags for `host:port` are not provided, it will use `$HUDSON_HOST` and `$HUDSON_PORT` if available.
|
60
|
+
|
61
|
+
License
|
62
|
+
=======
|
63
|
+
|
64
|
+
(The MIT License)
|
65
|
+
|
66
|
+
Copyright (c) 2010 Charles Lowell, cowboyd@thefrontside.net
|
67
|
+
|
68
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
69
|
+
a copy of this software and associated documentation files (the
|
70
|
+
'Software'), to deal in the Software without restriction, including
|
71
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
72
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
73
|
+
permit persons to whom the Software is furnished to do so, subject to
|
74
|
+
the following conditions:
|
75
|
+
|
76
|
+
The above copyright notice and this permission notice shall be
|
77
|
+
included in all copies or substantial portions of the Software.
|
78
|
+
|
79
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
80
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
81
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
82
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
83
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
84
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
85
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
$:.unshift('lib')
|
2
|
+
require 'hudson'
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
$gemspec = s
|
7
|
+
s.name = s.rubyforge_project = "hudson"
|
8
|
+
s.version = Hudson::VERSION
|
9
|
+
s.summary = "Painless Continuous Integration with Hudson Server"
|
10
|
+
s.description = "A suite of utilities for bringing continous integration to your projects (not the other way around) with hudson CI"
|
11
|
+
s.email = ["cowboyd@thefrontside.net", "drnicwilliams@gmail.com"]
|
12
|
+
s.homepage = "http://github.com/cowboyd/hudson.rb"
|
13
|
+
s.authors = ["Charles Lowell", "Dr Nic Williams"]
|
14
|
+
s.executables = ["hudson"]
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
s.files = Rake::FileList.new("**/*").tap do |manifest|
|
17
|
+
manifest.exclude "tmp", "**/*.gem"
|
18
|
+
end.to_a
|
19
|
+
s.add_dependency("term-ansicolor", [">= 1.0.4"])
|
20
|
+
s.add_dependency("yajl-ruby", [">= 0.7.6"])
|
21
|
+
s.add_dependency("httparty", ["~> 0.5.2"])
|
22
|
+
s.add_dependency("builder", ["~> 2.1.2"])
|
23
|
+
s.add_dependency("thor", ["~> 0.13.6"])
|
24
|
+
s.add_dependency("hpricot")
|
25
|
+
s.add_development_dependency("cucumber", ["~> 0.7.3"])
|
26
|
+
s.add_development_dependency("rspec", ["~> 1.3.0"])
|
27
|
+
s.add_development_dependency("json", ["~>1.4.0"])
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Build gem"
|
31
|
+
task :gem => :gemspec do
|
32
|
+
Gem::Builder.new($gemspec).build
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Build gemspec"
|
36
|
+
task :gemspec => :clean do
|
37
|
+
File.open("#{$gemspec.name}.gemspec", "w") do |f|
|
38
|
+
f.write($gemspec.to_ruby)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "Clean up"
|
43
|
+
task :clean do
|
44
|
+
sh "rm -rf *.gem"
|
45
|
+
end
|
46
|
+
|
47
|
+
namespace :cucumber do
|
48
|
+
require 'cucumber/rake/task'
|
49
|
+
Cucumber::Rake::Task.new(:wip, 'Run features that are being worked on') do |t|
|
50
|
+
t.cucumber_opts = "--tags @wip"
|
51
|
+
end
|
52
|
+
Cucumber::Rake::Task.new(:ok, 'Run features that should be working') do |t|
|
53
|
+
t.cucumber_opts = "--tags ~@wip"
|
54
|
+
end
|
55
|
+
task :all => [:ok, :wip]
|
56
|
+
end
|
57
|
+
|
58
|
+
desc 'Alias for cucumber:ok'
|
59
|
+
task :cucumber => 'cucumber:ok'
|
60
|
+
|
61
|
+
desc "Start test server; Run cucumber:ok; Kill Test Server;"
|
62
|
+
task :default => ["hudson:server:killtest", "hudson:server:test"] do
|
63
|
+
require 'socket'
|
64
|
+
print "waiting for at most 30 seconds for the server to start"
|
65
|
+
tries = 1
|
66
|
+
begin
|
67
|
+
print "."; $stdout.flush
|
68
|
+
tries += 1
|
69
|
+
Net::HTTP.start("localhost", "3010") { |http| http.get('/') }
|
70
|
+
sleep(10)
|
71
|
+
puts ""
|
72
|
+
Rake::Task["cucumber:ok"].invoke
|
73
|
+
rescue Exception => e
|
74
|
+
if tries <= 15
|
75
|
+
sleep 2
|
76
|
+
retry
|
77
|
+
end
|
78
|
+
raise
|
79
|
+
ensure
|
80
|
+
Rake::Task["hudson:server:killtest"].tap do |task|
|
81
|
+
task.reenable
|
82
|
+
task.invoke
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
namespace :hudson do
|
88
|
+
namespace :server do
|
89
|
+
require 'fileutils'
|
90
|
+
|
91
|
+
desc "Run a server for tests"
|
92
|
+
task :test do
|
93
|
+
port = 3010
|
94
|
+
control = 3011
|
95
|
+
|
96
|
+
FileUtils.chdir(File.dirname(__FILE__)) do
|
97
|
+
logfile = File.join("/tmp", "test_hudson.log")
|
98
|
+
puts "Launching hudson test server at http://localhost:#{port}..."
|
99
|
+
puts " output will be logged to #{logfile}"
|
100
|
+
`ruby bin/hudson server --home /tmp/test_hudson --port #{port} --control #{control} --daemon --logfile #{logfile}`
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
desc "Kill hudson test server if it is running."
|
105
|
+
task :killtest do
|
106
|
+
FileUtils.chdir(File.dirname(__FILE__)) do
|
107
|
+
puts "Killing any running server processes..."
|
108
|
+
`ruby bin/hudson server --control 3011 --kill 2>/dev/null`
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
desc "Grab the latest hudson.war from hudson-ci.org"
|
113
|
+
task :getwar do
|
114
|
+
sh "cd lib/hudson && rm hudson.war && wget http://hudson-ci.org/latest/hudson.war"
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
|
data/bin/hudson
CHANGED
@@ -1,58 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
$:.unshift(File.expand_path(File.dirname(File.dirname(__FILE__) + "/../lib/hudson.rb")))
|
2
4
|
require File.dirname(__FILE__) + '/../lib/hudson'
|
3
|
-
require '
|
4
|
-
require 'optparse'
|
5
|
-
|
6
|
-
|
7
|
-
options = {
|
8
|
-
:port => 3001,
|
9
|
-
:control => 3002,
|
10
|
-
:home => File.join(ENV['HOME'], '.hudson')
|
11
|
-
}
|
12
|
-
args = ARGV.dup
|
13
|
-
|
14
|
-
opts = OptionParser.new do |opts|
|
15
|
-
opts.banner = "Usage: hudson [options] [HUDSON_HOME]"
|
16
|
-
|
17
|
-
opts.on("-d", "--daemon", "fork into background and run as daemon") do
|
18
|
-
options[:daemon] = true
|
19
|
-
end
|
20
|
-
|
21
|
-
opts.on("-p", "--port [3001]", "run hudson on specified port ") do |port|
|
22
|
-
options[:port] = port
|
23
|
-
end
|
24
|
-
|
25
|
-
opts.on("-c", "--control-port [3002]", Integer, "set the shutdown/control port") do |port|
|
26
|
-
options[:control] = cport
|
27
|
-
end
|
28
|
-
|
29
|
-
opts.on_tail("-k", "--kill", "send shutdown signal to control port") do
|
30
|
-
require 'socket'
|
31
|
-
TCPSocket.open("localhost", options[:control]) do |sock|
|
32
|
-
sock.write("0")
|
33
|
-
end
|
34
|
-
exit
|
35
|
-
end
|
36
|
-
|
37
|
-
opts.on_tail("-v", "--version", "show version information") do
|
38
|
-
puts "#{Hudson::VERSION} (Hudson Server #{Hudson::HUDSON_VERSION})"
|
39
|
-
exit
|
40
|
-
end
|
41
|
-
opts.on_tail("-h", "--help") do
|
42
|
-
puts opts
|
43
|
-
exit
|
44
|
-
end
|
45
|
-
|
46
|
-
end
|
47
|
-
opts.parse!(args)
|
48
|
-
dir = args.shift || options[:home]
|
49
|
-
FileUtils.mkdir_p dir
|
50
|
-
FileUtils.cp_r Hudson::PLUGINS, dir
|
51
|
-
ENV['HUDSON_HOME'] = dir
|
52
|
-
cmd = ["java", "-jar", Hudson::WAR]
|
53
|
-
cmd << "--httpPort=#{options[:port]}"
|
54
|
-
cmd << "--controlPort=#{options[:control]}"
|
55
|
-
cmd << "--daemon" if options[:daemon]
|
56
|
-
puts cmd.join(" ")
|
57
|
-
exec(*cmd)
|
5
|
+
require 'hudson/cli'
|
58
6
|
|
7
|
+
Hudson::CLI.start
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Feature: Create jobs
|
2
|
+
In order to reduce cost of getting a new project up onto Hudson
|
3
|
+
As a project developer
|
4
|
+
I want to add a new project to Hudson as a job
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given I have a Hudson server running
|
8
|
+
And the Hudson server has no current jobs
|
9
|
+
|
10
|
+
Scenario: Discover Ruby project, on git scm, and create job
|
11
|
+
Given I am in the "ruby" project folder
|
12
|
+
And the project uses "git" scm
|
13
|
+
When I run local executable "hudson" with arguments "create . --host localhost --port 3010"
|
14
|
+
Then I should see "Added project 'ruby' to Hudson."
|
15
|
+
Then I should see "http://localhost:3010/job/ruby/build"
|
16
|
+
When I run local executable "hudson" with arguments "list --host localhost --port 3010"
|
17
|
+
Then I should see "ruby"
|
18
|
+
|
19
|
+
Scenario: Attempt to create project without scm
|
20
|
+
Given I am in the "ruby" project folder
|
21
|
+
When I run local executable "hudson" with arguments "create . --host localhost --port 3010"
|
22
|
+
Then I should see "Cannot determine project SCM. Currently supported:"
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Feature: Development processes of hudson itself (rake tasks)
|
2
|
+
|
3
|
+
As a Newgem maintainer or contributor
|
4
|
+
I want rake tasks to maintain and release the gem
|
5
|
+
So that I can spend time on the tests and code, and not excessive time on maintenance processes
|
6
|
+
|
7
|
+
Scenario: Generate RubyGem
|
8
|
+
Given this project is active project folder
|
9
|
+
When I invoke task "rake clean" so that I start with nothing
|
10
|
+
And I invoke task "rake gem"
|
11
|
+
Then file with name matching "hudson-*.gem" is created
|
12
|
+
And file with name matching "hudson.gemspec" is created
|
13
|
+
And the file "hudson.gemspec" is a valid gemspec
|
14
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
@wip
|
2
|
+
Feature: Managing remote servers
|
3
|
+
In order to reduce cost of referencing remote servers by explicit --host/--port options
|
4
|
+
As a user
|
5
|
+
I want a directory of remote servers I frequently use
|
6
|
+
|
7
|
+
Background:
|
8
|
+
Given I have a Hudson server running
|
9
|
+
And the Hudson server has no current jobs
|
10
|
+
|
11
|
+
Scenario: No remote servers
|
12
|
+
When I run local executable "hudson" with arguments "list"
|
13
|
+
Then I should see "Either use --host or add remote servers."
|
14
|
+
|
15
|
+
Scenario: Add a remote server
|
16
|
+
When I run local executable "hudson" with arguments "remotes add --host localhost --port 3010"
|
17
|
+
And I run local executable "hudson" with arguments "remotes add --host localhost --port 3011"
|
18
|
+
And I run local executable "hudson" with arguments "list"
|
19
|
+
Then I should not see "Either use --host or add remote servers."
|
20
|
+
And I should see "localhost:3010 -"
|
21
|
+
And I should see "No jobs"
|
22
|
+
And I should see "localhost:3011 - no connection"
|
23
|
+
|
24
|
+
Scenario: Add a remote server and access by abbreviation
|
25
|
+
When I run local executable "hudson" with arguments "remotes add --host localhost --port 3010"
|
26
|
+
When I run local executable "hudson" with arguments "remotes add --host another.server"
|
27
|
+
And I run local executable "hudson" with arguments "list --server local"
|
28
|
+
And I should see "localhost:3010 -"
|
29
|
+
And I should see "No jobs"
|
30
|
+
And I should not see "another.server"
|
31
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Feature: Running a Hudson Server
|
2
|
+
As a hudson server administrator
|
3
|
+
I want to be able to easily control a hudson server
|
4
|
+
In order to spend my time on how the process operates, not how to start stop and control it.
|
5
|
+
|
6
|
+
Scenario: Start a Hudson Server
|
7
|
+
Given env variable $HOME set to project path "home"
|
8
|
+
And "home/.hudson" folder is deleted
|
9
|
+
And there is nothing listening on port 5001
|
10
|
+
And there is nothing listening on port 5002
|
11
|
+
And I cleanup any hudson processes with control port 5002
|
12
|
+
When I run hudson server with arguments "--port 5001 --control 5002 --daemon --logfile=server.log"
|
13
|
+
Then I should see a hudson server on port 5001
|
14
|
+
And folder "home/.hudson/server" is created
|
15
|
+
And folder "home/.hudson/server/javatmp" is created
|
16
|
+
|
@@ -0,0 +1,181 @@
|
|
1
|
+
Given /^this project is active project folder/ do
|
2
|
+
@active_project_folder = File.expand_path(File.dirname(__FILE__) + "/../..")
|
3
|
+
end
|
4
|
+
|
5
|
+
Given /^env variable \$([\w_]+) set to( project path |)"(.*)"/ do |env_var, path, value|
|
6
|
+
in_project_folder {
|
7
|
+
value = File.expand_path(value)
|
8
|
+
} unless path.empty?
|
9
|
+
ENV[env_var] = value
|
10
|
+
end
|
11
|
+
|
12
|
+
Given /"(.*)" folder is deleted/ do |folder|
|
13
|
+
in_project_folder { FileUtils.rm_rf folder }
|
14
|
+
end
|
15
|
+
|
16
|
+
When /^I invoke "(.*)" generator with arguments "(.*)"$/ do |generator, arguments|
|
17
|
+
@stdout = StringIO.new
|
18
|
+
in_project_folder do
|
19
|
+
if Object.const_defined?("APP_ROOT")
|
20
|
+
APP_ROOT.replace(FileUtils.pwd)
|
21
|
+
else
|
22
|
+
APP_ROOT = FileUtils.pwd
|
23
|
+
end
|
24
|
+
run_generator(generator, arguments.split(' '), SOURCES, :stdout => @stdout)
|
25
|
+
end
|
26
|
+
File.open(File.join(@tmp_root, "generator.out"), "w") do |f|
|
27
|
+
@stdout.rewind
|
28
|
+
f << @stdout.read
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
When /^I run executable "(.*)" with arguments "(.*)"/ do |executable, arguments|
|
33
|
+
@stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
|
34
|
+
in_project_folder do
|
35
|
+
system "#{executable} #{arguments} > #{@stdout} 2> #{@stdout}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
When /^I run project executable "(.*)" with arguments "(.*)"/ do |executable, arguments|
|
40
|
+
@stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
|
41
|
+
in_project_folder do
|
42
|
+
system "ruby #{executable} #{arguments} > #{@stdout} 2> #{@stdout}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
When /^I run local executable "(.*)" with arguments "(.*)"/ do |executable, arguments|
|
47
|
+
@stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
|
48
|
+
executable = File.expand_path(File.join(File.dirname(__FILE__), "/../../bin", executable))
|
49
|
+
in_project_folder do
|
50
|
+
system "ruby #{executable} #{arguments} > #{@stdout} 2> #{@stdout}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
When /^I invoke task "rake (.*)"/ do |task|
|
55
|
+
@stdout = File.expand_path(File.join(@tmp_root, "tests.out"))
|
56
|
+
in_project_folder do
|
57
|
+
system "rake #{task} --trace > #{@stdout} 2> #{@stdout}"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
Then /^folder "(.*)" (is|is not) created/ do |folder, is|
|
62
|
+
in_project_folder do
|
63
|
+
File.exists?(folder).should(is == 'is' ? be_true : be_false)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
Then /^file "(.*)" (is|is not) created/ do |file, is|
|
68
|
+
in_project_folder do
|
69
|
+
File.exists?(file).should(is == 'is' ? be_true : be_false)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
Then /^file with name matching "(.*)" is created/ do |pattern|
|
74
|
+
in_project_folder do
|
75
|
+
Dir[pattern].should_not be_empty
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
Then /^file "(.*)" contents (does|does not) match \/(.*)\// do |file, does, regex|
|
80
|
+
in_project_folder do
|
81
|
+
actual_output = File.read(file)
|
82
|
+
(does == 'does') ?
|
83
|
+
actual_output.should(match(/#{regex}/)) :
|
84
|
+
actual_output.should_not(match(/#{regex}/))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
Then /gem file "(.*)" and generated file "(.*)" should be the same/ do |gem_file, project_file|
|
89
|
+
File.exists?(gem_file).should be_true
|
90
|
+
File.exists?(project_file).should be_true
|
91
|
+
gem_file_contents = File.read(File.dirname(__FILE__) + "/../../#{gem_file}")
|
92
|
+
project_file_contents = File.read(File.join(@active_project_folder, project_file))
|
93
|
+
project_file_contents.should == gem_file_contents
|
94
|
+
end
|
95
|
+
|
96
|
+
Then /^(does|does not) invoke generator "(.*)"$/ do |does_invoke, generator|
|
97
|
+
actual_output = File.read(@stdout)
|
98
|
+
does_invoke == "does" ?
|
99
|
+
actual_output.should(match(/dependency\s+#{generator}/)) :
|
100
|
+
actual_output.should_not(match(/dependency\s+#{generator}/))
|
101
|
+
end
|
102
|
+
|
103
|
+
Then /help options "(.*)" and "(.*)" are displayed/ do |opt1, opt2|
|
104
|
+
actual_output = File.read(@stdout)
|
105
|
+
actual_output.should match(/#{opt1}/)
|
106
|
+
actual_output.should match(/#{opt2}/)
|
107
|
+
end
|
108
|
+
|
109
|
+
Then /^I should see "([^\"]*)"$/ do |text|
|
110
|
+
actual_output = File.read(@stdout)
|
111
|
+
actual_output.should contain(text)
|
112
|
+
end
|
113
|
+
|
114
|
+
Then /^I should not see "([^\"]*)"$/ do |text|
|
115
|
+
actual_output = File.read(@stdout)
|
116
|
+
actual_output.should_not contain(text)
|
117
|
+
end
|
118
|
+
|
119
|
+
Then /^I should see$/ do |text|
|
120
|
+
actual_output = File.read(@stdout)
|
121
|
+
actual_output.should contain(text)
|
122
|
+
end
|
123
|
+
|
124
|
+
Then /^I should not see$/ do |text|
|
125
|
+
actual_output = File.read(@stdout)
|
126
|
+
actual_output.should_not contain(text)
|
127
|
+
end
|
128
|
+
|
129
|
+
Then /^I should see exactly$/ do |text|
|
130
|
+
actual_output = File.read(@stdout)
|
131
|
+
actual_output.should == text
|
132
|
+
end
|
133
|
+
|
134
|
+
Then /^I should see all (\d+) tests pass/ do |expected_test_count|
|
135
|
+
expected = %r{^#{expected_test_count} tests, \d+ assertions, 0 failures, 0 errors}
|
136
|
+
actual_output = File.read(@stdout)
|
137
|
+
actual_output.should match(expected)
|
138
|
+
end
|
139
|
+
|
140
|
+
Then /^I should see all (\d+) examples pass/ do |expected_test_count|
|
141
|
+
expected = %r{^#{expected_test_count} examples?, 0 failures}
|
142
|
+
actual_output = File.read(@stdout)
|
143
|
+
actual_output.should match(expected)
|
144
|
+
end
|
145
|
+
|
146
|
+
Then /^yaml file "(.*)" contains (\{.*\})/ do |file, yaml|
|
147
|
+
in_project_folder do
|
148
|
+
yaml = eval yaml
|
149
|
+
YAML.load(File.read(file)).should == yaml
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
Then /^Rakefile can display tasks successfully/ do
|
154
|
+
@stdout = File.expand_path(File.join(@tmp_root, "rakefile.out"))
|
155
|
+
in_project_folder do
|
156
|
+
system "rake -T > #{@stdout} 2> #{@stdout}"
|
157
|
+
end
|
158
|
+
actual_output = File.read(@stdout)
|
159
|
+
actual_output.should match(/^rake\s+\w+\s+#\s.*/)
|
160
|
+
end
|
161
|
+
|
162
|
+
Then /^task "rake (.*)" is executed successfully/ do |task|
|
163
|
+
@stdout.should_not be_nil
|
164
|
+
actual_output = File.read(@stdout)
|
165
|
+
actual_output.should_not match(/^Don't know how to build task '#{task}'/)
|
166
|
+
actual_output.should_not match(/Error/i)
|
167
|
+
end
|
168
|
+
|
169
|
+
Then /^gem spec key "(.*)" contains \/(.*)\// do |key, regex|
|
170
|
+
in_project_folder do
|
171
|
+
gem_file = Dir["pkg/*.gem"].first
|
172
|
+
gem_spec = Gem::Specification.from_yaml(`gem spec #{gem_file}`)
|
173
|
+
spec_value = gem_spec.send(key.to_sym)
|
174
|
+
spec_value.to_s.should match(/#{regex}/)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
Then /^the file "([^\"]*)" is a valid gemspec$/ do |filename|
|
179
|
+
spec = eval(File.read(filename))
|
180
|
+
spec.validate
|
181
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Given /^I am in the "([^\"]*)" project folder$/ do |project|
|
2
|
+
project_folder = File.expand_path(File.dirname(__FILE__) + "/../fixtures/projects/#{project}")
|
3
|
+
in_tmp_folder do
|
4
|
+
FileUtils.cp_r(project_folder, project)
|
5
|
+
setup_active_project_folder(project)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
Given /^I have a Hudson server running$/ do
|
2
|
+
unless ENV['HUDSON_PORT']
|
3
|
+
port = 3010
|
4
|
+
begin
|
5
|
+
res = Net::HTTP.start("localhost", port) { |http| http.get('/api/json') }
|
6
|
+
rescue Errno::ECONNREFUSED => e
|
7
|
+
puts "\n\n\nERROR: To run tests, launch hudson in test mode: 'rake hudson:server:test'\n\n\n"
|
8
|
+
exit
|
9
|
+
end
|
10
|
+
ENV['HUDSON_PORT'] = port.to_s
|
11
|
+
ENV['HUDSON_HOST'] = 'localhost'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Given /^the Hudson server has no current jobs$/ do
|
16
|
+
if port = ENV['HUDSON_PORT']
|
17
|
+
require "open-uri"
|
18
|
+
require "yajl"
|
19
|
+
hudson_info = Yajl::Parser.new.parse(open("http://localhost:#{ENV['HUDSON_PORT']}/api/json"))
|
20
|
+
|
21
|
+
hudson_info['jobs'].each do |job|
|
22
|
+
job_url = job['url']
|
23
|
+
res = Net::HTTP.start("localhost", port) { |http| http.post("#{job_url}doDelete/api/json", {}) }
|
24
|
+
end
|
25
|
+
hudson_info = Yajl::Parser.new.parse(open("http://localhost:#{ENV['HUDSON_PORT']}/api/json"))
|
26
|
+
hudson_info['jobs'].should == []
|
27
|
+
else
|
28
|
+
puts "WARNING: Run 'I have a Hudson server running' step first."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Given /^there is nothing listening on port (\d+)$/ do |port|
|
33
|
+
lambda {
|
34
|
+
TCPSocket.open("localhost", port) {}
|
35
|
+
}.should raise_error
|
36
|
+
end
|
37
|
+
|
38
|
+
Given /^I cleanup any hudson processes with control port (\d+)$/ do |port|
|
39
|
+
@hudson_cleanup << port
|
40
|
+
end
|
41
|
+
|
42
|
+
def try(times, interval = 1)
|
43
|
+
begin
|
44
|
+
times -= 1
|
45
|
+
return yield
|
46
|
+
rescue Exception => e
|
47
|
+
if times >= 0
|
48
|
+
sleep(interval)
|
49
|
+
retry
|
50
|
+
end
|
51
|
+
raise e
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
When /^I run hudson server with arguments "(.*)"/ do |arguments|
|
56
|
+
@stdout = File.expand_path(File.join(@tmp_root, "executable.out"))
|
57
|
+
executable = File.expand_path(File.join(File.dirname(__FILE__), "/../../bin","hudson"))
|
58
|
+
in_project_folder do
|
59
|
+
system "ruby #{executable} server #{arguments} > #{@stdout} 2>#{@stdout}"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
Then /^I should see a hudson server on port (\d+)$/ do |port|
|
65
|
+
require 'json'
|
66
|
+
try(15, 2) do
|
67
|
+
res = Net::HTTP.start("localhost", port) { |http| http.get('/api/json') }
|
68
|
+
JSON.parse(res.body)['nodeDescription'].should == "the master Hudson node"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module CommonHelpers
|
2
|
+
def in_tmp_folder(&block)
|
3
|
+
FileUtils.chdir(@tmp_root, &block)
|
4
|
+
end
|
5
|
+
|
6
|
+
def in_project_folder(&block)
|
7
|
+
project_folder = @active_project_folder || @tmp_root
|
8
|
+
FileUtils.chdir(project_folder, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def in_home_folder(&block)
|
12
|
+
FileUtils.chdir(@home_path, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def force_local_lib_override(project_name = @project_name)
|
16
|
+
rakefile = File.read(File.join(project_name, 'Rakefile'))
|
17
|
+
File.open(File.join(project_name, 'Rakefile'), "w+") do |f|
|
18
|
+
f << "$:.unshift('#{@lib_path}')\n"
|
19
|
+
f << rakefile
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def setup_active_project_folder project_name
|
24
|
+
@active_project_folder = File.join(@tmp_root, project_name)
|
25
|
+
@project_name = project_name
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
World(CommonHelpers)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
$:.unshift(File.expand_path(File.dirname(File.dirname(__FILE__) + "/../../lib/hudson.rb")))
|
2
|
+
require File.dirname(__FILE__) + "/../../lib/hudson.rb"
|
3
|
+
|
4
|
+
gem 'cucumber'
|
5
|
+
require 'cucumber'
|
6
|
+
gem 'rspec'
|
7
|
+
require 'spec'
|
8
|
+
|
9
|
+
Before do
|
10
|
+
@tmp_root = File.dirname(__FILE__) + "/../../tmp"
|
11
|
+
@home_path = File.expand_path(File.join(@tmp_root, "home"))
|
12
|
+
@lib_path = File.expand_path(File.dirname(__FILE__) + "/../../lib")
|
13
|
+
FileUtils.rm_rf @tmp_root
|
14
|
+
FileUtils.mkdir_p @home_path
|
15
|
+
ENV['HOME'] = @home_path
|
16
|
+
end
|