pact_broker-client 1.38.1 → 1.41.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +38 -0
  4. data/Gemfile +4 -0
  5. data/README.md +18 -0
  6. data/bin/pact-broker +6 -0
  7. data/doc/pacts/markdown/Pact Broker Client - Pact Broker.md +61 -140
  8. data/example/scripts/publish-pact.sh +1 -1
  9. data/lib/pact_broker/client/base_client.rb +1 -1
  10. data/lib/pact_broker/client/can_i_deploy.rb +20 -3
  11. data/lib/pact_broker/client/cli/broker.rb +35 -10
  12. data/lib/pact_broker/client/cli/record_deployment_long_desc.txt +0 -0
  13. data/lib/pact_broker/client/cli/version_selector_options_parser.rb +4 -0
  14. data/lib/pact_broker/client/colorize_notices.rb +31 -0
  15. data/lib/pact_broker/client/hal/entity.rb +16 -0
  16. data/lib/pact_broker/client/hal/http_client.rb +37 -1
  17. data/lib/pact_broker/client/hal/link.rb +12 -0
  18. data/lib/pact_broker/client/hal/links.rb +15 -0
  19. data/lib/pact_broker/client/hal_client_methods.rb +8 -0
  20. data/lib/pact_broker/client/matrix.rb +4 -0
  21. data/lib/pact_broker/client/matrix/abbreviate_version_number.rb +15 -0
  22. data/lib/pact_broker/client/matrix/resource.rb +26 -1
  23. data/lib/pact_broker/client/matrix/text_formatter.rb +11 -8
  24. data/lib/pact_broker/client/pacts.rb +0 -1
  25. data/lib/pact_broker/client/publish_pacts.rb +94 -128
  26. data/lib/pact_broker/client/publish_pacts_the_old_way.rb +194 -0
  27. data/lib/pact_broker/client/tasks/publication_task.rb +3 -3
  28. data/lib/pact_broker/client/version.rb +1 -1
  29. data/lib/pact_broker/client/versions/record_deployment.rb +6 -6
  30. data/lib/pact_broker/client/versions/record_undeployment.rb +45 -68
  31. data/pact-broker-client.gemspec +1 -0
  32. data/script/approve-all.sh +6 -0
  33. data/script/publish-pact.sh +36 -5
  34. data/script/record-deployment.sh +1 -3
  35. data/script/record-undeployment.sh +4 -0
  36. data/spec/fixtures/approvals/can_i_deploy_ignore.approved.txt +13 -0
  37. data/spec/fixtures/foo-bar.json +31 -0
  38. data/spec/lib/pact_broker/client/can_i_deploy_spec.rb +47 -5
  39. data/spec/lib/pact_broker/client/cli/broker_can_i_deploy_spec.rb +3 -3
  40. data/spec/lib/pact_broker/client/cli/broker_publish_spec.rb +36 -7
  41. data/spec/lib/pact_broker/client/cli/version_selector_options_parser_spec.rb +21 -0
  42. data/spec/lib/pact_broker/client/hal/http_client_spec.rb +64 -7
  43. data/spec/lib/pact_broker/client/pacticipants/create_spec.rb +3 -0
  44. data/spec/lib/pact_broker/client/{publish_pacts_spec.rb → publish_pacts_the_old_way_spec.rb} +10 -9
  45. data/spec/lib/pact_broker/client/tasks/publication_task_spec.rb +18 -12
  46. data/spec/lib/pact_broker/client/versions/record_deployment_spec.rb +5 -5
  47. data/spec/pacts/pact_broker_client-pact_broker.json +50 -124
  48. data/spec/service_providers/pact_broker_client_create_version_spec.rb +4 -4
  49. data/spec/service_providers/pact_broker_client_matrix_ignore_spec.rb +98 -0
  50. data/spec/service_providers/publish_pacts_spec.rb +116 -0
  51. data/spec/service_providers/record_deployment_spec.rb +6 -7
  52. data/spec/spec_helper.rb +2 -1
  53. data/spec/support/approvals.rb +26 -0
  54. data/spec/support/shared_context.rb +6 -2
  55. metadata +41 -5
