diff --git a/doc/pacts/markdown/Pact Broker Client - Pact Broker.md b/doc/pacts/markdown/Pact Broker Client - Pact Broker.md
index 403e7861..c63f15d8 100644
--- a/doc/pacts/markdown/Pact Broker Client - Pact Broker.md
+++ b/doc/pacts/markdown/Pact Broker Client - Pact Broker.md
@@ -40,6 +40,8 @@
* [A request for the index resource](#a_request_for_the_index_resource_given_the_pb:pacticipant-version_relation_exists_in_the_index_resource) given the pb:pacticipant-version relation exists in the index resource
+* [A request for the index resource](#a_request_for_the_index_resource_given_the_pb:publish-contracts_relations_exists_in_the_index_resource) given the pb:publish-contracts relations exists in the index resource
+
* [A request for the index resource with the webhook relation](#a_request_for_the_index_resource_with_the_webhook_relation)
* [A request for the list of the latest pacts from all consumers for the Pricing Service'](#a_request_for_the_list_of_the_latest_pacts_from_all_consumers_for_the_Pricing_Service'_given_a_latest_pact_between_Condor_and_the_Pricing_Service_exists) given a latest pact between Condor and the Pricing Service exists
@@ -92,6 +94,8 @@
* [A request to publish a pact with method put](#a_request_to_publish_a_pact_with_method_put_given_the_'Pricing_Service'_and_'Condor'_already_exist_in_the_pact-broker,_and_Condor_already_has_a_pact_published_for_version_1.3.0) given the 'Pricing Service' and 'Condor' already exist in the pact-broker, and Condor already has a pact published for version 1.3.0
+* [A request to publish contracts](#a_request_to_publish_contracts)
+
* [A request to record a deployment](#a_request_to_record_a_deployment_given_version_5556b8149bf8bac76bc30f50a8a2dd4c22c85f30_of_pacticipant_Foo_exists_with_a_test_environment_available_for_deployment) given version 5556b8149bf8bac76bc30f50a8a2dd4c22c85f30 of pacticipant Foo exists with a test environment available for deployment
* [A request to register the repository URL of a pacticipant](#a_request_to_register_the_repository_URL_of_a_pacticipant_given_the_'Pricing_Service'_already_exists_in_the_pact-broker) given the 'Pricing Service' already exists in the pact-broker
@@ -832,6 +836,33 @@ Pact Broker will respond with:
}
}
```
+
+Given **the pb:publish-contracts relations exists in the index resource**, upon receiving **a request for the index resource** from Pact Broker Client, with
+```json
+{
+ "method": "GET",
+ "path": "/",
+ "headers": {
+ "Accept": "application/hal+json"
+ }
+}
+```
+Pact Broker will respond with:
+```json
+{
+ "status": 200,
+ "headers": {
+ "Content-Type": "application/hal+json;charset=utf-8"
+ },
+ "body": {
+ "_links": {
+ "pb:publish-contracts": {
+ "href": "http://localhost:1234/HAL-REL-PLACEHOLDER-PB-PUBLISH-CONTRACTS"
+ }
+ }
+ }
+}
+```
Upon receiving **a request for the index resource with the webhook relation** from Pact Broker Client, with
```json
@@ -1928,6 +1959,75 @@ Pact Broker will respond with:
}
}
```
+
+Upon receiving **a request to publish contracts** from Pact Broker Client, with
+```json
+{
+ "method": "POST",
+ "path": "/HAL-REL-PLACEHOLDER-PB-PUBLISH-CONTRACTS",
+ "headers": {
+ "Content-Type": "application/json",
+ "Accept": "application/hal+json"
+ },
+ "body": {
+ "pacticipantName": "Foo",
+ "pacticipantVersionNumber": "5556b8149bf8bac76bc30f50a8a2dd4c22c85f30",
+ "branch": "main",
+ "tags": [
+ "dev"
+ ],
+ "buildUrl": "http://build",
+ "contracts": [
+ {
+ "consumerName": "Foo",
+ "providerName": "Bar",
+ "specification": "pact",
+ "contentType": "application/json",
+ "content": "eyJjb25zdW1lciI6eyJuYW1lIjoiRm9vIn0sInByb3ZpZGVyIjp7Im5hbWUiOiJCYXIifSwiaW50ZXJhY3Rpb25zIjpbeyJkZXNjcmlwdGlvbiI6ImFuIGV4YW1wbGUgcmVxdWVzdCIsInByb3ZpZGVyU3RhdGUiOiJhIHByb3ZpZGVyIHN0YXRlIiwicmVxdWVzdCI6eyJtZXRob2QiOiJHRVQiLCJwYXRoIjoiLyIsImhlYWRlcnMiOnt9fSwicmVzcG9uc2UiOnsic3RhdHVzIjoyMDAsImhlYWRlcnMiOnsiQ29udGVudC1UeXBlIjoiYXBwbGljYXRpb24vaGFsK2pzb24ifX19XSwibWV0YWRhdGEiOnsicGFjdFNwZWNpZmljYXRpb24iOnsidmVyc2lvbiI6IjIuMC4wIn19fQ==",
+ "writeMode": "overwrite"
+ }
+ ]
+ }
+}
+```
+Pact Broker will respond with:
+```json
+{
+ "status": 200,
+ "headers": {
+ "Content-Type": "application/hal+json;charset=utf-8"
+ },
+ "body": {
+ "_embedded": {
+ "pacticipant": {
+ "name": "Foo"
+ },
+ "version": {
+ "number": "5556b8149bf8bac76bc30f50a8a2dd4c22c85f30",
+ "buildUrl": "http://build"
+ }
+ },
+ "logs": [
+ {
+ "level": "info",
+ "message": "some message"
+ }
+ ],
+ "_links": {
+ "pb:pacticipant-version-tags": [
+ {
+ "name": "dev"
+ }
+ ],
+ "pb:contracts": [
+ {
+ "href": "http://some-pact"
+ }
+ ]
+ }
+ }
+}
+```
Given **version 5556b8149bf8bac76bc30f50a8a2dd4c22c85f30 of pacticipant Foo exists with a test environment available for deployment**, upon receiving **a request to record a deployment** from Pact Broker Client, with
```json
diff --git a/example/scripts/publish-pact.sh b/example/scripts/publish-pact.sh
index 3bfbdbd3..7811e414 100755
--- a/example/scripts/publish-pact.sh
+++ b/example/scripts/publish-pact.sh
@@ -1,3 +1,3 @@
# assumes you've set PACT_BROKER_BASE_URL, PACT_BROKER_USERNAME and PACT_BROKER_PASSWORD already
-bundle exec bin/pact-broker publish $(dirname "$0")/pact.json --consumer-app-version=1.0.0 --tag master
+bundle exec bin/pact-broker publish $(dirname "$0")/pact.json --consumer-app-version=1.0.0 --tag master --verbose
diff --git a/lib/pact_broker/client/cli/broker.rb b/lib/pact_broker/client/cli/broker.rb
index 493136bd..cc9ced55 100644
--- a/lib/pact_broker/client/cli/broker.rb
+++ b/lib/pact_broker/client/cli/broker.rb
@@ -51,14 +51,16 @@ def can_i_deploy(*ignored_but_necessary)
method_option :tag_with_git_branch, aliases: "-g", type: :boolean, default: false, required: false, desc: "Tag consumer version with the name of the current git branch. Default: false"
method_option :build_url, desc: "The build URL that created the pact"
method_option :merge, type: :boolean, default: false, require: false, desc: "If a pact already exists for this consumer version and provider, merge the contents. Useful when running Pact tests concurrently on different build nodes."
+ method_option :output, aliases: "-o", desc: "json or text", default: 'text'
shared_authentication_options
def publish(*pact_files)
require 'pact_broker/client/error'
validate_credentials
validate_pact_files(pact_files)
- success = publish_pacts(pact_files)
- raise PactPublicationError, "One or more pacts failed to be published" unless success
+ result = publish_pacts(pact_files)
+ $stdout.puts result.message
+ exit(1) unless result.success
rescue PactBroker::Client::Error => e
raise PactPublicationError, "#{e.class} - #{e.message}"
end
@@ -283,6 +285,7 @@ def publish_pacts pact_files
options.broker_base_url,
file_list(pact_files),
consumer_version_params,
+ { merge: options[:merge], output: options.output }.compact,
pact_broker_client_options.merge(write_options)
)
end
@@ -393,7 +396,6 @@ def parse_webhook_options(webhook_url)
provider: options.provider,
events: events
}
-
end
def run_webhook_commands webhook_url
diff --git a/lib/pact_broker/client/hal/http_client.rb b/lib/pact_broker/client/hal/http_client.rb
index 8d8922b0..ecfa59c1 100644
--- a/lib/pact_broker/client/hal/http_client.rb
+++ b/lib/pact_broker/client/hal/http_client.rb
@@ -54,7 +54,7 @@ def create_request uri, http_method, body = nil, headers = {}
end
def perform_request request, uri
- response = until_truthy_or_max_times(times: 5, sleep: 5, condition: ->(resp) { resp.code.to_i < 500 }) do
+ response = until_truthy_or_max_times(condition: ->(resp) { resp.code.to_i < 500 }) do
http = Net::HTTP.new(uri.host, uri.port, :ENV)
http.set_debug_output(output_stream) if verbose
http.use_ssl = (uri.scheme == 'https')
@@ -71,7 +71,7 @@ def perform_request request, uri
end
def until_truthy_or_max_times options = {}
- max_tries = options.fetch(:times, 3)
+ max_tries = options.fetch(:times, default_max_tries)
tries = 0
sleep_interval = options.fetch(:sleep, 5)
sleep(sleep_interval) if options[:sleep_first]
@@ -97,6 +97,10 @@ def until_truthy_or_max_times options = {}
end
end
+ def default_max_tries
+ 5
+ end
+
def sleep seconds
Kernel.sleep seconds
end
diff --git a/lib/pact_broker/client/pacts.rb b/lib/pact_broker/client/pacts.rb
index 9aa3236f..2486c67f 100644
--- a/lib/pact_broker/client/pacts.rb
+++ b/lib/pact_broker/client/pacts.rb
@@ -4,7 +4,6 @@
module PactBroker
module Client
class Pacts < BaseClient
-
def publish options
consumer_version = options[:consumer_version]
pact_hash = options[:pact_hash]
diff --git a/lib/pact_broker/client/publish_pacts.rb b/lib/pact_broker/client/publish_pacts.rb
index 439057de..35983ef4 100644
--- a/lib/pact_broker/client/publish_pacts.rb
+++ b/lib/pact_broker/client/publish_pacts.rb
@@ -1,11 +1,7 @@
require 'term/ansicolor'
-require 'pact_broker/client'
-require 'pact_broker/client/retry'
-require 'pact_broker/client/pact_file'
-require 'pact_broker/client/pact_hash'
-require 'pact_broker/client/merge_pacts'
require 'pact_broker/client/hal_client_methods'
-require 'pact_broker/client/hash_refinements'
+require 'base64'
+require 'pact_broker/client/publish_pacts_the_old_way'
module PactBroker
module Client
@@ -13,170 +9,132 @@ class PublishPacts
using PactBroker::Client::HashRefinements
include HalClientMethods
- def self.call(pact_broker_base_url, pact_file_paths, consumer_version_params, pact_broker_client_options={})
- new(pact_broker_base_url, pact_file_paths, consumer_version_params, pact_broker_client_options).call
+ def self.call(pact_broker_base_url, pact_file_paths, consumer_version_params, options, pact_broker_client_options={})
+ new(pact_broker_base_url, pact_file_paths, consumer_version_params, options, pact_broker_client_options).call
end
- def initialize pact_broker_base_url, pact_file_paths, consumer_version_params, pact_broker_client_options={}
+ def initialize pact_broker_base_url, pact_file_paths, consumer_version_params, options, pact_broker_client_options={}
@pact_broker_base_url = pact_broker_base_url
@pact_file_paths = pact_file_paths
- @consumer_version_number = consumer_version_params[:number].respond_to?(:strip) ? consumer_version_params[:number].strip : consumer_version_params[:number]
- @branch = consumer_version_params[:branch]
- @build_url = consumer_version_params[:build_url]
- @tags = consumer_version_params[:tags] ? consumer_version_params[:tags].collect{ |tag| tag.respond_to?(:strip) ? tag.strip : tag } : []
- @version_required = consumer_version_params[:version_required]
+ @consumer_version_params = consumer_version_params
+ @consumer_version_number = strip(consumer_version_params[:number])
+ @branch = strip(consumer_version_params[:branch])
+ @build_url = strip(consumer_version_params[:build_url])
+ @tags = consumer_version_params[:tags] ? consumer_version_params[:tags].collect{ |tag| strip(tag) } : []
+ @options = options
@pact_broker_client_options = pact_broker_client_options
end
def call
validate
- $stdout.puts("")
- result = create_consumer_versions && apply_tags && publish_pacts
- $stdout.puts("")
- result
+ if index_resource.can?("pb:publish-contracts")
+ publish_pacts
+ PactBroker::Client::CommandResult.new(success?, message)
+ else
+ PublishPactsTheOldWay.call(pact_broker_base_url, pact_file_paths, consumer_version_params, options, pact_broker_client_options)
+ end
end
private
- attr_reader :pact_broker_base_url, :pact_file_paths, :consumer_version_number, :branch, :tags, :build_url, :pact_broker_client_options, :version_required
-
- def pact_broker_client
- @pact_broker_client ||= PactBroker::Client::PactBrokerClient.new(base_url: pact_broker_base_url, client_options: pact_broker_client_options)
- end
-
- def index_entry_point
- @index_entry_point ||= create_index_entry_point(pact_broker_base_url, pact_broker_client_options)
- end
+ attr_reader :pact_broker_base_url, :pact_file_paths, :consumer_version_params, :consumer_version_number, :branch, :tags, :build_url, :options, :pact_broker_client_options, :response_entities
- def index_resource
- @index_resource ||= Retry.while_error do
- index_entry_point.get!
- end
- end
-
- def can_create_version_with_branch?
- @can_create_version_with_branch ||= index_resource.can?('pb:pacticipant-version')
- end
-
- def merge_on_server?
- pact_broker_client_options[:write] == :merge
+ def request_body_for(consumer_name)
+ {
+ pacticipantName: consumer_name,
+ pacticipantVersionNumber: consumer_version_number,
+ tags: tags,
+ branch: branch,
+ buildUrl: build_url,
+ contracts: contracts_for(consumer_name)
+ }.compact
end
def publish_pacts
- pact_files.group_by(&:pact_name).collect do | pact_name, pact_files |
- $stdout.puts "Merging #{pact_files.collect(&:path).join(", ")}" if pact_files.size > 1
- publish_pact(PactHash[merge_contents(pact_files)])
- end.all?
- end
-
- def merge_contents(pact_files)
- MergePacts.call(pact_files.collect(&:pact_hash))
- end
-
- def pact_files
- @pact_files ||= pact_file_paths.collect{ |pact_file_path| PactFile.new(pact_file_path) }
- end
-
- def consumer_names
- pact_files.collect(&:consumer_name).uniq
+ @response_entities = consumer_names.collect do | consumer_name |
+ index_resource._link("pb:publish-contracts").post(request_body_for(consumer_name))
+ end
end
- def publish_pact pact
- begin
- $stdout.puts "Publishing #{pact.pact_name} to pact broker at #{pact_broker_base_url}"
- publish_pact_contents pact
- rescue => e
- $stderr.puts "Failed to publish #{pact.pact_name} due to error: #{e.class} - #{e}"
- false
- end
+ def success?
+ response_entities.all?(&:success?)
end
- def create_consumer_versions
- if create_versions?
- consumer_names.collect do | consumer_name |
- create_version(index_resource, consumer_name)
- end
- true
+ def message
+ if options[:output] == "json"
+ response_entities.collect(&:response).collect(&:body).to_a.to_json
else
- true
+ text_message
end
end
- def create_versions?
- if version_required
- if can_create_version_with_branch?
- true
+ def text_message
+ response_entities.flat_map do | response_entity |
+ if response_entity.success?
+ if response_entity.logs
+ response_entity.logs.collect do | log |
+ colorized_message(log)
+ end
+ else
+ "Successfully published pacts"
+ end
else
- raise PactBroker::Client::Error.new("This version of the Pact Broker does not support versions with branches or build URLs. Please upgrade your broker to 2.76.2 or later.")
+ ::Term::ANSIColor.red(response_entity.response.body.to_s)
end
- elsif (branch || build_url) && can_create_version_with_branch?
- true
+ end.join("\n")
+ end
+
+ def colorized_message(log)
+ color = color_for_level(log["level"])
+ if color
+ ::Term::ANSIColor.send(color, log["message"])
else
- false
+ log["message"]
end
end
- def create_version(index_resource, consumer_name)
- Retry.while_error do
- version_resource = index_resource._link('pb:pacticipant-version').expand(version: consumer_version_number, pacticipant: consumer_name).put(version_body).assert_success!
- message = if version_resource.response.status == 200
- "Replaced version #{consumer_version_number} of #{consumer_name}"
- else
- "Created version #{consumer_version_number} of #{consumer_name}"
- end
+ def color_for_level(level)
+ case level
+ when "warn" then :yellow
+ when "error" then :red
+ when "info" then :green
+ else nil
+ end
+ end
- message = message + " (branch #{branch})" if branch
- $stdout.puts message
- if version_resource.response.status == 200
- $stdout.puts ::Term::ANSIColor.yellow("Replacing the version resource is not recommended under normal circumstances and may indicate that you have not configured your Pact pipeline correctly (unless you are just re-running a build for a particular commit). For more information see https://docs.pact.io/versioning")
- end
- true
+ def contracts_for(consumer_name)
+ pact_files_for(consumer_name).group_by(&:pact_name).values.collect do | pact_files |
+ $stderr.puts "Merging #{pact_files.collect(&:path).join(", ")}" if pact_files.size > 1
+ pact_hash = PactHash[merge_contents(pact_files)]
+ {
+ consumerName: pact_hash.consumer_name,
+ providerName: pact_hash.provider_name,
+ specification: "pact",
+ contentType: "application/json",
+ content: Base64.strict_encode64(pact_hash.to_json),
+ writeMode: write_mode
+ }
end
end
- def version_body
- {
- branch: branch,
- buildUrl: build_url
- }.compact
+ def merge_contents(pact_files)
+ MergePacts.call(pact_files.collect(&:pact_hash))
end
- def apply_tags
- return true if tags.empty?
- tags.all? do | tag |
- tag_consumer_version tag
- end
+ def pact_files
+ @pact_files ||= pact_file_paths.collect{ |pact_file_path| PactFile.new(pact_file_path) }
end
- def tag_consumer_version tag
- versions = pact_broker_client.pacticipants.versions
- Retry.while_error do
- consumer_names.collect do | consumer_name |
- versions.tag(pacticipant: consumer_name, version: consumer_version_number, tag: tag)
- $stdout.puts "Tagged version #{consumer_version_number} of #{consumer_name} as #{tag.inspect}"
- true
- end
- end
- rescue => e
- $stderr.puts "Failed to tag version due to error: #{e.class} - #{e}"
- false
+ def pact_files_for(consumer_name)
+ pact_files.select{ | pact_file | pact_file.consumer_name == consumer_name }
end
- def publish_pact_contents(pact)
- Retry.while_error do
- pacts = pact_broker_client.pacticipants.versions.pacts
- if pacts.version_published?(consumer: pact.consumer_name, provider: pact.provider_name, consumer_version: consumer_version_number)
- if merge_on_server?
- $stdout.puts "A pact for this consumer version is already published. Merging contents."
- else
- $stdout.puts ::Term::ANSIColor.yellow("A pact for this consumer version is already published. Overwriting. (Note: Overwriting pacts is not recommended as it can lead to race conditions. Best practice is to provide a unique consumer version number for each publication. For more information, see https://docs.pact.io/versioning)")
- end
- end
+ def consumer_names
+ pact_files.collect(&:consumer_name).uniq
+ end
- latest_pact_url = pacts.publish(pact_hash: pact, consumer_version: consumer_version_number)
- $stdout.puts "The latest version of this pact can be accessed at the following URL:\n#{latest_pact_url}"
- true
- end
+ def write_mode
+ options[:merge] ? "merge" : "overwrite"
end
def validate
@@ -184,6 +142,10 @@ def validate
raise PactBroker::Client::Error.new("Please specify the pact_broker_base_url") unless (pact_broker_base_url && pact_broker_base_url.to_s.strip.size > 0)
raise PactBroker::Client::Error.new("No pact files found") unless (pact_file_paths && pact_file_paths.any?)
end
+
+ def strip(maybe_string)
+ maybe_string.respond_to?(:strip) ? maybe_string.strip : maybe_string
+ end
end
end
end
diff --git a/lib/pact_broker/client/publish_pacts_the_old_way.rb b/lib/pact_broker/client/publish_pacts_the_old_way.rb
new file mode 100644
index 00000000..d3228872
--- /dev/null
+++ b/lib/pact_broker/client/publish_pacts_the_old_way.rb
@@ -0,0 +1,194 @@
+require 'term/ansicolor'
+require 'pact_broker/client'
+require 'pact_broker/client/retry'
+require 'pact_broker/client/pact_file'
+require 'pact_broker/client/pact_hash'
+require 'pact_broker/client/merge_pacts'
+require 'pact_broker/client/hal_client_methods'
+require 'pact_broker/client/hash_refinements'
+require 'pact_broker/client/command_result'
+
+module PactBroker
+ module Client
+ class PublishPactsTheOldWay
+ using PactBroker::Client::HashRefinements
+ include HalClientMethods
+
+ def self.call(pact_broker_base_url, pact_file_paths, consumer_version_params, options, pact_broker_client_options={})
+ new(pact_broker_base_url, pact_file_paths, consumer_version_params, options, pact_broker_client_options).call
+ end
+
+ def initialize pact_broker_base_url, pact_file_paths, consumer_version_params, options, pact_broker_client_options={}
+ @pact_broker_base_url = pact_broker_base_url
+ @pact_file_paths = pact_file_paths
+ @consumer_version_number = consumer_version_params[:number].respond_to?(:strip) ? consumer_version_params[:number].strip : consumer_version_params[:number]
+ @branch = consumer_version_params[:branch]
+ @build_url = consumer_version_params[:build_url]
+ @tags = consumer_version_params[:tags] ? consumer_version_params[:tags].collect{ |tag| tag.respond_to?(:strip) ? tag.strip : tag } : []
+ @version_required = consumer_version_params[:version_required]
+ @pact_broker_client_options = pact_broker_client_options
+ end
+
+ def call
+ validate
+ $stdout.puts("")
+ result = create_consumer_versions && apply_tags && publish_pacts
+ $stdout.puts("")
+ if result
+ PactBroker::Client::CommandResult.new(true)
+ else
+ PactBroker::Client::CommandResult.new(false, "One or more pacts failed to be published")
+ end
+ end
+
+ private
+
+ attr_reader :pact_broker_base_url, :pact_file_paths, :consumer_version_number, :branch, :tags, :build_url, :pact_broker_client_options, :version_required
+
+ def pact_broker_client
+ @pact_broker_client ||= PactBroker::Client::PactBrokerClient.new(base_url: pact_broker_base_url, client_options: pact_broker_client_options)
+ end
+
+ def index_entry_point
+ @index_entry_point ||= create_index_entry_point(pact_broker_base_url, pact_broker_client_options)
+ end
+
+ def index_resource
+ @index_resource ||= Retry.while_error do
+ index_entry_point.get!
+ end
+ end
+
+ def can_create_version_with_branch?
+ @can_create_version_with_branch ||= index_resource.can?('pb:pacticipant-version')
+ end
+
+ def merge_on_server?
+ pact_broker_client_options[:write] == :merge
+ end
+
+ def publish_pacts
+ pact_files.group_by(&:pact_name).collect do | pact_name, pact_files |
+ $stdout.puts "Merging #{pact_files.collect(&:path).join(", ")}" if pact_files.size > 1
+ publish_pact(PactHash[merge_contents(pact_files)])
+ end.all?
+ end
+
+ def merge_contents(pact_files)
+ MergePacts.call(pact_files.collect(&:pact_hash))
+ end
+
+ def pact_files
+ @pact_files ||= pact_file_paths.collect{ |pact_file_path| PactFile.new(pact_file_path) }
+ end
+
+ def consumer_names
+ pact_files.collect(&:consumer_name).uniq
+ end
+
+ def publish_pact pact
+ begin
+ $stdout.puts "Publishing #{pact.pact_name} to pact broker at #{pact_broker_base_url}"
+ publish_pact_contents pact
+ rescue => e
+ $stderr.puts "Failed to publish #{pact.pact_name} due to error: #{e.class} - #{e}"
+ false
+ end
+ end
+
+ def create_consumer_versions
+ if create_versions?
+ consumer_names.collect do | consumer_name |
+ create_version(index_resource, consumer_name)
+ end
+ true
+ else
+ true
+ end
+ end
+
+ def create_versions?
+ if version_required
+ if can_create_version_with_branch?
+ true
+ else
+ raise PactBroker::Client::Error.new("This version of the Pact Broker does not support versions with branches or build URLs. Please upgrade your broker to 2.76.2 or later.")
+ end
+ elsif (branch || build_url) && can_create_version_with_branch?
+ true
+ else
+ false
+ end
+ end
+
+ def create_version(index_resource, consumer_name)
+ Retry.while_error do
+ version_resource = index_resource._link('pb:pacticipant-version').expand(version: consumer_version_number, pacticipant: consumer_name).put(version_body).assert_success!
+ message = if version_resource.response.status == 200
+ "Replaced version #{consumer_version_number} of #{consumer_name}"
+ else
+ "Created version #{consumer_version_number} of #{consumer_name}"
+ end
+
+ message = message + " (branch #{branch})" if branch
+ $stdout.puts message
+ if version_resource.response.status == 200
+ $stdout.puts ::Term::ANSIColor.yellow("Replacing the version resource is not recommended under normal circumstances and may indicate that you have not configured your Pact pipeline correctly (unless you are just re-running a build for a particular commit). For more information see https://docs.pact.io/versioning")
+ end
+ true
+ end
+ end
+
+ def version_body
+ {
+ branch: branch,
+ buildUrl: build_url
+ }.compact
+ end
+
+ def apply_tags
+ return true if tags.empty?
+ tags.all? do | tag |
+ tag_consumer_version tag
+ end
+ end
+
+ def tag_consumer_version tag
+ versions = pact_broker_client.pacticipants.versions
+ Retry.while_error do
+ consumer_names.collect do | consumer_name |
+ versions.tag(pacticipant: consumer_name, version: consumer_version_number, tag: tag)
+ $stdout.puts "Tagged version #{consumer_version_number} of #{consumer_name} as #{tag.inspect}"
+ true
+ end
+ end
+ rescue => e
+ $stderr.puts "Failed to tag version due to error: #{e.class} - #{e}"
+ false
+ end
+
+ def publish_pact_contents(pact)
+ Retry.while_error do
+ pacts = pact_broker_client.pacticipants.versions.pacts
+ if pacts.version_published?(consumer: pact.consumer_name, provider: pact.provider_name, consumer_version: consumer_version_number)
+ if merge_on_server?
+ $stdout.puts "A pact for this consumer version is already published. Merging contents."
+ else
+ $stdout.puts ::Term::ANSIColor.yellow("A pact for this consumer version is already published. Overwriting. (Note: Overwriting pacts is not recommended as it can lead to race conditions. Best practice is to provide a unique consumer version number for each publication. For more information, see https://docs.pact.io/versioning)")
+ end
+ end
+
+ latest_pact_url = pacts.publish(pact_hash: pact, consumer_version: consumer_version_number)
+ $stdout.puts "The latest version of this pact can be accessed at the following URL:\n#{latest_pact_url}"
+ true
+ end
+ end
+
+ def validate
+ raise PactBroker::Client::Error.new("Please specify the consumer_version_number") unless (consumer_version_number && consumer_version_number.to_s.strip.size > 0)
+ raise PactBroker::Client::Error.new("Please specify the pact_broker_base_url") unless (pact_broker_base_url && pact_broker_base_url.to_s.strip.size > 0)
+ raise PactBroker::Client::Error.new("No pact files found") unless (pact_file_paths && pact_file_paths.any?)
+ end
+ end
+ end
+end
diff --git a/lib/pact_broker/client/tasks/publication_task.rb b/lib/pact_broker/client/tasks/publication_task.rb
index 1e612f8e..84f36554 100644
--- a/lib/pact_broker/client/tasks/publication_task.rb
+++ b/lib/pact_broker/client/tasks/publication_task.rb
@@ -63,8 +63,9 @@ def rake_task &block
pact_broker_client_options[:basic_auth] = pact_broker_basic_auth if pact_broker_basic_auth && pact_broker_basic_auth.any?
pact_broker_client_options.compact!
consumer_version_params = { number: consumer_version, branch: the_branch, build_url: build_url, tags: all_tags, version_required: version_required }.compact
- success = PactBroker::Client::PublishPacts.new(pact_broker_base_url, FileList[pattern], consumer_version_params, pact_broker_client_options).call
- raise "One or more pacts failed to be published" unless success
+ result = PactBroker::Client::PublishPacts.new(pact_broker_base_url, FileList[pattern], consumer_version_params, {}, pact_broker_client_options).call
+ $stdout.puts result.message
+ raise "One or more pacts failed to be published" unless result.success
end
end
end
@@ -86,7 +87,6 @@ def the_branch
branch
end
end
-
end
end
end
diff --git a/script/publish-pact.sh b/script/publish-pact.sh
index 7560e17f..c4f784ef 100755
--- a/script/publish-pact.sh
+++ b/script/publish-pact.sh
@@ -1,7 +1,20 @@
-bundle exec bin/pact-broker publish spec/pacts/pact_broker_client-pact_broker.json \
- --consumer-app-version 1.2.7 \
+# bundle exec bin/pact-broker create-or-update-webhook http://localhost:9393 \
+# --uuid d40f38c3-aaa3-47f5-9161-95c07bc16b14 \
+# --request POST \
+# --description "foo webhook" \
+# --contract-published
+
+bundle exec bin/pact-broker create-or-update-webhook http://localhost:9393 \
+ --uuid d40f38c3-aaa3-47f5-9161-95c07bc16555 \
+ --provider Bar \
+ --request POST \
+ --contract-published
+
+bundle exec bin/pact-broker publish spec/pacts/pact_broker_client-pact_broker.json spec/pacts/foo-bar.json \
+ --consumer-app-version 1.2.12 \
--broker-base-url http://localhost:9292 \
--broker-username localhost --broker-password localhost \
- --auto-detect-branch \
- --build-url http://mybuild
+ --auto-detect-version-properties \
+ --build-url http://mybuild \
+ --branch master --tag foo5
diff --git a/spec/fixtures/foo-bar.json b/spec/fixtures/foo-bar.json
new file mode 100644
index 00000000..d9679455
--- /dev/null
+++ b/spec/fixtures/foo-bar.json
@@ -0,0 +1,31 @@
+{
+ "consumer": {
+ "name": "Foo"
+ },
+ "provider": {
+ "name": "Bar"
+ },
+ "interactions": [
+ {
+ "description": "an example request",
+ "providerState": "a provider state",
+ "request": {
+ "method": "GET",
+ "path": "/",
+ "headers": {
+ }
+ },
+ "response": {
+ "status": 200,
+ "headers": {
+ "Content-Type": "application/hal+json"
+ }
+ }
+ }
+ ],
+ "metadata": {
+ "pactSpecification": {
+ "version": "2.0.0"
+ }
+ }
+}
diff --git a/spec/lib/pact_broker/client/cli/broker_publish_spec.rb b/spec/lib/pact_broker/client/cli/broker_publish_spec.rb
index 6088ff0b..25278451 100644
--- a/spec/lib/pact_broker/client/cli/broker_publish_spec.rb
+++ b/spec/lib/pact_broker/client/cli/broker_publish_spec.rb
@@ -6,11 +6,14 @@ module PactBroker::Client::CLI
describe Broker do
describe ".broker" do
before do
- allow(PactBroker::Client::PublishPacts).to receive(:call).and_return(true)
+ allow(PactBroker::Client::PublishPacts).to receive(:call).and_return(result)
allow(PactBroker::Client::Git).to receive(:branch).and_return("bar")
subject.options = OpenStruct.new(minimum_valid_options)
+ allow($stdout).to receive(:puts)
end
+ let(:success) { true }
+ let(:result) { instance_double(PactBroker::Client::CommandResult, success: success, message: "message")}
let(:file_list) { ["spec/support/cli_test_pacts/foo.json"] }
let(:minimum_valid_options) do
{
@@ -28,7 +31,8 @@ module PactBroker::Client::CLI
"http://pact-broker",
["spec/support/cli_test_pacts/foo.json"],
{ number: "1.2.3", tags: [], version_required: false },
- { }
+ {},
+ {}
)
invoke_broker
end
@@ -42,6 +46,7 @@ module PactBroker::Client::CLI
anything,
["spec/support/cli_test_pacts/bar.json", "spec/support/cli_test_pacts/foo.json"],
anything,
+ anything,
anything
)
invoke_broker
@@ -56,6 +61,7 @@ module PactBroker::Client::CLI
anything,
["spec/support/cli_test_pacts/bar.json", "spec/support/cli_test_pacts/foo.json"],
anything,
+ anything,
anything
)
invoke_broker
@@ -70,6 +76,7 @@ module PactBroker::Client::CLI
anything,
["spec/support/cli_test_pacts/bar.json", "spec/support/cli_test_pacts/foo.json"],
anything,
+ anything,
anything
)
invoke_broker
@@ -102,6 +109,7 @@ module PactBroker::Client::CLI
anything,
anything,
hash_including(tags: ['foo']),
+ anything,
anything
)
invoke_broker
@@ -125,6 +133,7 @@ module PactBroker::Client::CLI
anything,
anything,
hash_including(tags: ['foo', 'bar']),
+ anything,
anything
)
invoke_broker
@@ -143,6 +152,7 @@ module PactBroker::Client::CLI
anything,
anything,
hash_including(branch: "main", version_required: true),
+ anything,
anything
)
invoke_broker
@@ -167,6 +177,7 @@ module PactBroker::Client::CLI
anything,
anything,
hash_including(branch: "bar", version_required: false),
+ anything,
anything
)
invoke_broker
@@ -192,6 +203,7 @@ module PactBroker::Client::CLI
anything,
anything,
hash_including(branch: "bar", version_required: true),
+ anything,
anything
)
invoke_broker
@@ -209,6 +221,7 @@ module PactBroker::Client::CLI
anything,
anything,
hash_including(branch: "specified-branch", version_required: true),
+ anything,
anything
)
invoke_broker
@@ -228,6 +241,7 @@ module PactBroker::Client::CLI
anything,
anything,
hash_including(build_url: "http://ci"),
+ anything,
anything
)
invoke_broker
@@ -246,6 +260,7 @@ module PactBroker::Client::CLI
anything,
anything,
anything,
+ anything,
hash_including(basic_auth: { username: 'foo', password: 'bar' })
)
invoke_broker
@@ -283,12 +298,10 @@ module PactBroker::Client::CLI
end
context "when the publish command is not successful" do
- before do
- allow(PactBroker::Client::PublishPacts).to receive(:call).and_return(false)
- end
+ let(:success) { false }
- it "raises a PactPublicationError" do
- expect { invoke_broker }.to raise_error PactPublicationError
+ it "raises a SystemExit" do
+ expect { invoke_broker }.to raise_error SystemExit
end
end
end
diff --git a/spec/lib/pact_broker/client/publish_pacts_spec.rb b/spec/lib/pact_broker/client/publish_pacts_the_old_way_spec.rb
similarity index 95%
rename from spec/lib/pact_broker/client/publish_pacts_spec.rb
rename to spec/lib/pact_broker/client/publish_pacts_the_old_way_spec.rb
index 37633ece..b8444a0d 100644
--- a/spec/lib/pact_broker/client/publish_pacts_spec.rb
+++ b/spec/lib/pact_broker/client/publish_pacts_the_old_way_spec.rb
@@ -1,11 +1,11 @@
require 'spec_helper'
require 'fakefs/safe'
-require 'pact_broker/client/publish_pacts'
+require 'pact_broker/client/publish_pacts_the_old_way'
require 'json'
module PactBroker
module Client
- describe PublishPacts do
+ describe PublishPactsTheOldWay do
# The amount of stubbing that we have to do here indicates this class is doing
# TOO MUCH and needs to be split up!
@@ -23,7 +23,7 @@ module Client
File.open("spec/pacts/consumer-provider.json", "w") { |file| file << pact_hash.to_json }
File.open("spec/pacts/consumer-provider-2.json", "w") { |file| file << pact_hash.to_json }
File.open("spec/pacts/foo-bar.json", "w") { |file| file << pact_hash_2.to_json }
- allow_any_instance_of(PublishPacts).to receive(:create_index_entry_point).and_return(index_entry_point)
+ allow_any_instance_of(PublishPactsTheOldWay).to receive(:create_index_entry_point).and_return(index_entry_point)
end
after do
@@ -63,8 +63,9 @@ module Client
let(:index_entry_point) { instance_double("PactBroker::Client::Hal::EntryPoint", :get! => index_resource )}
let(:index_resource) { instance_double("PactBroker::Client::Hal::Entity", can?: can_create_version ) }
let(:can_create_version) { false }
+ let(:options) { {} }
- subject { PublishPacts.new(pact_broker_base_url, pact_file_paths, consumer_version_params, pact_broker_client_options) }
+ subject { PublishPactsTheOldWay.new(pact_broker_base_url, pact_file_paths, consumer_version_params, options, pact_broker_client_options) }
describe "call" do
it "creates a PactBroker Client" do
@@ -85,7 +86,7 @@ module Client
end
it "returns true" do
- expect(subject.call).to be true
+ expect(subject.call.success).to eq true
end
end
@@ -140,7 +141,7 @@ module Client
end
it "returns false" do
- expect(subject.call).to be false
+ expect(subject.call.success).to be false
end
end
@@ -212,7 +213,7 @@ module Client
end
it "returns false" do
- expect(subject.call).to eq false
+ expect(subject.call.success).to eq false
end
end
end
@@ -230,7 +231,7 @@ module Client
end
it "returns false" do
- expect(subject.call).to eq false
+ expect(subject.call.success).to eq false
end
end
@@ -255,7 +256,7 @@ module Client
end
it "returns true" do
- expect(subject.call).to eq true
+ expect(subject.call.success).to eq true
end
end
diff --git a/spec/lib/pact_broker/client/tasks/publication_task_spec.rb b/spec/lib/pact_broker/client/tasks/publication_task_spec.rb
index b8110cda..6908be3f 100644
--- a/spec/lib/pact_broker/client/tasks/publication_task_spec.rb
+++ b/spec/lib/pact_broker/client/tasks/publication_task_spec.rb
@@ -1,6 +1,7 @@
require 'spec_helper'
require 'pact_broker/client/tasks/publication_task'
require 'pact_broker/client/publish_pacts'
+require 'pact_broker/client/command_result'
module PactBroker::Client
describe PublicationTask do
@@ -9,13 +10,16 @@ module PactBroker::Client
@consumer_version = "1.2.3"
end
- let(:publish_pacts) { instance_double("PactBroker::ClientSupport::PublishPacts", call: true)}
+ let(:publish_pacts) { instance_double("PactBroker::ClientSupport::PublishPacts", call: result)}
let(:pact_file_list) { ['spec/pact/consumer-provider.json'] }
+ let(:success) { true }
+ let(:result) { instance_double(PactBroker::Client::CommandResult, success: success, message: "message")}
before do
allow(PactBroker::Client::PublishPacts).to receive(:new).and_return(publish_pacts)
allow(FileList).to receive(:[]).with(pattern).and_return(pact_file_list)
allow(PactBroker::Client::Git).to receive(:branch).and_return('foo')
+ allow($stdout).to receive(:puts)
end
let(:pattern) { "spec/pacts/*.json" }
@@ -29,15 +33,16 @@ module PactBroker::Client
context "when pacts are succesfully published" do
it "invokes PublishPacts with the default values" do
- expect(PactBroker::Client::PublishPacts).to receive(:new).with('http://pact-broker', pact_file_list, { number: '1.2.3', branch: "foo", tags: [], version_required: false}, {}).and_return(publish_pacts)
- expect(publish_pacts).to receive(:call).and_return(true)
+ expect(PactBroker::Client::PublishPacts).to receive(:new).with('http://pact-broker', pact_file_list, { number: '1.2.3', branch: "foo", tags: [], version_required: false}, {}, {}).and_return(publish_pacts)
+ expect(publish_pacts).to receive(:call).and_return(result)
Rake::Task['pact:publish'].execute
end
end
context "when a pact fails to be published" do
+ let(:success) { false }
+
it "raises an error" do
- expect(publish_pacts).to receive(:call).and_return(false)
expect { Rake::Task['pact:publish'].execute }.to raise_error("One or more pacts failed to be published")
end
end
@@ -52,8 +57,8 @@ module PactBroker::Client
end
it "invokes PublishPacts with the write method set" do
- expect(PactBroker::Client::PublishPacts).to receive(:new).with('http://pact-broker', pact_file_list, { number: "1.2.3", branch: "foo", tags: [], version_required: false }, {write: :merge}).and_return(publish_pacts)
- expect(publish_pacts).to receive(:call).and_return(true)
+ expect(PactBroker::Client::PublishPacts).to receive(:new).with('http://pact-broker', pact_file_list, { number: "1.2.3", branch: "foo", tags: [], version_required: false }, {}, {write: :merge}).and_return(publish_pacts)
+ expect(publish_pacts).to receive(:call).and_return(result)
Rake::Task['pact:publish:merge'].execute
end
end
@@ -74,7 +79,7 @@ module PactBroker::Client
end
it "invokes PublishPacts with the git branch name as a tag" do
- expect(PactBroker::Client::PublishPacts).to receive(:new).with(anything, anything, hash_including(tags: ['bar', 'foo']), anything).and_return(publish_pacts)
+ expect(PactBroker::Client::PublishPacts).to receive(:new).with(anything, anything, hash_including(tags: ['bar', 'foo']), anything, anything).and_return(publish_pacts)
Rake::Task['pact:publish:git_branch'].execute
end
end
@@ -93,7 +98,7 @@ module PactBroker::Client
end
it "invokes PublishPacts with the branch name" do
- expect(PactBroker::Client::PublishPacts).to receive(:new).with(anything, anything, hash_including(branch: "foo"), anything).and_return(publish_pacts)
+ expect(PactBroker::Client::PublishPacts).to receive(:new).with(anything, anything, hash_including(branch: "foo"), anything, anything).and_return(publish_pacts)
Rake::Task['pact:publish:git_branch_auto_detect_true'].execute
end
end
@@ -113,7 +118,7 @@ module PactBroker::Client
end
it "invokes PublishPacts with the specified branch name" do
- expect(PactBroker::Client::PublishPacts).to receive(:new).with(anything, anything, hash_including(branch: "main"), anything).and_return(publish_pacts)
+ expect(PactBroker::Client::PublishPacts).to receive(:new).with(anything, anything, hash_including(branch: "main"), anything, anything).and_return(publish_pacts)
Rake::Task['pact:publish:git_branch_auto_detect_true_with_branch'].execute
end
end
@@ -132,7 +137,7 @@ module PactBroker::Client
end
it "invokes PublishPacts without the branch name" do
- expect(PactBroker::Client::PublishPacts).to receive(:new).with(anything, anything, hash_not_including(branch: "foo"), anything).and_return(publish_pacts)
+ expect(PactBroker::Client::PublishPacts).to receive(:new).with(anything, anything, hash_not_including(branch: "foo"), anything, anything).and_return(publish_pacts)
Rake::Task['pact:publish:git_branch_auto_detect_false'].execute
end
end
@@ -150,7 +155,7 @@ module PactBroker::Client
end
it "invokes PublishPacts with the branch name" do
- expect(PactBroker::Client::PublishPacts).to receive(:new).with(anything, anything, hash_including(branch: "foo"), anything).and_return(publish_pacts)
+ expect(PactBroker::Client::PublishPacts).to receive(:new).with(anything, anything, hash_including(branch: "foo"),anything, anything).and_return(publish_pacts)
Rake::Task['pact:publish:git_branch_auto_detect_default'].execute
end
end
@@ -180,9 +185,10 @@ module PactBroker::Client
@pact_broker_base_url,
pact_file_list,
{ number: "1.2.3", tags: [@tag], branch: "foo", version_required: false},
+ {},
{ basic_auth: @pact_broker_basic_auth, token: @pact_broker_token }
)
- expect(publish_pacts).to receive(:call).and_return(true)
+ expect(publish_pacts).to receive(:call).and_return(result)
Rake::Task['pact:publish:custom'].execute
end
end
diff --git a/spec/pacts/pact_broker_client-pact_broker.json b/spec/pacts/pact_broker_client-pact_broker.json
index 42011183..056ed4b8 100644
--- a/spec/pacts/pact_broker_client-pact_broker.json
+++ b/spec/pacts/pact_broker_client-pact_broker.json
@@ -1550,6 +1550,112 @@
}
}
},
+ {
+ "description": "a request for the index resource",
+ "providerState": "the pb:publish-contracts relations exists in the index resource",
+ "request": {
+ "method": "GET",
+ "path": "/",
+ "headers": {
+ "Accept": "application/hal+json"
+ }
+ },
+ "response": {
+ "status": 200,
+ "headers": {
+ "Content-Type": "application/hal+json;charset=utf-8"
+ },
+ "body": {
+ "_links": {
+ "pb:publish-contracts": {
+ "href": "http://localhost:1234/HAL-REL-PLACEHOLDER-PB-PUBLISH-CONTRACTS"
+ }
+ }
+ },
+ "matchingRules": {
+ "$.body._links.pb:publish-contracts.href": {
+ "match": "regex",
+ "regex": "http:\\/\\/.*"
+ }
+ }
+ }
+ },
+ {
+ "description": "a request to publish contracts",
+ "request": {
+ "method": "POST",
+ "path": "/HAL-REL-PLACEHOLDER-PB-PUBLISH-CONTRACTS",
+ "headers": {
+ "Content-Type": "application/json",
+ "Accept": "application/hal+json"
+ },
+ "body": {
+ "pacticipantName": "Foo",
+ "pacticipantVersionNumber": "5556b8149bf8bac76bc30f50a8a2dd4c22c85f30",
+ "branch": "main",
+ "tags": [
+ "dev"
+ ],
+ "buildUrl": "http://build",
+ "contracts": [
+ {
+ "consumerName": "Foo",
+ "providerName": "Bar",
+ "specification": "pact",
+ "contentType": "application/json",
+ "content": "eyJjb25zdW1lciI6eyJuYW1lIjoiRm9vIn0sInByb3ZpZGVyIjp7Im5hbWUiOiJCYXIifSwiaW50ZXJhY3Rpb25zIjpbeyJkZXNjcmlwdGlvbiI6ImFuIGV4YW1wbGUgcmVxdWVzdCIsInByb3ZpZGVyU3RhdGUiOiJhIHByb3ZpZGVyIHN0YXRlIiwicmVxdWVzdCI6eyJtZXRob2QiOiJHRVQiLCJwYXRoIjoiLyIsImhlYWRlcnMiOnt9fSwicmVzcG9uc2UiOnsic3RhdHVzIjoyMDAsImhlYWRlcnMiOnsiQ29udGVudC1UeXBlIjoiYXBwbGljYXRpb24vaGFsK2pzb24ifX19XSwibWV0YWRhdGEiOnsicGFjdFNwZWNpZmljYXRpb24iOnsidmVyc2lvbiI6IjIuMC4wIn19fQ==",
+ "writeMode": "overwrite"
+ }
+ ]
+ }
+ },
+ "response": {
+ "status": 200,
+ "headers": {
+ "Content-Type": "application/hal+json;charset=utf-8"
+ },
+ "body": {
+ "_embedded": {
+ "pacticipant": {
+ "name": "Foo"
+ },
+ "version": {
+ "number": "5556b8149bf8bac76bc30f50a8a2dd4c22c85f30",
+ "buildUrl": "http://build"
+ }
+ },
+ "logs": [
+ {
+ "level": "info",
+ "message": "some message"
+ }
+ ],
+ "_links": {
+ "pb:pacticipant-version-tags": [
+ {
+ "name": "dev"
+ }
+ ],
+ "pb:contracts": [
+ {
+ "href": "http://some-pact"
+ }
+ ]
+ }
+ },
+ "matchingRules": {
+ "$.body.logs": {
+ "min": 1
+ },
+ "$.body.logs[*].*": {
+ "match": "type"
+ },
+ "$.body._links.pb:contracts[0].href": {
+ "match": "type"
+ }
+ }
+ }
+ },
{
"description": "a request for the index resource",
"providerState": "the pb:pacticipant-version and pb:environments relations exist in the index resource",
diff --git a/spec/service_providers/pact_broker_client_create_version_spec.rb b/spec/service_providers/pact_broker_client_create_version_spec.rb
index 02098581..28090c53 100644
--- a/spec/service_providers/pact_broker_client_create_version_spec.rb
+++ b/spec/service_providers/pact_broker_client_create_version_spec.rb
@@ -1,6 +1,6 @@
require_relative 'pact_helper'
require 'pact_broker/client'
-require 'pact_broker/client/publish_pacts'
+require 'pact_broker/client/publish_pacts_the_old_way'
describe PactBroker::Client::Versions, pact: true do
@@ -9,7 +9,7 @@
describe "creating a pacticipant version" do
before do
- allow(publish_pacts).to receive(:consumer_names).and_return(["Foo"])
+ allow(publish_pacts_the_old_way).to receive(:consumer_names).and_return(["Foo"])
allow($stdout).to receive(:puts)
end
let(:version_path) { "/HAL-REL-PLACEHOLDER-INDEX-PB-PACTICIPANT-VERSION-{pacticipant}-{version}" }
@@ -18,11 +18,11 @@
let(:branch) { "main" }
let(:build_url) { "http://my-ci/builds/1" }
let(:consumer_version_params) { { number: number, branch: branch, build_url: build_url } }
- let(:publish_pacts) { PactBroker::Client::PublishPacts.new(pact_broker.mock_service_base_url, ["some-pact.json"], consumer_version_params, {}) }
+ let(:publish_pacts_the_old_way) { PactBroker::Client::PublishPactsTheOldWay.new(pact_broker.mock_service_base_url, ["some-pact.json"], consumer_version_params, {}) }
let(:provider_state) { "version #{number} of pacticipant Foo does not exist" }
let(:expected_response_status) { 201 }
- subject { publish_pacts.send(:create_consumer_versions) }
+ subject { publish_pacts_the_old_way.send(:create_consumer_versions) }
before do
pact_broker
diff --git a/spec/service_providers/publish_pacts_spec.rb b/spec/service_providers/publish_pacts_spec.rb
new file mode 100644
index 00000000..f8765013
--- /dev/null
+++ b/spec/service_providers/publish_pacts_spec.rb
@@ -0,0 +1,115 @@
+require 'pact_broker/client/publish_pacts'
+require 'service_providers/pact_helper'
+
+RSpec.describe "publishing contracts", pact: true do
+ before do
+ allow_any_instance_of(PactBroker::Client::Hal::HttpClient).to receive(:sleep)
+ allow_any_instance_of(PactBroker::Client::Hal::HttpClient).to receive(:default_max_tries).and_return(1)
+ end
+ include_context "pact broker"
+ include PactBrokerPactHelperMethods
+
+ let(:pacticipant_name) { "Foo" }
+ let(:version_number) { "5556b8149bf8bac76bc30f50a8a2dd4c22c85f30" }
+ let(:output) { "text" }
+ let(:build_url) { "http://build" }
+ let(:consumer_version_params) do
+ {
+ pacticipant_name: pacticipant_name,
+ number: version_number,
+ tags: ["dev"],
+ branch: "main",
+ build_url: build_url,
+ output: output
+ }
+ end
+ let(:pact_file_path_1) { "spec/fixtures/foo-bar.json" }
+ let(:pact_file_paths) { [pact_file_path_1] }
+ let(:options) { {} }
+ let(:pact_broker_client_options) { {} }
+ let(:expected_content) { Base64.strict_encode64(JSON.parse(File.read(pact_file_path_1)).to_json) }
+ let(:request_body) do
+ {
+ pacticipantName: pacticipant_name,
+ pacticipantVersionNumber: version_number,
+ branch: "main",
+ tags: ["dev"],
+ buildUrl: "http://build",
+ contracts: [
+ {
+ consumerName: pacticipant_name,
+ providerName: "Bar",
+ specification: "pact",
+ contentType: "application/json",
+ content: expected_content,
+ writeMode: "overwrite"
+ }
+ ]
+ }
+ end
+
+ subject { PactBroker::Client::PublishPacts.call(broker_base_url, pact_file_paths, consumer_version_params, options, pact_broker_client_options) }
+
+ def mock_index
+ pact_broker
+ .given("the pb:publish-contracts relations exists in the index resource")
+ .upon_receiving("a request for the index resource")
+ .with(
+ method: "GET",
+ path: '/',
+ headers: get_request_headers).
+ will_respond_with(
+ status: 200,
+ headers: pact_broker_response_headers,
+ body: {
+ _links: {
+ :'pb:publish-contracts' => {
+ href: placeholder_url_term("pb:publish-contracts")
+ }
+ }
+ }
+ )
+ end
+
+ def mock_contract_publication
+ pact_broker
+ .upon_receiving("a request to publish contracts")
+ .with(
+ method: "POST",
+ path: '/HAL-REL-PLACEHOLDER-PB-PUBLISH-CONTRACTS',
+ headers: post_request_headers,
+ body: request_body).
+ will_respond_with(
+ status: 200,
+ headers: pact_broker_response_headers,
+ body: {
+ _embedded: {
+ pacticipant: {
+ name: pacticipant_name
+ },
+ version: {
+ number: version_number,
+ buildUrl: build_url
+ }
+ },
+ logs: Pact.each_like(level: "info", message: "some message"),
+ _links: {
+ :'pb:pacticipant-version-tags' => [{ name: "dev"} ],
+ :'pb:contracts' => [{ href: Pact.like("http://some-pact") }]
+ }
+ }
+ )
+ end
+
+ context "with valid params" do
+ before do
+ mock_index
+ mock_contract_publication
+ end
+
+ it "returns a success result" do
+ expect(subject.success).to be true
+ expect(subject.message).to include "some message"
+ end
+ end
+end