pact_broker-client 1.44.0 → 1.45.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,219 @@
1
+ require 'pact_broker/client/deployments/record_undeployment'
2
+
3
+ module PactBroker
4
+ module Client
5
+ module Deployments
6
+ describe RecordUndeployment do
7
+ let(:params) do
8
+ {
9
+ pacticipant_name: "Foo",
10
+ target: target,
11
+ environment_name: "test"
12
+ }
13
+ end
14
+ let(:target) { "customer-1" }
15
+ let(:output) { "text" }
16
+ let(:options) { { output: output, verbose: true } }
17
+ let(:pact_broker_base_url) { "http://broker" }
18
+ let(:pact_broker_client_options) { { pact_broker_base_url: pact_broker_base_url } }
19
+
20
+ let(:index_body_hash) do
21
+ {
22
+ _links: {
23
+ :'pb:environments' => {
24
+ href: environments_url
25
+ },
26
+ :'pb:pacticipant' => {
27
+ href: pacticipant_url
28
+ }
29
+ }
30
+ }
31
+ end
32
+
33
+ let(:environments_hash) do
34
+ {
35
+ _links: {
36
+ :'pb:environments' => [
37
+ {
38
+ name: "test",
39
+ href: test_environment_url
40
+ }
41
+ ]
42
+ }
43
+ }
44
+ end
45
+
46
+ let(:environment_hash) do
47
+ {
48
+ _links: {
49
+ :'pb:currently-deployed-versions' => {
50
+ href: currently_deployed_versions_url
51
+ }
52
+ }
53
+ }
54
+ end
55
+
56
+ let(:deployed_versions_hash) do
57
+ {
58
+ _embedded: {
59
+ deployedVersions: [
60
+ {
61
+ target: "customer-1",
62
+ _links: {
63
+ self: {
64
+ href: deployed_version_url_1
65
+ }
66
+ }
67
+ },
68
+ {
69
+ target: returned_target_2,
70
+ _links: {
71
+ self: {
72
+ href: deployed_version_url_2
73
+ }
74
+ }
75
+ }
76
+ ]
77
+ }
78
+ }
79
+ end
80
+
81
+ let(:returned_target_2) { nil }
82
+ let(:deployed_version_hash) do
83
+ {
84
+ _embedded: {
85
+ version: {
86
+ number: "2"
87
+ }
88
+ }
89
+ }
90
+ end
91
+
92
+ let(:environments_url) { "#{webmock_base_url}/environments" }
93
+ let(:test_environment_url) { "#{webmock_base_url}/environments/1234" }
94
+ let(:currently_deployed_versions_url) { "#{webmock_base_url}/currently-deployed-versions" }
95
+ let(:deployed_version_url_1) { "#{webmock_base_url}/deployed-version-1" }
96
+ let(:deployed_version_url_2) { "#{webmock_base_url}/deployed-version-2" }
97
+ let(:pacticipant_url) { "#{webmock_base_url}/pacticipant" }
98
+
99
+ let(:webmock_base_url) { "http://broker" }
100
+
101
+ let!(:index_request) do
102
+ stub_request(:get, "http://broker").to_return(status: 200, body: index_body_hash.to_json, headers: { "Content-Type" => "application/hal+json" } )
103
+ end
104
+
105
+ let!(:environments_request) do
106
+ stub_request(:get, "http://broker/environments").to_return(status: 200, body: environments_hash.to_json, headers: { "Content-Type" => "application/hal+json" } )
107
+ end
108
+
109
+ let!(:environment_request) do
110
+ stub_request(:get, test_environment_url).to_return(status: 200, body: environment_hash.to_json, headers: { "Content-Type" => "application/hal+json" } )
111
+ end
112
+
113
+ let!(:deployed_versions_request) do
114
+ stub_request(:get, currently_deployed_versions_url + "?pacticipant=Foo").to_return(status: 200, body: deployed_versions_hash.to_json, headers: { "Content-Type" => "application/hal+json" } )
115
+ end
116
+
117
+ let!(:deployed_version_patch_request_1) do
118
+ stub_request(:patch, deployed_version_url_1).with(body: { currentlyDeployed: false}.to_json).to_return(status: 200, body: deployed_version_hash.to_json, headers: { "Content-Type" => "application/hal+json" })
119
+ end
120
+
121
+ let!(:deployed_version_patch_request_2) do
122
+ stub_request(:patch, deployed_version_url_2).with(body: { currentlyDeployed: false}.to_json).to_return(status: 200, body: deployed_version_hash.to_json, headers: { "Content-Type" => "application/hal+json" })
123
+ end
124
+
125
+ let!(:pacticipant_request) do
126
+ stub_request(:get, pacticipant_url).to_return(status: pacticipant_request_status, body: {}.to_json, headers: { "Content-Type" => "application/hal+json" })
127
+ end
128
+
129
+ let(:pacticipant_request_status) { 200 }
130
+
131
+ subject { RecordUndeployment.call(params, options, pact_broker_client_options) }
132
+
133
+ its(:success) { is_expected.to eq true }
134
+ its(:message) { is_expected.to include "Recorded undeployment of Foo version 2 from test environment (target customer-1) in the Pact Broker" }
135
+
136
+ context "when there is no pb:environments relation in the index" do
137
+ let(:index_body_hash) do
138
+ {
139
+ _links: {}
140
+ }
141
+ end
142
+
143
+ its(:success) { is_expected.to be false }
144
+ its(:message) { is_expected.to include "support" }
145
+ end
146
+
147
+ context "when output is json" do
148
+ let(:output) { "json" }
149
+ its(:message) { is_expected.to eq [deployed_version_hash].to_json }
150
+ end
151
+
152
+ context "when there is an error returned from one of the deployed version updates (there should only ever be one deployed version, but testing just for the sake of it)" do
153
+ let!(:deployed_version_patch_request_2) do
154
+ stub_request(:patch, deployed_version_url_2).to_return(status: 400, body: { errors: { foo: ["some error"]}}.to_json, headers: { "Content-Type" => "application/hal+json" })
155
+ end
156
+
157
+ let(:returned_target_2) { "customer-1" }
158
+
159
+ its(:success) { is_expected.to be false }
160
+ its(:message) { is_expected.to include "Recorded undeployment of Foo version 2" }
161
+ its(:message) { is_expected.to include "some error" }
162
+ end
163
+
164
+ context "when there is no currently-deployed-versions relation in the environment resource" do
165
+ let(:environment_hash) do
166
+ {
167
+ _links: {}
168
+ }
169
+ end
170
+
171
+ its(:success) { is_expected.to be false }
172
+ its(:message) { is_expected.to include "support" }
173
+ end
174
+
175
+ context "when a target is provided and there is no deployed version with a matching target" do
176
+ let(:target) { "wrong" }
177
+ let(:expected_message) { "Foo is not currently deployed to target 'wrong' in test environment. Please specify one of the following targets to record the undeployment from: customer-1, <no target>" }
178
+
179
+ its(:success) { is_expected.to be false }
180
+ its(:message) { is_expected.to include expected_message }
181
+
182
+ context "when output is json" do
183
+ let(:output) { "json" }
184
+
185
+ its(:message) { is_expected.to eq({ error: { message: expected_message } }.to_json) }
186
+ end
187
+ end
188
+
189
+ context "when a target is not provided and there is no deployed verison without a target" do
190
+ let(:target) { nil }
191
+ let(:returned_target_2) { "customer-2" }
192
+
193
+ its(:success) { is_expected.to be false }
194
+ its(:message) { is_expected.to include "Please specify one of the following targets to record the undeployment from: customer-1, customer-2" }
195
+ end
196
+
197
+ context "when there are no deployed versions for the pacticipant" do
198
+ let(:deployed_versions_hash) do
199
+ {
200
+ _embedded: {
201
+ deployedVersions: []
202
+ }
203
+ }
204
+ end
205
+
206
+ its(:success) { is_expected.to be false }
207
+ its(:message) { is_expected.to include "Foo is not currently deployed to test environment. Cannot record undeployment." }
208
+
209
+ context "when the pacticipant does not exist" do
210
+ let(:pacticipant_request_status) { 404 }
211
+
212
+ its(:success) { is_expected.to be false }
213
+ its(:message) { is_expected.to include "No pacticipant with name 'Foo' found" }
214
+ end
215
+ end
216
+ end
217
+ end
218
+ end
219
+ end
@@ -14,7 +14,7 @@ module PactBroker::Client
14
14
  with(
15
15
  method: :patch,
16
16
  path: '/pacticipants/Pricing%20Service',
17
- headers: patch_request_headers,
17
+ headers: old_patch_request_headers,
18
18
  body: {repository_url: repository_url} ).
