pact_broker-client 1.58.0 → 1.61.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -18,29 +18,40 @@ module PactBroker
18
18
  def merge original, additional
19
19
  new_pact = JSON.parse(original.to_json, symbolize_names: true)
20
20
 
21
- additional[:interactions].each do |new_interaction|
21
+ merge_interactions_or_messages(new_pact, original, additional, :interactions)
22
+ merge_interactions_or_messages(new_pact, original, additional, :messages)
23
+
24
+ new_pact
25
+ end
26
+
27
+ private
28
+
29
+ def merge_interactions_or_messages(new_pact, original, additional, key)
30
+ return unless additional[key] || original[key]
31
+
32
+ additional_messages_or_interactions = additional[key] || []
33
+ original_messages_or_interactions = original[key] || []
34
+ new_pact[key] ||= []
35
+
36
+ additional_messages_or_interactions.each do |new_interaction|
22
37
  # check to see if this interaction matches an existing interaction
23
- overwrite_index = original[:interactions].find_index do |original_interaction|
38
+ overwrite_index = original_messages_or_interactions.find_index do |original_interaction|
24
39
  same_description_and_state?(original_interaction, new_interaction)
25
40
  end
26
41
 
27
42
  # overwrite existing interaction if a match is found, otherwise appends the new interaction
28
43
  if overwrite_index
29
- if new_interaction == original[:interactions][overwrite_index]
30
- new_pact[:interactions][overwrite_index] = new_interaction
44
+ if new_interaction == original_messages_or_interactions[overwrite_index]
45
+ new_pact[key][overwrite_index] = new_interaction
31
46
  else
32
- raise PactMergeError, almost_duplicate_message(original[:interactions][overwrite_index], new_interaction)
47
+ raise PactMergeError, almost_duplicate_message(original_messages_or_interactions[overwrite_index], new_interaction)
33
48
  end
34
49
  else
35
- new_pact[:interactions] << new_interaction
50
+ new_pact[key] << new_interaction
36
51
  end
37
52
  end
38
-
39
- new_pact
40
53
  end
41
54
 
42
- private
43
-
44
55
  def almost_duplicate_message(original, new_interaction)
45
56
  "Two interactions have been found with same description (#{new_interaction[:description].inspect}) and provider state (#{new_interaction[:providerState].inspect}) but a different request or response. " +
46
57
  "Please use a different description or provider state, or hard-code any random data.\n\n" +
@@ -30,7 +30,7 @@ module PactBroker
30
30
  if json_output?
31
31
  response_entity.response.raw_body
32
32
  else
33
- green(message = "Pacticipant \"#{params[:name]}\" #{action} in #{pact_broker_name}")
33
+ green("Pacticipant \"#{params[:name]}\" #{action} in #{pact_broker_name}")
34
34
  end
35
35
  end
36
36
 
@@ -3,6 +3,7 @@ require 'pact_broker/client/hal_client_methods'
3
3
  require 'base64'
4
4
  require 'pact_broker/client/publish_pacts_the_old_way'
5
5
  require 'pact_broker/client/colorize_notices'
6
+ require 'pact_broker/client/hash_refinements'
6
7
 
7
8
  module PactBroker
8
9
  module Client
@@ -1,5 +1,5 @@
1
1
  module PactBroker
2
2
  module Client
3
- VERSION = '1.58.0'
3
+ VERSION = '1.61.0'
4
4
  end
5
5
  end
