hudkins 0.0.1

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/.autotest ADDED
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ # Autotest.add_hook :initialize do |at|
6
+ # at.extra_files << "../some/external/dependency.rb"
7
+ #
8
+ # at.libs << ":../some/external"
9
+ #
10
+ # at.add_exception 'vendor'
11
+ #
12
+ # at.add_mapping(/dependency.rb/) do |f, _|
13
+ # at.files_matching(/test_.*rb$/)
14
+ # end
15
+ #
16
+ # %w(TestA TestB).each do |klass|
17
+ # at.extra_class_map[klass] = "test/test_misc.rb"
18
+ # end
19
+ # end
20
+
21
+ # Autotest.add_hook :run_command do |at|
22
+ # system "rake build"
23
+ # end
data/.gemtest ADDED
File without changes
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 0.0.1 / 2011-09-16
2
+
3
+ * 1 major enhancement
4
+
5
+ * Ported hapi repo to hudkins for public release.
6
+
data/Manifest.txt ADDED
@@ -0,0 +1,29 @@
1
+ .autotest
2
+ History.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ bin/hudkins
7
+ lib/assets/config.xml
8
+ lib/assets/config_snippets/builders.xml
9
+ lib/assets/free_style_project.xml.erb
10
+ lib/assets/hudkinsrc
11
+ lib/hudkins.rb
12
+ lib/hudkins/command.rb
13
+ lib/hudkins/command/exec.rb
14
+ lib/hudkins/command/irb_start.rb
15
+ lib/hudkins/common.rb
16
+ lib/hudkins/errors.rb
17
+ lib/hudkins/job.rb
18
+ lib/hudkins/jobs.rb
19
+ lib/hudkins/mixin.rb
20
+ lib/hudkins/rake.rb
21
+ lib/hudkins/restclient.rb
22
+ lib/hudkins/sysinfo.rb
23
+ test/fixtures/config.erb
24
+ test/fixtures/jobs.erb
25
+ test/fixtures/new_project_config.erb
26
+ test/test_helper.rb
27
+ test/unit/hudkins/test_job.rb
28
+ test/unit/hudkins/test_jobs.rb
29
+ test/unit/test_hudkins.rb
data/README.txt ADDED
@@ -0,0 +1,98 @@
1
+ = hudkins
2
+
3
+ * http://github.com/bhenderson/hudkins
4
+
5
+ == DESCRIPTION:
6
+
7
+ Hudson interaction gem.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * so far this is mostly for inspection of current jobs. There are quite a few
12
+ options in hudson for creating a new job and these haven't been implemented
13
+ yet.
14
+
15
+ === Implemented:
16
+
17
+ * Create new job
18
+
19
+ === Unimplemented:
20
+
21
+ * Copy job
22
+ * Build Que
23
+
24
+ * Hudson returns incorrect mime types!!! I've hacked it by setting response.type to the :accept header. This needs to be extracted out to dry up the code
25
+
26
+ == SYNOPSIS:
27
+
28
+ See Hudkins class documentation.
29
+ hud = Hudkins.new "http://example.com"
30
+ hud.jobs # => Hudkins::Jobs
31
+
32
+ === Working with Jobs
33
+
34
+ job = hud.jobs.find_by_name "project-main"
35
+ job.scm_url # => "https://subversion/project/branches/1.1"
36
+ job.scm_url = "https://subversion/project/branches/1.2"
37
+ job.post_config! # => Hudkins::Response
38
+ job.build!
39
+
40
+ === Creating new jobs
41
+
42
+ new_job = hud.add_job new_project_name
43
+ new_job.disabled? # => true
44
+ new_job.scm_url # => nil
45
+ new_job.scm_use :git/:svn, "http://svn/my_cool_repo/new_project_name/trunk"
46
+
47
+ job = hud.jobs.find_by_name :job_name
48
+ job2 = job.copy new_name ||
49
+ hud.copy_job job, new_name
50
+ job2.scm_url = "http://svn/new/url"
51
+ job2.post_config!
52
+
53
+
54
+ == REQUIREMENTS:
55
+
56
+ * heavily built ontop of "https://github.com/archiloque/rest-client"
57
+ * see link:Rakefile
58
+
59
+ == INSTALL:
60
+
61
+ * git clone http://github.com/bhenderson/hudkins.git
62
+ * cd hudkins/
63
+ * rake package
64
+ * gem install pkg/hudkins.gem
65
+
66
+ == DEVELOPERS:
67
+
68
+ After checking out the source, run:
69
+
70
+ $ rake newb
71
+
72
+ This task will install any missing dependencies, run the tests/specs,
73
+ and generate the RDoc.
74
+
75
+ == LICENSE:
76
+
77
+ (The MIT License)
78
+
79
+ Copyright (c) 2011
80
+
81
+ Permission is hereby granted, free of charge, to any person obtaining
82
+ a copy of this software and associated documentation files (the
83
+ 'Software'), to deal in the Software without restriction, including
84
+ without limitation the rights to use, copy, modify, merge, publish,
85
+ distribute, sublicense, and/or sell copies of the Software, and to
86
+ permit persons to whom the Software is furnished to do so, subject to
87
+ the following conditions:
88
+
89
+ The above copyright notice and this permission notice shall be
90
+ included in all copies or substantial portions of the Software.
91
+
92
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
93
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
94
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
95
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
96
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
97
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
98
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+
6
+ Hoe.plugin :isolate
7
+
8
+ $:.unshift './'
9
+
10
+ Hoe.spec 'hudkins' do
11
+ developer('Brian Henderson', 'bhenderson@attinteractive.com')
12
+ developer('Adam Avilla', 'bhenderson@attinteractive.com')
13
+
14
+ extra_deps << [ "json", "~> 1.5.0"]
15
+ extra_deps << [ "nokogiri", "~> 1.5.0"]
16
+ extra_deps << [ "rest-client", "~> 1.6.1"]
17
+
18
+ extra_dev_deps << [ "minitest", "~> 1.7.2"]
19
+ extra_dev_deps << [ "mocha", "~> 0.9.8"]
20
+ end
21
+
22
+
23
+ #require "lib/hudkins/rake"
24
+
25
+ # vim: syntax=ruby
data/bin/hudkins ADDED
@@ -0,0 +1,5 @@
1
+ #!/user/bin/env ruby
2
+
3
+ require "hudkins/command"
4
+
5
+ Hudkins::Command.run
@@ -0,0 +1,30 @@
1
+ <?xml version='1.0' encoding='UTF-8'?>
2
+ <project>
3
+ <actions/>
4
+ <description>foo bar</description>
5
+ <keepDependencies>false</keepDependencies>
6
+ <properties/>
7
+ <scm class="hudson.scm.SubversionSCM">
8
+ <locations>
9
+ <hudson.scm.SubversionSCM_-ModuleLocation>
10
+ <remote>svn://subversion.flight.yellowpages.com/search/syndication/tags/1.1.0_201008</remote>
11
+ </hudson.scm.SubversionSCM_-ModuleLocation>
12
+ </locations>
13
+ <useUpdate>true</useUpdate>
14
+ <doRevert>false</doRevert>
15
+ <excludedRegions></excludedRegions>
16
+ <includedRegions></includedRegions>
17
+ <excludedUsers></excludedUsers>
18
+ <excludedRevprop></excludedRevprop>
19
+ <excludedCommitMessages></excludedCommitMessages>
20
+ </scm>
21
+ <assignedNode>master</assignedNode>
22
+ <canRoam>false</canRoam>
23
+ <disabled>true</disabled>
24
+ <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
25
+ <triggers class="vector"/>
26
+ <concurrentBuild>false</concurrentBuild>
27
+ <builders/>
28
+ <publishers/>
29
+ <buildWrappers/>
30
+ </project>
@@ -0,0 +1,5 @@
1
+ <builders>
2
+ <hudson.tasks.Shell>
3
+ <command></command>
4
+ </hudson.tasks.Shell>
5
+ </builders>
@@ -0,0 +1,14 @@
1
+ <?xml version='1.0' encoding='UTF-8'?>
2
+ <project>
3
+ <keepDependencies>false</keepDependencies>
4
+ <properties/>
5
+ <scm class="hudson.scm.NullSCM"/>
6
+ <canRoam>true</canRoam>
7
+ <disabled>true</disabled>
8
+ <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
9
+ <triggers class="vector"/>
10
+ <concurrentBuild>false</concurrentBuild>
11
+ <builders/>
12
+ <publishers/>
13
+ <buildWrappers/>
14
+ </project>
@@ -0,0 +1,4 @@
1
+ # Sample rc file
2
+ ---
3
+ :host: http://example.com
4
+ :verbose: true
data/lib/hudkins.rb ADDED
@@ -0,0 +1,263 @@
1
+ require "rest_client"
2
+ require "json"
3
+ require "nokogiri"
4
+
5
+ require "hudkins/restclient"
6
+ require "hudkins/mixin"
7
+ require "hudkins/common"
8
+
9
+ ##
10
+ # === Description
11
+ # Primary class used to interact with your Hudson server
12
+ #
13
+ # === Examples
14
+ # hud = Hudkins.new "http://my-hudson.localdomain.com:8080"
15
+ # hud.jobs # => Hudkins::Jobs
16
+ # job = hud.jobs.find_by_name :job_name
17
+ #
18
+ # == Command Line
19
+ # There is an included binary for doing simple commands.
20
+ # See Hudkins::Command#run_start_irb for a powerful way to interact with your
21
+ # hudson server at an irb cmd prompt.
22
+ #
23
+ class Hudkins
24
+ include Hudkins::Common
25
+ VERSION = '0.0.1'
26
+
27
+ attr_reader :host, :resource
28
+
29
+ ##
30
+ # === Examples
31
+ # Hudkins.new <host_name> [opts]
32
+ #
33
+ # <host_name> will be URI parsed
34
+ #
35
+ # === Options
36
+ # +host_timeout+:: number of seconds to timeout trying to connect to the server. see Hudkins#host_available?
37
+ #
38
+ def initialize(host = "http://example.com", opts = {})
39
+ @host = URI.parse( ENV["hudkins_host"] || host )
40
+ @options = opts
41
+ @resource = RestClient::Resource.new @host.to_s
42
+ end
43
+
44
+ ##
45
+ # === Description
46
+ # Reset what Hudkins#host is after initialization. Also updates Hudkins#reset_resource.
47
+ def host= host_name
48
+ @host = URI.parse host_name
49
+ # reinitialize @resource
50
+ resource = @host
51
+ end
52
+
53
+ ##
54
+ # === Description
55
+ # Update Hudkins#resource with new host name.
56
+ def reset_resource= uri = host, opts = {}
57
+ @resource = RestClient::Resource.new( uri.to_s, opts)
58
+ end
59
+
60
+ ##
61
+ # === Description
62
+ # Access to internal list of jobs. see Hudkins::Jobs
63
+ #
64
+ # One inital api call is made and then cached. See Hudkins#initialize_jobs
65
+ def jobs
66
+ @jobs ||= initialize_jobs
67
+ end
68
+
69
+ ##
70
+ # === Description
71
+ # Reload jobs from the server
72
+ def update_jobs
73
+ # I might need to reinitiailze
74
+ @jobs = initialize_jobs
75
+ end
76
+
77
+ ##
78
+ # === Description
79
+ # Available to make arbitrary HTTP/get calls to the server.
80
+ # Returns an Hudkins::Response object. (see that class for reasoning.)
81
+ #
82
+ # === Parameters
83
+ # +path+:: "/path/to/resource"
84
+ # +opts+:: {:accept => "text/plain"} (default)
85
+ # +block+:: { optional return block for RestClient#get }
86
+ def get path = nil, opts = {}, &block
87
+ use_resource :get, path, nil, opts, &block
88
+ end
89
+
90
+ ##
91
+ # === Description
92
+ # Available to make arbitrary HTTP/post calls to the server.
93
+ #
94
+ # === Parameters
95
+ # +path+:: "/path/to/resource"
96
+ # +data+:: "<?xml...>" (any object that responds to to_s).
97
+ # +opts+:: {:content => "text/plain"} (default)
98
+ # +block+:: { optional return block for RestClient#get }
99
+ def post path = nil, data = "", opts = {}, &block
100
+ use_resource :post, path, data, opts, &block
101
+ end
102
+
103
+ ##
104
+ # === Description
105
+ # Same as #get but attempt to parse the response body.
106
+ # Raise unless Response#success?
107
+ def get_parsed *args
108
+ parse_response get(*args)
109
+ end
110
+
111
+ ##
112
+ # === Description
113
+ # Same as #post but attempt to parse the response body.
114
+ # Raise unless Response#success?
115
+ def post_parsed *args
116
+ parse_response post(*args)
117
+ end
118
+
119
+ # Action methods
120
+
121
+ ##
122
+ # === Description
123
+ # TODO this needs cleaned up to be more like copy_job
124
+ # Use remote api to create a new job.
125
+ # Updates internal job list (Hudkins#jobs) afterwards
126
+ #
127
+ # === Example
128
+ # hud.add_job :job_name, "<?xml..>"
129
+ #
130
+ # === Options
131
+ # +job_name+:: String or Symbol used as the name of the new job.
132
+ # +config_data+:: Uses provided template for bare-bones config, but
133
+ # optionally takes a string parameter (such as xml from
134
+ # another job's config)
135
+ #
136
+ # === Notes
137
+ # The remote api here is not fun. It uses HTTP#post instead of HTTP#create
138
+ # (which is normal) but the error messages are not very useful.
139
+ def add_job job_name, config_data = new_config
140
+ # yuck..
141
+ job = update_jobs.find_by_name( job_name )
142
+ unless job
143
+ response = post "/createItem?" + url_escape(:name => job_name), config_data, :content_type => "text/xml"
144
+ if response.success?
145
+ update_jobs.find_by_name job_name
146
+ else
147
+ case response.code
148
+ when 400
149
+ warn "the server returned an error. most likely the job name already exists."
150
+ jobs.find_by_name( job_name ) || ( raise response.errors )
151
+ else
152
+ warn "there was a problem."
153
+ raise response.errors
154
+ end
155
+ end
156
+ else
157
+ job
158
+ end
159
+ end
160
+
161
+ ##
162
+ # === Description
163
+ # Copy a job
164
+ #
165
+ # === Examples
166
+ # new_job = hud.copy_job "job-name", "new-job-name"
167
+ #
168
+ # job = hud.find_by_name "job-name"
169
+ # new_job = hud.copy_job job, "new-job-name"
170
+ def copy_job job, new_job
171
+ job = Hudkins::Job === job ? job : jobs.find_by_name( job )
172
+ job.copy( new_job ) if job # find_by_name didn't return nil
173
+ end
174
+
175
+ ##
176
+ # === Description
177
+ # Gets the hudson version the server is running
178
+ #
179
+ # === Examples
180
+ # hud.server_version # => "1.37.0"
181
+ def server_version
182
+ get.response.headers[:x_hudson]
183
+ end
184
+
185
+ def parse_string string, format
186
+ case format
187
+ when :xml then
188
+ Nokogiri::XML string
189
+ when :json then
190
+ JSON.parse string
191
+ else
192
+ raise "unsupported type #{format.inspect}"
193
+ end
194
+ end
195
+
196
+ private
197
+ def initialize_jobs
198
+ Hudkins::Jobs.new(self)
199
+ end
200
+
201
+ def get_default_options
202
+ {:accept => "text/plain"}
203
+ end
204
+
205
+ def post_default_options
206
+ {:content_type => "text/plain"}
207
+ end
208
+
209
+ def new_config
210
+ File.read( File.join( File.dirname(__FILE__), "assets", "free_style_project.xml.erb" ) )
211
+ end
212
+
213
+ def use_resource verb, path, data = nil, opts = {}, &block
214
+ check_host_availability
215
+ # allow symbals
216
+ new_resource = path.nil? ? @resource : @resource[path.to_s]
217
+ args = [ send("#{verb}_default_options").merge( opts ) ]
218
+ # not sure how else to make this generic for both get and post
219
+ # maybe something like opts.delete :data
220
+ args.unshift data.to_s if data
221
+ new_resource.send(verb, *args, &(block || resource_block))
222
+ end
223
+
224
+ def resource_block
225
+ # restclient
226
+ # |response, request, result|
227
+ Proc.new {|*args| Response.new *args}
228
+ end
229
+
230
+ # body = @response.body, format = @response.format
231
+ def parse_response response
232
+ # I debated on wether or not to push up the raise statement. But it seems like I might want to do a "get" even if it doesn't return a valid response whereas why would I want to parse an invalid response?
233
+ raise response.result unless response.success?
234
+ body, format = response.body, response.type
235
+ begin
236
+ parse_string body, format
237
+ rescue => e
238
+ raise "unparsable response for #{response.request.url}.\n#{e.message}"
239
+ end
240
+ end
241
+
242
+ #def parse_response response
243
+ #raise response.result unless response.success?
244
+ #body = response.body
245
+ #begin
246
+ #case body
247
+ #when /^\s*<\?xml/ then
248
+ #Nokogiri::XML body
249
+ #when /^\s*\{/ then
250
+ #JSON.parse body
251
+ #else
252
+ #body
253
+ #end
254
+ #rescue => e
255
+ #raise "unparsable response. #{e.message}"
256
+ #end
257
+ #end
258
+ # private
259
+ end # Hudkins
260
+
261
+ require "hudkins/jobs"
262
+ require "hudkins/job"
263
+ require "hudkins/errors"