pact_broker-client 1.25.1 → 1.27.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release_gem.yml +35 -0
  3. data/.github/workflows/trigger_pact_cli_release.yml +15 -0
  4. data/.github/workflows/trigger_pact_docs_update.yml +19 -0
  5. data/CHANGELOG.md +39 -0
  6. data/Gemfile +10 -1
  7. data/README.md +4 -3
  8. data/appveyor.yml +1 -1
  9. data/doc/pacts/markdown/Pact Broker Client - Pact Broker.md +168 -10
  10. data/lib/pact_broker/client/can_i_deploy.rb +6 -0
  11. data/lib/pact_broker/client/cli/broker.rb +32 -0
  12. data/lib/pact_broker/client/cli/custom_thor.rb +12 -1
  13. data/lib/pact_broker/client/git.rb +2 -1
  14. data/lib/pact_broker/client/hal/entity.rb +12 -1
  15. data/lib/pact_broker/client/hal/http_client.rb +6 -0
  16. data/lib/pact_broker/client/hal/link.rb +4 -0
  17. data/lib/pact_broker/client/hal_client_methods.rb +15 -0
  18. data/lib/pact_broker/client/matrix/resource.rb +5 -1
  19. data/lib/pact_broker/client/pacticipants/create.rb +57 -0
  20. data/lib/pact_broker/client/pacts/list_latest_versions.rb +65 -0
  21. data/lib/pact_broker/client/publish_pacts.rb +1 -1
  22. data/lib/pact_broker/client/version.rb +1 -1
  23. data/lib/pact_broker/client/webhooks/test.rb +16 -0
  24. data/pact-broker-client.gemspec +3 -5
  25. data/script/prepare-release.sh +11 -0
  26. data/script/release-gem.sh +23 -0
  27. data/script/release.sh +1 -1
  28. data/script/trigger-release.sh +15 -0
  29. data/spec/integration/can_i_deploy_spec.rb +3 -3
  30. data/spec/integration/create_version_tag_spec.rb +2 -3
  31. data/spec/lib/pact_broker/client/can_i_deploy_spec.rb +22 -4
  32. data/spec/lib/pact_broker/client/pacticipants/create_spec.rb +28 -0
  33. data/spec/pacts/pact_broker_client-pact_broker.json +179 -10
  34. data/spec/service_providers/pact_broker_client_matrix_spec.rb +10 -10
  35. data/spec/service_providers/pact_helper.rb +29 -0
  36. data/spec/service_providers/pacticipants_create_spec.rb +118 -0
  37. metadata +29 -44
@@ -87,6 +87,8 @@ module PactBroker
87
87
  if retry_while_unknown?
88
88
  check_if_retry_while_unknown_supported(matrix)
89
89
  if matrix.any_unknown?
90
+ results = matrix.unknown_count == 1 ? "result" : "results"
91
+ $stderr.puts "Waiting for #{matrix.unknown_count} verification #{results} to be published (maximum of #{wait_time} seconds)"
90
92
  matrix = Retry.until_truthy_or_max_times(retry_options) do
91
93
  fetch_matrix
92
94
  end
@@ -120,6 +122,10 @@ module PactBroker
120
122
  options[:retry_while_unknown]
121
123
  end
122
124
 
125
+ def wait_time
126
+ retry_interval * retry_tries
127
+ end
128
+
123
129
  def check_if_retry_while_unknown_supported(matrix)
124
130
  if !matrix.supports_unknown_count?
125
131
  raise PactBroker::Client::Error.new("This version of the Pact Broker does not provide a count of the unknown verification results. Please upgrade your Broker to >= v2.23.4")
@@ -130,6 +130,15 @@ module PactBroker
130
130
  run_webhook_commands webhook_url
131
131
  end
132
132
 
133
+ desc 'test-webhook', 'Test the execution of a webhook'
134
+ method_option :uuid, type: :string, required: true, desc: "Specify the uuid for the webhook"
135
+ shared_authentication_options_for_pact_broker
136
+ def test_webhook
137
+ require 'pact_broker/client/webhooks/test'
138
+ result = PactBroker::Client::Webhooks::Test.call(options, pact_broker_client_options)
139
+ $stdout.puts result.message
140
+ end
141
+
133
142
  ignored_and_hidden_potential_options_from_environment_variables
134
143
  desc 'generate-uuid', 'Generate a UUID for use when calling create-or-update-webhook'
