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.
@@ -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
- raise ErrorResponseReturned.new("Error retrieving #{@href} status=#{response ? response.code: nil} #{response ? response.raw_body : ''}")
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
@@ -83,6 +83,10 @@ module PactBroker
83
83
  end
84
84
  end
85
85
 
86
+ def headers
87
+ __getobj__().to_hash
88
+ end
89
+
86
90
  def raw_body
87
91
  __getobj__().body
88
92
  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
@@ -1,5 +1,5 @@
1
1
  module PactBroker
2
2
  module Client
3
- VERSION = '1.36.0'
3
+ VERSION = '1.37.0'
4
4
  end
5
5
  end
@@ -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
@@ -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\/1.1 204" > /dev/null; then
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', code: 200, raw_body: "body") }
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
 
@@ -5,7 +5,6 @@ module PactBroker
5
5
  class Versions
6
6
  describe Describe do
7
7
  describe ".call" do
8
-
9
8
  let(:versions_client) do
10
9
  instance_double('PactBroker::Client::Versions', latest: version_hash)
11
10
  end
@@ -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