@@ -63,8 +63,9 @@ module PactBroker
63
63
  pact_broker_client_options[:basic_auth] = pact_broker_basic_auth if pact_broker_basic_auth && pact_broker_basic_auth.any?
64
64
  pact_broker_client_options.compact!
65
65
  consumer_version_params = { number: consumer_version, branch: the_branch, build_url: build_url, tags: all_tags, version_required: version_required }.compact
66
- success = PactBroker::Client::PublishPacts.new(pact_broker_base_url, FileList[pattern], consumer_version_params, pact_broker_client_options).call
67
- raise "One or more pacts failed to be published" unless success
66
+ result = PactBroker::Client::PublishPacts.new(pact_broker_base_url, FileList[pattern], consumer_version_params, {}, pact_broker_client_options).call
67
+ $stdout.puts result.message
68
+ raise "One or more pacts failed to be published" unless result.success
68
69
  end
69
70
  end
70
71
  end
@@ -86,7 +87,6 @@ module PactBroker
86
87
  branch
87
88
  end
88
89
  end
89
-
90
90
  end
91
91
  end
92
92
  end
@@ -1,5 +1,5 @@
1
1
  module PactBroker
2
2
  module Client
3
- VERSION = '1.38.1'
3
+ VERSION = '1.41.0'
4
4
  end
5
5
  end
@@ -19,7 +19,7 @@ module PactBroker
19
19
  @pacticipant_name = params.fetch(:pacticipant_name)
20
20
  @version_number = params.fetch(:version_number)
21
21
  @environment_name = params.fetch(:environment_name)
22
- @replaced_previous_deployed_version = params.fetch(:replaced_previous_deployed_version)
22
+ @target = params.fetch(:target)
23
23
  @output = params.fetch(:output)
24
24
  @pact_broker_client_options = pact_broker_client_options
25
25
  end
@@ -36,7 +36,7 @@ module PactBroker
36
36
  private
37
37
 
38
38
  attr_reader :pact_broker_base_url, :pact_broker_client_options
39
- attr_reader :pacticipant_name, :version_number, :environment_name, :replaced_previous_deployed_version, :output
39
+ attr_reader :pacticipant_name, :version_number, :environment_name, :target, :output
40
40
  attr_reader :deployed_version_resource
41
41
 
42
42
  def check_environment_exists
@@ -75,14 +75,14 @@ module PactBroker
75
75
  end
76
76
 
77
77
  def record_deployment_request_body
78
- { replacedPreviousDeployedVersion: replaced_previous_deployed_version }
78
+ { target: target }
79
79
  end
80
80
 
81
81
  def result_message
82
82
  if output == "text"
83
- message = "Recorded deployment of #{pacticipant_name} version #{version_number} to #{environment_name} in #{pact_broker_name}."
84
- suffix = replaced_previous_deployed_version ? " Marked previous deployed version as undeployed." : ""
85
- message + suffix
83
+ message = "Recorded deployment of #{pacticipant_name} version #{version_number} to #{environment_name}"
84
+ message = "#{message} (target #{target})" if target
85
+ "#{message} in #{pact_broker_name}."
86
86
  elsif output == "json"
87
87
  deployed_version_resource.response.raw_body
88
88
  else
@@ -2,6 +2,10 @@ require 'pact_broker/client/hal_client_methods'
2
2
  require 'pact_broker/client/error'
3
3
  require 'pact_broker/client/command_result'
4
4
 
5
+ # TODO
6
+ # --limit 1
7
+ # order by date so that the oldest one gets undeployed first
8
+
5
9
  module PactBroker
6
10
  module Client
7
11
  class Versions
@@ -24,10 +28,17 @@ module PactBroker
24
28
  end
25
29
 
26
30
  def call
27
- check_environment_exists
28
- # record_undeployment
31
+ check_if_command_supported
32
+ if deployed_version_links_for_environment.any?
33
+ @undeployment_entities = deployed_version_links_for_environment.collect do | deployed_version_link |
34
+ deployed_version_link.get!._link!("pb:record-undeployment").post!
35
+ end
36
+ else
37
+ check_environment_exists
38
+ raise_not_found_error
39
+ end
29
40
 
