pact_broker-client 1.60.0 → 1.62.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/README.md +44 -11
  4. data/bin/pactflow +4 -0
  5. data/doc/pacts/markdown/Pact Broker Client - Pactflow.md +36 -0
  6. data/lib/pact_broker/client/cli/broker.rb +15 -199
  7. data/lib/pact_broker/client/cli/custom_thor.rb +23 -0
  8. data/lib/pact_broker/client/cli/pact_commands.rb +128 -0
  9. data/lib/pact_broker/client/cli/version_commands.rb +102 -0
  10. data/lib/pact_broker/client/deployments/record_deployment.rb +3 -0
  11. data/lib/pact_broker/client/deployments/record_undeployment.rb +3 -0
  12. data/lib/pact_broker/client/environments/environment_command.rb +3 -0
  13. data/lib/pact_broker/client/hal/links.rb +3 -0
  14. data/lib/pact_broker/client/hal_client_methods.rb +4 -0
  15. data/lib/pact_broker/client/hash_refinements.rb +9 -0
  16. data/lib/pact_broker/client/pacticipants/create.rb +1 -1
  17. data/lib/pact_broker/client/publish_pacts.rb +1 -0
  18. data/lib/pact_broker/client/version.rb +1 -1
  19. data/lib/pact_broker/client/versions/create.rb +111 -0
  20. data/lib/pact_broker/client/versions.rb +1 -0
  21. data/lib/pact_broker/client/webhooks/create.rb +3 -0
  22. data/lib/pactflow/client/cli/pactflow.rb +12 -0
  23. data/lib/pactflow/client/cli/provider_contract_commands.rb +68 -0
  24. data/lib/pactflow/client/provider_contracts/publish.rb +79 -0
  25. data/pact-broker-client.gemspec +1 -1
  26. data/script/oas.yml +49 -0
  27. data/script/publish-provider-contract.sh +27 -0
  28. data/script/record-undeployment.sh +1 -1
  29. data/script/update-cli-usage-in-readme.rb +1 -1
  30. data/script/verification-results.txt +1 -0
  31. data/spec/lib/pact_broker/client/versions/create_spec.rb +174 -0
  32. data/spec/pacts/pact_broker_client-pactflow.json +30 -0
  33. data/spec/service_providers/pactflow_publish_provider_contract_spec.rb +92 -0
  34. metadata +20 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8cd60c123fbe4481515d784d73f97296280109f50252c150c1c0c083813cb34b
4
- data.tar.gz: 3b8371bd71d74a2b9ada1b3ba2d54a24f5ae6349ce2c6a44075e72546f6dbf6e
3
+ metadata.gz: 03d1e24dc52514c490a7d3aa1825ae71cba4e313662d7bab06d23091c42d9686
4
+ data.tar.gz: 7f66cf8204b1089c896d3ea3294a926a5dc5c4c0b8b8cc20ef74306f96fe4e0c
5
5
  SHA512:
6
- metadata.gz: 828e7e3d9eae551b586bff597b7229c5174ab4000fda79cab8567163b7b3c7443c535c35f504f530dc611bee0708240e27a8756bd394f5b9780047b3f8fc2391
7
- data.tar.gz: 9d64d148a588d7aa240decdab057c2352409944036d35f6d7ff67a18f673107b7324d383a96bdaaa67b14e837556d04b87f91b5126c77e8103e4a3cffd153ff2
6
+ metadata.gz: 30f083d1dc9c6effdd2cd9972ca252551ba3f13ce44dbe42f150fe11195a653a40aff596baa16f85dec1994a85161a0564a3ca822d9fb4286fa5ea0086bedc84
7
+ data.tar.gz: 75b6386136cfc65d1487cc2a4428195dc4655143e7cc81a8c033cb7723a3986fc8691bacf0c078658200d2930ae3ff619b0774cb67e5235c3fea0c96d01d426f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ <a name="v1.62.0"></a>
2
+ ### v1.62.0 (2022-05-10)
3
+
4
+ #### Features
5
+
6
+ * add command to publish provider contracts to pactflow (feature toggle required) (#107) ([80cc10e](/../../commit/80cc10e))
7
+
8
+ #### Bug Fixes
9
+
10
+ * use ruby < 2.3 syntax. (#108) ([20f1e01](/../../commit/20f1e01))
11
+
12
+ <a name="v1.61.1"></a>
13
+ ### v1.61.1 (2022-05-09)
14
+
15
+ #### Bug Fixes
16
+
17
+ * Aushm use ruby 2.2 syntax (#110) ([b006ad7](/../../commit/b006ad7))
18
+
19
+ <a name="v1.61.0"></a>
20
+ ### v1.61.0 (2022-05-06)
21
+
22
+ #### Features
23
+
24
+ * **create-or-update-version**
25
+ * support creating or updating a pacticipant version with a branch and/or tags ([e38e728](/../../commit/e38e728))
26
+
1
27
  <a name="v1.60.0"></a>
2
28
  ### v1.60.0 (2022-05-03)
3
29
 
data/README.md CHANGED
@@ -482,8 +482,8 @@ Description:
482
482
  support for environments, deployments and releases. For documentation on how to use can-i-deploy with tags, please see
483
483
  https://docs.pact.io/pact_broker/client_cli/can_i_deploy_usage_with_tags/
484
484
 
485
- Before `can-i-deploy` can be used, the relevant environment resources must first be created in the Pact Broker using the `create-environment` command. The
486
- "test" and "production" environments will have been seeded for you. You can check the existing environments by running `pact-broker list-environments`. See
485
+ Before `can-i-deploy` can be used, the relevant environment resources must first be created in the Pact Broker using the `create-environment` command. The "test"
486
+ and "production" environments will have been seeded for you. You can check the existing environments by running `pact-broker list-environments`. See
487
487
  https://docs.pact.io/pact_broker/client_cli/readme#environments for more information.
488
488
 
489
489
  $ pact-broker create-environment --name "uat" --display-name "UAT" --no-production
@@ -493,8 +493,8 @@ Description:
493
493
 
494
494
  $ pact-broker record-deployment --pacticipant Foo --version 173153ae0 --environment uat
495
495
 
496
- Before an application is deployed or released to an environment, the can-i-deploy command must be run to check that the application version is safe to deploy
497
- with the versions of each integrated application that are already in that environment.
496
+ Before an application is deployed or released to an environment, the can-i-deploy command must be run to check that the application version is safe to deploy with
497
+ the versions of each integrated application that are already in that environment.
498
498
 
499
499
  $ pact-broker can-i-deploy --pacticipant PACTICIPANT --version VERSION --to-environment ENVIRONMENT
500
500
 
@@ -502,8 +502,8 @@ Description:
502
502
 
503
503
  $ pact-broker can-i-deploy --pacticipant Foo --version 173153ae0 --to-environment test
504
504
 
505
- Can-i-deploy can also be used to check if arbitrary versions have a successful verification. When asking "Can I deploy this application version with the
506
- latest version from the main branch of another application" it functions as a "can I merge" check.
505
+ Can-i-deploy can also be used to check if arbitrary versions have a successful verification. When asking "Can I deploy this application version with the latest version
506
+ from the main branch of another application" it functions as a "can I merge" check.
507
507
 
508
508
  $ pact-broker can-i-deploy --pacticipant Foo 173153ae0 \ --pacticipant Bar --latest main
509
509
 
@@ -650,8 +650,8 @@ Options:
650
650
  ```
651
651
 
652
652
  Description:
653
- Create a curl command that executes the request that you want your webhook to execute, then replace "curl" with "pact-broker create-webhook" and add the
654
- consumer, provider, event types and broker details. Note that the URL must be the first parameter when executing create-webhook.
653
+ Create a curl command that executes the request that you want your webhook to execute, then replace "curl" with "pact-broker create-webhook" and add the consumer,
654
+ provider, event types and broker details. Note that the URL must be the first parameter when executing create-webhook.
655
655
 
656
656
  Note that the -u option from the curl command clashes with the -u option from the pact-broker CLI. When used in this command, the -u will be used as a curl
657
657
  option. Please use the --broker-username or environment variable for the Pact Broker username.
@@ -715,9 +715,9 @@ Options:
715
715
  ```
716
716
 
717
717
  Description:
718
- Create a curl command that executes the request that you want your webhook to execute, then replace "curl" with "pact-broker create-or-update-webhook" and
719
- add the consumer, provider, event types and broker details. Note that the URL must be the first parameter when executing create-or-update-webhook and a uuid
720
- must also be provided. You can generate a valid UUID by using the `generate-uuid` command.
718
+ Create a curl command that executes the request that you want your webhook to execute, then replace "curl" with "pact-broker create-or-update-webhook" and add the
719
+ consumer, provider, event types and broker details. Note that the URL must be the first parameter when executing create-or-update-webhook and a uuid must
720
+ also be provided. You can generate a valid UUID by using the `generate-uuid` command.
721
721
 
722
722
  Note that the -u option from the curl command clashes with the -u option from the pact-broker CLI. When used in this command, the -u will be used as a curl
723
723
  option. Please use the --broker-username or environment variable for the Pact Broker username.
@@ -814,6 +814,39 @@ Options:
814
814
 
815
815
  Describes a pacticipant version. If no version or tag is specified, the latest version is described.
816
816
 
817
+ #### create-or-update-version
818
+
819
+ ```
820
+ Usage:
821
+ pact-broker create-or-update-version -a, --pacticipant=PACTICIPANT -b, --broker-base-url=BROKER_BASE_URL -e, --version=VERSION
822
+
823
+ Options:
824
+ -a, --pacticipant=PACTICIPANT
825
+ # The pacticipant name
826
+ -e, --version=VERSION
827
+ # The pacticipant version number
828
+ [--branch=BRANCH]
829
+ # The repository branch name
830
+ -t, [--tag=TAG]
831
+ # Tag name for pacticipant version. Can be specified multiple
832
+ times.
833
+ -b, --broker-base-url=BROKER_BASE_URL
834
+ # The base URL of the Pact Broker
835
+ -u, [--broker-username=BROKER_USERNAME]
836
+ # Pact Broker basic auth username
837
+ -p, [--broker-password=BROKER_PASSWORD]
838
+ # Pact Broker basic auth password
839
+ -k, [--broker-token=BROKER_TOKEN]
840
+ # Pact Broker bearer token
841
+ -v, [--verbose], [--no-verbose]
842
+ # Verbose output. Default: false
843
+ -o, [--output=OUTPUT]
844
+ # json or text
845
+ # Default: text
846
+ ```
847
+
848
+ Create or update pacticipant version by version number
849
+
817
850
  ### Miscellaneous
818
851
 
819
852
  #### generate-uuid
data/bin/pactflow ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require "pactflow/client/cli/pactflow"
3
+
4
+ Pactflow::Client::CLI::Pactflow.start
@@ -4,6 +4,8 @@
4
4
 
5
5
  * [A request for the index resource](#a_request_for_the_index_resource)
6
6
 
7
+ * [A request to create a provider contract](#a_request_to_create_a_provider_contract)
8
+
7
9
  * [A request to create a webhook for a team](#a_request_to_create_a_webhook_for_a_team_given_a_team_with_UUID_2abbc12a-427d-432a-a521-c870af1739d9_exists) given a team with UUID 2abbc12a-427d-432a-a521-c870af1739d9 exists
8
10
 
9
11
  #### Interactions
@@ -41,6 +43,40 @@ Pactflow will respond with:
41
43
  }
42
44
  }
43
45
  ```
46
+ <a name="a_request_to_create_a_provider_contract"></a>
47
+ Upon receiving **a request to create a provider contract** from Pact Broker Client, with
48
+ ```json
49
+ {
50
+ "method": "put",
51
+ "path": "/contracts/provider/Bar/version/1",
52
+ "headers": {
53
+ "Content-Type": "application/json",
54
+ "Accept": "application/hal+json"
55
+ },
56
+ "body": {
57
+ "content": "LS0tCjpzb21lOiBjb250cmFjdAo=",
58
+ "contractType": "oas",
59
+ "contentType": "application/yaml",
60
+ "verificationResults": {
61
+ "success": true,
62
+ "content": "c29tZSByZXN1bHRz",
63
+ "contentType": "text/plain",
64
+ "format": "text",
65
+ "verifier": "my custom tool",
66
+ "verifierVersion": "1.0"
67
+ }
68
+ }
69
+ }
70
+ ```
71
+ Pactflow will respond with:
72
+ ```json
73
+ {
74
+ "status": 201,
75
+ "headers": {
76
+ "Content-Type": "application/hal+json;charset=utf-8"
77
+ }
78
+ }
79
+ ```
44
80
  <a name="a_request_to_create_a_webhook_for_a_team_given_a_team_with_UUID_2abbc12a-427d-432a-a521-c870af1739d9_exists"></a>
45
81
  Given **a team with UUID 2abbc12a-427d-432a-a521-c870af1739d9 exists**, upon receiving **a request to create a webhook for a team** from Pact Broker Client, with
46
82
  ```json
@@ -1,228 +1,44 @@
1
- require 'pact_broker/client/cli/custom_thor'
2
- require 'pact_broker/client/hash_refinements'
3
- require 'thor/error'
4
- require 'pact_broker/client/cli/environment_commands'
5
- require 'pact_broker/client/cli/deployment_commands'
6
- require 'pact_broker/client/cli/pacticipant_commands'
7
- require 'pact_broker/client/cli/webhook_commands'
1
+ require "pact_broker/client/cli/custom_thor"
2
+ require "pact_broker/client/hash_refinements"
3
+ require "thor/error"
4
+ require "pact_broker/client/cli/pact_commands"
5
+ require "pact_broker/client/cli/environment_commands"
6
+ require "pact_broker/client/cli/deployment_commands"
7
+ require "pact_broker/client/cli/pacticipant_commands"
8
+ require "pact_broker/client/cli/version_commands"
9
+ require "pact_broker/client/cli/webhook_commands"
8
10
  require "pact_broker/client/cli/matrix_commands"
9
11
 
10
12
  module PactBroker
11
13
  module Client
12
14
  module CLI
13
- # Thor::Error will have its backtrace hidden
14
- class PactPublicationError < ::Thor::Error; end
15
- class AuthError < ::Thor::Error; end
16
- class VersionCreationError < ::Thor::Error; end
17
-
18
15
  class Broker < CustomThor
19
- using PactBroker::Client::HashRefinements
20
-
16
+ include PactBroker::Client::CLI::PactCommands
21
17
  include PactBroker::Client::CLI::EnvironmentCommands
22
18
  include PactBroker::Client::CLI::DeploymentCommands
23
19
  include PactBroker::Client::CLI::MatrixCommands
24
20
  include PactBroker::Client::CLI::PacticipantCommands
21
+ include PactBroker::Client::CLI::VersionCommands
25
22
  include PactBroker::Client::CLI::WebhookCommands
26
23
 
27
- desc 'publish PACT_DIRS_OR_FILES ...', "Publish pacts to a Pact Broker."
28
- method_option :consumer_app_version, required: true, aliases: "-a", desc: "The consumer application version"
29
- method_option :branch, aliases: "-h", desc: "Repository branch of the consumer version"
30
- method_option :auto_detect_version_properties, hidden: true, type: :boolean, default: false, desc: "Automatically detect the repository branch from known CI environment variables or git CLI."
31
- method_option :tag, aliases: "-t", type: :array, banner: "TAG", desc: "Tag name for consumer version. Can be specified multiple times."
32
- 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"
33
- method_option :build_url, desc: "The build URL that created the pact"
34
- 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."
35
- output_option_json_or_text
36
- shared_authentication_options
37
-
38
- def publish(*pact_files)
39
- require 'pact_broker/client/error'
40
- validate_credentials
41
- validate_pact_files(pact_files)
42
- result = publish_pacts(pact_files)
43
- $stdout.puts result.message
44
- exit(1) unless result.success
45
- rescue PactBroker::Client::Error => e
46
- raise PactPublicationError, "#{e.class} - #{e.message}"
47
- end
48
-
49
- desc 'create-version-tag', 'Add a tag to a pacticipant version'
50
- method_option :pacticipant, required: true, aliases: "-a", desc: "The pacticipant name"
51
- method_option :version, required: true, aliases: "-e", desc: "The pacticipant version"
52
- method_option :tag, aliases: "-t", type: :array, banner: "TAG", desc: "Tag name for pacticipant version. Can be specified multiple times."
53
- method_option :auto_create_version, type: :boolean, default: false, desc: "Automatically create the pacticipant version if it does not exist. Default: false"
54
- method_option :tag_with_git_branch, aliases: "-g", type: :boolean, default: false, required: false, desc: "Tag pacticipant version with the name of the current git branch. Default: false"
55
- shared_authentication_options
56
-
57
- def create_version_tag
58
- require 'pact_broker/client/create_tag'
59
-
60
- validate_credentials
61
- PactBroker::Client::CreateTag.call(
62
- options.broker_base_url,
63
- options.pacticipant,
64
- options.version,
65
- tags,
66
- options.auto_create_version,
67
- pact_broker_client_options)
68
- rescue PactBroker::Client::Error => e
69
- raise VersionCreationError.new(e.message)
70
- end
71
-
72
- method_option :pacticipant, required: true, aliases: "-a", desc: "The name of the pacticipant that the version belongs to."
73
- method_option :version, required: false, aliases: "-e", desc: "The pacticipant version number."
74
- method_option :latest, required: false, aliases: "-l", banner: '[TAG]', desc: "Describe the latest pacticipant version. Optionally specify a TAG to describe the latest version with the specified tag."
75
- method_option :output, aliases: "-o", desc: "json or table or id", default: 'table'
76
- shared_authentication_options
77
-
78
- desc 'describe-version', 'Describes a pacticipant version. If no version or tag is specified, the latest version is described.'
79
- def describe_version
80
- require 'pact_broker/client/versions/describe'
81
-
82
- validate_credentials
83
- latest = !options.latest.nil? || (options.latest.nil? && options.version.nil?)
84
- params = {
85
- pacticipant: options.pacticipant,
86
- version: options.version,
87
- latest: latest,
88
- tag: options.latest != "latest" ? options.latest : nil
89
- }
90
- opts = {
91
- output: options.output
92
- }
93
- result = PactBroker::Client::Versions::Describe.call(params, opts, options.broker_base_url, pact_broker_client_options)
94
- $stdout.puts result.message
95
- exit(1) unless result.success
96
- end
97
-
98
-
99
-
100
24
  ignored_and_hidden_potential_options_from_environment_variables
101
- desc 'generate-uuid', 'Generate a UUID for use when calling create-or-update-webhook'
25
+ desc "generate-uuid", "Generate a UUID for use when calling create-or-update-webhook"
102
26
  def generate_uuid
103
- require 'securerandom'
104
-
27
+ require "securerandom"
105
28
  puts SecureRandom.uuid
106
29
  end
107
30
 
108
- desc 'list-latest-pact-versions', 'List the latest pact for each integration'
109
- shared_authentication_options
110
- output_option_json_or_table
111
- def list_latest_pact_versions(*required_but_ignored)
112
- require 'pact_broker/client/pacts/list_latest_versions'
113
- result = PactBroker::Client::Pacts::ListLatestVersions.call(options.broker_base_url, options.output, pact_broker_client_options)
114
- $stdout.puts result.message
115
- exit(1) unless result.success
116
- end
117
-
118
31
  ignored_and_hidden_potential_options_from_environment_variables
119
- desc 'version', "Show the pact_broker-client gem version"
32
+ desc "version", "Show the pact_broker-client gem version"
120
33
  def version
121
- require 'pact_broker/client/version'
122
-
34
+ require "pact_broker/client/version"
123
35
  $stdout.puts PactBroker::Client::VERSION
124
36
  end
125
37
 
126
38
  no_commands do
127
-
128
39
  def self.exit_on_failure?
129
40
  true
130
41
  end
131
-
132
- def validate_credentials
133
- if options.broker_username && options.broker_token
134
- raise AuthError, "You cannot provide both a username/password and a bearer token. If your Pact Broker uses a bearer token, please remove the username and password configuration."
135
- end
136
- end
137
-
138
- def validate_pact_files pact_files
139
- unless pact_files && pact_files.any?
140
- raise ::Thor::RequiredArgumentMissingError, "No value provided for required pact_files"
141
- end
142
- end
143
-
144
-
145
- def publish_pacts pact_files
146
- require 'pact_broker/client/publish_pacts'
147
-
148
- write_options = options[:merge] ? { write: :merge } : {}
149
- consumer_version_params = {
150
- number: options.consumer_app_version,
151
- branch: branch,
152
- tags: tags,
153
- build_url: options.build_url,
154
- version_required: (!!options.branch || !!options.build_url || explict_auto_detect_version_properties)
155
- }.compact
156
-
157
- PactBroker::Client::PublishPacts.call(
158
- options.broker_base_url,
159
- file_list(pact_files),
160
- consumer_version_params,
161
- { merge: options[:merge], output: options.output }.compact,
162
- pact_broker_client_options.merge(write_options)
163
- )
164
- end
165
-
166
- def file_list pact_files
167
- require 'rake/file_list'
168
-
169
- correctly_separated_pact_files = pact_files.collect{ |path| path.gsub(/\\+/, '/') }
170
- paths = Rake::FileList[correctly_separated_pact_files].collect do | path |
171
- if File.directory?(path)
172
- Rake::FileList[File.join(path, "*.json")]
173
- else
174
- path
175
- end
176
- end.flatten
177
- validate_pact_path_list(paths)
178
- end
179
-
180
- def validate_pact_path_list(paths)
181
- paths.collect do | path |
182
- if File.exist?(path)
183
- path
184
- elsif path.start_with?("-")
185
- raise Thor::Error.new("ERROR: pact-broker publish was called with invalid arguments #{[path]}")
186
- else
187
- raise Thor::Error.new("Specified pact file '#{path}' does not exist. This sometimes indicates one of the arguments has been specified with the wrong name and has been incorrectly identified as a file path.")
188
- end
189
- end
190
- end
191
-
192
- def tags
193
- require 'pact_broker/client/git'
194
-
195
- t = [*options.tag]
196
- t << PactBroker::Client::Git.branch(raise_error: true) if options.tag_with_git_branch
197
- t.compact.uniq
198
- end
199
-
200
- def branch
201
- require 'pact_broker/client/git'
202
-
203
- if options.branch.nil? && options.auto_detect_version_properties
204
- PactBroker::Client::Git.branch(raise_error: explict_auto_detect_version_properties)
205
- else
206
- options.branch
207
- end
208
- end
209
-
210
- def explict_auto_detect_version_properties
211
- @explict_auto_detect_version_properties ||= ARGV.include?("--auto-detect-version-properties")
212
- end
213
-
214
- def pact_broker_client_options
215
- client_options = { verbose: options.verbose, pact_broker_base_url: options.broker_base_url }
216
- client_options[:token] = options.broker_token || ENV['PACT_BROKER_TOKEN']
217
- if options.broker_username || ENV['PACT_BROKER_USERNAME']
218
- client_options[:basic_auth] = {
219
- username: options.broker_username || ENV['PACT_BROKER_USERNAME'],
220
- password: options.broker_password || ENV['PACT_BROKER_PASSWORD']
221
- }.compact
222
- end
223
-
224
- client_options.compact
225
- end
226
42
  end
227
43
  end
228
44
  end
@@ -1,14 +1,18 @@
1
1
  require 'thor'
2
+ require 'pact_broker/client/hash_refinements'
2
3
 
3
4
  module PactBroker
4
5
  module Client
5
6
  module CLI
7
+ class AuthError < ::Thor::Error; end
8
+
6
9
  ##
7
10
  # Custom Thor task allows the following:
8
11
  #
9
12
  # `--option 1 --option 2` to be interpreted as `--option 1 2` (the standard Thor format for multiple value options)
10
13
  #
11
14
  class CustomThor < ::Thor
15
+ using PactBroker::Client::HashRefinements
12
16
 
13
17
  no_commands do
14
18
  def self.start given_args = ARGV, config = {}
@@ -106,6 +110,25 @@ module PactBroker
106
110
  def params_from_options(keys)
107
111
  keys.each_with_object({}) { | key, p | p[key] = options[key] }
108
112
  end
113
+
114
+ def pact_broker_client_options
115
+ client_options = { verbose: options.verbose, pact_broker_base_url: options.broker_base_url }
116
+ client_options[:token] = options.broker_token || ENV['PACT_BROKER_TOKEN']
117
+ if options.broker_username || ENV['PACT_BROKER_USERNAME']
118
+ client_options[:basic_auth] = {
119
+ username: options.broker_username || ENV['PACT_BROKER_USERNAME'],
120
+ password: options.broker_password || ENV['PACT_BROKER_PASSWORD']
121
+ }.compact
122
+ end
123
+
124
+ client_options.compact
125
+ end
126
+
127
+ def validate_credentials
128
+ if options.broker_username && options.broker_token
129
+ raise AuthError, "You cannot provide both a username/password and a bearer token. If your Pact Broker uses a bearer token, please remove the username and password configuration."
130
+ end
131
+ end
109
132
  end
110
133
  end
111
134
  end
@@ -0,0 +1,128 @@
1
+ require "pact_broker/client/hash_refinements"
2
+
3
+ module PactBroker
4
+ module Client
5
+ module CLI
6
+ # Thor::Error will have its backtrace hidden
7
+ class PactPublicationError < ::Thor::Error; end
8
+
9
+ module PactCommands
10
+ using PactBroker::Client::HashRefinements
11
+
12
+ def self.included(thor)
13
+ thor.class_eval do
14
+ desc 'publish PACT_DIRS_OR_FILES ...', "Publish pacts to a Pact Broker."
15
+ method_option :consumer_app_version, required: true, aliases: "-a", desc: "The consumer application version"
16
+ method_option :branch, aliases: "-h", desc: "Repository branch of the consumer version"
17
+ method_option :auto_detect_version_properties, hidden: true, type: :boolean, default: false, desc: "Automatically detect the repository branch from known CI environment variables or git CLI."
18
+ method_option :tag, aliases: "-t", type: :array, banner: "TAG", desc: "Tag name for consumer version. Can be specified multiple times."
19
+ 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"
20
+ method_option :build_url, desc: "The build URL that created the pact"
21
+ 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."
22
+ output_option_json_or_text
23
+ shared_authentication_options
24
+
25
+ def publish(*pact_files)
26
+ require 'pact_broker/client/error'
27
+ validate_credentials
28
+ validate_pact_files(pact_files)
29
+ result = publish_pacts(pact_files)
30
+ $stdout.puts result.message
31
+ exit(1) unless result.success
32
+ rescue PactBroker::Client::Error => e
33
+ raise PactPublicationError, "#{e.class} - #{e.message}"
34
+ end
35
+
36
+ desc 'list-latest-pact-versions', 'List the latest pact for each integration'
37
+ shared_authentication_options
38
+ output_option_json_or_table
39
+ def list_latest_pact_versions(*required_but_ignored)
40
+ require 'pact_broker/client/pacts/list_latest_versions'
41
+ result = PactBroker::Client::Pacts::ListLatestVersions.call(options.broker_base_url, options.output, pact_broker_client_options)
42
+ $stdout.puts result.message
43
+ exit(1) unless result.success
44
+ end
45
+
46
+ no_commands do
47
+ def validate_pact_files pact_files
48
+ unless pact_files && pact_files.any?
49
+ raise ::Thor::RequiredArgumentMissingError, "No value provided for required pact_files"
50
+ end
51
+ end
52
+
53
+
54
+ def publish_pacts pact_files
55
+ require 'pact_broker/client/publish_pacts'
56
+
57
+ write_options = options[:merge] ? { write: :merge } : {}
58
+ consumer_version_params = {
59
+ number: options.consumer_app_version,
60
+ branch: branch,
61
+ tags: tags,
62
+ build_url: options.build_url,
63
+ version_required: (!!options.branch || !!options.build_url || explict_auto_detect_version_properties)
64
+ }.compact
65
+
66
+ PactBroker::Client::PublishPacts.call(
67
+ options.broker_base_url,
68
+ file_list(pact_files),
69
+ consumer_version_params,
70
+ { merge: options[:merge], output: options.output }.compact,
71
+ pact_broker_client_options.merge(write_options)
72
+ )
73
+ end
74
+
75
+ def file_list pact_files
76
+ require 'rake/file_list'
77
+
78
+ correctly_separated_pact_files = pact_files.collect{ |path| path.gsub(/\\+/, '/') }
79
+ paths = Rake::FileList[correctly_separated_pact_files].collect do | path |
80
+ if File.directory?(path)
81
+ Rake::FileList[File.join(path, "*.json")]
82
+ else
83
+ path
84
+ end
85
+ end.flatten
86
+ validate_pact_path_list(paths)
87
+ end
88
+
89
+ def validate_pact_path_list(paths)
90
+ paths.collect do | path |
91
+ if File.exist?(path)
92
+ path
93
+ elsif path.start_with?("-")
94
+ raise Thor::Error.new("ERROR: pact-broker publish was called with invalid arguments #{[path]}")
95
+ else
96
+ raise Thor::Error.new("Specified pact file '#{path}' does not exist. This sometimes indicates one of the arguments has been specified with the wrong name and has been incorrectly identified as a file path.")
97
+ end
98
+ end
99
+ end
100
+
101
+ def tags
102
+ require 'pact_broker/client/git'
103
+
104
+ t = [*options.tag]
105
+ t << PactBroker::Client::Git.branch(raise_error: true) if options.tag_with_git_branch
106
+ t.compact.uniq
107
+ end
108
+
109
+ def branch
110
+ require 'pact_broker/client/git'
111
+
112
+ if options.branch.nil? && options.auto_detect_version_properties
113
+ PactBroker::Client::Git.branch(raise_error: explict_auto_detect_version_properties)
114
+ else
115
+ options.branch
116
+ end
117
+ end
118
+
119
+ def explict_auto_detect_version_properties
120
+ @explict_auto_detect_version_properties ||= ARGV.include?("--auto-detect-version-properties")
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end