19
19
  will_respond_with(
20
20
  status: 201,
@@ -33,7 +33,7 @@ module PactBroker::Client
33
33
  with(
34
34
  method: :patch,
35
35
  path: '/pacticipants/Pricing%20Service',
36
- headers: patch_request_headers,
36
+ headers: old_patch_request_headers,
37
37
  body: { repository_url: repository_url }).
38
38
  will_respond_with(
39
39
  status: 200,
@@ -113,10 +113,7 @@ RSpec.describe "recording a release", pact: true, skip: !deployment_feature_on d
113
113
  )
114
114
  .will_respond_with(
115
115
  status: 201,
116
- headers: pact_broker_response_headers,
117
- body: {
118
- target: target
119
- }
116
+ headers: pact_broker_response_headers
120
117
  )
121
118
  end
122
119
 
@@ -0,0 +1,166 @@
1
+ require 'service_providers/pact_helper'
2
+ require 'pact_broker/client/deployments/record_undeployment'
3
+
4
+ deployment_feature_on = ENV.fetch('PACT_BROKER_FEATURES', '').include?("deployments")
5
+
6
+ RSpec.describe "recording an undeployment", pact: true, skip: !deployment_feature_on do
7
+ include_context "pact broker"
8
+ include PactBrokerPactHelperMethods
9
+
10
+ let(:pacticipant_name) { "Foo" }
11
+ let(:environment_name) { "test" }
12
+ let(:output) { "text" }
13
+ let(:target) { "customer-1" }
14
+ let(:params) do
15
+ {
16
+ pacticipant_name: pacticipant_name,
17
+ environment_name: environment_name,
18
+ target: target
19
+ }
20
+ end
21
+ let(:options) do
22
+ {
23
+ output: output,
24
+ verbose: true
25
+ }
26
+ end
27
+ let(:webmock_base_url) { "http://broker" }
28
+ let(:pact_broker_client_options) { { pact_broker_base_url: webmock_base_url } }
29
+ let(:test_environment_placeholder_path) { "/HAL-REL-PLACEHOLDER-PB-ENVIRONMENT-16926ef3-590f-4e3f-838e-719717aa88c9" }
30
+ let(:currently_deployed_versions_placeholder_path) { "/PLACEHOLDER-ENVIRONMENT-CURRENTLY-DEPLOYED-16926ef3-590f-4e3f-838e-719717aa88c9" }
31
+ let(:deployed_version_placeholder_path) { "/PLACEHOLDER-DEPLOYED-VERSION-ff3adecf-cfc5-4653-a4e3-f1861092f8e0"}
32
+
33
+ subject { PactBroker::Client::Deployments::RecordUndeployment.call(params, options, pact_broker_client_options) }
34
+
35
+ let(:index_body_hash) do
36
+ {
37
+ _links: {
38
+ :'pb:environments' => {
39
+ href: "#{webmock_base_url}/environments"
40
+ }
41
+ }
42
+ }
43
+ end
44
+
45
+ let(:environments_hash) do
46
+ {
47
+ _links: {
48
+ :'pb:environments' => [
49
+ {
50
+ name: "test",
51
+ href: pact_broker.mock_service_base_url + test_environment_placeholder_path
52
+ }
53
+ ]
54
+ }
55
+ }
56
+ end
57
+
58
+ let!(:index_request) do
59
+ stub_request(:get, "http://broker").to_return(status: 200, body: index_body_hash.to_json, headers: { "Content-Type" => "application/hal+json" } )
60
+ end
61
+
62
+ let!(:environments_request) do
63
+ stub_request(:get, "http://broker/environments").to_return(status: 200, body: environments_hash.to_json, headers: { "Content-Type" => "application/hal+json" } )
64
+ end
65
+
66
+ def mock_test_environment
67
+ pact_broker
68
+ .given("an environment with name test and UUID 16926ef3-590f-4e3f-838e-719717aa88c9 exists")
69
+ .upon_receiving("a request for an environment")
70
+ .with(
71
+ method: "GET",
72
+ path: test_environment_placeholder_path,
73
+ headers: get_request_headers
74
+ )
75
+ .will_respond_with(
76
+ status: 200,
77
+ headers: pact_broker_response_headers,
78
+ body: {
79
+ _links: {
80
+ :'pb:currently-deployed-versions' => {
81
+ href: Pact.term( pact_broker.mock_service_base_url + currently_deployed_versions_placeholder_path, /^http.*/)
82
+ }
83
+ }
84
+ }
85
+ )
86
+ end
87
+
88
+ def mock_deployed_versions_search_results
89
+ pact_broker
90
+ .given("an version is deployed to environment with UUID 16926ef3-590f-4e3f-838e-719717aa88c9 with target customer-1")
91
+ .upon_receiving("a request to list the versions deployed to an environment for a pacticipant name and target")
92
+ .with(
93
+ method: "GET",
94
+ path: currently_deployed_versions_placeholder_path,
95
+ query: { pacticipant: pacticipant_name },
96
+ headers: get_request_headers
97
+ )
98
+ .will_respond_with(
99
+ status: 200,
100
+ headers: pact_broker_response_headers,
101
+ body: {
102
+ _embedded: {
103
+ deployedVersions: [
104
+ {
105
+ target: target,
106
+ _links: {
107
+ self: {
108
+ href: Pact.term(pact_broker.mock_service_base_url + deployed_version_placeholder_path, /^http/)
109
+ }
110
+ }
111
+ }
112
+ ]
113
+ }
114
+ }
115
+ )
116
+ end
117
+
118
+ def mock_mark_deployed_version_as_undeployed
119
+ pact_broker
120
+ .given("a currently deployed version exists")
121
+ .upon_receiving("a request to mark a deployed version as not currently deploye")
122
+ .with(
123
+ method: "PATCH",
124
+ path: deployed_version_placeholder_path,
125
+ body: { currentlyDeployed: false },
126
+ headers: patch_request_headers
127
+ )
128
+ .will_respond_with(
129
+ status: 200,
130
+ headers: pact_broker_response_headers,
131
+ body: deployed_version_hash
132
+ )
133
+ end
134
+
135
+ let(:deployed_version_hash) do
136
+ {
137
+ "currentlyDeployed" => false,
138
+ "_embedded" => {
139
+ "version" => {
140
+ "number" => Pact.like("2")
141
+ }
142
+ }
143
+ }
144
+ end
145
+
146
+ context "when the deployment is recorded successfully" do
147
+ before do
148
+ mock_test_environment
149
+ mock_deployed_versions_search_results
150
+ mock_mark_deployed_version_as_undeployed
151
+ end
152
+
153
+ it "returns a success message" do
154
+ expect(subject.success).to be true
155
+ expect(subject.message).to include "Recorded undeployment of Foo version 2 from test environment (target customer-1) in the Pact Broker"
156
+ end
157
+
158
+ context "when the output is json" do
159
+ let(:output) { "json" }
160
+
161
+ it "returns the JSON payload" do
162
+ expect(JSON.parse(subject.message)).to eq [Pact::Reification.from_term(deployed_version_hash)]
163
+ end
164
+ end
165
+ end
166
+ end
@@ -17,7 +17,8 @@ shared_context "pact broker" do
17
17
  let(:pact_broker_version) { Pact::Term.new(:matcher => /\d+\.\d+\.\d+/, :generate => '1.0.0') }
18
18
  let(:pact_broker_response_headers) { {'Content-Type' => 'application/hal+json;charset=utf-8'} }
19
19
  let(:default_request_headers) { { 'Content-Type' => 'application/json'} }
20
- let(:patch_request_headers) { { 'Content-Type' => 'application/json'} }
20
+ let(:old_patch_request_headers) { { 'Content-Type' => 'application/json'} }
21
+ let(:patch_request_headers) { { 'Content-Type' => 'application/merge-patch+json'} }
21
22
  let(:put_request_headers) { { 'Content-Type' => 'application/json', 'Accept' => 'application/hal+json'} }
22
23
  let(:post_request_headers) { { 'Content-Type' => 'application/json', 'Accept' => 'application/hal+json'} }
23
24
  let(:get_request_headers) { { 'Accept' => 'application/hal+json'} }
data/tasks/pact.rake CHANGED
@@ -18,17 +18,19 @@ PactBroker::Client::PublicationTask.new(:remote) do | task |
18
18
  end
19
19
 
20
20
  PactBroker::Client::PublicationTask.new(:pactflow) do | task |
21
- version = ENV['GITHUB_SHA']
22
- tags = ENV['GITHUB_REF'] ? [ENV['GITHUB_REF'].gsub("refs/heads/", "")] : []
21
+ version = ENV.fetch('GITHUB_SHA')
22
+ branch = ENV.fetch('GITHUB_REF').gsub("refs/heads/", "")
23
+ feature = ENV.fetch('TEST_FEATURE', '')
24
+ tag = branch
23
25
 
24
- if ENV.fetch('TEST_FEATURE', '') != ''
25
- version = "#{version}+#{ENV['TEST_FEATURE']}"
26
- tags = ENV['TEST_FEATURE']
26
+ if feature != ''
27
+ version = "#{version}+#{feature}"
28
+ tag = "#{tag}+#{feature}"
27
29
  end
28
30
 
29
31
  require 'pact_broker/client/version'
30
32
  task.auto_detect_version_properties = false
31
- task.tags = tags
33
+ task.tags = [tag]
32
34
  task.branch = nil
33
35
  task.consumer_version = version
34
36
  task.pact_broker_base_url = "https://pact-oss.pactflow.io"