135
144
  def generate_uuid
@@ -138,6 +147,29 @@ module PactBroker
138
147
  puts SecureRandom.uuid
139
148
  end
140
149
 
150
+ desc 'create-or-update-pacticipant', 'Create or update pacticipant by name'
151
+ method_option :name, type: :string, required: true, desc: "Pacticipant name"
152
+ method_option :repository_url, type: :string, required: false, desc: "The repository URL of the pacticipant"
153
+ shared_authentication_options_for_pact_broker
154
+ verbose_option
155
+ def create_or_update_pacticipant(*required_but_ignored)
156
+ raise ::Thor::RequiredArgumentMissingError, "Pacticipant name cannot be blank" if options.name.strip.size == 0
157
+ require 'pact_broker/client/pacticipants/create'
158
+ result = PactBroker::Client::Pacticipants2::Create.call({ name: options.name, repository_url: options.repository_url }, options.broker_base_url, pact_broker_client_options)
159
+ $stdout.puts result.message
160
+ exit(1) unless result.success
161
+ end
162
+
163
+ desc 'list-latest-pact-versions', 'List the latest pact for each integration'
164
+ shared_authentication_options_for_pact_broker
165
+ method_option :output, aliases: "-o", desc: "json or table", default: 'table'
166
+ def list_latest_pact_versions(*required_but_ignored)
167
+ require 'pact_broker/client/pacts/list_latest_versions'
168
+ result = PactBroker::Client::Pacts::ListLatestVersions.call(options.broker_base_url, options.output, pact_broker_client_options)
169
+ $stdout.puts result.message
170
+ exit(1) unless result.success
171
+ end
172
+
141
173
  ignored_and_hidden_potential_options_from_environment_variables
142
174
  desc 'version', "Show the pact_broker-client gem version"
143
175
  def version
@@ -20,7 +20,7 @@ module PactBroker
20
20
  end
21
21
 
22
22
  def self.add_broker_config_from_environment_variables argv
23
- return argv if argv[0] == 'help'
23
+ return argv if argv[0] == 'help' || argv.empty?
24
24
 
25
25
  new_argv = add_option_from_environment_variable(argv, 'broker-base-url', 'b', 'PACT_BROKER_BASE_URL')
26
26
  new_argv = add_option_from_environment_variable(new_argv, 'broker-username', 'u', 'PACT_BROKER_USERNAME')
@@ -105,6 +105,17 @@ module PactBroker
105
105
  method_option :provider_verification_succeeded, type: :boolean, desc: "Trigger this webhook when a successful provider verification result is published"
106
106
  method_option :verbose, aliases: "-v", type: :boolean, default: false, required: false, desc: "Verbose output. Default: false"
107
107
  end
108
+
109
+ def self.shared_authentication_options_for_pact_broker
110
+ method_option :broker_base_url, required: true, aliases: "-b", desc: "The base URL of the Pact Broker"
111
+ method_option :broker_username, aliases: "-u", desc: "Pact Broker basic auth username"
112
+ method_option :broker_password, aliases: "-p", desc: "Pact Broker basic auth password"
113
+ method_option :broker_token, aliases: "-k", desc: "Pact Broker bearer token"
114
+ end
115
+
116
+ def self.verbose_option
117
+ method_option :verbose, aliases: "-v", type: :boolean, default: false, required: false, desc: "Verbose output. Default: false"
118
+ end
108
119
  end
109
120
  end
110
121
  end
@@ -11,6 +11,7 @@ APPVEYOR_REPO_COMMIT APPVEYOR_REPO_BRANCH https://www.appveyor.com/docs/en
11
11
  CI_COMMIT_REF_NAME https://docs.gitlab.com/ee/ci/variables/predefined_variables.html
12
12
  CI_BRANCH CI_COMMIT_ID https://documentation.codeship.com/pro/builds-and-configuration/environment-variables/
13
13
  bamboo.repository.git.branch https://confluence.atlassian.com/bamboo/bamboo-variables-289277087.html
14
+ BITBUCKET_BRANCH https://confluence.atlassian.com/bitbucket/variables-in-pipelines-794502608.html
14
15
 
15
16
  =end
16
17
 
@@ -19,7 +20,7 @@ module PactBroker
19
20
  module Client
20
21
  module Git
