pact_broker 2.76.0 → 2.76.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d14eafba260b6b71dd75c725768863c0f923e167bdb37084606a0b51d110d363
4
- data.tar.gz: 545dabeda5ede4c25508e8ca5135d94dacec61f9df1692207787bdc6e3227ec4
3
+ metadata.gz: a1ab8b654502c5bbc4d263c4bd14fdb0e6dc3771173cfdf21a01118143528bd4
4
+ data.tar.gz: b1d929d7bfe56369c5985b94ad88f9adf3abdb27e9177b6249ba7cd68d03c85d
5
5
  SHA512:
6
- metadata.gz: c8df83a6bf1588e8a9a96f915b0926d1a164ebd8f246d7ed831d83d43610bcbaf38875800bbd56ab792af3c9b2b6a9b2f415b6e3a581b6d8955e80248b25d67d
7
- data.tar.gz: f1bb7162afee7913b9ac53fc523aa47d021f760350cca52758af1f626f3c440dd73bd02921254487820b1724b5a4c3e334283f728e7b279d92a69b29995de074
6
+ metadata.gz: ca79f6928c69425d89d0fa179094d007f26d5f25f02ee7fc2be771bb4208d2ecaef136af5391feea4c92588876e7162d205774451d00f9175463f03b9f1cdcd9
7
+ data.tar.gz: febb82748bb5929d393af212797a3d9c484c9825a8c83bc44e4d52aa7cb6fbce93863decb305a7d6ed3160a3b447bed6368339a38322f6084fb34de97f3698cc
@@ -5,12 +5,18 @@ on: push
5
5
  jobs:
6
6
  sqlite:
7
7
  runs-on: "ubuntu-latest"
8
+ continue-on-error: ${{ matrix.experimental }}
8
9
  strategy:
10
+ fail-fast: false
9
11
  matrix:
10
12
  ruby_version: ["2.7"]
13
+ experimental: [false]
14
+ include:
15
+ - ruby_version: "3.0"
16
+ experimental: true
11
17
  steps:
12
18
  - uses: actions/checkout@v2
13
- - uses: actions/setup-ruby@v1
19
+ - uses: ruby/setup-ruby@v1
14
20
  with:
15
21
  ruby-version: ${{ matrix.ruby_version }}
16
22
  - run: "bundle install"
@@ -34,7 +40,7 @@ jobs:
34
40
  - 5432:5432
35
41
  steps:
36
42
  - uses: actions/checkout@v2
37
- - uses: actions/setup-ruby@v1
43
+ - uses: ruby/setup-ruby@v1
38
44
  with:
39
45
  ruby-version: ${{ matrix.ruby_version }}
40
46
  - run: "gem install bundler && bundle install"
