pact_broker-client 1.43.0 → 1.47.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +35 -0
  3. data/CHANGELOG.md +41 -0
  4. data/README.md +54 -54
  5. data/doc/pacts/markdown/Pact Broker Client - Pact Broker.md +127 -94
  6. data/doc/pacts/markdown/Pact Broker Client - Pactflow.md +94 -0
  7. data/doc/pacts/markdown/README.md +1 -0
  8. data/lib/pact_broker/client/base_command.rb +3 -0
  9. data/lib/pact_broker/client/can_i_deploy.rb +40 -5
  10. data/lib/pact_broker/client/cli/broker.rb +8 -190
  11. data/lib/pact_broker/client/cli/custom_thor.rb +0 -16
  12. data/lib/pact_broker/client/cli/deployment_commands.rb +94 -0
  13. data/lib/pact_broker/client/cli/matrix_commands.rb +93 -0
  14. data/lib/pact_broker/client/cli/pacticipant_commands.rb +9 -0
  15. data/lib/pact_broker/client/cli/webhook_commands.rb +122 -0
  16. data/lib/pact_broker/client/deployments.rb +4 -0
  17. data/lib/pact_broker/client/deployments/record_deployment.rb +38 -0
  18. data/lib/pact_broker/client/deployments/record_release.rb +99 -0
  19. data/lib/pact_broker/client/deployments/record_support_ended.rb +103 -0
  20. data/lib/pact_broker/client/deployments/record_undeployment.rb +127 -0
  21. data/lib/pact_broker/client/describe_text_formatter.rb +23 -0
  22. data/lib/pact_broker/client/environments.rb +6 -3
  23. data/lib/pact_broker/client/environments/describe_environment.rb +3 -13
  24. data/lib/pact_broker/client/hal/entity.rb +22 -4
  25. data/lib/pact_broker/client/hal/http_client.rb +3 -2
  26. data/lib/pact_broker/client/pacticipants.rb +3 -3
  27. data/lib/pact_broker/client/pacticipants/create.rb +2 -2
  28. data/lib/pact_broker/client/pacticipants/describe.rb +33 -0
  29. data/lib/pact_broker/client/verification_required.rb +32 -0
  30. data/lib/pact_broker/client/version.rb +1 -1
  31. data/lib/pact_broker/client/versions.rb +4 -1
  32. data/lib/pact_broker/client/versions/describe.rb +3 -1
  33. data/lib/pact_broker/client/versions/formatter.rb +3 -1
  34. data/lib/pact_broker/client/versions/json_formatter.rb +5 -3
  35. data/lib/pact_broker/client/versions/text_formatter.rb +3 -1
  36. data/lib/pact_broker/client/webhooks/create.rb +14 -8
  37. data/script/record-deployment.sh +1 -1
  38. data/script/record-deployments-and-releases.sh +16 -0
  39. data/script/record-undeployment.sh +1 -1
  40. data/script/webhook-commands.sh +12 -0
  41. data/spec/fixtures/approvals/can_i_deploy_failure_dry_run.approved.txt +7 -0
  42. data/spec/fixtures/approvals/can_i_deploy_success_dry_run.approved.txt +7 -0
  43. data/spec/fixtures/approvals/describe_pacticipant.approved.txt +2 -0
  44. data/spec/integration/describe_environment_spec.rb +31 -0
  45. data/spec/lib/pact_broker/client/can_i_deploy_spec.rb +62 -2
  46. data/spec/lib/pact_broker/client/cli/broker_can_i_deploy_spec.rb +15 -2
  47. data/spec/lib/pact_broker/client/cli/broker_run_webhook_commands_spec.rb +4 -2
  48. data/spec/lib/pact_broker/client/deployments/record_deployment_spec.rb +204 -0
  49. data/spec/lib/pact_broker/client/deployments/record_support_ended_spec.rb +208 -0
  50. data/spec/lib/pact_broker/client/deployments/record_undeployment_spec.rb +219 -0
  51. data/spec/pacts/pact_broker_client-pact_broker.json +140 -112
  52. data/spec/pacts/pact_broker_client-pactflow.json +118 -0
  53. data/spec/service_providers/pact_broker_client_register_repository_spec.rb +2 -2
  54. data/spec/service_providers/pact_helper.rb +15 -10
  55. data/spec/service_providers/pactflow_webhooks_create_spec.rb +86 -0
  56. data/spec/service_providers/publish_pacts_spec.rb +3 -1
  57. data/spec/service_providers/record_deployment_spec.rb +4 -28
  58. data/spec/service_providers/record_release_spec.rb +130 -0
  59. data/spec/service_providers/record_undeployment_spec.rb +164 -0
  60. data/spec/service_providers/webhooks_create_spec.rb +1 -1
  61. data/spec/spec_helper.rb +14 -2
  62. data/spec/support/shared_context.rb +2 -1
  63. data/tasks/pact.rake +21 -1
  64. metadata +39 -7
  65. data/lib/pact_broker/client/versions/record_deployment.rb +0 -85
  66. data/lib/pact_broker/client/versions/record_undeployment.rb +0 -102
  67. data/spec/lib/pact_broker/client/versions/record_deployment_spec.rb +0 -75