@@ -0,0 +1,111 @@
1
+ require "pact_broker/client/base_client"
2
+ require "pact_broker/client/base_command"
3
+
4
+ module PactBroker
5
+ module Client
6
+ class Versions < BaseClient # need to retire the old base client code
7
+ class Create < PactBroker::Client::BaseCommand
8
+
9
+ def do_call
10
+ if branch_name
11
+ if branch_versions_supported?
12
+ create_branch_version
13
+ else
14
+ raise PactBroker::Client::Error.new("This version of #{pact_broker_name} does not support branch versions,or you do not have the required permissions to create one. Please ensure you have upgraded to version 2.82.0 or later for branch support.")
15
+ end
16
+ end
17
+
18
+ if tags
19
+ create_version_tags
20
+ end
21
+
22
+ if !branch_name && !tags.any?
23
+ create_version
24
+ end
25
+
26
+ PactBroker::Client::CommandResult.new(true, result_message)
27
+ end
28
+
29
+ private
30
+
31
+ def pacticipant_name
32
+ params.fetch(:pacticipant_name)
33
+ end
34
+
35
+ def version_number
36
+ params.fetch(:version_number)
37
+ end
38
+
39
+ def branch_name
40
+ params[:branch_name]
41
+ end
42
+
43
+ def tags
44
+ params[:tags] || []
45
+ end
46
+
47
+ def branch_versions_supported?
48
+ index_resource._link("pb:pacticipant-branch-version")
49
+ end
50
+
51
+ def create_branch_version
52
+ branch_params = {
53
+ "pacticipant" => pacticipant_name,
54
+ "version" => version_number,
55
+ "branch" => branch_name
56
+ }
57
+ branch_version_entity = index_resource
58
+ ._link("pb:pacticipant-branch-version")
59
+ .expand(branch_params)
60
+ .put!
61
+ end
62
+
63
+ def create_version_tags
64
+ tags.each do | tag |
65
+ tag_params = {
66
+ "pacticipant" => pacticipant_name,
67
+ "version" => version_number,
68
+ "tag" => tag
69
+ }
70
+ index_resource
71
+ ._link("pb:pacticipant-version-tag")
72
+ .expand(tag_params)
73
+ .put!
74
+ end
75
+ end
76
+
77
+ def create_version
78
+ @version_resource ||= expanded_version_relation.put!
79
+ end
80
+
81
+ def expanded_version_relation
82
+ version_params = {
83
+ "pacticipant" => pacticipant_name,
84
+ "version" => version_number
85
+ }
86
+ index_resource
87
+ ._link("pb:pacticipant-version")
88
+ .expand(version_params)
89
+ end
90
+
91
+ def result_message
92
+ if json_output?
93
+ (@version_resource || expanded_version_relation.get).response.raw_body
94
+ else
95
+ message = "Created/updated pacticipant version #{version_number}"
96
+ if branch_name && tags.any?
97
+ message = message + " with branch #{branch_name} and tag(s) #{tags.join(", ")}"
98
+ elsif branch_name
99
+ message = message + " with branch #{branch_name}"
100
+ elsif tags.any?
101
+ message = message + " with tag(s) #{tags.join(", ")}"
102
+ end
103
+
104
+ message = message + " in #{pact_broker_name}"
105
+ green(message)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -1,5 +1,6 @@
1
1
  require 'pact_broker/client/base_client'
2
2
  require 'pact_broker/client/versions/describe'
3
+ require 'pact_broker/client/versions/create'
3
4
 
4
5
  # Old code
5
6
  require 'pact_broker/client/pacts'
@@ -4,11 +4,14 @@ require 'ostruct'
4
4
  require 'json'
5
5
  require 'pact_broker/client/command_result'
6
6
  require "pact_broker/client/backports"
7
+ require "pact_broker/client/hash_refinements"
7
8
 
8
9
  module PactBroker
9
10
  module Client
10
11
  module Webhooks
11
12
  class Create
13
+ using PactBroker::Client::HashRefinements
14
+
12
15
  WEBHOOKS_WITH_OPTIONAL_PACTICICPANTS_NOT_SUPPORTED = "This version of the Pact Broker requires that both consumer and provider are specified for a webhook. Please upgrade your broker to >= 2.22.0 to create a webhook with optional consumer and provider."
13
16
  CREATING_WEBHOOK_WITH_UUID_NOT_SUPPORTED = "This version of the Pact Broker does not support creating webhooks with a specified UUID. Please upgrade your broker to >= 2.49.0 or use the create-webhook command."
14
17
 
@@ -50,7 +53,7 @@ module PactBroker
50
53
  return error_result(CREATING_WEBHOOK_WITH_UUID_NOT_SUPPORTED)
51
54
  end
52
55
  else