@@ -1,3 +1,12 @@
1
+ <a name="v2.76.1"></a>
2
+ ### v2.76.1 (2021-01-28)
3
+
4
+ #### Bug Fixes
5
+
6
+ * deduplicate wip pacts by content ([0af90776](/../../commit/0af90776))
7
+ * message when pending pact is verified successfully for the first time (#376) ([4fc69190](/../../commit/4fc69190))
8
+ * use base URL from rack env in UI ([5bf21324](/../../commit/5bf21324))
9
+
1
10
  <a name="v2.76.0"></a>
2
11
  ### v2.76.0 (2021-01-21)
3
12
 
data/README.md CHANGED
@@ -116,7 +116,7 @@ Use the HAL browser to view documentation as you browse.
116
116
 
117
117
  ### To have a play around on your local machine
118
118
 
119
- * Install ruby 2.2.0 or later and bundler >= 1.12.0
119
+ * Install Ruby and Bundler (check the automated tests to find the most recent version of Ruby and Bundler that are supported)
120
120
  * Windows users: get a Rails/Ruby installer from [RailsInstaller](http://railsinstaller.org/) and run it
121
121
  * unix users just use your package manager
122
122
  * Run `git clone git@github.com:pact-foundation/pact_broker.git && cd pact_broker/example`
@@ -39,7 +39,7 @@ module PactBroker
39
39
  query_results_with_deployment_status_summary
40
40
  .deployment_status_summary
41
41
  .reasons
42
- .collect{ | reason | ReasonDecorator.new(reason).to_s }
42
+ .collect{ | reason | reason_decorator_class.new(reason).to_s }
43
43
  .join("\n")
44
44
  end
45
45
 
@@ -47,6 +47,10 @@ module PactBroker
47
47
 
48
48
  attr_reader :query_results_with_deployment_status_summary
49
49
 
50
+ def reason_decorator_class
51
+ ReasonDecorator
52
+ end
53
+
50
54
  def matrix(base_url)
51
55
  query_results_with_deployment_status_summary.rows.collect do | line |
52
56
  provider = OpenStruct.new(name: line.provider_name)
@@ -14,8 +14,8 @@ module PactBroker
14
14
  "There is no verified pact between #{reason.consumer_selector.description} and #{reason.provider_selector.description}"
15
15
  when PactBroker::Matrix::PactNotVerifiedByRequiredProviderVersion
16
16
  "There is no verified pact between #{reason.consumer_selector.description} and #{reason.provider_selector.description}"
17
- when PactBroker::Matrix::VerificationFailed
18
- "The verification between #{reason.consumer_selector.description} and #{reason.provider_selector.description} failed"
17
+ # when PactBroker::Matrix::VerificationFailed
18
+ # "The pact verification between #{reason.consumer_selector.description} and #{reason.provider_selector.description} failed"
19
19
  when PactBroker::Matrix::SpecifiedVersionDoesNotExist
20
20
  version_does_not_exist_description(reason.selector)
21
21
  when PactBroker::Matrix::VerificationFailed
@@ -5,7 +5,6 @@ require 'pact_broker/logging/default_formatter'
5
5
  require 'pact_broker/policies'
6
6
  require 'rack-protection'
7
7
  require 'rack/hal_browser'
8
- require 'rack/pact_broker/hal_browser_redirect'
9
8
  require 'rack/pact_broker/set_base_url'
10
9
  require 'rack/pact_broker/add_pact_broker_version_header'
11
10
  require 'rack/pact_broker/convert_file_extension_to_accept_header'
@@ -197,7 +196,6 @@ module PactBroker
197
196
  if configuration.use_hal_browser
198
197
  logger.info "Mounting HAL browser"
199
198
  @app_builder.use Rack::HalBrowser::Redirect
200
- @app_builder.use Rack::PactBroker::HalBrowserRedirect
201
199
  else
202
200
  logger.info "Not mounting HAL browser"
203
201
  end
@@ -218,7 +218,7 @@ module PactBroker
218
218
 
219
219
  provider_version_count = scope_for(PactBroker::Domain::Version).where(pacticipant: provider).count
220
220
 
221
- wip_pacts.collect do | pact|
221
+ verifiable_pacts = wip_pacts.collect do | pact|
222
222
  pending_tag_names = find_provider_tags_for_which_pact_publication_id_is_pending(pact, successfully_verified_head_pact_publication_ids_for_each_provider_tag)
223
223
  pre_existing_tag_names = find_provider_tag_names_that_were_first_used_before_pact_published(pact, provider_tag_collection)
224
224
 
@@ -229,6 +229,8 @@ module PactBroker
229
229
  VerifiablePact.new(pact.to_domain, selectors, true, pre_existing_pending_tags, [], true)
230
230
  end
231
231
  end.compact.sort
232
+
233
+ deduplicate_verifiable_pacts(verifiable_pacts)
232
234
  end
233
235
 
234
236
  def find_pact_versions_for_provider provider_name, tag = nil
@@ -595,6 +597,13 @@ module PactBroker
595
597
  hash[provider_tag] = head_pacts
596
598
  end
597
599
  end
600
+
601
+ def deduplicate_verifiable_pacts(verifiable_pacts)
602
+ verifiable_pacts
603
+ .group_by { | verifiable_pact | verifiable_pact.pact_version_sha }
604
+ .values
605
+ .collect { | verifiable_pacts | verifiable_pacts.reduce(&:+) }
606
+ end
598
607
  end
599
608
  end
600
609
  end
@@ -1,4 +1,5 @@
1
1
  require 'delegate'
2
+ require 'pact_broker/error'
2
3
 
3
4
  module PactBroker
4
5
  module Pacts
@@ -23,6 +24,23 @@ module PactBroker
23
24
  wip
24
25
  end
25
26
 
27
+ def + other
28
+ if pact_version_sha != other.pact_version_sha
29
+ raise PactBroker::Error.new("Can't merge two verifiable pacts with different pact content")
30
+ end
31
+
32
+ latest_pact = [self, other].sort_by(&:consumer_version_order).last.__getobj__()
33
+
34
+ VerifiablePact.new(
35
+ latest_pact,
36
+ selectors + other.selectors,
37
+ pending || other.pending,
38
+ pending_provider_tags + other.pending_provider_tags,
39
+ non_pending_provider_tags + other.non_pending_provider_tags,
40
+ wip || other.wip
41
+ )
42
+ end
43
+
26
44
  def <=> other
27
45
  if self.consumer_name != other.consumer_name
28
46
  return self.consumer_name <=> other.consumer_name
@@ -30,6 +48,10 @@ module PactBroker
30
48
  return self.consumer_version.order <=> other.consumer_version.order
31
49
  end
32
50
  end
51
+
52
+ def consumer_version_order
53
+ __getobj__().consumer_version.order
54
+ end
33
55
  end
34
56
  end
35
57
  end
@@ -52,7 +52,7 @@ module PactBroker
52
52
 
53
53
  def verification_success_true_published_true
54
54
  if pending?
55
- "This pact is no longer in pending state for #{pending_provider_tags_description}, as a successful verification result #{with_these_tags}has been published. If a verification for a version with fails in the future, it will fail the build. #{READ_MORE_PENDING}"
55
+ "This pact is no longer in pending state for #{pending_provider_tags_description}, as a successful verification result #{with_these_tags}has been published. If a verification for a version of #{provider_name} #{with_these_tags}fails in the future, it will fail the build. #{READ_MORE_PENDING}"
56
56
  end
57
57
  end
58
58
 
@@ -173,7 +173,12 @@ module PactBroker
173
173
  can_i_deploy_response = client.get("can-i-deploy", { pacticipant: pacticipant, version: version, to: to} ).tap { |response| check_for_error(response) }
174
174
  can = !!(can_i_deploy_response.body['summary'] || {})['deployable']
175
175
  puts "can-i-deploy #{pacticipant} version #{version} to #{to}: #{can ? 'yes' : 'no'}"
176
- puts (can_i_deploy_response.body['summary'] || can_i_deploy_response.body).to_yaml
176
+ summary = can_i_deploy_response.body['summary']
177
+ verification_result_urls = (can_i_deploy_response.body['matrix'] || []).collect do | row |
178
+ row.dig("verificationResult", "_links", "self", "href")
179
+ end.compact
180
+ summary.merge!("verification_result_urls" => verification_result_urls)
181
+ puts summary.to_yaml
177
182
  separate
178
183
  self
179
184
  end
@@ -1,5 +1,6 @@
1
1
  require 'pact_broker/ui/controllers/index'
2
2
  require 'pact_broker/ui/controllers/groups'
3
+ require 'pact_broker/ui/controllers/pacts'
3
4
  require 'pact_broker/ui/controllers/matrix'
4
5
  require 'pact_broker/ui/controllers/can_i_deploy'
5
6
  require 'pact_broker/ui/controllers/error_test'
@@ -47,6 +48,11 @@ module PactBroker
47
48
  run PactBroker::UI::Controllers::CanIDeploy
48
49
  end
49
50
 
51
+ map "/pacts/" do
52
+ use PathInfoFixer
53
+ run PactBroker::UI::Controllers::Pacts
54
+ end
55
+
50
56
  map "/test/error" do
51
57
  use PathInfoFixer
52
58
  run PactBroker::UI::Controllers::ErrorTest
@@ -12,7 +12,11 @@ module PactBroker
12
12
  set :dump_errors, false # The padrino logger logs these for us. If this is enabled we get duplicate logging.
13
13
 
14
14
  def base_url
15
- PactBroker.configuration.base_url || ''
15
+ # Using the X-Forwarded headers in the UI can leave the app vulnerable
16
+ # https://www.acunetix.com/blog/articles/automated-detection-of-host-header-attacks/
17
+ # Either use the explicitly configured base url or an empty string,
18
+ # rather than request.base_url, which uses the X-Forwarded headers.
19
+ env["pactbroker.base_url"] || ''
16
20
  end
17
21
  end
18
22
  end
@@ -0,0 +1,18 @@
1
+ require 'pact_broker/ui/controllers/base_controller'
2
+
3
+ module PactBroker
4
+ module UI
5
+ module Controllers
6
+ class Pacts < Base
7
+ include PactBroker::Services
8
+
9
+ get "/provider/:provider_name/consumer/:consumer_name/pact-version/:pact_version/verification-results/:number" do
10
+ url = URI.parse("#{env["pactbroker.base_url"]}/hal-browser/browser.html")
11
+ url.fragment = "#{env["pactbroker.base_url"]}#{env["SCRIPT_NAME"]}#{env["PATH_INFO"]}"
12
+ response.headers["Location"] = url.to_s
13
+ response.status = 302
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = '2.76.0'
2
+ VERSION = '2.76.1'
3
3
  end
@@ -14,7 +14,9 @@ describe "UI index" do
14
14
  get "/"
15
15
  end
16
16
 
17
- subject { get("/", params, {}); last_response }
17
+ let(:rack_env) { {} }
18
+
19
+ subject { get("/", params, rack_env) }
18
20
 
19
21
  describe "GET" do
20
22
  it "returns a success response" do
@@ -40,9 +42,7 @@ describe "UI index" do
40
42
  end
41
43
 
42
44
  context "with the base_url set" do
43
- before do
44
- allow(PactBroker.configuration).to receive(:base_url).and_return('http://example.org/pact-broker')
45
- end
45
+ let(:rack_env) { { "pactbroker.base_url" => "http://example.org/pact-broker"} }
46
46
 
47
47
  it "returns absolute links" do
48
48
  expect(subject.body).to include "href='http://example.org/pact-broker/stylesheets"
@@ -5,17 +5,17 @@ module PactBroker
5
5
  module Api
6
6
  module Decorators
7
7
  describe ReasonDecorator do
8
-
9
- REASON_CLASSES = ObjectSpace.each_object(Class).select { |klass| klass < PactBroker::Matrix::Reason }
8
+ REASON_CLASSES = ObjectSpace.each_object(Class).select { |klass| klass < PactBroker::Matrix::Reason && klass.name&.start_with?("PactBroker") }
10
9
 
11
10
  describe "the number of Reason classes" do
12
- it "is 9 - add another spec here if a new Reason is added" do
13
- expect(REASON_CLASSES.size).to eq 10
11
+ let(:expected_number_of_reason_classes) { 10 }
12
+
13
+ it "is 10 - add another spec here if a new Reason is added" do
14
+ expect(REASON_CLASSES.size).to eq expected_number_of_reason_classes
14
15
  end
15
16
  end
16
17
 
17
18
  describe "#to_s" do
18
-
19
19
  let(:consumer_selector) { double('consumer selector', description: "version 2 of Foo") }
20
20
  let(:provider_selector) { double('provider selector', description: "version 6 of Bar") }
21
21
  let(:selectors) { [consumer_selector, provider_selector] }
@@ -38,7 +38,7 @@ module PactBroker
38
38
  context "when the reason is PactBroker::Matrix::VerificationFailed" do
39
39
  let(:reason) { PactBroker::Matrix::VerificationFailed.new(*selectors) }
40
40
 
41
- its(:to_s) { is_expected.to eq "The verification between version 2 of Foo and version 6 of Bar failed" }
41
+ its(:to_s) { is_expected.to eq "The verification for the pact between version 2 of Foo and version 6 of Bar failed" }
42
42
  end
43
43
 
44
44
  context "when the reason is PactBroker::Matrix::NoDependenciesMissing" do
@@ -54,6 +54,32 @@ module PactBroker
54
54
  end
55
55
  end
56
56
 
57
+ context "when there are multiple wip pacts with the same content" do
58
+ before do
59
+ td.create_provider("bar")
60
+ .create_provider_version("333")
61
+ .create_provider_version_tag("dev")
62
+ .add_day
63
+ .create_pact_with_hierarchy("foo", "1", "bar", json_content)
64
+ .create_consumer_version_tag("feat-1")
65
+ .add_day
66
+ .create_pact_with_hierarchy("meep", "2", "bar", json_content)
67
+ .create_consumer_version_tag("feat-2")
68
+ end
69
+
70
+ let(:json_content) { { "interactions" => ["foo"] }.to_json }
71
+ let(:provider_tags) { %w[dev] }
72
+
73
+ it "de-duplicates them" do
74
+ expect(subject.size).to eq 1
75
+ end
76
+
77
+ it "merges the selectors" do
78
+ expect(subject.first.selectors.size).to eq 2
79
+ expect(subject.first.wip).to be true
80
+ end
81
+ end
82
+
57
83
  context "when the latest pact for a tag has been successfully verified by the given provider tag" do
58
84
  before do
59
85
  td.create_pact_with_hierarchy("foo", "1", "bar")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pact_broker
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.76.0
4
+ version: 2.76.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bethany Skurrie
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-01-21 00:00:00.000000000 Z
13
+ date: 2021-01-27 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: httparty
@@ -907,6 +907,7 @@ files:
907
907
  - lib/pact_broker/ui/controllers/groups.rb
908
908
  - lib/pact_broker/ui/controllers/index.rb
909
909
  - lib/pact_broker/ui/controllers/matrix.rb
910
+ - lib/pact_broker/ui/controllers/pacts.rb
910
911
  - lib/pact_broker/ui/helpers/matrix_helper.rb
911
912
  - lib/pact_broker/ui/helpers/url_helper.rb
912
913
  - lib/pact_broker/ui/view_models/clusters.rb
@@ -971,7 +972,6 @@ files:
971
972
  - lib/rack/pact_broker/convert_404_to_hal.rb
972
973
  - lib/rack/pact_broker/convert_file_extension_to_accept_header.rb
973
974
  - lib/rack/pact_broker/database_transaction.rb
974
- - lib/rack/pact_broker/hal_browser_redirect.rb
975
975
  - lib/rack/pact_broker/invalid_uri_protection.rb
976
976
  - lib/rack/pact_broker/no_auth.rb
977
977
  - lib/rack/pact_broker/request_target.rb
@@ -1383,7 +1383,6 @@ files:
1383
1383
  - spec/lib/rack/hal_browser/redirect_spec.rb
1384
1384
  - spec/lib/rack/pact_broker/add_pact_broker_version_header_spec.rb
1385
1385
  - spec/lib/rack/pact_broker/database_transaction_spec.rb
1386
- - spec/lib/rack/pact_broker/hal_browser_redirect_spec.rb
1387
1386
  - spec/lib/rack/pact_broker/invalid_uri_protection_spec.rb
1388
1387
  - spec/lib/rack/pact_broker/request_target_spec.rb
1389
1388
  - spec/lib/rack/pact_broker/use_when_spec.rb
@@ -1503,7 +1502,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1503
1502
  - !ruby/object:Gem::Version
1504
1503
  version: '0'
1505
1504
  requirements: []
1506
- rubygems_version: 3.2.6
1505
+ rubygems_version: 3.2.7
1507
1506
  signing_key:
1508
1507
  specification_version: 4
1509
1508
  summary: See description
@@ -1786,7 +1785,6 @@ test_files:
1786
1785
  - spec/lib/rack/hal_browser/redirect_spec.rb
1787
1786
  - spec/lib/rack/pact_broker/add_pact_broker_version_header_spec.rb
1788
1787
  - spec/lib/rack/pact_broker/database_transaction_spec.rb
1789
- - spec/lib/rack/pact_broker/hal_browser_redirect_spec.rb
1790
1788
  - spec/lib/rack/pact_broker/invalid_uri_protection_spec.rb
1791
1789
  - spec/lib/rack/pact_broker/request_target_spec.rb
1792
1790
  - spec/lib/rack/pact_broker/use_when_spec.rb
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'pact_broker/api/paths'
3
- require 'pact_broker/configuration'
4
-
5
- module Rack
6
- module PactBroker
7
- class HalBrowserRedirect
8
- include ::PactBroker::Api::Paths
9
-
10
- def initialize(app, options = {}, &block)
11
- @app = app
12
- end
13
-
14
- def call(env)
15
- if redirect?(env)
16
- return [303, {'Location' => hal_browser_url_from_request(env)}, []]
17
- else
18
- app.call(env)
19
- end
20
- end
21
-
22
- private
23
-
24
- attr_reader :app
25
-
26
- def redirect?(env)
27
- is_get_for_html?(env) && is_verification_results_path?(env["PATH_INFO"])
28
- end
29
-
30
- def is_get_for_html?(env)
31
- env["REQUEST_METHOD"] == "GET" && env["HTTP_ACCEPT"]&.include?("text/html")
32
- end
33
-
34
- # Doesn't support non root URLs currently
35
- def hal_browser_url_from_request(env)
36
- url = URI.parse("#{env["pactbroker.base_url"]}/hal-browser/browser.html")
37
- url.fragment = "#{env["pactbroker.base_url"]}#{env["PATH_INFO"]}"
38
- url.to_s
39
- end
40
- end
41
- end
42
- end
@@ -1,27 +0,0 @@
1
- require 'rack/pact_broker/hal_browser_redirect'
2
-
3
- module Rack
4
- module PactBroker
5
- describe HalBrowserRedirect do
6
- let(:target_app) { ->(env){ [200, {}, []] } }
7
- let(:app) { HalBrowserRedirect.new(target_app) }
8
- let(:rack_env) do
9
- {
10
- "pactbroker.base_url" => "http://base/foo",
11
- "HTTP_ACCEPT" => "text/html"
12
- }
13
- end
14
-
15
- subject { get(path, nil, rack_env) }
16
-
17
- context "when requesting verification results" do
18
- let(:path) { "/pacts/provider/Bar/consumer/Foo/pact-version/a2456ade40d0e148e23fb3310ec56831fef6ce8e/verification-results/106" }
19
-
20
- it "redirects to the HAL browser" do
21
- expect(subject.status).to eq 303
22
- expect(subject.headers["Location"]).to eq "http://base/foo/hal-browser/browser.html#http://base/foo/pacts/provider/Bar/consumer/Foo/pact-version/a2456ade40d0e148e23fb3310ec56831fef6ce8e/verification-results/106"
23
- end
24
- end
25
- end
26
- end
27
- end