30
- PactBroker::Client::CommandResult.new(true, result_message)
41
+ PactBroker::Client::CommandResult.new(true, "foo")
31
42
  rescue PactBroker::Client::Error => e
32
43
  PactBroker::Client::CommandResult.new(false, e.message)
33
44
  end
@@ -35,83 +46,49 @@ module PactBroker
35
46
  private
36
47
 
37
48
  attr_reader :pact_broker_base_url, :pact_broker_client_options
38
- attr_reader :pacticipant_name, :version_number, :environment_name, :replaced_previous_deployed_version, :output
39
- attr_reader :deployed_version_resource
49
+ attr_reader :pacticipant_name, :version_number, :environment_name, :target, :output
50
+ attr_reader :deployed_version_resource, :undeployment_entities
40
51
 
41
- def check_environment_exists
42
- deployed_versions = currently_deployed_versions_for_pacticipant
43
- .get(version: version_number)
44
- .embedded_entities("deployedVersions")
45
- deployed_versions
52
+ def version_resource
53
+ index_resource._link!("pb:pacticipant-version").expand(pacticipant: pacticipant_name, version: version_number).get!
46
54
  end
47
55
 
48
- def currently_deployed_versions_for_pacticipant
49
- @currently_deployed_versions_for_pacticipant ||= index_resource
50
- ._link!("pb:environments")
51
- .get!(name: environment_name)
52
- .embedded_entities("environments")
53
- .tap { |it| raise "Environment not found '#{environment_name}'" if it.empty? }
54
- .first
55
- ._link!("pb:currently-deployed-versions-for-pacticipant")
56
- .expand(pacticipant: pacticipant_name)
56
+ def deployed_version_links
57
+ @deployed_version_links ||= version_resource._links!("pb:currently-deployed-versions")
57
58
  end
58
59
 
59
- def currently_deployed_versions_for_pacticipant_version
60
- @currently_deployed_versions ||= currently_deployed_versions_for_pacticipant
61
- .get(version: version_number)
62
- .embedded_entities("deployedVersions")
60
+ def deployed_version_links_for_environment
61
+ @deployed_version_links_for_environment ||= deployed_version_links.select(environment_name)
63
62
  end
64
63
 
65
- # def record_deployment
66
- # @deployed_version_resource =
67
- # get_record_deployment_relation
68
- # .post(record_deployment_request_body)
69
- # .assert_success!
70
- # end
71
-
72
- # def get_record_deployment_relation
73
- # record_deployment_links = get_pacticipant_version._links!("pb:record-deployment")
74
- # link_for_environment = record_deployment_links.find(environment_name)
75
- # if link_for_environment
76
- # link_for_environment
77
- # else
78
- # check_environment_exists
79
- # # Force the exception to be raised
80
- # record_deployment_links.find!(environment_name, "Environment '#{environment_name}' is not an available option for recording a deployment of #{pacticipant_name}.")
81
- # end
82
- # end
83
-
84
- # def get_pacticipant_version
85
- # index_resource
86
- # ._link!("pb:pacticipant-version")
87
- # .expand(pacticipant: pacticipant_name, version: version_number)
88
- # .get
89
- # .assert_success!(404 => "#{pacticipant_name} version #{version_number} not found")
90
- # end
91
-
92
- # def record_deployment_request_body
93
- # { replacedPreviousDeployedVersion: replaced_previous_deployed_version }
94
- # end
64
+ def check_environment_exists
65
+ index_resource
66
+ ._link!("pb:environments")
67
+ .get!
68
+ ._links("pb:environments")
69
+ .find!(environment_name, "No environment found with name '#{environment_name}'")
70
+ end
95
71
 
96
- def result_message
97
- ""
98
- # if output == "text"
99
- # message = "Recorded deployment of #{pacticipant_name} version #{version_number} to #{environment_name} in #{pact_broker_name}."
100
- # suffix = replaced_previous_deployed_version ? " Marked previous deployed version as undeployed." : ""
101
- # message + suffix
102
- # elsif output == "json"
103
- # deployed_version_resource.response.raw_body
104
- # else
105
- # ""
106
- # end
72
+ def raise_not_found_error
73
+ raise PactBroker::Client::Error.new(deployed_version_not_found_message)
107
74
  end