53
- webhook_entity = index_entity._link("pb:webhooks").post(request_body_with_optional_consumer_and_provider)
56
+ webhook_entity = index_entity._link!("pb:webhooks").post(request_body_with_optional_consumer_and_provider)
54
57
  end
55
58
 
56
59
  if webhook_entity.response.status == 405
@@ -8,10 +8,10 @@ Gem::Specification.new do |gem|
8
8
  gem.name = "pact_broker-client"
9
9
  gem.version = PactBroker::Client::VERSION
10
10
  gem.authors = ["Beth Skurrie"]
11
- gem.email = ["bskurrie@dius.com.au"]
12
- gem.description = %q{Client for the Pact Broker. Publish, retrieve and query pacts and verification results.}
11
+ gem.email = ["beth@bethesque.com"]
12
+ gem.description = %q{Client for the Pact Broker. Publish, retrieve and query pacts and verification results. Manage webhooks and environments.}
13
13
  gem.summary = %q{See description}
14
- gem.homepage = "https://github.com/bethesque/pact_broker-client.git"
14
+ gem.homepage = "https://github.com/pact-foundation/pact_broker-client.git"
15
15
 
16
16
  gem.required_ruby_version = '>= 2.0'
17
17
 
@@ -33,6 +33,6 @@ Gem::Specification.new do |gem|
33
33
  gem.add_development_dependency 'conventional-changelog', '~>1.3'
34
34
  gem.add_development_dependency 'pact', '~> 1.16'
35
35
  gem.add_development_dependency 'pact-support', '~> 1.16'
36
- gem.add_development_dependency 'approvals', '>=0.0.24', '<1.0.0'
36
+ gem.add_development_dependency 'approvals', '0.0.24'
37
37
  gem.add_development_dependency 'rspec-its', '~> 1.3'
38
38
  end
@@ -1,4 +1,4 @@
1
1
  bundle exec bin/pact-broker record-undeployment \
2
- --pacticipant foo-consumer --version 1 --environment prod --broker-base-url http://localhost:9292 --output json --verbose
2
+ --pacticipant foo-consumer --environment production --broker-base-url http://localhost:9292 --output json --verbose
3
3
 
4
4
 
@@ -58,7 +58,7 @@ def generate_thor_docs
58
58
  ["Pacticipants", %w[create-or-update-pacticipant describe-pacticipant list-pacticipants]],
59
59
  ["Webhooks", %w[create-webhook create-or-update-webhook test-webhook]],
60
60
  ["Tags", %w[create-version-tag]],
61
- ["Versions", %w[describe-version]],
61
+ ["Versions", %w[describe-version create-or-update-version]],
62
62
  ["Miscellaneous", %w[generate-uuid]]
63
63
  ]
64
64
 
@@ -137,8 +137,12 @@ def reformat_docs(generated_thor_docs)
137
137
  else
138
138
  lines
139
139
  end
140
- # line
141
- end.flatten.join("\n").gsub("/go/", "/").gsub(File.basename(__FILE__), "pact-broker")
140
+ end
141
+ .flatten
142
+ .collect { | line | line.gsub(/\s+$/, "") }
143
+ .join("\n")
144
+ .gsub("/go/", "/")
145
+ .gsub(File.basename(__FILE__), "pact-broker")
142
146
  end
143
147
 
144
148
  def update_readme(usage_docs)
@@ -112,7 +112,7 @@ module PactBroker::Client
112
112
 
113
113
  context 'when the key does not exist' do
114
114
  it 'raises an error' do
115
- expect { subject._link!('foo') }.to raise_error RelationNotFoundError, "Could not find relation 'foo' in resource at http://pact"
115
+ expect { subject._link!('foo') }.to raise_error RelationNotFoundError, /Could not find relation 'foo' in resource at http:\/\/pact/
116
116
  end
117
117
  end
118
118
  end
@@ -4,63 +4,166 @@ module PactBroker
4
4
  module Client
5
5
  describe MergePacts do
6
6
  describe ".call" do