21
22
  COMMAND = 'git name-rev --name-only HEAD'.freeze
22
- BRANCH_ENV_VAR_NAMES = %w{BUILDKITE_BRANCH CIRCLE_BRANCH TRAVIS_BRANCH GIT_BRANCH GIT_LOCAL_BRANCH APPVEYOR_REPO_BRANCH CI_COMMIT_REF_NAME}.freeze
23
+ 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
23
24
 
24
25
  def self.branch
25
26
  find_branch_from_env_vars || branch_from_git_command
@@ -29,6 +29,10 @@ module PactBroker
29
29
  _link(key).put(*args)
30
30
  end
31
31
 
32
+ def patch(key, *args)
33
+ _link(key).patch(*args)
34
+ end
35
+
32
36
  def can?(key)
33
37
  @links.key? key.to_s
34
38
  end
@@ -55,6 +59,10 @@ module PactBroker
55
59
  true
56
60
  end
57
61
 
62
+ def does_not_exist?
63
+ false
64
+ end
65
+
58
66
  def response
59
67
  @response
60
68
  end
@@ -83,7 +91,6 @@ module PactBroker
83
91
  end
84
92
 
85
93
  class ErrorEntity < Entity
86
-
87
94
  def initialize(href, data, http_client, response = nil)
88
95
  @href = href
89
96
  @data = data
@@ -92,6 +99,10 @@ module PactBroker
92
99
  @response = response
93
100
  end
94
101
 
102
+ def does_not_exist?
103
+ response && response.status == 404
104
+ end
105
+
95
106
  def success?
96
107
  false
97
108
  end
@@ -1,6 +1,7 @@
1
1
  require 'pact_broker/client/retry'
2
2
  require 'pact_broker/client/hal/authorization_header_redactor'
3
3
  require 'net/http'
4
+ require 'json'
4
5
 
5
6
  module PactBroker
6
7
  module Client
@@ -32,6 +33,11 @@ module PactBroker
32
33
  perform_request(create_request(uri, 'Post', body, headers), uri)
33
34
  end
34
35
 
36
+ def patch href, body = nil, headers = {}
37
+ uri = URI(href)
38
+ perform_request(create_request(uri, 'Patch', body, headers), uri)
39
+ end
40
+
35
41
  def create_request uri, http_method, body = nil, headers = {}
36
42
  request = Net::HTTP.const_get(http_method).new(uri.request_uri)
37
43
  request['Content-Type'] = "application/json" if ['Post', 'Put', 'Patch'].include?(http_method)
@@ -53,6 +53,10 @@ module PactBroker
53
53
  wrap_response(href, @http_client.post(href, payload ? JSON.dump(payload) : nil, headers))
54
54
  end
55
55
 
56
+ def patch(payload = nil, headers = {})
57
+ wrap_response(href, @http_client.patch(href, payload ? JSON.dump(payload) : nil, headers))
58
+ end
59
+
56
60
  def expand(params)
57
61
  expanded_url = expand_url(params, href)
58
62
  new_attrs = @attrs.merge('href' => expanded_url)
@@ -0,0 +1,15 @@
1
+ require 'pact_broker/client/hal'
2
+
3
+ module PactBroker
4
+ module Client
5
+ module HalClientMethods
6
+ def create_index_entry_point(pact_broker_base_url, pact_broker_client_options)
7
+ PactBroker::Client::Hal::EntryPoint.new(pact_broker_base_url, create_http_client(pact_broker_client_options))
8
+ end
9
+
10
+ def create_http_client(pact_broker_client_options)
11
+ PactBroker::Client::Hal::HttpClient.new(pact_broker_client_options.merge(pact_broker_client_options[:basic_auth] || {}))
12
+ end
13
+ end
14
+ end
15
+ end
@@ -11,7 +11,7 @@ module PactBroker
11
11
 
12
12
  def any_unknown?
13
13
  if supports_unknown_count?
14
- self[:summary][:unknown] > 0
14
+ unknown_count > 0
15
15
  else
16
16
  false
17
17
  end
@@ -21,6 +21,10 @@ module PactBroker
21
21
  !!(self[:summary] && Integer === self[:summary][:unknown] )
22
22
  end
23
23
 
24
+ def unknown_count
25
+ supports_unknown_count? ? self[:summary][:unknown] : nil
26
+ end
27
+
24
28
  def reason
25
29
  self[:summary][:reason]