108
75
 
109
- def pact_broker_name
110
- is_pactflow? ? "Pactflow" : "the Pact Broker"
76
+ def deployed_version_not_found_message
77
+ if (env_names = deployed_version_links.names).any?
78
+ "#{pacticipant_name} version #{version_number} is not currently deployed to #{environment_name}. It is currently deployed to: #{env_names.join(", ")}"
79
+ else
80
+ "#{pacticipant_name} version #{version_number} is not currently deployed to any environment."
81
+ end
111
82
  end
112
83
 
113
- def is_pactflow?
114
- deployed_version_resource.response.headers.keys.any?{ | header_name | header_name.downcase.include?("pactflow") }
84
+ def result_message
85
+ if output == "text"
86
+ message = "Recorded undeployment of #{pacticipant_name} version #{version_number} from #{environment_name} in #{pact_broker_name}."
87
+ elsif output == "json"
88
+ undeployment_entities.last.response.raw_body
89
+ else
90
+ ""
91
+ end
115
92
  end
116
93
 
117
94
  def check_if_command_supported
@@ -33,4 +33,5 @@ Gem::Specification.new do |gem|
33
33
  gem.add_development_dependency 'conventional-changelog', '~>1.3'
34
34
  gem.add_development_dependency 'pact', '~> 1.16'
35
35
  gem.add_development_dependency 'pact-support', '~> 1.16'
36
+ gem.add_development_dependency 'approvals', '>=0.0.24', '<1.0.0'
36
37
  end
@@ -0,0 +1,6 @@
1
+ #!/bin/sh
2
+
3
+ for file in $(find spec/fixtures/approvals -ipath "*.received.*"); do
4
+ approved_path=$(echo "$file" | sed 's/received/approved/')
5
+ mv "$file" "$approved_path"
6
+ done;
@@ -1,7 +1,38 @@
1
- bundle exec bin/pact-broker publish spec/pacts/pact_broker_client-pact_broker.json \
2
- --consumer-app-version 1.2.7 \
1
+ export PACT_BROKER_BASE_URL="http://localhost:9292"
2
+ export PACT_BROKER_TOKEN="localhost"
3
+
4
+ # bundle exec bin/pact-broker create-or-update-webhook http://localhost:9393 \
5
+ # --uuid d40f38c3-aaa3-47f5-9161-95c07bc16b14 \
6
+ # --request POST \
7
+ # --description "foo webhook" \
8
+ # --contract-published
9
+
10
+ bundle exec bin/pact-broker create-or-update-webhook http://localhost:9393 \
11
+ --uuid d40f38c3-aaa3-47f5-9161-95csfadfsd7 \
12
+ --description "This is quite a long description for a webhook that I hope will be truncated" \
13
+ --request POST \
14
+ --contract-published
15
+
16
+ # bundle exec bin/pact-broker publish spec/pacts/pact_broker_client-pact_broker.json spec/fixtures/foo-bar.json \
17
+ # --consumer-app-version 1.2.12 \
18
+ # --broker-base-url http://localhost:9292 \
19
+ # --broker-username localhost --broker-password localhost \
20
+ # --auto-detect-version-properties \
21
+ # --build-url http://mybuild \
22
+ # --branch master --tag foo5
23
+
24
+ # bundle exec bin/pact-broker create-or-update-webhook http://localhost:9393 \
25
+ # --uuid d40f38c3-aaa3-47f5-9161-95c07bc16555 \
26
+ # --provider Bar \
27
+ # --request POST \
28
+ # --contract-published
29
+
30
+
31
+ PACT_BROKER_FEATURES=publish_contracts bundle exec bin/pact-broker publish spec/pacts/pact_broker_client-pact_broker.json \
32
+ --consumer-app-version 1.2.26 \
3
33
  --broker-base-url http://localhost:9292 \
4
- --broker-username localhost --broker-password localhost \
5
- --auto-detect-branch \
6
- --build-url http://mybuild
34
+ --broker-token localhost \
35
+ --auto-detect-version-properties \
36
+ --build-url http://mybuild \
37
+ --branch master --tag foo5 --tag foo6
7
38
 
