build_eval 0.0.3 → 0.0.4
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.
- checksums.yaml +4 -4
- data/lib/build_eval/error.rb +11 -0
- data/lib/build_eval/http.rb +17 -3
- data/lib/build_eval/result/build_result.rb +2 -2
- data/lib/build_eval/result/status.rb +5 -4
- data/lib/build_eval/server/cruise_control_response.rb +22 -0
- data/lib/build_eval/server/decorator.rb +1 -1
- data/lib/build_eval/server/invalid_selector_error.rb +13 -0
- data/lib/build_eval/server/jenkins.rb +23 -0
- data/lib/build_eval/server/team_city.rb +2 -5
- data/lib/build_eval/server/travis.rb +3 -6
- data/lib/build_eval/version.rb +1 -1
- data/lib/build_eval.rb +7 -1
- data/spec/lib/build_eval/error_spec.rb +21 -0
- data/spec/lib/build_eval/http_shared_context.rb +7 -0
- data/spec/lib/build_eval/http_spec.rb +25 -5
- data/spec/lib/build_eval/result/build_result_spec.rb +4 -4
- data/spec/lib/build_eval/result/status_spec.rb +30 -11
- data/spec/lib/build_eval/server/cruise_control_response_spec.rb +115 -0
- data/spec/lib/build_eval/server/decorator_spec.rb +6 -6
- data/spec/lib/build_eval/server/invalid_selector_error_spec.rb +27 -0
- data/spec/lib/build_eval/server/jenkins_integration_spec.rb +52 -0
- data/spec/lib/build_eval/server/jenkins_spec.rb +70 -0
- data/spec/lib/build_eval/server/server_shared_examples.rb +15 -0
- data/spec/lib/build_eval/server/team_city_integration_spec.rb +85 -0
- data/spec/lib/build_eval/server/team_city_spec.rb +24 -88
- data/spec/lib/build_eval/server/travis_integration_spec.rb +53 -0
- data/spec/lib/build_eval/server/travis_spec.rb +33 -55
- data/spec/lib/build_eval_smoke_spec.rb +25 -0
- data/spec/spec_helper.rb +14 -6
- metadata +42 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9ed39e2bae3a1ef5d1ffd40242183287fae193a
|
4
|
+
data.tar.gz: bff2e6552ad2a28e5d1dbc0cea6b463cd6a82a3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b6006e6709284a157a71b6b48f09b0706f9112c89706e57de79faf3a40d3b46d8e998366c422420349f5d48e1e2beb6e0f6ff3cdddb59993efb5abe34bc862a6
|
7
|
+
data.tar.gz: 6c2978e0ce2095206a9086b018beef07e409f18dbf3c8e9afb5c7b8210942728b496ac04d8af499f3e9d54deb5df6435dfedef34f18d252661602afc1f1113b1
|
data/lib/build_eval/http.rb
CHANGED
@@ -2,15 +2,29 @@ module BuildEval
|
|
2
2
|
|
3
3
|
class Http
|
4
4
|
|
5
|
-
def
|
5
|
+
def initialize(config)
|
6
|
+
@username = config[:username]
|
7
|
+
@password = config[:password]
|
8
|
+
@ssl_verify_mode = config[:ssl_verify_mode]
|
9
|
+
end
|
10
|
+
|
11
|
+
def get(uri_string)
|
6
12
|
uri = URI.parse(uri_string)
|
7
|
-
Net::HTTP.start(uri.host, uri.port,
|
13
|
+
Net::HTTP.start(uri.host, uri.port, ssl_options(uri)) do |http|
|
8
14
|
request = Net::HTTP::Get.new(uri.request_uri)
|
9
|
-
request.basic_auth(
|
15
|
+
request.basic_auth(@username, @password) if @username && @password
|
10
16
|
http.request(request)
|
11
17
|
end
|
12
18
|
end
|
13
19
|
|
20
|
+
private
|
21
|
+
|
22
|
+
def ssl_options(uri)
|
23
|
+
ssl_options = { use_ssl: uri.scheme == "https" }
|
24
|
+
ssl_options[:ssl_verify_mode] = @ssl_verify_mode if @ssl_verify_mode
|
25
|
+
ssl_options
|
26
|
+
end
|
27
|
+
|
14
28
|
end
|
15
29
|
|
16
30
|
end
|
@@ -9,8 +9,8 @@ module BuildEval
|
|
9
9
|
self.new(build_name: args[:build_name], status: BuildEval::Result::Status.find(args[:status_name]))
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
self.new(build_name: build_name, status: BuildEval::Result::Status::
|
12
|
+
def indeterminate(build_name)
|
13
|
+
self.new(build_name: build_name, status: BuildEval::Result::Status::INDETERMINATE)
|
14
14
|
end
|
15
15
|
|
16
16
|
end
|
@@ -13,10 +13,11 @@ module BuildEval
|
|
13
13
|
|
14
14
|
public
|
15
15
|
|
16
|
-
SUCCESS
|
17
|
-
UNKNOWN
|
18
|
-
|
19
|
-
|
16
|
+
SUCCESS = self.new(severity: 0, symbol: :success!, description: "succeeded")
|
17
|
+
UNKNOWN = self.new(severity: 1, symbol: :warning!, description: "unknown")
|
18
|
+
INDETERMINATE = self.new(severity: 2, symbol: :warning!, description: "indeterminate")
|
19
|
+
FAILURE = self.new(severity: 3, symbol: :failure!, description: "failed")
|
20
|
+
ERROR = self.new(severity: 4, symbol: :failure!, description: "errored")
|
20
21
|
|
21
22
|
class << self
|
22
23
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module BuildEval
|
2
|
+
module Server
|
3
|
+
|
4
|
+
class CruiseControlResponse
|
5
|
+
|
6
|
+
def initialize(raw_response)
|
7
|
+
@raw_response = raw_response
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse_result(project_selector)
|
11
|
+
build_element = Nokogiri::XML(@raw_response.body).xpath(project_selector).first
|
12
|
+
raise BuildEval::Server::InvalidSelectorError.new(@raw_response, project_selector) unless build_element
|
13
|
+
BuildEval::Result::BuildResult.create(
|
14
|
+
build_name: build_element.attribute("name").value.match(/[^\/]+$/)[0],
|
15
|
+
status_name: build_element.attribute("lastBuildStatus").value
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module BuildEval
|
2
|
+
module Server
|
3
|
+
|
4
|
+
class InvalidSelectorError < BuildEval::Error
|
5
|
+
|
6
|
+
def initialize(response, selector)
|
7
|
+
super("Build response did not match selector:\nResponse: #{response.message}\nSelector: #{selector}")
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module BuildEval
|
2
|
+
module Server
|
3
|
+
|
4
|
+
class Jenkins
|
5
|
+
|
6
|
+
def initialize(args)
|
7
|
+
@http = BuildEval::Http.new(args)
|
8
|
+
@base_uri = args[:uri]
|
9
|
+
end
|
10
|
+
|
11
|
+
def build_result(name)
|
12
|
+
raw_response = @http.get("#{@base_uri}/cc.xml")
|
13
|
+
BuildEval::Server::CruiseControlResponse.new(raw_response).parse_result("//Project[@name=\"#{name}\"]")
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
"Jenkins server #{@base_uri}"
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -4,15 +4,12 @@ module BuildEval
|
|
4
4
|
class TeamCity
|
5
5
|
|
6
6
|
def initialize(args)
|
7
|
+
@http = BuildEval::Http.new(args)
|
7
8
|
@base_uri = args[:uri]
|
8
|
-
@username = args[:username]
|
9
|
-
@password = args[:password]
|
10
9
|
end
|
11
10
|
|
12
11
|
def build_result(name)
|
13
|
-
response =
|
14
|
-
"#{@base_uri}/httpAuth/app/rest/buildTypes/id:#{name}/builds", username: @username, password: @password
|
15
|
-
)
|
12
|
+
response = @http.get("#{@base_uri}/httpAuth/app/rest/buildTypes/id:#{name}/builds")
|
16
13
|
build_element = Nokogiri::XML(response.body).xpath("//build").first
|
17
14
|
raise "Unexpected build response: #{response.message}" unless build_element
|
18
15
|
BuildEval::Result::BuildResult.create(build_name: name, status_name: build_element.attribute("status").value)
|
@@ -4,16 +4,13 @@ module BuildEval
|
|
4
4
|
class Travis
|
5
5
|
|
6
6
|
def initialize(args)
|
7
|
+
@http = BuildEval::Http.new(args)
|
7
8
|
@username = args[:username]
|
8
9
|
end
|
9
10
|
|
10
11
|
def build_result(name)
|
11
|
-
|
12
|
-
|
13
|
-
raise "Unexpected build response: #{response.message}" unless build_element
|
14
|
-
BuildEval::Result::BuildResult.create(
|
15
|
-
build_name: name, status_name: build_element.attribute("lastBuildStatus").value
|
16
|
-
)
|
12
|
+
raw_response = @http.get("https://api.travis-ci.org/repositories/#{@username}/#{name}/cc.xml")
|
13
|
+
BuildEval::Server::CruiseControlResponse.new(raw_response).parse_result("//Project")
|
17
14
|
end
|
18
15
|
|
19
16
|
def to_s
|
data/lib/build_eval/version.rb
CHANGED
data/lib/build_eval.rb
CHANGED
@@ -1,13 +1,19 @@
|
|
1
1
|
require 'nokogiri'
|
2
|
-
|
2
|
+
require 'uri'
|
3
|
+
require 'net/http'
|
4
|
+
require 'net/https'
|
5
|
+
require_relative 'build_eval/error'
|
3
6
|
require_relative 'build_eval/http'
|
4
7
|
require_relative 'build_eval/result/status'
|
5
8
|
require_relative 'build_eval/result/build_result'
|
6
9
|
require_relative 'build_eval/result/server_result'
|
7
10
|
require_relative 'build_eval/result/composite_result'
|
11
|
+
require_relative 'build_eval/server/invalid_selector_error'
|
8
12
|
require_relative 'build_eval/server/decorator'
|
13
|
+
require_relative 'build_eval/server/cruise_control_response'
|
9
14
|
require_relative 'build_eval/server/team_city'
|
10
15
|
require_relative 'build_eval/server/travis'
|
16
|
+
require_relative 'build_eval/server/jenkins'
|
11
17
|
require_relative 'build_eval/monitor/base'
|
12
18
|
require_relative 'build_eval/monitor/server'
|
13
19
|
require_relative 'build_eval/monitor/composite'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
describe BuildEval::Error do
|
2
|
+
|
3
|
+
let(:message) { "some message" }
|
4
|
+
|
5
|
+
let(:error) { described_class.new(message) }
|
6
|
+
|
7
|
+
it "is a standard error" do
|
8
|
+
expect(error).to be_a(::StandardError)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#messsage" do
|
12
|
+
|
13
|
+
subject { error.message }
|
14
|
+
|
15
|
+
it "returns the provided message" do
|
16
|
+
expect(subject).to eql(message)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -1,5 +1,9 @@
|
|
1
1
|
describe BuildEval::Http do
|
2
2
|
|
3
|
+
let(:config) { {} }
|
4
|
+
|
5
|
+
let(:http) { described_class.new(config) }
|
6
|
+
|
3
7
|
shared_examples_for "a http method returning a response" do
|
4
8
|
|
5
9
|
let(:response_status) { [ "200", "OK" ] }
|
@@ -19,14 +23,14 @@ describe BuildEval::Http do
|
|
19
23
|
|
20
24
|
end
|
21
25
|
|
22
|
-
describe "
|
26
|
+
describe "#get" do
|
23
27
|
|
24
28
|
let(:scheme) { "http" }
|
25
29
|
let(:host) { "a.host" }
|
26
30
|
let(:path) { "some/path" }
|
27
31
|
let(:uri_string) { "#{scheme}://#{host}/#{path}" }
|
28
32
|
|
29
|
-
subject {
|
33
|
+
subject { http.get(uri_string) }
|
30
34
|
|
31
35
|
context "when the uri is valid" do
|
32
36
|
|
@@ -52,15 +56,31 @@ describe BuildEval::Http do
|
|
52
56
|
|
53
57
|
end
|
54
58
|
|
55
|
-
context "and
|
59
|
+
context "and an ssl verification mode configuration option was established" do
|
60
|
+
|
61
|
+
let(:ssl_verification_mode) { OpenSSL::SSL::VERIFY_NONE }
|
62
|
+
let(:config) { { ssl_verify_mode: ssl_verification_mode } }
|
63
|
+
|
64
|
+
it_behaves_like "a http method returning a response"
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
context "and partial authentication configuration options were established" do
|
69
|
+
|
70
|
+
let(:config) { { username: "some_username" } }
|
71
|
+
|
72
|
+
it_behaves_like "a http method returning a response"
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
context "and basic authentication configuration options were established" do
|
56
77
|
|
57
78
|
let(:username) { "some_username" }
|
58
79
|
let(:password) { "some_password" }
|
80
|
+
let(:config) { { username: username, password: password } }
|
59
81
|
|
60
82
|
let(:expected_request_uri) { "#{scheme}://#{username}:#{password}@#{host}/#{path}" }
|
61
83
|
|
62
|
-
subject { described_class.get(uri_string, basic_authentication: { username: username, password: password }) }
|
63
|
-
|
64
84
|
it_behaves_like "a http method returning a response"
|
65
85
|
|
66
86
|
end
|
@@ -27,18 +27,18 @@ describe BuildEval::Result::BuildResult do
|
|
27
27
|
|
28
28
|
end
|
29
29
|
|
30
|
-
describe "::
|
30
|
+
describe "::indeterminate" do
|
31
31
|
|
32
32
|
let(:build_name) { "Some build name" }
|
33
33
|
|
34
|
-
subject { described_class.
|
34
|
+
subject { described_class.indeterminate(build_name) }
|
35
35
|
|
36
36
|
it "returns a result with the provided build name" do
|
37
37
|
expect(subject.build_name).to eql(build_name)
|
38
38
|
end
|
39
39
|
|
40
|
-
it "returns a result with an
|
41
|
-
expect(subject.status).to eql(BuildEval::Result::Status::
|
40
|
+
it "returns a result with an indeterminate status" do
|
41
|
+
expect(subject.status).to eql(BuildEval::Result::Status::INDETERMINATE)
|
42
42
|
end
|
43
43
|
|
44
44
|
end
|
@@ -50,13 +50,16 @@ describe BuildEval::Result::Status do
|
|
50
50
|
|
51
51
|
end
|
52
52
|
|
53
|
-
context "when the statuses are ordered in
|
53
|
+
context "when the statuses are ordered in ascending severity" do
|
54
54
|
|
55
55
|
let(:statuses) do
|
56
|
-
[
|
56
|
+
[
|
57
|
+
BuildEval::Result::Status::ERROR,
|
57
58
|
BuildEval::Result::Status::FAILURE,
|
58
59
|
BuildEval::Result::Status::UNKNOWN,
|
59
|
-
BuildEval::Result::Status::
|
60
|
+
BuildEval::Result::Status::INDETERMINATE,
|
61
|
+
BuildEval::Result::Status::SUCCESS
|
62
|
+
]
|
60
63
|
end
|
61
64
|
|
62
65
|
it "returns the most severe status" do
|
@@ -65,13 +68,16 @@ describe BuildEval::Result::Status do
|
|
65
68
|
|
66
69
|
end
|
67
70
|
|
68
|
-
context "when the statuses are ordered in
|
71
|
+
context "when the statuses are ordered in descending severity" do
|
69
72
|
|
70
73
|
let(:statuses) do
|
71
|
-
[
|
74
|
+
[
|
75
|
+
BuildEval::Result::Status::SUCCESS,
|
72
76
|
BuildEval::Result::Status::UNKNOWN,
|
77
|
+
BuildEval::Result::Status::INDETERMINATE,
|
73
78
|
BuildEval::Result::Status::FAILURE,
|
74
|
-
BuildEval::Result::Status::ERROR
|
79
|
+
BuildEval::Result::Status::ERROR
|
80
|
+
]
|
75
81
|
end
|
76
82
|
|
77
83
|
it "returns the most severe status" do
|
@@ -97,9 +103,10 @@ describe BuildEval::Result::Status do
|
|
97
103
|
end
|
98
104
|
|
99
105
|
{
|
100
|
-
"UNKNOWN"
|
101
|
-
"FAILURE"
|
102
|
-
"ERROR"
|
106
|
+
"UNKNOWN" => BuildEval::Result::Status::UNKNOWN,
|
107
|
+
"FAILURE" => BuildEval::Result::Status::FAILURE,
|
108
|
+
"ERROR" => BuildEval::Result::Status::ERROR,
|
109
|
+
"INDETERMINATE" => BuildEval::Result::Status::INDETERMINATE
|
103
110
|
}.each do |name, status|
|
104
111
|
|
105
112
|
context "when the status is #{name}" do
|
@@ -120,7 +127,13 @@ describe BuildEval::Result::Status do
|
|
120
127
|
|
121
128
|
subject { status.to_sym }
|
122
129
|
|
123
|
-
{
|
130
|
+
{
|
131
|
+
SUCCESS: :success!,
|
132
|
+
UNKNOWN: :warning!,
|
133
|
+
INDETERMINATE: :warning!,
|
134
|
+
FAILURE: :failure!,
|
135
|
+
ERROR: :failure!
|
136
|
+
}.each do |name, expected_symbol|
|
124
137
|
|
125
138
|
context "when the status is #{name}" do
|
126
139
|
|
@@ -140,7 +153,13 @@ describe BuildEval::Result::Status do
|
|
140
153
|
|
141
154
|
subject { status.to_s }
|
142
155
|
|
143
|
-
{
|
156
|
+
{
|
157
|
+
SUCCESS: "succeeded",
|
158
|
+
UNKNOWN: "unknown",
|
159
|
+
INDETERMINATE: "indeterminate",
|
160
|
+
FAILURE: "failed",
|
161
|
+
ERROR: "errored"
|
162
|
+
}.each do |name, expected_string|
|
144
163
|
|
145
164
|
context "when the status is #{name}" do
|
146
165
|
|
@@ -0,0 +1,115 @@
|
|
1
|
+
describe BuildEval::Server::CruiseControlResponse do
|
2
|
+
|
3
|
+
let(:raw_response) { double("RawResponse", body: response_body) }
|
4
|
+
|
5
|
+
let(:cruise_control_response) { described_class.new(raw_response) }
|
6
|
+
|
7
|
+
describe "#parse_result" do
|
8
|
+
|
9
|
+
let(:build_name) { "some_build_name" }
|
10
|
+
let(:response_build_name) { build_name }
|
11
|
+
let(:project_selector) { "//Project[2]" }
|
12
|
+
|
13
|
+
subject { cruise_control_response.parse_result(project_selector) }
|
14
|
+
|
15
|
+
context "when the response is successful, containing projects" do
|
16
|
+
|
17
|
+
let(:latest_build_status) { "Success" }
|
18
|
+
let(:response_body) do
|
19
|
+
<<-RESPONSE
|
20
|
+
<Projects>
|
21
|
+
<Project name="another_build_name" activity="Sleeping" lastBuildStatus="Unknown" lastBuildLabel="2" lastBuildTime="2015-08-02T00:00:00.000+0000" webUrl="https://my.build.server/another_build_name" />
|
22
|
+
<Project name="#{response_build_name}" activity="Sleeping" lastBuildStatus="#{latest_build_status}" lastBuildLabel="1" lastBuildTime="2015-08-01T00:00:00.000+0000" webUrl="https://my.build.server/#{build_name}" />
|
23
|
+
<Project name="yet_another_build_name" activity="Sleeping" lastBuildStatus="Error" lastBuildLabel="3" lastBuildTime="2015-08-03T00:00:00.000+0000" webUrl="https://my.build.server/yet_another_build_name" />
|
24
|
+
</Projects>
|
25
|
+
RESPONSE
|
26
|
+
end
|
27
|
+
|
28
|
+
context "and the selector matches a project" do
|
29
|
+
|
30
|
+
context "and the build name in the response is not a path" do
|
31
|
+
|
32
|
+
it "creates a build result with the build name from the response" do
|
33
|
+
expect(BuildEval::Result::BuildResult).to receive(:create).with(hash_including(build_name: build_name))
|
34
|
+
|
35
|
+
subject
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
context "and the build name in the response is a path" do
|
41
|
+
|
42
|
+
let(:response_build_name) { "some/path/to/#{build_name}" }
|
43
|
+
|
44
|
+
it "creates a build result with the build name from the response with the path omitted" do
|
45
|
+
expect(BuildEval::Result::BuildResult).to receive(:create).with(hash_including(build_name: build_name))
|
46
|
+
|
47
|
+
subject
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
it "creates a build result containing the latest build status" do
|
53
|
+
expect(BuildEval::Result::BuildResult).to(
|
54
|
+
receive(:create).with(hash_including(status_name: latest_build_status))
|
55
|
+
)
|
56
|
+
|
57
|
+
subject
|
58
|
+
end
|
59
|
+
|
60
|
+
it "returns the created result" do
|
61
|
+
build_result = instance_double(BuildEval::Result::BuildResult)
|
62
|
+
allow(BuildEval::Result::BuildResult).to receive(:create).and_return(build_result)
|
63
|
+
|
64
|
+
expect(subject).to eql(build_result)
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
context "and the selector does not match a project" do
|
70
|
+
|
71
|
+
let(:project_selector) { "does_not_match" }
|
72
|
+
let(:error) { "an error" }
|
73
|
+
|
74
|
+
before(:example) { allow(BuildEval::Server::InvalidSelectorError).to receive(:new).and_return(error) }
|
75
|
+
|
76
|
+
it "creates an invalid selector error" do
|
77
|
+
expect(BuildEval::Server::InvalidSelectorError).to(
|
78
|
+
receive(:new).with(raw_response, project_selector).and_return(error)
|
79
|
+
)
|
80
|
+
|
81
|
+
subject rescue Exception
|
82
|
+
end
|
83
|
+
|
84
|
+
it "raises the error" do
|
85
|
+
expect { subject }.to raise_error(error)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
context "when the response is in error" do
|
93
|
+
|
94
|
+
let(:response_body) { { "file" => "not found" }.to_json }
|
95
|
+
let(:error) { "an error" }
|
96
|
+
|
97
|
+
before(:example) { allow(BuildEval::Server::InvalidSelectorError).to receive(:new).and_return(error) }
|
98
|
+
|
99
|
+
it "creates an invalid selector error" do
|
100
|
+
expect(BuildEval::Server::InvalidSelectorError).to(
|
101
|
+
receive(:new).with(raw_response, project_selector).and_return(error)
|
102
|
+
)
|
103
|
+
|
104
|
+
subject rescue Exception
|
105
|
+
end
|
106
|
+
|
107
|
+
it "raises an invalid selector error" do
|
108
|
+
expect { subject }.to raise_error(error)
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
@@ -32,17 +32,17 @@ describe BuildEval::Server::Decorator do
|
|
32
32
|
|
33
33
|
before(:example) { allow(server).to receive(:build_result).and_raise("Forced error") }
|
34
34
|
|
35
|
-
it "creates an
|
36
|
-
expect(BuildEval::Result::BuildResult).to receive(:
|
35
|
+
it "creates an indeterminate result" do
|
36
|
+
expect(BuildEval::Result::BuildResult).to receive(:indeterminate).with(build_name)
|
37
37
|
|
38
38
|
subject
|
39
39
|
end
|
40
40
|
|
41
|
-
it "returns the
|
42
|
-
|
43
|
-
allow(BuildEval::Result::BuildResult).to receive(:
|
41
|
+
it "returns the indeterminate result" do
|
42
|
+
indeterminate_result = instance_double(BuildEval::Result::BuildResult)
|
43
|
+
allow(BuildEval::Result::BuildResult).to receive(:indeterminate).and_return(indeterminate_result)
|
44
44
|
|
45
|
-
expect(subject).to eql(
|
45
|
+
expect(subject).to eql(indeterminate_result)
|
46
46
|
end
|
47
47
|
|
48
48
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
describe BuildEval::Server::InvalidSelectorError do
|
2
|
+
|
3
|
+
let(:response_message) { "Some response message" }
|
4
|
+
let(:response) { double("HttpResponse", message: response_message) }
|
5
|
+
let(:selector) { "some/selector" }
|
6
|
+
|
7
|
+
let(:error) { described_class.new(response, selector) }
|
8
|
+
|
9
|
+
describe "#message" do
|
10
|
+
|
11
|
+
subject { error.message }
|
12
|
+
|
13
|
+
it "indicates the selector was not matched" do
|
14
|
+
expect(subject).to match(/response did not match selector/i)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "contains a message describing the response" do
|
18
|
+
expect(subject).to include(response_message)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "contains the selector that was invalid" do
|
22
|
+
expect(subject).to include(selector)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
describe BuildEval::Server::Jenkins, "integrating with a response parser", integration: true do
|
2
|
+
include_context "stubbed http interactions"
|
3
|
+
|
4
|
+
let(:uri) { "https://some.jenkins.server" }
|
5
|
+
|
6
|
+
let(:jenkins) { described_class.new(uri: uri) }
|
7
|
+
|
8
|
+
describe "#build_result" do
|
9
|
+
|
10
|
+
let(:build_name) { "some_build_name" }
|
11
|
+
let(:response) { instance_double(Net::HTTPResponse, body: response_body) }
|
12
|
+
|
13
|
+
subject { jenkins.build_result(build_name) }
|
14
|
+
|
15
|
+
before(:example) { allow(http).to receive(:get).and_return(response) }
|
16
|
+
|
17
|
+
context "when the server responds successfully with build results" do
|
18
|
+
|
19
|
+
let(:latest_build_status) { "Failure" }
|
20
|
+
let(:response_body) do
|
21
|
+
<<-RESPONSE
|
22
|
+
<Projects>
|
23
|
+
<Project webUrl="#{uri}/job/#{build_name}/" name="#{build_name}" lastBuildLabel="190" lastBuildTime="2015-10-09T02:39:36Z" lastBuildStatus="#{latest_build_status}" activity="Sleeping"/>
|
24
|
+
<Project webUrl="#{uri}/job/another_build_name/" name="another_build_name" lastBuildLabel="71" lastBuildTime="2015-10-12T17:07:00Z" lastBuildStatus="Success" activity="Sleeping"/>
|
25
|
+
<Project webUrl="#{uri}/job/yet_another_build_name/" name="yet_another_build_name" lastBuildLabel="15" lastBuildTime="2015-10-13T01:40:32Z" lastBuildStatus="Success" activity="Sleeping"/>
|
26
|
+
</Projects>
|
27
|
+
RESPONSE
|
28
|
+
end
|
29
|
+
|
30
|
+
it "creates a build result containing the build name" do
|
31
|
+
expect(BuildEval::Result::BuildResult).to receive(:create).with(hash_including(build_name: build_name))
|
32
|
+
|
33
|
+
subject
|
34
|
+
end
|
35
|
+
|
36
|
+
it "creates a build result containing the latest build status" do
|
37
|
+
expect(BuildEval::Result::BuildResult).to receive(:create).with(hash_including(status_name: latest_build_status))
|
38
|
+
subject
|
39
|
+
end
|
40
|
+
|
41
|
+
it "returns the created result" do
|
42
|
+
build_result = instance_double(BuildEval::Result::BuildResult)
|
43
|
+
allow(BuildEval::Result::BuildResult).to receive(:create).and_return(build_result)
|
44
|
+
|
45
|
+
expect(subject).to eql(build_result)
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|