@@ -0,0 +1,118 @@
1
+ {
2
+ "consumer": {
3
+ "name": "Pact Broker Client"
4
+ },
5
+ "provider": {
6
+ "name": "Pactflow"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "a request for the index resource",
11
+ "request": {
12
+ "method": "get",
13
+ "path": "/",
14
+ "headers": {
15
+ "Accept": "application/hal+json"
16
+ }
17
+ },
18
+ "response": {
19
+ "status": 200,
20
+ "headers": {
21
+ "Content-Type": "application/hal+json;charset=utf-8"
22
+ },
23
+ "body": {
24
+ "_links": {
25
+ "pb:webhooks": {
26
+ "href": "http://localhost:1235/HAL-REL-PLACEHOLDER-PB-WEBHOOKS"
27
+ },
28
+ "pb:pacticipants": {
29
+ "href": "http://localhost:1235/HAL-REL-PLACEHOLDER-PB-PACTICIPANTS"
30
+ },
31
+ "pb:pacticipant": {
32
+ "href": "http://localhost:1235/HAL-REL-PLACEHOLDER-PB-PACTICIPANT-{pacticipant}"
33
+ }
34
+ }
35
+ },
36
+ "matchingRules": {
37
+ "$.body._links.pb:webhooks.href": {
38
+ "match": "regex",
39
+ "regex": "http:\\/\\/.*"
40
+ },
41
+ "$.body._links.pb:pacticipants.href": {
42
+ "match": "regex",
43
+ "regex": "http:\\/\\/.*"
44
+ },
45
+ "$.body._links.pb:pacticipant.href": {
46
+ "match": "regex",
47
+ "regex": "http:\\/\\/.*{pacticipant}"
48
+ }
49
+ }
50
+ }
51
+ },
52
+ {
53
+ "description": "a request to create a webhook for a team",
54
+ "providerState": "a team with UUID 2abbc12a-427d-432a-a521-c870af1739d9 exists",
55
+ "request": {
56
+ "method": "post",
57
+ "path": "/HAL-REL-PLACEHOLDER-PB-WEBHOOKS",
58
+ "headers": {
59
+ "Content-Type": "application/json",
60
+ "Accept": "application/hal+json"
61
+ },
62
+ "body": {
63
+ "description": "a webhook",
64
+ "events": [
65
+ {
66
+ "name": "contract_content_changed"
67
+ }
68
+ ],
69
+ "request": {
70
+ "url": "https://webhook",
71
+ "method": "POST",
72
+ "headers": {
73
+ "Foo": "bar",
74
+ "Bar": "foo"
75
+ },
76
+ "body": {
77
+ "some": "body"
78
+ }
79
+ },
80
+ "teamUuid": "2abbc12a-427d-432a-a521-c870af1739d9"
81
+ }
82
+ },
83
+ "response": {
84
+ "status": 201,
85
+ "headers": {
86
+ "Content-Type": "application/hal+json;charset=utf-8"
87
+ },
88
+ "body": {
89
+ "description": "a webhook",
90
+ "teamUuid": "2abbc12a-427d-432a-a521-c870af1739d9",
91
+ "_links": {
92
+ "self": {
93
+ "href": "http://localhost:1234/some-url",
94
+ "title": "A title"
95
+ }
96
+ }
97
+ },
98
+ "matchingRules": {
99
+ "$.body.description": {
100
+ "match": "type"
101
+ },
102
+ "$.body._links.self.href": {
103
+ "match": "regex",
104
+ "regex": "http:\\/\\/.*"
105
+ },
106
+ "$.body._links.self.title": {
107
+ "match": "type"
108
+ }
109
+ }
110
+ }
111
+ }
112
+ ],
113
+ "metadata": {
114
+ "pactSpecification": {
115
+ "version": "2.0.0"
116
+ }
117
+ }
118
+ }
@@ -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,
@@ -8,7 +8,6 @@ Pact.configure do | config |
8
8
  end
