pact_broker-client 1.36.0 → 1.37.0
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/.github/workflows/release_gem.yml +1 -0
- data/CHANGELOG.md +11 -0
- data/Rakefile +2 -0
- data/doc/pacts/markdown/Pact Broker Client - Pact Broker.md +180 -0
- data/lib/pact_broker/client.rb +1 -1
- data/lib/pact_broker/client/backports.rb +13 -0
- data/lib/pact_broker/client/cli/broker.rb +42 -23
- data/lib/pact_broker/client/cli/custom_thor.rb +9 -12
- data/lib/pact_broker/client/git.rb +3 -0
- data/lib/pact_broker/client/hal/entity.rb +27 -3
- data/lib/pact_broker/client/hal/http_client.rb +4 -0
- data/lib/pact_broker/client/hal/links.rb +39 -0
- data/lib/pact_broker/client/hal_client_methods.rb +11 -0
- data/lib/pact_broker/client/hash_refinements.rb +19 -0
- data/lib/pact_broker/client/matrix/text_formatter.rb +2 -0
- data/lib/pact_broker/client/publish_pacts.rb +2 -1
- data/lib/pact_broker/client/tasks/publication_task.rb +2 -0
- data/lib/pact_broker/client/version.rb +1 -1
- data/lib/pact_broker/client/versions/record_deployment.rb +109 -0
- data/script/trigger-release.sh +1 -1
- data/spec/lib/pact_broker/client/hal/entity_spec.rb +4 -3
- data/spec/lib/pact_broker/client/versions/describe_spec.rb +0 -1
- data/spec/lib/pact_broker/client/versions/record_deployment_spec.rb +82 -0
- data/spec/pacts/pact_broker_client-pact_broker.json +181 -0
- data/spec/service_providers/record_deployment_spec.rb +219 -0
- metadata +10 -2
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'pact_broker/client/error'
|
2
|
+
require 'pact_broker/client/hash_refinements'
|
2
3
|
|
3
4
|
=begin
|
4
5
|
|
@@ -21,6 +22,8 @@ BITBUCKET_BRANCH BITBUCKET_COMMIT https://confluence.atlassian.com/bitbucket/var
|
|
21
22
|
module PactBroker
|
22
23
|
module Client
|
23
24
|
module Git
|
25
|
+
using PactBroker::Client::HashRefinements
|
26
|
+
|
24
27
|
COMMAND = 'git rev-parse --abbrev-ref HEAD'.freeze
|
25
28
|
BRANCH_ENV_VAR_NAMES = %w{BUILDKITE_BRANCH CIRCLE_BRANCH TRAVIS_BRANCH GIT_BRANCH GIT_LOCAL_BRANCH APPVEYOR_REPO_BRANCH CI_COMMIT_REF_NAME BITBUCKET_BRANCH}.freeze
|
26
29
|
COMMIT_ENV_VAR_NAMES = %w{BUILDKITE_COMMIT CIRCLE_SHA1 TRAVIS_COMMIT GIT_COMMIT APPVEYOR_REPO_COMMIT CI_COMMIT_ID BITBUCKET_COMMIT}
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'erb'
|
2
2
|
require 'delegate'
|
3
3
|
require 'pact_broker/client/hal/link'
|
4
|
+
require 'pact_broker/client/hal/links'
|
4
5
|
|
5
6
|
module PactBroker
|
6
7
|
module Client
|
@@ -51,10 +52,27 @@ module PactBroker
|
|
51
52
|
end
|
52
53
|
end
|
53
54
|
|
55
|
+
def _links(key)
|
56
|
+
if @links[key] && @links[key].is_a?(Array)
|
57
|
+
link_collection = @links[key].collect do | hash |
|
58
|
+
Link.new(hash, @client)
|
59
|
+
end
|
60
|
+
Links.new(@href, key, link_collection)
|
61
|
+
elsif @links[key].is_a?(Hash)
|
62
|
+
Links.new(@href, key, [Link.new(@links[key], @client)])
|
63
|
+
else
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
54
68
|
def _link!(key)
|
55
69
|
_link(key) or raise RelationNotFoundError.new("Could not find relation '#{key}' in resource at #{@href}")
|
56
70
|
end
|
57
71
|
|
72
|
+
def _links!(key)
|
73
|
+
_links(key) or raise RelationNotFoundError.new("Could not find relation '#{key}' in resource at #{@href}")
|
74
|
+
end
|
75
|
+
|
58
76
|
def success?
|
59
77
|
true
|
60
78
|
end
|
@@ -85,7 +103,7 @@ module PactBroker
|
|
85
103
|
@data.key?(method_name) || @links.key?(method_name)
|
86
104
|
end
|
87
105
|
|
88
|
-
def assert_success!
|
106
|
+
def assert_success!(_ignored = nil)
|
89
107
|
self
|
90
108
|
end
|
91
109
|
end
|
@@ -107,8 +125,14 @@ module PactBroker
|
|
107
125
|
false
|
108
126
|
end
|
109
127
|
|
110
|
-
def assert_success!
|
111
|
-
|
128
|
+
def assert_success!(messages = {})
|
129
|
+
default_message = "Error retrieving #{@href} status=#{response ? response.status: nil} #{response ? response.raw_body : ''}".strip
|
130
|
+
message = if response && messages[response.status]
|
131
|
+
(messages[response.status] || "") + " (#{default_message})"
|
132
|
+
else
|
133
|
+
default_message
|
134
|
+
end
|
135
|
+
raise ErrorResponseReturned.new(message)
|
112
136
|
end
|
113
137
|
end
|
114
138
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'delegate'
|
3
|
+
|
4
|
+
module PactBroker
|
5
|
+
module Client
|
6
|
+
module Hal
|
7
|
+
class Links
|
8
|
+
def initialize(href, key, links)
|
9
|
+
@href = href
|
10
|
+
@key = key
|
11
|
+
@links = links
|
12
|
+
end
|
13
|
+
|
14
|
+
def names
|
15
|
+
@names ||= links.collect(&:name).compact.uniq
|
16
|
+
end
|
17
|
+
|
18
|
+
def find!(name, not_found_message = nil)
|
19
|
+
link = find(name)
|
20
|
+
if link
|
21
|
+
link
|
22
|
+
else
|
23
|
+
message = not_found_message || "Could not find relation '#{key}' with name '#{name}' in resource at #{href}."
|
24
|
+
available_options = names.any? ? names.join(", ") : "<none found>"
|
25
|
+
raise RelationNotFoundError.new(message.chomp(".") + ". Available options: #{available_options}")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def find(name)
|
30
|
+
links.find{ | link | link.name == name }
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
attr_reader :links, :key, :href
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'pact_broker/client/hal'
|
2
|
+
require 'pact_broker/client/retry'
|
2
3
|
|
3
4
|
module PactBroker
|
4
5
|
module Client
|
@@ -10,6 +11,16 @@ module PactBroker
|
|
10
11
|
def create_http_client(pact_broker_client_options)
|
11
12
|
PactBroker::Client::Hal::HttpClient.new(pact_broker_client_options.merge(pact_broker_client_options[:basic_auth] || {}))
|
12
13
|
end
|
14
|
+
|
15
|
+
def index_entry_point
|
16
|
+
@index_entry_point ||= create_index_entry_point(pact_broker_base_url, pact_broker_client_options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def index_resource
|
20
|
+
@index_resource ||= Retry.while_error do
|
21
|
+
index_entry_point.get!
|
22
|
+
end
|
23
|
+
end
|
13
24
|
end
|
14
25
|
end
|
15
26
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module PactBroker
|
2
|
+
module Client
|
3
|
+
module HashRefinements
|
4
|
+
refine Hash do
|
5
|
+
def compact
|
6
|
+
h = {}
|
7
|
+
each do |key, value|
|
8
|
+
h[key] = value unless value == nil
|
9
|
+
end
|
10
|
+
h
|
11
|
+
end unless Hash.method_defined? :compact
|
12
|
+
|
13
|
+
def compact!
|
14
|
+
reject! {|_key, value| value == nil}
|
15
|
+
end unless Hash.method_defined? :compact!
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
require 'table_print'
|
2
2
|
require 'dig_rb'
|
3
|
+
require 'pact_broker/client/hash_refinements'
|
3
4
|
|
4
5
|
module PactBroker
|
5
6
|
module Client
|
6
7
|
class Matrix
|
7
8
|
class TextFormatter
|
9
|
+
using PactBroker::Client::HashRefinements
|
8
10
|
|
9
11
|
Line = Struct.new(:consumer, :consumer_version, :provider, :provider_version, :success, :ref)
|
10
12
|
|
@@ -5,11 +5,12 @@ require 'pact_broker/client/pact_file'
|
|
5
5
|
require 'pact_broker/client/pact_hash'
|
6
6
|
require 'pact_broker/client/merge_pacts'
|
7
7
|
require 'pact_broker/client/hal_client_methods'
|
8
|
+
require 'pact_broker/client/hash_refinements'
|
8
9
|
|
9
10
|
module PactBroker
|
10
11
|
module Client
|
11
12
|
class PublishPacts
|
12
|
-
|
13
|
+
using PactBroker::Client::HashRefinements
|
13
14
|
include HalClientMethods
|
14
15
|
|
15
16
|
def self.call(pact_broker_base_url, pact_file_paths, consumer_version_params, pact_broker_client_options={})
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rake/tasklib'
|
2
2
|
require 'pact_broker/client/git'
|
3
|
+
require 'pact_broker/client/hash_refinements'
|
3
4
|
|
4
5
|
=begin
|
5
6
|
require pact_broker/client/tasks
|
@@ -17,6 +18,7 @@ end
|
|
17
18
|
module PactBroker
|
18
19
|
module Client
|
19
20
|
class PublicationTask < ::Rake::TaskLib
|
21
|
+
using PactBroker::Client::HashRefinements
|
20
22
|
|
21
23
|
attr_accessor :pattern, :pact_broker_base_url, :consumer_version, :tag, :write_method, :tag_with_git_branch, :pact_broker_basic_auth, :pact_broker_token
|
22
24
|
attr_reader :auto_detect_version_properties, :branch, :build_url
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'pact_broker/client/hal_client_methods'
|
2
|
+
require 'pact_broker/client/error'
|
3
|
+
require 'pact_broker/client/command_result'
|
4
|
+
|
5
|
+
module PactBroker
|
6
|
+
module Client
|
7
|
+
class Versions
|
8
|
+
class RecordDeployment
|
9
|
+
include PactBroker::Client::HalClientMethods
|
10
|
+
|
11
|
+
NOT_SUPPORTED_MESSAGE = "This version of the Pact Broker does not support recording deployments. Please upgrade to version 2.80.0 or later."
|
12
|
+
|
13
|
+
def self.call(params, pact_broker_base_url, pact_broker_client_options)
|
14
|
+
new(params, pact_broker_base_url, pact_broker_client_options).call
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(params, pact_broker_base_url, pact_broker_client_options)
|
18
|
+
@pact_broker_base_url = pact_broker_base_url
|
19
|
+
@pacticipant_name = params.fetch(:pacticipant_name)
|
20
|
+
@version_number = params.fetch(:version_number)
|
21
|
+
@environment_name = params.fetch(:environment_name)
|
22
|
+
@replaced_previous_deployed_version = params.fetch(:replaced_previous_deployed_version)
|
23
|
+
@output = params.fetch(:output)
|
24
|
+
@pact_broker_client_options = pact_broker_client_options
|
25
|
+
end
|
26
|
+
|
27
|
+
def call
|
28
|
+
check_if_command_supported
|
29
|
+
record_deployment
|
30
|
+
|
31
|
+
PactBroker::Client::CommandResult.new(true, result_message)
|
32
|
+
rescue PactBroker::Client::Error => e
|
33
|
+
PactBroker::Client::CommandResult.new(false, e.message)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
attr_reader :pact_broker_base_url, :pact_broker_client_options
|
39
|
+
attr_reader :pacticipant_name, :version_number, :environment_name, :replaced_previous_deployed_version, :output
|
40
|
+
attr_reader :deployed_version_resource
|
41
|
+
|
42
|
+
def check_environment_exists
|
43
|
+
index_resource
|
44
|
+
._link!("pb:environments")
|
45
|
+
.get!
|
46
|
+
._links("pb:environments")
|
47
|
+
.find!(environment_name, "No environment found with name '#{environment_name}'")
|
48
|
+
end
|
49
|
+
|
50
|
+
def record_deployment
|
51
|
+
@deployed_version_resource =
|
52
|
+
get_record_deployment_relation
|
53
|
+
.post(record_deployment_request_body)
|
54
|
+
.assert_success!
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_record_deployment_relation
|
58
|
+
record_deployment_links = get_pacticipant_version._links!("pb:record-deployment")
|
59
|
+
link_for_environment = record_deployment_links.find(environment_name)
|
60
|
+
if link_for_environment
|
61
|
+
link_for_environment
|
62
|
+
else
|
63
|
+
check_environment_exists
|
64
|
+
# Force the exception to be raised
|
65
|
+
record_deployment_links.find!(environment_name, "Environment '#{environment_name}' is not an available option for recording a deployment of #{pacticipant_name}.")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_pacticipant_version
|
70
|
+
index_resource
|
71
|
+
._link!("pb:pacticipant-version")
|
72
|
+
.expand(pacticipant: pacticipant_name, version: version_number)
|
73
|
+
.get
|
74
|
+
.assert_success!(404 => "#{pacticipant_name} version #{version_number} not found")
|
75
|
+
end
|
76
|
+
|
77
|
+
def record_deployment_request_body
|
78
|
+
{ replacedPreviousDeployedVersion: replaced_previous_deployed_version }
|
79
|
+
end
|
80
|
+
|
81
|
+
def result_message
|
82
|
+
if output == "text"
|
83
|
+
message = "Recorded deployment of #{pacticipant_name} version #{version_number} to #{environment_name} in #{pact_broker_name}."
|
84
|
+
suffix = replaced_previous_deployed_version ? " Marked previous deployed version as undeployed." : ""
|
85
|
+
message + suffix
|
86
|
+
elsif output == "json"
|
87
|
+
deployed_version_resource.response.raw_body
|
88
|
+
else
|
89
|
+
""
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def pact_broker_name
|
94
|
+
is_pactflow? ? "Pactflow" : "the Pact Broker"
|
95
|
+
end
|
96
|
+
|
97
|
+
def is_pactflow?
|
98
|
+
deployed_version_resource.response.headers.keys.any?{ | header_name | header_name.downcase.include?("pactflow") }
|
99
|
+
end
|
100
|
+
|
101
|
+
def check_if_command_supported
|
102
|
+
unless index_resource.can?("pb:environments")
|
103
|
+
raise PactBroker::Client::Error.new(NOT_SUPPORTED_MESSAGE)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/script/trigger-release.sh
CHANGED
@@ -19,7 +19,7 @@ output=$(curl -v -X POST https://api.github.com/repos/${repository_slug}/dispatc
|
|
19
19
|
-H "Authorization: Bearer $GITHUB_ACCESS_TOKEN_FOR_PF_RELEASES" \
|
20
20
|
-d "{\"event_type\": \"release-triggered\", \"client_payload\": {\"increment\": ${increment}}}" 2>&1)
|
21
21
|
|
22
|
-
if ! echo "${output}" | grep "HTTP
|
22
|
+
if ! echo "${output}" | grep "HTTP\/.* 204" > /dev/null; then
|
23
23
|
echo "$output" | sed "s/${GITHUB_ACCESS_TOKEN_FOR_PF_RELEASES}/********/g"
|
24
24
|
echo "Failed to trigger release"
|
25
25
|
exit 1
|
@@ -9,8 +9,9 @@ module PactBroker::Client
|
|
9
9
|
end
|
10
10
|
|
11
11
|
let(:provider_response) do
|
12
|
-
double('response', body: provider_hash, success?: true)
|
12
|
+
double('response', body: provider_hash, success?: true, status: status)
|
13
13
|
end
|
14
|
+
let(:status) { 200 }
|
14
15
|
|
15
16
|
let(:provider_hash) do
|
16
17
|
{
|
@@ -72,12 +73,12 @@ module PactBroker::Client
|
|
72
73
|
subject(:entity) { ErrorEntity.new("http://pact", pact_hash, http_client) }
|
73
74
|
|
74
75
|
it "raises an error" do
|
75
|
-
expect { entity.assert_success! }.to raise_error ErrorResponseReturned, "Error retrieving http://pact status=
|
76
|
+
expect { entity.assert_success! }.to raise_error ErrorResponseReturned, "Error retrieving http://pact status="
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
79
80
|
context "when the response is not successful and there is a response" do
|
80
|
-
let(:response) { double('response',
|
81
|
+
let(:response) { double('response', status: 200, raw_body: "body") }
|
81
82
|
|
82
83
|
subject(:entity) { ErrorEntity.new("http://pact", pact_hash, http_client, response) }
|
83
84
|
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'pact_broker/client/versions/record_deployment'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Client
|
5
|
+
class Versions
|
6
|
+
describe RecordDeployment do
|
7
|
+
describe ".call" do
|
8
|
+
let(:broker_base_url) { "http://broker" }
|
9
|
+
let(:index_body_hash) do
|
10
|
+
{
|
11
|
+
_links: {}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
let!(:index_request) do
|
15
|
+
stub_request(:get, broker_base_url).to_return(status: 200, body: index_body_hash.to_json, headers: { "Content-Type" => "application/hal+json" } )
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:replaced_previous_deployed_version) { true }
|
19
|
+
|
20
|
+
let(:params) do
|
21
|
+
{
|
22
|
+
pacticipant_name: "Foo",
|
23
|
+
version_number: "1",
|
24
|
+
environment_name: "test",
|
25
|
+
replaced_previous_deployed_version: replaced_previous_deployed_version,
|
26
|
+
output: "text"
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
let(:pact_broker_client_options) { {} }
|
31
|
+
|
32
|
+
subject { RecordDeployment.call(params, broker_base_url, pact_broker_client_options) }
|
33
|
+
|
34
|
+
context "when the pb:environments relation does not exist" do
|
35
|
+
it "returns an error response" do
|
36
|
+
expect(subject.success).to be false
|
37
|
+
expect(subject.message).to include "does not support"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when the response headers contain Pactflow" do
|
42
|
+
before do
|
43
|
+
allow_any_instance_of(RecordDeployment).to receive(:check_if_command_supported)
|
44
|
+
allow_any_instance_of(RecordDeployment).to receive(:check_environment_exists)
|
45
|
+
allow_any_instance_of(RecordDeployment).to receive(:record_deployment)
|
46
|
+
allow_any_instance_of(RecordDeployment).to receive(:deployed_version_resource).and_return(deployed_version_resource)
|
47
|
+
end
|
48
|
+
|
49
|
+
let(:response_headers) { { "X-Pactflow-Sha" => "abc" } }
|
50
|
+
|
51
|
+
let(:deployed_version_resource) do
|
52
|
+
double('PactBroker::Client::Hal::Entity', response: double('response', headers: response_headers) )
|
53
|
+
end
|
54
|
+
|
55
|
+
it "indicates the API was Pactflow" do
|
56
|
+
expect(subject.message).to include "Recorded deployment of Foo version 1 to test in Pactflow"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when replaced_previous_deployed_version is false" do
|
61
|
+
before do
|
62
|
+
allow_any_instance_of(RecordDeployment).to receive(:check_if_command_supported)
|
63
|
+
allow_any_instance_of(RecordDeployment).to receive(:check_environment_exists)
|
64
|
+
allow_any_instance_of(RecordDeployment).to receive(:record_deployment)
|
65
|
+
allow_any_instance_of(RecordDeployment).to receive(:pact_broker_name).and_return("")
|
66
|
+
end
|
67
|
+
|
68
|
+
let(:replaced_previous_deployed_version) { false }
|
69
|
+
|
70
|
+
let(:deployed_version_resource) do
|
71
|
+
double('PactBroker::Client::Hal::Entity', response: double('response', headers: response_headers) )
|
72
|
+
end
|
73
|
+
|
74
|
+
it "does not include the message about marking the previous version as undeployed" do
|
75
|
+
expect(subject.message).to_not include "undeployed"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|