7
- let(:pact_hash_1) do
8
- {
9
- other: 'info',
10
- interactions: [
11
- {providerState: 1, description: 1, foo: 'bar' }
12
- ]
13
- }
14
- end
7
+ describe "with a pact with interactions" do
8
+ let(:pact_hash_1) do
9
+ {
10
+ other: 'info',
11
+ interactions: [
12
+ { providerState: 1, description: 1, foo: 'bar' }
13
+ ]
14
+ }
15
+ end
15
16
 
16
- let(:pact_hash_2) do
17
- {
18
- interactions: [
19
- {providerState: 2, description: 2, foo: 'wiffle' }
20
- ]
21
- }
22
- end
17
+ let(:pact_hash_2) do
18
+ {
19
+ interactions: [
20
+ { providerState: 2, description: 2, foo: 'wiffle' }
21
+ ]
22
+ }
23
+ end
23
24
 
24
- let(:pact_hash_3) do
25
- {
26
- interactions: [
27
- {providerState: 3, description: 3, foo: 'meep' },
28
- {providerState: 1, description: 1, foo: 'bar' }
29
- ]
30
- }
31
- end
25
+ let(:pact_hash_3) do
26
+ {
27
+ interactions: [
28
+ { providerState: 3, description: 3, foo: 'meep' },
29
+ { providerState: 1, description: 1, foo: 'bar' }
30
+ ]
31
+ }
32
+ end
32
33
 
33
- let(:pact_hashes) { [pact_hash_1, pact_hash_2, pact_hash_3] }
34
-
35
- let(:expected_merge) do
36
- {
37
- other: 'info',
38
- interactions: [
39
- {providerState: 1, description: 1, foo: 'bar' },
40
- {providerState: 2, description: 2, foo: 'wiffle' },
41
- {providerState: 3, description: 3, foo: 'meep' }
42
- ]
43
- }
44
- end
34
+ let(:pact_hashes) { [pact_hash_1, pact_hash_2, pact_hash_3] }
35
+
36
+ let(:expected_merge) do
37
+ {
38
+ other: 'info',
39
+ interactions: [
40
+ { providerState: 1, description: 1, foo: 'bar' },
41
+ { providerState: 2, description: 2, foo: 'wiffle' },
42
+ { providerState: 3, description: 3, foo: 'meep' }
43
+ ]
44
+ }
45
+ end
46
+
47
+ subject { MergePacts.call(pact_hashes) }
45
48
 
46
- subject { MergePacts.call(pact_hashes) }
49
+ it "merges the interactions by consumer/provider" do
50
+ expect(subject).to eq expected_merge
51
+ end
52
+
53
+ context "when an interaction is found with the same state and description but has a difference elsewhere" do
54
+ let(:pact_hash_3) do
55
+ {
56
+ interactions: [
57
+ { providerState: 3, description: 3, foo: 'meep' },
58
+ { providerState: 1, description: 1, foo: 'different' }
59
+ ]
60
+ }
61
+ end
47
62
 
48
- it "merges the interactions by consumer/provider" do
49
- expect(subject).to eq expected_merge
63
+ it "raises an error" do
64
+ expect { subject }.to raise_error PactMergeError, /foo.*different/
65
+ end
66
+ end
50
67
  end
51
68
 
52
- context "when an interaction is found with the same state and description but has a difference elsewhere" do
69
+ describe "with a pact with messages" do
70
+ let(:pact_hash_1) do
71
+ {
72
+ other: 'info',
73
+ messages: [
74
+ { providerState: 1, description: 1, foo: 'bar' }
75
+ ]
76
+ }
77
+ end
78
+
79
+ let(:pact_hash_2) do
80
+ {
81
+ messages: [
82
+ { providerState: 2, description: 2, foo: 'wiffle' }
83
+ ]
84
+ }
85
+ end
86
+
53
87
  let(:pact_hash_3) do
