teamcity-rest-client 0.1.0 → 0.1.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/VERSION +1 -1
- data/lib/teamcity-rest-client.rb +58 -16
- data/spec/spec_helper.rb +4 -0
- data/spec/teamcity-rest-client_spec.rb +125 -30
- data/teamcity-rest-client.gemspec +1 -1
- metadata +10 -10
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
data/lib/teamcity-rest-client.rb
CHANGED
@@ -23,6 +23,41 @@ module TeamcityRestClient
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
class HttpBasicAuthentication
|
27
|
+
def initialize host, port, user, password
|
28
|
+
@host, @port, @user, @password = host, port, user, password
|
29
|
+
end
|
30
|
+
|
31
|
+
def get path
|
32
|
+
open(url(path), :http_basic_authentication => [@user, @password]).read
|
33
|
+
end
|
34
|
+
|
35
|
+
def url path
|
36
|
+
"http://#{@host}:#{@port}/httpAuth#{path}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_s
|
40
|
+
"HttpBasicAuthentication #{@user}:#{@password}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class Open
|
45
|
+
def initialize host, port
|
46
|
+
@host, @port = host, port
|
47
|
+
end
|
48
|
+
|
49
|
+
def get path
|
50
|
+
open(url(path)).read
|
51
|
+
end
|
52
|
+
|
53
|
+
def url path
|
54
|
+
"http://#{@host}:#{@port}#{path}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
"No Authentication"
|
59
|
+
end
|
60
|
+
end
|
26
61
|
end
|
27
62
|
|
28
63
|
class REXML::Element
|
@@ -33,10 +68,15 @@ end
|
|
33
68
|
|
34
69
|
class Teamcity
|
35
70
|
|
36
|
-
attr_reader :host, :port, :
|
71
|
+
attr_reader :host, :port, :authentication
|
37
72
|
|
38
73
|
def initialize host, port, user = nil, password = nil
|
39
|
-
@host, @port
|
74
|
+
@host, @port = host, port
|
75
|
+
if user != nil && password != nil
|
76
|
+
@authentication = TeamcityRestClient::HttpBasicAuthentication.new host, port, user, password
|
77
|
+
else
|
78
|
+
@authentication = TeamcityRestClient::Open.new host, port
|
79
|
+
end
|
40
80
|
end
|
41
81
|
|
42
82
|
def project spec
|
@@ -47,37 +87,39 @@ class Teamcity
|
|
47
87
|
end
|
48
88
|
|
49
89
|
def projects
|
50
|
-
doc(get(
|
90
|
+
doc(get('/app/rest/projects')).elements.collect('//project') do |e|
|
51
91
|
TeamcityRestClient::Project.new(self, e.att("name"), e.att("id"), url(e.att("href")))
|
52
92
|
end
|
53
93
|
end
|
54
94
|
|
55
95
|
def build_types
|
56
|
-
doc(get(
|
96
|
+
doc(get('/app/rest/buildTypes')).elements.collect('//buildType') do |e|
|
57
97
|
TeamcityRestClient::BuildType.new(e.att("id"), e.att("name"), url(e.att("href")), e.att('projectName'), e.att('projectId'), e.att('webUrl'))
|
58
98
|
end
|
59
99
|
end
|
60
100
|
|
61
101
|
def builds
|
62
|
-
doc(get(
|
102
|
+
doc(get('/app/rest/builds').gsub(/&buildTypeId/,'&buildTypeId')).elements.collect('//build') do |e|
|
63
103
|
TeamcityRestClient::Build.new(e.att('id'), e.att('number'), e.att('status').to_sym, e.att('buildTypeId'), e.att('startDate'), url(e.att('href')), e.att('webUrl'))
|
64
104
|
end
|
65
105
|
end
|
66
|
-
|
67
|
-
def url path
|
68
|
-
if user != nil && password != nil
|
69
|
-
"http://#{user}:#{password}@#{host}:#{port}#{path}"
|
70
|
-
else
|
71
|
-
"http://#{host}:#{port}#{path}"
|
72
|
-
end
|
73
|
-
end
|
74
106
|
|
107
|
+
def to_s
|
108
|
+
"Teamcity @ http://#{host}:#{port}"
|
109
|
+
end
|
110
|
+
|
75
111
|
private
|
76
112
|
def doc string
|
77
113
|
REXML::Document.new string
|
78
114
|
end
|
115
|
+
|
116
|
+
def get path
|
117
|
+
result = @authentication.get(path)
|
118
|
+
raise "Teamcity returned html, perhaps you need to use authentication??" if result =~ /.*<html.*<\/html>.*/im
|
119
|
+
result
|
120
|
+
end
|
79
121
|
|
80
|
-
def
|
81
|
-
|
122
|
+
def url path
|
123
|
+
@authentication.url(path)
|
82
124
|
end
|
83
|
-
end
|
125
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,51 +1,117 @@
|
|
1
1
|
require_relative 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module TeamcityRestClient
|
4
|
+
|
5
|
+
describe Project do
|
6
|
+
before :each do
|
7
|
+
@bt11 = stub('bt11', :id => "bt11", :name => "project1-build1", :project_id => "project1")
|
8
|
+
@bt12 = stub('bt12', :id => "bt12", :name => "project1-build2", :project_id => "project1")
|
9
|
+
@bt21 = stub('bt21', :id => "bt21", :name => "project2-build1", :project_id => "project2")
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
@bt11_1 = stub('bt11_1', :id => "1", :build_type_id => "bt11")
|
12
|
+
@bt11_2 = stub('bt11_2', :id => "2", :build_type_id => "bt11")
|
13
|
+
@bt12_33 = stub('bt12_33', :id => "33", :build_type_id => "bt12")
|
14
|
+
@bt21_666 = stub('bt21_666', :id => "666", :build_type_id => "bt21")
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
@tc = stub('teamcity', :build_types => [@bt11, @bt12, @bt21], :builds => [@bt11_1, @bt11_2, @bt12_33, @bt21_666])
|
17
|
+
@project1 = Project.new @tc, "Project 1", "project1", "http://www.example.com"
|
18
|
+
end
|
17
19
|
|
18
|
-
|
20
|
+
describe "asking it for it's build types" do
|
21
|
+
before :each do
|
22
|
+
@build_types = @project1.build_types
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should have only those for project 1" do
|
26
|
+
@build_types.should == [@bt11, @bt12]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "asking it for it's builds" do
|
31
|
+
before :each do
|
32
|
+
@builds = @project1.builds
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should have only builds for project 1" do
|
36
|
+
@builds.should == [@bt11_1, @bt11_2, @bt12_33]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe HttpBasicAuthentication do
|
19
42
|
before :each do
|
20
|
-
@
|
43
|
+
@host, @port, @user, @password = "auth.example.com", 2233, "john", "wayne"
|
44
|
+
@auth = HttpBasicAuthentication.new @host, @port, @user, @password
|
45
|
+
@io = stub(:read => "<xml/>")
|
21
46
|
end
|
22
47
|
|
23
|
-
|
24
|
-
|
48
|
+
describe "url" do
|
49
|
+
it "should add /httpAuth to path" do
|
50
|
+
@auth.url("/something").should == "http://auth.example.com:2233/httpAuth/something"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "get" do
|
55
|
+
it "should call open with http basic auth options" do
|
56
|
+
@auth.should_receive(:open).with("http://auth.example.com:2233/httpAuth/somethingElse", :http_basic_authentication=>[@user, @password]).and_return(@io)
|
57
|
+
@auth.get("/somethingElse")
|
58
|
+
end
|
25
59
|
end
|
26
60
|
end
|
27
61
|
|
28
|
-
describe
|
62
|
+
describe Open do
|
29
63
|
before :each do
|
30
|
-
@
|
64
|
+
@host, @port = "auth.example.com", 2233
|
65
|
+
@auth = Open.new @host, @port
|
66
|
+
@io = stub(:read => "<xml/>")
|
31
67
|
end
|
32
68
|
|
33
|
-
|
34
|
-
|
69
|
+
describe "url" do
|
70
|
+
it "should create valid url" do
|
71
|
+
@auth.url("/something").should == "http://auth.example.com:2233/something"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "get" do
|
76
|
+
it "should call open with no auth options" do
|
77
|
+
@auth.should_receive(:open).with("http://auth.example.com:2233/somethingElse").and_return(@io)
|
78
|
+
@auth.get("/somethingElse")
|
79
|
+
end
|
35
80
|
end
|
36
81
|
end
|
82
|
+
|
37
83
|
end
|
38
84
|
|
39
85
|
describe Teamcity do
|
40
|
-
|
86
|
+
before :all do
|
87
|
+
@sample_projects_xml = sample_xml "projects"
|
88
|
+
@sample_builds_xml = sample_xml "builds"
|
89
|
+
@sample_build_types_xml = sample_xml "buildTypes"
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "specifying username and password" do
|
41
93
|
before :each do
|
42
|
-
@user = "bob"
|
43
|
-
@
|
44
|
-
|
94
|
+
@host, @port, @user, @password = "authtc.example.com", 8877, "bob", "marley"
|
95
|
+
@authentication = mock('authentication')
|
96
|
+
TeamcityRestClient::HttpBasicAuthentication.should_receive(:new).with(@host, @port, @user, @password).and_return(@authentication)
|
97
|
+
@tc = Teamcity.new @host, @port, @user, @password
|
45
98
|
end
|
46
99
|
|
47
|
-
it "should create
|
48
|
-
@tc.
|
100
|
+
it "should create HttpBasicAuthetication" do
|
101
|
+
@tc.authentication.should === @authentication
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "specifying no username and password" do
|
106
|
+
before :each do
|
107
|
+
@host, @port = "authtc.example.com", 8877
|
108
|
+
@authentication = mock('authentication')
|
109
|
+
TeamcityRestClient::Open.should_receive(:new).with(@host, @port).and_return(@authentication)
|
110
|
+
@tc = Teamcity.new @host, @port
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should create HttpBasicAuthetication" do
|
114
|
+
@tc.authentication.should === @authentication
|
49
115
|
end
|
50
116
|
end
|
51
117
|
|
@@ -83,9 +149,32 @@ describe Teamcity do
|
|
83
149
|
end
|
84
150
|
end
|
85
151
|
|
152
|
+
describe "when authentication fails" do
|
153
|
+
before :each do
|
154
|
+
@host, @port = "fail.example.com", 1234
|
155
|
+
@authentication = TeamcityRestClient::Open.new @host, @port
|
156
|
+
TeamcityRestClient::Open.should_receive(:new).and_return(@authentication)
|
157
|
+
fail_html = <<HTML
|
158
|
+
|
159
|
+
<!DOCTYPE html>
|
160
|
+
<html id="htmlId">
|
161
|
+
something
|
162
|
+
</html>
|
163
|
+
HTML
|
164
|
+
|
165
|
+
@authentication.should_receive(:get).with("/app/rest/buildTypes").and_return(fail_html)
|
166
|
+
@tc = Teamcity.new @host, @port
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should raise an error" do
|
170
|
+
lambda { @tc.build_types }.should raise_error "Teamcity returned html, perhaps you need to use authentication??"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
86
174
|
describe "parsing xml feeds" do
|
87
175
|
before :each do
|
88
|
-
@
|
176
|
+
@host, @port = "tc.example.com", 1234
|
177
|
+
@authentication = TeamcityRestClient::Open.new @host, @port
|
89
178
|
end
|
90
179
|
|
91
180
|
describe "projects" do
|
@@ -97,7 +186,9 @@ describe Teamcity do
|
|
97
186
|
<project name="Apache Ant" id="project28" href="/app/rest/projects/id:project28"/>
|
98
187
|
</projects>
|
99
188
|
XML
|
100
|
-
@
|
189
|
+
@authentication.should_receive(:get).with("/app/rest/projects").and_return(xml)
|
190
|
+
TeamcityRestClient::Open.should_receive(:new).and_return(@authentication)
|
191
|
+
@tc = Teamcity.new @host, @port
|
101
192
|
@projects = @tc.projects
|
102
193
|
end
|
103
194
|
|
@@ -131,7 +222,9 @@ XML
|
|
131
222
|
projectName="Amazon API client" projectId="project54" webUrl="http://teamcity.jetbrains.com/viewType.html?buildTypeId=bt296"/>
|
132
223
|
</buildTypes>
|
133
224
|
XML
|
134
|
-
@
|
225
|
+
@authentication.should_receive(:get).with("/app/rest/buildTypes").and_return(xml)
|
226
|
+
TeamcityRestClient::Open.should_receive(:new).and_return(@authentication)
|
227
|
+
@tc = Teamcity.new @host, @port
|
135
228
|
@build_types = @tc.build_types
|
136
229
|
end
|
137
230
|
|
@@ -171,7 +264,9 @@ XML
|
|
171
264
|
webUrl="http://teamcity.jetbrains.com/viewLog.html?buildId=56262&buildTypeId=bt213"/>
|
172
265
|
</builds>
|
173
266
|
XML
|
174
|
-
@
|
267
|
+
@authentication.should_receive(:get).with("/app/rest/builds").and_return(xml)
|
268
|
+
TeamcityRestClient::Open.should_receive(:new).and_return(@authentication)
|
269
|
+
@tc = Teamcity.new @host, @port
|
175
270
|
@builds = @tc.builds
|
176
271
|
end
|
177
272
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: teamcity-rest-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2011-10-24 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &2159395860 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 2.3.0
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2159395860
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: bundler
|
27
|
-
requirement: &
|
27
|
+
requirement: &2159395380 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 1.0.0
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2159395380
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: jeweler
|
38
|
-
requirement: &
|
38
|
+
requirement: &2159394900 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 1.6.4
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2159394900
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rcov
|
49
|
-
requirement: &
|
49
|
+
requirement: &2159394420 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *2159394420
|
58
58
|
description: Teamcity rest api client (readonly)
|
59
59
|
email: simojenki@gmail.com
|
60
60
|
executables: []
|
@@ -94,7 +94,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
94
|
version: '0'
|
95
95
|
segments:
|
96
96
|
- 0
|
97
|
-
hash:
|
97
|
+
hash: 2223201661142505741
|
98
98
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
99
|
none: false
|
100
100
|
requirements:
|