@@ -1,4 +1,2 @@
1
1
  PACT_BROKER_FEATURES=deployments bundle exec bin/pact-broker record-deployment \
2
- --pacticipant Foo --version 1.0.0 --environment prod --broker-base-url http://localhost:9292
3
-
4
-
2
+ --pacticipant foo-consumer --version 1 --environment prod --broker-base-url http://localhost:9292
@@ -0,0 +1,4 @@
1
+ PACT_BROKER_FEATURES=deployments bundle exec bin/pact-broker record-undeployment \
2
+ --pacticipant foo-consumer --version 1 --environment prod --broker-base-url http://localhost:9292 --output json --verbose
3
+
4
+
@@ -0,0 +1,13 @@
1
+ Computer says yes \o/ 
2
+
3
+ CONSUMER | C.VERSION | PROVIDER | P.VERSION | SUCCESS? | RESULT#
4
+ ---------|-----------|----------|-----------|-----------------|--------
5
+ Foo | 1.2.3 | Bar | 4.5.6 | true | 1
6
+ Foo | 3.4.5 | Bar | 4.5.6 | false [ignored] | 2
7
+
8
+ VERIFICATION RESULTS
9
+ --------------------
10
+ 1. http://result (success)
11
+ 2. http://result (failure)
12
+
13
+ some notice
@@ -0,0 +1,31 @@
1
+ {
2
+ "consumer": {
3
+ "name": "Foo"
4
+ },
5
+ "provider": {
6
+ "name": "Bar"
7
+ },
8
+ "interactions": [
9
+ {
10
+ "description": "an example request",
11
+ "providerState": "a provider state",
12
+ "request": {
13
+ "method": "GET",
14
+ "path": "/",
15
+ "headers": {
16
+ }
17
+ },
18
+ "response": {
19
+ "status": 200,
20
+ "headers": {
21
+ "Content-Type": "application/hal+json"
22
+ }
23
+ }
24
+ }
25
+ ],
26
+ "metadata": {
27
+ "pactSpecification": {
28
+ "version": "2.0.0"
29
+ }
30
+ }
31
+ }
@@ -6,22 +6,27 @@ module PactBroker
6
6
  describe CanIDeploy do
7
7
  let(:pact_broker_base_url) { 'http://example.org' }
8
8
  let(:version_selectors) { [{ pacticipant: "Foo", version: "1" }] }
9
- let(:matrix_options) { {} }
9
+ let(:matrix_options) { { } }
10
10
  let(:pact_broker_client_options) { { foo: 'bar' } }
11
11
  let(:matrix_client) { instance_double('PactBroker::Client::Matrix') }
12
12
  let(:matrix) do
13
13
  instance_double('Matrix::Resource',
14
- deployable?: true,
14
+ deployable?: deployable,
15
15
  reason: 'some reason',
16
16
  any_unknown?: any_unknown,
17
17
  supports_unknown_count?: supports_unknown_count,
18
- unknown_count: unknown_count)
18
+ supports_ignore?: supports_ignore,
19
+ unknown_count: unknown_count,
20
+ notices: notices)
19
21
  end
20
22
  let(:unknown_count) { 0 }
21
23
  let(:any_unknown) { unknown_count > 0 }
22
24
  let(:supports_unknown_count) { true }
23
25
  let(:retry_while_unknown) { 0 }
24
26
  let(:options) { { output: 'text', retry_while_unknown: retry_while_unknown, retry_interval: 5 } }
27
+ let(:notices) { nil }
28
+ let(:supports_ignore) { true }
29
+ let(:deployable) { true }
25
30
 
26
31
 
27
32
  before do
@@ -55,10 +60,19 @@ module PactBroker
55
60
  it "returns a success reason" do
56
61
  expect(subject.message).to include "some reason"
57
62
  end
63
+
64
+ context "when there are notices" do
65
+ let(:notices) { [Notice.new(text: "some notice", type: "info")] }
66
+
67
+ it "returns the notices instead of the reason" do
68
+ expect(subject.message).to_not include "some reason"
69
+ expect(subject.message).to include "some notice"
70
+ end
71
+ end
58
72
  end