88
+ {
89
+ messages: [
90
+ { providerState: 3, description: 3, foo: 'meep' },
91
+ { providerState: 1, description: 1, foo: 'bar' }
92
+ ]
93
+ }
94
+ end
95
+
96
+ let(:pact_hashes) { [pact_hash_1, pact_hash_2, pact_hash_3] }
97
+
98
+ let(:expected_merge) do
99
+ {
100
+ other: 'info',
101
+ messages: [
102
+ { providerState: 1, description: 1, foo: 'bar' },
103
+ { providerState: 2, description: 2, foo: 'wiffle' },
104
+ { providerState: 3, description: 3, foo: 'meep' }
105
+ ]
106
+ }
107
+ end
108
+
109
+ subject { MergePacts.call(pact_hashes) }
110
+
111
+ it "merges the messages by consumer/provider" do
112
+ expect(subject).to eq expected_merge
113
+ end
114
+
115
+ context "when an interaction is found with the same state and description but has a difference elsewhere" do
116
+ let(:pact_hash_3) do
117
+ {
118
+ messages: [
119
+ { providerState: 3, description: 3, foo: 'meep' },
120
+ { providerState: 1, description: 1, foo: 'different' }
121
+ ]
122
+ }
123
+ end
124
+
125
+ it "raises an error" do
126
+ expect { subject }.to raise_error PactMergeError, /foo.*different/
127
+ end
128
+ end
129
+ end
130
+
131
+ describe "with a pact with messages and a pact with interactions" do
132
+ let(:pact_hash_1) do
133
+ {
134
+ other: 'info',
135
+ messages: [
136
+ { providerState: 1, description: 1, foo: 'bar' }
137
+ ]
138
+ }
139
+ end
140
+
141
+ let(:pact_hash_2) do
54
142
  {
55
143
  interactions: [
56
- {providerState: 3, description: 3, foo: 'meep' },
57
- {providerState: 1, description: 1, foo: 'different' }
144
+ { providerState: 2, description: 2, foo: 'wiffle' }
58
145
  ]
59
146
  }
60
147
  end
61
148
 
62
- it "raises an error" do
63
- expect { subject }.to raise_error PactMergeError, /foo.*different/
149
+ let(:pact_hashes) { [pact_hash_1, pact_hash_2] }
150
+
151
+ let(:expected_merge) do
152
+ {
153
+ other: 'info',
154
+ messages: [
155
+ { providerState: 1, description: 1, foo: 'bar' }
156
+ ],
157
+ interactions: [
158
+ { providerState: 2, description: 2, foo: 'wiffle' }
159
+ ]
160
+ }
161
+ end
162
+
163
+ subject { MergePacts.call(pact_hashes) }
164
+
165
+ it "merges the messages by consumer/provider" do
166
+ expect(subject).to eq expected_merge
64
167
  end
65
168
  end
66
169
  end