26
30
  end
@@ -0,0 +1,57 @@
1
+ require 'pact_broker/client/hal'
2
+ require 'json'
3
+ require 'pact_broker/client/command_result'
4
+ require 'pact_broker/client/hal_client_methods'
5
+
6
+ module PactBroker
7
+ module Client
8
+ module Pacticipants2
9
+ class Create
10
+
11
+ include HalClientMethods
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
+ @params = params
19
+ @index_entry_point = create_index_entry_point(pact_broker_base_url, pact_broker_client_options)
20
+ @verbose = pact_broker_client_options[:verbose]
21
+ end
22
+
23
+ def call
24
+ pacticipant_entity = index_entity._link('pb:pacticipant').expand('pacticipant' => params[:name]).get
25
+ message = nil
26
+ response_entity = if pacticipant_entity.does_not_exist?
27
+ message = "Pacticipant \"#{params[:name]}\" created"
28
+ index_entity._link!('pb:pacticipants').post(pacticipant_resource_params)
29
+ else
30
+ message = "Pacticipant \"#{params[:name]}\" updated"
31
+ pacticipant_entity._link!('self').patch(pacticipant_resource_params)
32
+ end
33
+
34
+ response_entity.assert_success!
35
+ PactBroker::Client::CommandResult.new(true, message)
36
+ rescue StandardError => e
37
+ $stderr.puts("#{e.class} - #{e}\n#{e.backtrace.join("\n")}") if verbose
38
+ PactBroker::Client::CommandResult.new(false, "#{e.class} - #{e}")
39
+ end
40
+
41
+ private
42
+
43
+ attr_reader :index_entry_point, :params, :verbose
44
+
45
+ def index_entity
46
+ @index_entity ||= index_entry_point.get!
47
+ end
48
+
49
+ def pacticipant_resource_params
50
+ p = { name: params[:name] }
51
+ p[:repositoryUrl] = params[:repository_url] if params[:repository_url]
52
+ p
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,65 @@
1
+ require 'pact_broker/client/hal'
2
+ require 'pact_broker/client/command_result'
3
+ require 'pact_broker/client/hal_client_methods'
4
+
5
+ module PactBroker
6
+ module Client
7
+ module Pacts
8
+ class ListLatestVersions
9
+
10
+ include HalClientMethods
11
+
12
+ def self.call(pact_broker_base_url, output, pact_broker_client_options)
13
+ new(pact_broker_base_url, output, pact_broker_client_options).call
14
+ end
15
+
16
+ def initialize(pact_broker_base_url, output, pact_broker_client_options)
17
+ @index_entry_point = create_index_entry_point(pact_broker_base_url, pact_broker_client_options)
18
+ @output = output
19
+ end
20
+
21
+ def call
22
+ message = if output == 'json'
23
+ versions_resource.response.body
24
+ else
25
+ to_text(versions)
26
+ end
27
+ PactBroker::Client::CommandResult.new(true, message)
28
+
29
+ rescue StandardError => e
30
+ PactBroker::Client::CommandResult.new(false, e.message)
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :index_entry_point, :output
36
+
37
+ def versions
38
+ versions_resource.pacts.collect do | pact |
39
+ OpenStruct.new(
40
+ consumer_name: pact['_embedded']['consumer']['name'],
41
+ provider_name: pact['_embedded']['provider']['name'],
42
+ consumer_version_number: pact['_embedded']['consumer']['_embedded']['version']['number'],
43
+ created_at: pact['createdAt']
44
+ )
45
+ end
46
+ end
47
+
48
+ def versions_resource
49
+ index_entry_point.get!._link('pb:latest-pact-versions').get!
50
+ end
51
+
52
+ def to_text(pacts)
53
+ require 'table_print'
54
+ options = [
55
+ { consumer_name: {display_name: 'consumer'} },
56
+ { consumer_version_number: {display_name: 'consumer_version'} },
57
+ { provider_name: {display_name: 'provider'} },
58
+ { created_at: {} }
59
+ ]
60
+ TablePrint::Printer.new(pacts, options).table_print
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -85,7 +85,7 @@ module PactBroker
85
85
  Retry.while_error do
86
86
  pacts = pact_broker_client.pacticipants.versions.pacts
87
87
  if pacts.version_published?(consumer: pact.consumer_name, provider: pact.provider_name, consumer_version: consumer_version)