59
73
 
60
74
  context "when the versions are not deployable" do
61
- let(:matrix) { instance_double('Matrix::Resource', deployable?: false, reason: 'some reason', any_unknown?: false) }
75
+ let(:matrix) { instance_double('Matrix::Resource', deployable?: false, reason: 'some reason', any_unknown?: false, notices: notices) }
62
76
 
63
77
  it "returns a failure response" do
64
78
  expect(subject.success).to be false
@@ -71,6 +85,15 @@ module PactBroker
71
85
  it "returns a failure reason" do
72
86
  expect(subject.message).to include "some reason"
73
87
  end
88
+
89
+ context "when there are notices" do
90
+ let(:notices) { [Notice.new(text: "some notice", type: "info")] }
91
+
92
+ it "returns the notices instead of the reason" do
93
+ expect(subject.message).to_not include "some reason"
94
+ expect(subject.message).to include "some notice"
95
+ end
96
+ end
74
97
  end
75
98
 
76
99
  context "when retry_while_unknown is greater than 0" do
@@ -115,6 +138,25 @@ module PactBroker
115
138
  end
116
139
  end
117
140
 
141
+ context "when there are ignore selectors but the matrix does not support ignoring" do
142
+ let(:matrix_options) { { ignore_selectors: [{ pacticipant_name: "Foo" }]} }
143
+ let(:supports_ignore) { false }
144
+
145
+ context "when deployable" do
146
+ it "returns a warning" do
147
+ expect(subject.message).to include "does not support"
148
+ end
149
+ end
150
+
151
+ context "when not deployable" do
152
+ let(:deployable) { false }
153
+
154
+ it "returns a warning" do
155
+ expect(subject.message).to include "does not support"
156
+ end
157
+ end
158
+ end
159
+
118
160
  context "when a PactBroker::Client::Error is raised" do
119
161
  before do
120
162
  allow(matrix_client).to receive(:get).and_raise(PactBroker::Client::Error.new('error text'))
@@ -125,7 +167,7 @@ module PactBroker
125
167
  end
126
168
 
127
169
  it "returns a failure message" do
128
- expect(subject.message).to eq "error text"
170
+ expect(subject.message).to include "error text"
129
171
  end
130
172
  end
131
173
 
@@ -37,7 +37,7 @@ module PactBroker
37
37
  end
38
38
 
39
39
  it "invokes the CanIDeploy service" do
40
- expect(CanIDeploy).to receive(:call).with('http://pact-broker', version_selectors, {to_tag: nil, to_environment: nil, limit: 1000}, {output: 'table', retry_while_unknown: 1, retry_interval: 2}, {verbose: 'verbose'})
40
+ expect(CanIDeploy).to receive(:call).with('http://pact-broker', version_selectors, {to_tag: nil, to_environment: nil, limit: 1000, ignore_selectors: []}, {output: 'table', retry_while_unknown: 1, retry_interval: 2}, {verbose: 'verbose'})
41
41
  invoke_can_i_deploy
42
42
  end
43
43
 
@@ -55,7 +55,7 @@ module PactBroker
55
55
  end
56
56
 
57
57
  it "passes the value as the matrix options" do
58
- expect(CanIDeploy).to receive(:call).with(anything, anything, {to_tag: 'prod', to_environment: nil, limit: 1000}, anything, anything)
58
+ expect(CanIDeploy).to receive(:call).with(anything, anything, {to_tag: 'prod', to_environment: nil, limit: 1000, ignore_selectors: []}, anything, anything)
59
59
  invoke_can_i_deploy
60
60
  end
61
61
  end
@@ -66,7 +66,7 @@ module PactBroker
66
66
  end
67
67
 
68
68
  it "passes the value as the matrix options" do
69
- expect(CanIDeploy).to receive(:call).with(anything, anything, {to_tag: nil, to_environment: 'prod', limit: 1000}, anything, anything)
69
+ expect(CanIDeploy).to receive(:call).with(anything, anything, {to_tag: nil, to_environment: 'prod', limit: 1000, ignore_selectors: []}, anything, anything)
70
70
  invoke_can_i_deploy
71
71
  end
72
72
  end