9
9
 
10
10
  Pact.service_consumer 'Pact Broker Client' do
11
-
12
11
  has_pact_with "Pact Broker" do
13
12
  mock_service :pact_broker do
14
13
  port 1234
@@ -16,6 +15,12 @@ Pact.service_consumer 'Pact Broker Client' do
16
15
  end
17
16
  end
18
17
 
18
+ has_pact_with "Pactflow" do
19
+ mock_service :pactflow do
20
+ port 1235
21
+ pact_specification_version "2.0"
22
+ end
23
+ end
19
24
  end
20
25
 
21
26
  module PactBrokerPactHelperMethods
@@ -30,22 +35,22 @@ module PactBrokerPactHelperMethods
30
35
  path
31
36
  end
32
37
 
33
- def placeholder_url(relation, params = [])
34
- "#{pact_broker.mock_service_base_url}#{placeholder_path(relation, params)}"
38
+ def placeholder_url(relation, params = [], mock_service = pact_broker)
39
+ "#{mock_service.mock_service_base_url}#{placeholder_path(relation, params)}"
35
40
  end
36
41
 
37
- def placeholder_url_term(relation, params = [])
42
+ def placeholder_url_term(relation, params = [], mock_service = pact_broker)
38
43
  regexp = "http:\/\/.*"
39
44
  if params.any?
40
45
  joined_params_for_regexp = params.collect{ |param| "{#{param}}"}.join(".*")
41
46
  regexp = "#{regexp}#{joined_params_for_regexp}"
42
47
  end
43
48
 
