pact_broker 2.77.0 → 2.78.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/db/migrations/20210210_create_environments_table.rb +16 -0
- data/lib/pact_broker/api.rb +5 -0
- data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +8 -0
- data/lib/pact_broker/api/contracts/environment_schema.rb +49 -0
- data/lib/pact_broker/api/decorators/base_decorator.rb +11 -0
- data/lib/pact_broker/api/decorators/environment_decorator.rb +30 -0
- data/lib/pact_broker/api/decorators/environments_decorator.rb +21 -0
- data/lib/pact_broker/api/decorators/version_decorator.rb +12 -1
- data/lib/pact_broker/api/pact_broker_urls.rb +8 -0
- data/lib/pact_broker/api/resources/default_base_resource.rb +9 -0
- data/lib/pact_broker/api/resources/environment.rb +76 -0
- data/lib/pact_broker/api/resources/environments.rb +75 -0
- data/lib/pact_broker/api/resources/index.rb +14 -0
- data/lib/pact_broker/api/resources/version.rb +2 -2
- data/lib/pact_broker/configuration.rb +1 -0
- data/lib/pact_broker/deployments/environment.rb +15 -0
- data/lib/pact_broker/deployments/environment_service.rb +39 -0
- data/lib/pact_broker/doc/views/index/environment.markdown +37 -0
- data/lib/pact_broker/doc/views/index/environments.markdown +53 -0
- data/lib/pact_broker/doc/views/index/latest-pact-versions.markdown +1 -1
- data/lib/pact_broker/doc/views/index/pacticipant-version-tag.markdown +1 -0
- data/lib/pact_broker/locale/en.yml +3 -1
- data/lib/pact_broker/services.rb +9 -0
- data/lib/pact_broker/test/test_data_builder.rb +14 -0
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/repository.rb +15 -4
- data/lib/pact_broker/versions/service.rb +2 -2
- data/lib/pact_broker/webhooks/webhook_execution_result.rb +4 -1
- data/spec/features/create_environment_spec.rb +47 -0
- data/spec/features/create_tag_spec.rb +32 -0
- data/spec/features/create_version_spec.rb +30 -4
- data/spec/features/delete_environment_spec.rb +16 -0
- data/spec/features/end_deployment_spec.rb +29 -0
- data/spec/features/get_environment_spec.rb +19 -0
- data/spec/features/get_environments_spec.rb +20 -0
- data/spec/features/record_deployment_spec.rb +28 -0
- data/spec/features/update_environment_spec.rb +44 -0
- data/spec/fixtures/approvals/modifiable_resources.approved.json +6 -0
- data/spec/lib/pact_broker/api/contracts/environment_schema_spec.rb +83 -0
- data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +18 -0
- data/spec/lib/pact_broker/api/resources/default_base_resource_approval_spec.rb +1 -1
- data/spec/lib/pact_broker/api/resources/webhook_execution_result_spec.rb +56 -0
- data/spec/lib/pact_broker/versions/repository_spec.rb +14 -4
- data/spec/service_consumers/hal_relation_proxy_app.rb +3 -1
- data/spec/service_consumers/provider_states_for_pact_broker_client.rb +16 -0
- data/spec/support/shared_examples_for_responses.rb +11 -0
- metadata +33 -3
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'pact_broker/api/pact_broker_urls'
|
2
|
+
|
3
|
+
describe "Deleting an environment" do
|
4
|
+
before do
|
5
|
+
td.create_environment("test", uuid: "1234")
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:path) { PactBroker::Api::PactBrokerUrls.environment_url(td.and_return(:environment)) }
|
9
|
+
|
10
|
+
subject { delete(path, nil) }
|
11
|
+
|
12
|
+
it "returns a 204 response" do
|
13
|
+
subject
|
14
|
+
expect(last_response.status).to be 204
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#
|
2
|
+
# RPC style seems cleaner than REST here, as setting the endedAt parameter directly
|
3
|
+
# seems likely to end in Timezone tears
|
4
|
+
# This endpoint would be called by the pact broker client during `record-deployment` if the
|
5
|
+
# --end-previous-deployment (on by default) was specified.
|
6
|
+
# This allows us to know exactly what is deployed to a particular environment at a given time,
|
7
|
+
# (eg. /environments/test/deployments/current)
|
8
|
+
# and provides first class support for mobile clients that have multiple versions in prod
|
9
|
+
# at once.
|
10
|
+
|
11
|
+
describe "Record deployment ended", skip: "Not yet implemented" do
|
12
|
+
before do
|
13
|
+
td.create_environment("test")
|
14
|
+
.create_pacticipant("Foo")
|
15
|
+
.create_pacticipant_version("1")
|
16
|
+
.create_deployment("test")
|
17
|
+
end
|
18
|
+
let(:path) { "/pacticipants/Foo/deployments/test/latest/end" }
|
19
|
+
let(:headers) { {} }
|
20
|
+
let(:response_body) { JSON.parse(last_response.body, symbolize_names: true) }
|
21
|
+
|
22
|
+
subject { post(path, nil, headers) }
|
23
|
+
|
24
|
+
it { is_expected.be_a_hal_json_success_response }
|
25
|
+
|
26
|
+
it "returns the updated deployment" do
|
27
|
+
expect(subject[:endedAt]).to_not be nil
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'pact_broker/api/pact_broker_urls'
|
2
|
+
|
3
|
+
describe "Get an environment" do
|
4
|
+
before do
|
5
|
+
td.create_environment("test", display_name: "Test", uuid: "1234", contacts: [ { name: "Foo" } ] )
|
6
|
+
end
|
7
|
+
let(:path) { PactBroker::Api::PactBrokerUrls.environment_url(td.and_return(:environment)) }
|
8
|
+
let(:headers) { {'HTTP_ACCEPT' => 'application/hal+json'} }
|
9
|
+
let(:response_body) { JSON.parse(subject.body, symbolize_names: true)}
|
10
|
+
|
11
|
+
subject { get(path, nil, headers) }
|
12
|
+
|
13
|
+
it { is_expected.to be_a_hal_json_success_response }
|
14
|
+
|
15
|
+
it "returns the environment" do
|
16
|
+
expect(response_body[:uuid]).to eq "1234"
|
17
|
+
expect(response_body[:name]).to eq "test"
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'pact_broker/api/pact_broker_urls'
|
2
|
+
|
3
|
+
describe "Get all environments" do
|
4
|
+
before do
|
5
|
+
td.create_environment("test", display_name: "Test", uuid: "1234", contacts: [ { name: "Foo" } ] )
|
6
|
+
.create_environment("prod", display_name: "Production", uuid: "5678", contacts: [ { name: "Foo" } ] )
|
7
|
+
end
|
8
|
+
let(:path) { PactBroker::Api::PactBrokerUrls.environments_url }
|
9
|
+
let(:headers) { {'HTTP_ACCEPT' => 'application/hal+json'} }
|
10
|
+
let(:response_body) { JSON.parse(last_response.body, symbolize_names: true)}
|
11
|
+
|
12
|
+
subject { get(path, nil, headers) }
|
13
|
+
|
14
|
+
it { is_expected.to be_a_hal_json_success_response }
|
15
|
+
|
16
|
+
it "returns the environments" do
|
17
|
+
subject
|
18
|
+
expect(response_body[:_embedded][:environments].size).to be 2
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#
|
2
|
+
# pact-broker record-deployment --pacticipant Foo --version 1 --environment test --end-previous-deployment
|
3
|
+
#
|
4
|
+
|
5
|
+
describe "Record deployment", skip: "Not yet implemented" do
|
6
|
+
before do
|
7
|
+
td.create_environment("test")
|
8
|
+
.create_pacticipant("Foo")
|
9
|
+
.create_pacticipant_version("1")
|
10
|
+
end
|
11
|
+
let(:path) { "/pacticipants/Foo/versions/1/deployments/test" }
|
12
|
+
let(:headers) { {"CONTENT_TYPE" => "application/json"} }
|
13
|
+
let(:response_body) { JSON.parse(last_response.body, symbolize_names: true)}
|
14
|
+
|
15
|
+
subject { post(path, nil, headers) }
|
16
|
+
|
17
|
+
it { is_expected.to be_a_hal_json_created_response }
|
18
|
+
|
19
|
+
it "returns the Location header" do
|
20
|
+
subject
|
21
|
+
expect(last_response.headers["Location"]).to eq "http://example.org/deployments/123456"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns the newly created deployment" do
|
25
|
+
subject
|
26
|
+
expect(response_body).to include_key(:createdAt)
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'pact_broker/api/pact_broker_urls'
|
2
|
+
|
3
|
+
describe "Updating an environment" do
|
4
|
+
before do
|
5
|
+
td.create_environment("test", uuid: "1234", contacts: [ { name: "Foo" } ] )
|
6
|
+
end
|
7
|
+
let(:path) { PactBroker::Api::PactBrokerUrls.environment_url(td.and_return(:environment)) }
|
8
|
+
let(:headers) { {'CONTENT_TYPE' => 'application/json'} }
|
9
|
+
let(:response_body) { JSON.parse(last_response.body, symbolize_names: true)}
|
10
|
+
let(:environment_hash) do
|
11
|
+
{
|
12
|
+
name: "test",
|
13
|
+
production: false,
|
14
|
+
displayName: "Testing"
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
subject { put(path, environment_hash.to_json, headers) }
|
19
|
+
|
20
|
+
it { is_expected.to be_a_hal_json_success_response }
|
21
|
+
|
22
|
+
it "returns the updated environment" do
|
23
|
+
subject
|
24
|
+
expect(response_body[:displayName]).to eq "Testing"
|
25
|
+
expect(response_body[:contacts]).to be nil
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when the environment doesn't exist" do
|
29
|
+
let(:path) { "/environments/5678" }
|
30
|
+
|
31
|
+
it "returns a 404" do
|
32
|
+
expect(subject.status).to eq 404
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "with invalid params" do
|
37
|
+
let(:environment_hash) { {} }
|
38
|
+
|
39
|
+
it "returns a 400 response" do
|
40
|
+
expect(subject.status).to be 400
|
41
|
+
expect(response_body[:errors]).to_not be nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -6,6 +6,12 @@
|
|
6
6
|
{
|
7
7
|
"resource_class_name": "PactBroker::Api::Resources::Clean"
|
8
8
|
},
|
9
|
+
{
|
10
|
+
"resource_class_name": "PactBroker::Api::Resources::Environment"
|
11
|
+
},
|
12
|
+
{
|
13
|
+
"resource_class_name": "PactBroker::Api::Resources::Environments"
|
14
|
+
},
|
9
15
|
{
|
10
16
|
"resource_class_name": "PactBroker::Api::Resources::ErrorTest"
|
11
17
|
},
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'pact_broker/api/contracts/environment_schema'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Api
|
5
|
+
module Contracts
|
6
|
+
describe EnvironmentSchema do
|
7
|
+
before do
|
8
|
+
allow(PactBroker::Deployments::EnvironmentService).to receive(:find_by_name).and_return(existing_environment)
|
9
|
+
end
|
10
|
+
let(:existing_environment) { nil }
|
11
|
+
let(:name) { "test" }
|
12
|
+
|
13
|
+
let(:params) do
|
14
|
+
{
|
15
|
+
uuid: "1234",
|
16
|
+
name: name,
|
17
|
+
displayName: "Test",
|
18
|
+
production: false,
|
19
|
+
contacts: contacts
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:contacts) do
|
24
|
+
[{
|
25
|
+
name: "Foo",
|
26
|
+
details: { email: "foo@bar.com" }
|
27
|
+
}]
|
28
|
+
end
|
29
|
+
|
30
|
+
subject { EnvironmentSchema.call(params) }
|
31
|
+
|
32
|
+
context "with valid params" do
|
33
|
+
it { is_expected.to be_empty }
|
34
|
+
end
|
35
|
+
|
36
|
+
context "with a name with a new line" do
|
37
|
+
let(:name) { "test 1" }
|
38
|
+
|
39
|
+
it { is_expected.to_not be_empty }
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with empty params" do
|
43
|
+
let(:params) { {} }
|
44
|
+
|
45
|
+
it { is_expected.to_not be_empty }
|
46
|
+
end
|
47
|
+
|
48
|
+
context "when there is another environment with the same name but a different uuid" do
|
49
|
+
let(:existing_environment) { instance_double("PactBroker::Deployments::Environment", uuid: "5678")}
|
50
|
+
|
51
|
+
its([:name]) { is_expected.to eq ["Another environment with name 'test' already exists."] }
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when there is another environment with the same name and same uuid" do
|
55
|
+
let(:existing_environment) { instance_double("PactBroker::Deployments::Environment", uuid: "1234")}
|
56
|
+
|
57
|
+
it { is_expected.to be_empty }
|
58
|
+
end
|
59
|
+
|
60
|
+
context "with no owner name" do
|
61
|
+
let(:contacts) do
|
62
|
+
[{
|
63
|
+
details: { email: "foo@bar.com" }
|
64
|
+
}]
|
65
|
+
end
|
66
|
+
|
67
|
+
its([:contacts, 0]) { is_expected.to eq "name is missing at index 0" }
|
68
|
+
end
|
69
|
+
|
70
|
+
context "with string contact details" do
|
71
|
+
let(:contacts) do
|
72
|
+
[{
|
73
|
+
name: "foo",
|
74
|
+
details: "foo"
|
75
|
+
}]
|
76
|
+
end
|
77
|
+
|
78
|
+
its([:contacts, 0]) { is_expected.to eq "details must be a hash at index 0" }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -6,6 +6,24 @@ module PactBroker
|
|
6
6
|
module Decorators
|
7
7
|
describe VersionDecorator do
|
8
8
|
|
9
|
+
describe "from_json" do
|
10
|
+
let(:hash) do
|
11
|
+
{
|
12
|
+
branch: "branch",
|
13
|
+
buildUrl: "buildUrl",
|
14
|
+
tags: [{ name: "main" }]
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
subject { VersionDecorator.new(OpenStruct.new).from_json(hash.to_json) }
|
19
|
+
|
20
|
+
it "sets the properties" do
|
21
|
+
expect(subject.branch).to eq "branch"
|
22
|
+
expect(subject.build_url).to eq "buildUrl"
|
23
|
+
expect(subject.tags.first.name).to eq "main"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
9
27
|
let(:version) do
|
10
28
|
TestDataBuilder.new
|
11
29
|
.create_consumer("Consumer")
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module PactBroker
|
2
|
+
module Webhooks
|
3
|
+
describe WebhookExecutionResult do
|
4
|
+
subject { WebhookExecutionResult::new(request, response, nil) }
|
5
|
+
let(:request) do
|
6
|
+
Net::HTTP::Get.new("http://example.org?foo=bar")
|
7
|
+
end
|
8
|
+
|
9
|
+
context "When 'webhook_http_code_success' has [200, 201]" do
|
10
|
+
before do
|
11
|
+
allow(PactBroker.configuration).to receive(:webhook_http_code_success).and_return([200, 201])
|
12
|
+
end
|
13
|
+
|
14
|
+
context "and response is '200'" do
|
15
|
+
let(:response) { double(code: '200') }
|
16
|
+
|
17
|
+
it "then it should be success" do
|
18
|
+
expect(subject.success?).to be_truthy
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "and response is '400'" do
|
23
|
+
let(:response) { double(code: '400') }
|
24
|
+
|
25
|
+
it "then it should fail" do
|
26
|
+
expect(subject.success?).to be_falsey
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
context "When 'webhook_http_code_success' has [400, 401]" do
|
33
|
+
before do
|
34
|
+
allow(PactBroker.configuration).to receive(:webhook_http_code_success).and_return([400, 401])
|
35
|
+
end
|
36
|
+
|
37
|
+
context "and response is '200'" do
|
38
|
+
let(:response) { double(code: '200') }
|
39
|
+
|
40
|
+
it "then it should fail" do
|
41
|
+
expect(subject.success?).to be_falsey
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "and response is '400'" do
|
46
|
+
let(:response) { double(code: '400') }
|
47
|
+
|
48
|
+
it "then it should be success" do
|
49
|
+
expect(subject.success?).to be_truthy
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -123,7 +123,7 @@ module PactBroker
|
|
123
123
|
end
|
124
124
|
end
|
125
125
|
|
126
|
-
describe "#
|
126
|
+
describe "#create_or_overwrite" do
|
127
127
|
before do
|
128
128
|
td.subtract_day
|
129
129
|
.create_consumer("Foo")
|
@@ -133,9 +133,10 @@ module PactBroker
|
|
133
133
|
|
134
134
|
let(:pacticipant) { td.and_return(:consumer) }
|
135
135
|
let(:version_number) { "1234" }
|
136
|
-
let(:
|
136
|
+
let(:tags) { nil }
|
137
|
+
let(:open_struct_version) { OpenStruct.new(branch: "new-branch", tags: tags) }
|
137
138
|
|
138
|
-
subject { Repository.new.
|
139
|
+
subject { Repository.new.create_or_overwrite(pacticipant, version_number, open_struct_version) }
|
139
140
|
|
140
141
|
it "overwrites the values" do
|
141
142
|
expect(subject.branch).to eq "new-branch"
|
@@ -146,6 +147,15 @@ module PactBroker
|
|
146
147
|
expect { subject }.to_not change { PactBroker::Domain::Version.for("Foo", "1234").tags }
|
147
148
|
end
|
148
149
|
|
150
|
+
context "when there are tags specified" do
|
151
|
+
let(:tags) { [ OpenStruct.new(name: "main")] }
|
152
|
+
|
153
|
+
it "overwrites the tags" do
|
154
|
+
expect(subject.tags.count).to eq 1
|
155
|
+
expect(subject.tags.first.name).to eq "main"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
149
159
|
it "does not change the created date" do
|
150
160
|
expect { subject }.to_not change { PactBroker::Domain::Version.for("Foo", "1234").created_at }
|
151
161
|
end
|
@@ -159,7 +169,7 @@ module PactBroker
|
|
159
169
|
end
|
160
170
|
|
161
171
|
context "when the version does not already exist" do
|
162
|
-
let(:version) {
|
172
|
+
let(:version) { OpenStruct.new(number: "555", branch: "new-branch") }
|
163
173
|
|
164
174
|
it "sets the order" do
|
165
175
|
expect(subject.order).to_not be nil
|
@@ -9,7 +9,9 @@ class HalRelationProxyApp
|
|
9
9
|
'/HAL-REL-PLACEHOLDER-INDEX-PB-LATEST-VERSION-Condor' =>
|
10
10
|
'/pacticipants/Condor/latest-version',
|
11
11
|
'/HAL-REL-PLACEHOLDER-PB-WEBHOOKS' =>
|
12
|
-
'/webhooks'
|
12
|
+
'/webhooks',
|
13
|
+
'/HAL-REL-PLACEHOLDER-INDEX-PB-PACTICIPANT-VERSION-Foo-26f353580936ad3b9baddb17b00e84f33c69e7cb' =>
|
14
|
+
'/pacticipants/Foo/versions/26f353580936ad3b9baddb17b00e84f33c69e7cb'
|
13
15
|
}
|
14
16
|
|
15
17
|
RESPONSE_BODY_REPLACEMENTS = {
|
@@ -255,4 +255,20 @@ Pact.provider_states_for "Pact Broker Client" do
|
|
255
255
|
.create_consumer("Foo")
|
256
256
|
end
|
257
257
|
end
|
258
|
+
|
259
|
+
provider_state "the pb:pacticipant-version relation exists in the index resource" do
|
260
|
+
no_op
|
261
|
+
end
|
262
|
+
|
263
|
+
provider_state "version 26f353580936ad3b9baddb17b00e84f33c69e7cb of pacticipant Foo does not exist" do
|
264
|
+
no_op
|
265
|
+
end
|
266
|
+
|
267
|
+
provider_state "version 26f353580936ad3b9baddb17b00e84f33c69e7cb of pacticipant Foo does exist" do
|
268
|
+
set_up do
|
269
|
+
TestDataBuilder.new
|
270
|
+
.create_consumer("Foo")
|
271
|
+
.create_consumer_version("26f353580936ad3b9baddb17b00e84f33c69e7cb")
|
272
|
+
end
|
273
|
+
end
|
258
274
|
end
|
@@ -22,6 +22,17 @@ RSpec::Matchers.define :be_a_hal_json_success_response do
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
+
RSpec::Matchers.define :be_a_hal_json_created_response do
|
26
|
+
match do | actual |
|
27
|
+
expect(actual.status).to be 201
|
28
|
+
expect(actual.headers['Content-Type']).to eq 'application/hal+json;charset=utf-8'
|
29
|
+
end
|
30
|
+
|
31
|
+
failure_message do
|
32
|
+
"Expected creation successful json response, got #{actual.status} #{actual.headers['Content-Type']} with body #{actual.body}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
25
36
|
RSpec::Matchers.define :be_a_json_response do
|
26
37
|
match do | actual |
|
27
38
|
expect(actual.headers['Content-Type']).to eq 'application/hal+json;charset=utf-8'
|