@@ -0,0 +1,174 @@
1
+ require "pact_broker/client/versions/create"
2
+
3
+ module PactBroker
4
+ module Client
5
+ describe Versions::Create do
6
+ describe "#call" do
7
+ let(:index_body) do
8
+ {
9
+ "_links" => {
10
+ "pb:pacticipant-branch-version" => {
11
+ "href" => "http://broker/pacticipants/{pacticipant}/branches/{branch}/versions/{version}"
12
+ },
13
+ "pb:pacticipant-version-tag" => {
14
+ "href" => "http://broker/pacticipants/{pacticipant}/versions/{version}/tags/{tag}"
15
+ },
16
+ "pb:pacticipant-version" => {
17
+ "href" => "http://broker/pacticipants/{pacticipant}/versions/{version}"
18
+ }
19
+ }
20
+ }
21
+ end
22
+
23
+ let!(:index_request) do
24
+ stub_request(:get, "http://broker").to_return(status: 200, body: index_body.to_json, headers: { "Content-Type" => "application/hal+json" } )
25
+ end
26
+
27
+ let!(:branch_request) do
28
+ stub_request(:put, "http://broker/pacticipants/Foo/branches/main/versions/1").to_return(status: 200, body: "{}", headers: { "Content-Type" => "application/hal+json" } )
29
+ end
30
+
31
+ let!(:tag_request) do
32
+ stub_request(:put, "http://broker/pacticipants/Foo/versions/1/tags/dev").to_return(status: 200, body: "{}", headers: { "Content-Type" => "application/hal+json" } )
33
+ end
34
+
35
+ let!(:create_version_request) do
36
+ stub_request(:put, "http://broker/pacticipants/Foo/versions/1").to_return(status: 200, body: { version: "created" }.to_json, headers: { "Content-Type" => "application/hal+json" } )
37
+ end
38
+
39
+ let!(:get_version_request) do
40
+ stub_request(:get, "http://broker/pacticipants/Foo/versions/1").to_return(status: 200, body: { version: "got" }.to_json, headers: { "Content-Type" => "application/hal+json" } )
41
+ end
42
+
43
+ let(:params) do
44
+ {
45
+ pacticipant_name: "Foo",
46
+ version_number: "1",
47
+ branch_name: branch_name,
48
+ tags: tags
49
+ }
50
+ end
51
+
52
+ let(:branch_name) { "main" }
53
+ let(:tags) { ["dev"] }
54
+
55
+ let(:options) do
56
+ {
57
+ verbose: "verbose",
58
+ output: output
59
+ }
60
+ end
61
+
62
+ let(:output) { "text" }
63
+
64
+ let(:pact_broker_client_options) do
65
+ {
66
+ token: "token",
67
+ pact_broker_base_url: "http://broker"
68
+ }
69
+ end
70
+
71
+ subject { PactBroker::Client::Versions::Create.call(params, options, pact_broker_client_options)}
72
+
73
+ context "with a branch and tags" do
74
+ it "creates a branch version" do
75
+ subject
76
+ expect(branch_request).to have_been_made
77
+ end
78
+
79
+ it "creates the tag" do
80
+ subject
81
+ expect(tag_request).to have_been_made
82
+ end
83
+
84
+ it "returns a message" do
85
+ expect(subject.message).to include "Created/updated pacticipant version 1 with branch main and tag(s) dev in the Pact Broker"
86
+ expect(subject.success).to be true
87
+ end
88
+
89
+ context "without output json" do
90
+ let(:output) { "json" }
91
+
92
+ it "returns a json message" do
93
+ expect(subject.message).to eq({ version: "got" }.to_json)
94
+ end
95
+ end
96
+ end
97
+
98
+ context "with only tags" do
99
+ let(:branch_name) { nil }
100
+
101
+ it "returns a message" do
102
+ expect(subject.message).to include "Created/updated pacticipant version 1 with tag(s) dev in the Pact Broker"
103
+ expect(subject.success).to be true
104
+ end
105
+
106
+ context "without output json" do
107
+ let(:output) { "json" }
108
+
109
+ it "returns a json message" do
110
+ expect(subject.message).to eq({ version: "got" }.to_json)
111
+ end
112
+ end
113
+ end
114
+
115
+ context "with only a branch" do
116
+ let(:tags) { nil }
117
+
118
+ it "returns a message" do
119
+ expect(subject.message).to include "Created/updated pacticipant version 1 with branch main in the Pact Broker"
120
+ expect(subject.success).to be true
121
+ end
122
+
123
+ context "without output json" do
124
+ let(:output) { "json" }
125
+
126
+ it "returns a json message" do
127
+ expect(subject.message).to eq({ version: "got" }.to_json)
128
+ end
129
+ end
130
+ end
131
+
132
+ context "with no branch or tags" do
133
+ let(:tags) { nil }
134
+ let(:branch_name) { nil }
135
+
136
+ it "creates a version" do
137
+ subject
138
+ expect(create_version_request).to have_been_made
139
+ end
140
+
141
+ it "returns a message" do
142
+ expect(subject.message).to include "Created/updated pacticipant version 1 in the Pact Broker"
143
+ expect(subject.success).to be true
144
+ end
145
+
146
+ context "without output json" do
147
+ let(:output) { "json" }
148
+
149
+ it "returns a json message" do
150
+ expect(subject.message).to eq({ version: "created" }.to_json)
151
+ end
152
+ end
153
+ end
154
+
155
+ context "when the Pact Broker does not support branch versions" do
156
+ before do
157
+ index_body["_links"].delete("pb:pacticipant-branch-version")
158
+ end
159
+
160
+ let(:index_body) do
161
+ {
162
+ "_links" => {}
163
+ }
164
+ end
165
+
166
+ it "returns an error" do
167
+ expect(subject.message).to include "does not support branch versions"
168
+ expect(subject.success).to be false
169
+ end
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end