44
- Pact.term(placeholder_url(relation, params), /#{regexp}/)
49
+ Pact.term(placeholder_url(relation, params, mock_service), /#{regexp}/)
45
50
  end
46
51
 
47
- def mock_pact_broker_index(context)
48
- pact_broker
52
+ def mock_pact_broker_index(context, mock_service = pact_broker)
53
+ mock_service
49
54
  .upon_receiving("a request for the index resource")
50
55
  .with(
51
56
  method: :get,
@@ -57,13 +62,13 @@ module PactBrokerPactHelperMethods
57
62
  body: {
58
63
  _links: {
59
64
  :'pb:webhooks' => {
60
- href: placeholder_url_term('pb:webhooks')
65
+ href: placeholder_url_term('pb:webhooks', [], mock_service)
61
66
  },
62
67
  :'pb:pacticipants' => {
63
- href: placeholder_url_term('pb:pacticipants')
68
+ href: placeholder_url_term('pb:pacticipants', [], mock_service)
64
69
  },
65
70
  :'pb:pacticipant' => {
66
- href: placeholder_url_term('pb:pacticipant', ['pacticipant'])
71
+ href: placeholder_url_term('pb:pacticipant', ['pacticipant'], mock_service)
67
72
  }
68
73
  }
69
74
  }
@@ -0,0 +1,86 @@
1
+ require_relative 'pact_helper'
2
+ require 'pact_broker/client/webhooks/create'
3
+
4
+ RSpec.describe "creating a webhook in Pactflow", pact: true do
5
+
6
+ include_context "pact broker"
7
+ include PactBrokerPactHelperMethods
8
+
9
+ let(:params) do
10
+ {
11
+ description: "a webhook",
12
+ events: %w{contract_content_changed},
13
+ http_method: "POST",
14
+ url: "https://webhook",
15
+ headers: { "Foo" => "bar", "Bar" => "foo"},
16
+ body: body,
17
+ team_uuid: "2abbc12a-427d-432a-a521-c870af1739d9"
18
+ }
19
+ end
20
+
21
+ let(:body) { { some: "body" }.to_json }
22
+
23
+ let(:request_body) do
24
+ {
25
+ "description" => "a webhook",
26
+ "events" => [
27
+ "name" => "contract_content_changed"
28
+ ],
29
+ "request" => {
30
+ "url" => "https://webhook",
31
+ "method" => "POST",
32
+ "headers" => {
33
+ "Foo" => "bar",
34
+ "Bar" => "foo"
35
+ },
36
+ "body" => {
37
+ "some" => "body"
38
+ },
39
+ },
40
+ "teamUuid" => "2abbc12a-427d-432a-a521-c870af1739d9"
41
+ }
42
+ end
43
+
44
+ let(:response_status) { 201 }
45
+ let(:success_response) do
46
+ {
47
+ status: response_status,
48
+ headers: pact_broker_response_headers,
49
+ body: {
50
+ description: Pact.like("a webhook"),
51
+ teamUuid: "2abbc12a-427d-432a-a521-c870af1739d9",
52
+ _links: {
53
+ self: {
54
+ href: Pact.term('http://localhost:1234/some-url', %r{http://.*}),
55
+ title: Pact.like("A title")
56
+ }
57
+ }
58
+ }
59
+ }
60
+ end
61
+
62
+ let(:pact_broker_client_options) { {} }
63
+
64
+ subject { PactBroker::Client::Webhooks::Create.call(params, pactflow.mock_service_base_url, pact_broker_client_options) }
65
+
66
+ context "when a valid webhook with a team specified is submitted" do
67
+ before do
68
+ mock_pact_broker_index(self, pactflow)
69
+ pactflow
70
+ .given("a team with UUID 2abbc12a-427d-432a-a521-c870af1739d9 exists")
71
+ .upon_receiving("a request to create a webhook for a team")
72
+ .with(
73
+ method: :post,
74
+ path: '/HAL-REL-PLACEHOLDER-PB-WEBHOOKS',
75
+ headers: post_request_headers,
76
+ body: request_body)
77
+ .will_respond_with(success_response)
78
+ end
79
+
80
+ it "returns a CommandResult with success = true" do
81
+ expect(subject).to be_a PactBroker::Client::CommandResult
82
+ expect(subject.success).to be true
83
+ expect(subject.message).to eq "Webhook \"a webhook\" created"
84
+ end
85
+ end
86
+ end
@@ -1,7 +1,9 @@
1
1
  require 'pact_broker/client/publish_pacts'
2
2
  require 'service_providers/pact_helper'
3
3
 
4
- RSpec.describe "publishing contracts", pact: true do
4
+ publish_contracts_feature_on = ENV.fetch('PACT_BROKER_FEATURES', '').include?("publish_contracts")
5
+
6
+ RSpec.describe "publishing contracts", pact: true, skip: !publish_contracts_feature_on do
5
7
  before do
6
8
  allow_any_instance_of(PactBroker::Client::Hal::HttpClient).to receive(:sleep)
7
9
  allow_any_instance_of(PactBroker::Client::Hal::HttpClient).to receive(:default_max_tries).and_return(1)
@@ -1,5 +1,5 @@
1
1
  require 'service_providers/pact_helper'
2
- require 'pact_broker/client/versions/record_deployment'
2
+ require 'pact_broker/client/deployments/record_deployment'
3
3
 
4
4
  RSpec.describe "recording a deployment", pact: true do
5
5
  include_context "pact broker"
@@ -25,7 +25,7 @@ RSpec.describe "recording a deployment", pact: true do
25
25
  end
26
26
  let(:pact_broker_client_options) { { pact_broker_base_url: broker_base_url } }
27
27
 
28
- subject { PactBroker::Client::Versions::RecordDeployment.call(params, options, pact_broker_client_options) }
28
+ subject { PactBroker::Client::Deployments::RecordDeployment.call(params, options, pact_broker_client_options) }
29
29
 
30
30
  def mock_index
31
31
  pact_broker
@@ -105,18 +105,6 @@ RSpec.describe "recording a deployment", pact: true do
105
105
  )
106
106
  end
107
107
 
108
- def mock_pacticipant_version_not_found
109
- pact_broker
110
- .given("version 5556b8149bf8bac76bc30f50a8a2dd4c22c85f30 of pacticipant Foo does not exist")
111
- .upon_receiving("a request for a pacticipant version")
112
- .with(
113
- method: "GET",
114
- path: "/HAL-REL-PLACEHOLDER-PB-PACTICIPANT-VERSION-Foo-5556b8149bf8bac76bc30f50a8a2dd4c22c85f30",
115
- headers: get_request_headers
116
- )
117
- .will_respond_with(status: 404)
118
- end
119
-
120
108
  def mock_environments
121
109
  pact_broker
122
110
  .given("an environment with name test exists")
@@ -184,18 +172,6 @@ RSpec.describe "recording a deployment", pact: true do
184
172
  end
185
173
  end
186
174
 
187
- context "when the specified version does not exist" do
188
- before do
189
- mock_index
190
- mock_pacticipant_version_not_found
191
- end
192
-
193
- it "returns an error response" do
194
- expect(subject.success).to be false
195
- expect(subject.message).to include "Foo version 5556b8149bf8bac76bc30f50a8a2dd4c22c85f30 not found"
196
- end
197
- end
198
-
199
175
  context "when the specified environment is not available for recording a deployment" do
200
176
  before do
201
177
  mock_index
@@ -208,14 +184,14 @@ RSpec.describe "recording a deployment", pact: true do
208
184
 
209
185
  it "returns an error response" do
210
186
  expect(subject.success).to be false
211
- expect(subject.message).to include "No environment found with name 'foo'. Available options: test"
187
+ expect(subject.message).to include "No environment found"
212
188
  end
213
189
  end
214
190
 
215
191
  context "when the specified environment does exist" do
216
192
  it "returns an error response" do
217
193
  expect(subject.success).to be false
218
- expect(subject.message).to include "Environment 'test' is not an available option for recording a deployment of Foo. Available options: prod, dev"
194
+ expect(subject.message).to include "not an available option"
219
195
  end
220
196
  end
221
197
  end
@@ -0,0 +1,130 @@
1
+ require 'service_providers/pact_helper'
2
+ require 'pact_broker/client/deployments/record_deployment'
3
+
4
+ RSpec.describe "recording a release", pact: true do
5
+ include_context "pact broker"
6
+ include PactBrokerPactHelperMethods
7
+
8
+ let(:pacticipant_name) { "Foo" }
9
+ let(:version_number) { "5556b8149bf8bac76bc30f50a8a2dd4c22c85f30" }
10
+ let(:environment_name) { "test" }
11
+ let(:output) { "text" }
12
+ let(:target) { "blue" }
13
+ let(:params) do
14
+ {
15
+ pacticipant_name: pacticipant_name,
16
+ version_number: version_number,
17
+ environment_name: environment_name
18
+ }
19
+ end
20
+ let(:options) do
21
+ {
22
+ output: output
23
+ }
24
+ end
25
+ let(:pact_broker_client_options) { { pact_broker_base_url: broker_base_url } }
26
+
27
+ subject { PactBroker::Client::Deployments::RecordRelease.call(params, options, pact_broker_client_options) }
28
+
29
+ def mock_index
30
+ pact_broker
31
+ .given("the pb:pacticipant-version and pb:environments relations exist in the index resource")
32
+ .upon_receiving("a request for the index resource")
33
+ .with(
34
+ method: "GET",
35
+ path: '/',
36
+ headers: get_request_headers).
37
+ will_respond_with(
38
+ status: 200,
39
+ headers: pact_broker_response_headers,
40
+ body: {
41
+ _links: {
42
+ :'pb:pacticipant-version' => {
43
+ href: placeholder_url_term("pb:pacticipant-version", ["pacticipant", "version"])
44
+ },
45
+ :'pb:environments' => {
46
+ href: placeholder_url_term("pb:environments")
47
+ }
48
+ }
49
+ }
50
+ )
51
+ end
52
+
53
+ def mock_pacticipant_version_with_test_environment_available_for_release
54
+ pact_broker
55
+ .given("version 5556b8149bf8bac76bc30f50a8a2dd4c22c85f30 of pacticipant Foo exists with a test environment available for release")
56
+ .upon_receiving("a request for a pacticipant version")
57
+ .with(
58
+ method: "GET",
59
+ path: "/HAL-REL-PLACEHOLDER-PB-PACTICIPANT-VERSION-Foo-5556b8149bf8bac76bc30f50a8a2dd4c22c85f30",
60
+ headers: get_request_headers
61
+ )
62
+ .will_respond_with(
63
+ status: 200,
64
+ headers: pact_broker_response_headers,
65
+ body: {
66
+ _links: {
67
+ "pb:record-release" => [
68
+ {
69
+ name: "test",
70
+ href: placeholder_url_term("pb:record-release-#{pacticipant_name}-#{version_number}-#{environment_name}")
71
+ }
72
+ ]
73
+ }
74
+ }
75
+ )
76
+ end
77
+
78
+ def mock_environments
79
+ pact_broker
80
+ .given("an environment with name test exists")
81
+ .upon_receiving("a request for the environments")
82
+ .with(
83
+ method: "GET",
84
+ path: "/HAL-REL-PLACEHOLDER-PB-ENVIRONMENTS",
85
+ headers: get_request_headers
86
+ )
87
+ .will_respond_with(
88
+ status: 200,
89
+ headers: pact_broker_response_headers,
90
+ body: {
91
+ _links: {
92
+ "pb:environments" => [
93
+ {
94
+ name: "test",
95
+ href: Pact.like("href")
96
+ }
97
+ ]
98
+ }
99
+ }
100
+ )
101
+ end
102
+
103
+ def mock_record_release
104
+ pact_broker
105
+ .given("version 5556b8149bf8bac76bc30f50a8a2dd4c22c85f30 of pacticipant Foo exists with a test environment available for deployment")
106
+ .upon_receiving("a request to record a release")
107
+ .with(
108
+ method: "POST",
109
+ path: "/HAL-REL-PLACEHOLDER-PB-RECORD-RELEASE-FOO-5556B8149BF8BAC76BC30F50A8A2DD4C22C85F30-TEST",
110
+ headers: post_request_headers
111
+ )
112
+ .will_respond_with(
113
+ status: 201,
114
+ headers: pact_broker_response_headers
115
+ )
116
+ end
117
+
118
+ context "when the deployment is recorded successfully" do
119
+ before do
120
+ mock_index
121
+ mock_pacticipant_version_with_test_environment_available_for_release
122
+ mock_record_release
123
+ end
124
+
125
+ it "returns a success message" do
126
+ expect(subject.success).to be true
127
+ expect(subject.message).to include "Recorded release of Foo version 5556b8149bf8bac76bc30f50a8a2dd4c22c85f30 to test environment in the Pact Broker."
128
+ end
129
+ end
130
+ end