88
- $stdout.puts ::Term::ANSIColor.yellow("The given version of pact is already published. Overwriting...")
88
+ $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.)")
89
89
  end
90
90
 
91
91
  latest_pact_url = pacts.publish(pact_hash: pact, consumer_version: consumer_version)
@@ -1,5 +1,5 @@
1
1
  module PactBroker
2
2
  module Client
3
- VERSION = '1.25.1'
3
+ VERSION = '1.27.4'
4
4
  end
5
5
  end
@@ -0,0 +1,16 @@
1
+ require 'pact_broker/client/hal'
2
+ require 'pact_broker/client/command_result'
3
+
4
+ module PactBroker
5
+ module Client
6
+ module Webhooks
7
+ class Test
8
+ def self.call(options, pact_broker_client_options)
9
+ http_client = PactBroker::Client::Hal::HttpClient.new(pact_broker_client_options.merge(pact_broker_client_options[:basic_auth] || {}))
10
+ execution_result = PactBroker::Client::Hal::EntryPoint.new(options.broker_base_url, http_client).get!._link!('pb:webhook').expand('uuid' => options.uuid).get!.post('pb:execute')
11
+ PactBroker::Client::CommandResult.new(true, execution_result.response.body['logs'])
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -21,16 +21,14 @@ Gem::Specification.new do |gem|
21
21
  gem.require_paths = ["lib"]
22
22
  gem.license = 'MIT'
23
23
 
24
- gem.add_runtime_dependency 'httparty'
25
- gem.add_runtime_dependency 'json'
26
- gem.add_runtime_dependency 'term-ansicolor'
24
+ gem.add_runtime_dependency 'httparty', '~>0.18'
25
+ gem.add_runtime_dependency 'term-ansicolor', '~> 1.7'
27
26
  gem.add_runtime_dependency 'table_print', '~> 1.5'
28
27
  gem.add_runtime_dependency 'thor', '~> 0.20'
29
- gem.add_runtime_dependency 'rake' #For FileList
28
+ gem.add_runtime_dependency 'rake', '~> 13.0' #For FileList
30
29
 
31
30
  gem.add_development_dependency 'fakefs', '~> 0.4'
32
31
  gem.add_development_dependency 'webmock', '~> 3.0'
33
32
  gem.add_development_dependency 'conventional-changelog', '~>1.3'
34
33
  gem.add_development_dependency 'pact', '~> 1.16'
35
- gem.add_development_dependency 'bump', '~> 0.5'
36
34
  end
@@ -0,0 +1,11 @@
1
+ #!/bin/sh
2
+ set -e
3
+
4
+ # bundle exec rake
5
+ increment=${INCREMENT:-patch}
6
+ bundle exec bump ${increment} --no-commit
7
+ bundle exec rake generate_changelog
8
+ version_file=$(bundle exec bump file --value-only)
9
+ version=$(bundle exec bump current --value-only)
10
+ git add CHANGELOG.md "${version_file}"
11
+ git commit -m "chore(release): version ${version}"
@@ -0,0 +1,23 @@
1
+ #!/bin/bash
2
+
3
+ # if [ -n "${GITHUB_ACTIONS}" ]; then
4
+ # : "${RUBYGEMS_API_KEY:?RUBYGEMS_API_KEY must be set}"
5
+ # : "${GITHUB_TOKEN:?GITHUB_TOKEN must be set}"
6
+
7
+ # echo "Setting up gem credentials..."
8
+ # set +x
9
+ # mkdir -p ~/.gem
10
+
11
+ # cat << EOF > ~/.gem/credentials
12
+ # ---
13
+ # :github: Bearer ${GITHUB_TOKEN}
14
+ # :rubygems_api_key: ${RUBYGEMS_API_KEY}
15
+ # EOF
16
+
17
+ # chmod 0600 ~/.gem/credentials
18
+ # set -x
19
+
20
+ # fi
21
+
22
+ echo "Running gem release task..."
23
+ bundle exec rake release
@@ -1,7 +1,7 @@
1
1
  #!/bin/sh
2
2
  set -e
3
3
 
4
- bundle exec rake
4
+ # bundle exec rake
5
5
  bundle exec bump ${1:-minor} --no-commit
6
6
  bundle exec rake generate_changelog
7
7
  git add CHANGELOG.md lib/pact_broker/client/version.rb