pact_broker 2.75.0 → 2.76.0

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: fe978e58a9f4c7e3e190b8fd5b48ce70212bac2dcc4c0ea795565a00db6127e3
4
- data.tar.gz: 551b0f07b25b75db367cb4a6d16ce114ab64b2541f1a452ab686145d3b5610ec
3
+ metadata.gz: d14eafba260b6b71dd75c725768863c0f923e167bdb37084606a0b51d110d363
4
+ data.tar.gz: 545dabeda5ede4c25508e8ca5135d94dacec61f9df1692207787bdc6e3227ec4
5
5
  SHA512:
6
- metadata.gz: 87c8c396ed8dd5aaabd184a7a65a24c7ba641d11a257bfb17d3cf497e4cc9e3e33a2a761143f3c59d511e0d42c3440ea3117f186ee179aff095d917c228dd820
7
- data.tar.gz: 5d4b9dfc5bab8f3f3671dc10011a11c925bbf2ff2edc8b3a8196c204c6bdace6bc09d8c004e3bbed438a111c202b99b01937163708da591375f8828ef02e81a4
6
+ metadata.gz: c8df83a6bf1588e8a9a96f915b0926d1a164ebd8f246d7ed831d83d43610bcbaf38875800bbd56ab792af3c9b2b6a9b2f415b6e3a581b6d8955e80248b25d67d
7
+ data.tar.gz: f1bb7162afee7913b9ac53fc523aa47d021f760350cca52758af1f626f3c440dd73bd02921254487820b1724b5a4c3e334283f728e7b279d92a69b29995de074
@@ -1,3 +1,11 @@
1
+ <a name="v2.76.0"></a>
2
+ ### v2.76.0 (2021-01-21)
3
+
4
+ #### Features
5
+
6
+ * **verification results**
7
+ * redirect requests for verification results to the HAL browser if requested in a web browser ([0f948de5](/../../commit/0f948de5))
8
+
1
9
  <a name="v2.75.0"></a>
2
10
  ### v2.75.0 (2021-01-18)
3
11
 
data/ISSUES.md CHANGED
@@ -8,16 +8,16 @@ You can use it to easily reproduce issues.
8
8
 
9
9
  To use it:
10
10
 
11
- * Run the Pact Broker using the latest development code:
11
+ * Run the Pact Broker using a specific Pact Broker Docker image by setting the required tag for the pact-broker service in the docker-compose-issue-repro-with-pact-broker-docker-image.yml file.
12
12
 
13
13
  ```
14
- docker-compose -f docker-compose-issue-repro.yml up --build pact-broker
14
+ docker-compose -f docker-compose-issue-repro-with-pact-broker-docker-image.yml up --build pact-broker
15
15
  ```
16
16
 
17
17
  * Run the reproduction script.
18
18
 
19
19
  ```
20
- docker-compose -f docker-compose-issue-repro.yml up repro-issue
20
+ docker-compose -f docker-compose-issue-repro-with-pact-broker-docker-image.yml up repro-issue
21
21
  ```
22
22
 
23
23
  You can modify `script/reproduce-issue.rb` and then re-run it with the change applied.
@@ -0,0 +1,33 @@
1
+ version: "3"
2
+
3
+ services:
4
+ postgres:
5
+ image: postgres
6
+ healthcheck:
7
+ test: psql postgres --command "select 1" -U postgres
8
+ environment:
9
+ POSTGRES_USER: postgres
10
+ POSTGRES_PASSWORD: password
11
+ POSTGRES_DB: postgres
12
+
13
+ pact-broker:
14
+ image: pactfoundation/pact-broker:2.73.0.0
15
+ ports:
16
+ - "9292:9292"
17
+ depends_on:
18
+ - postgres
19
+ environment:
20
+ PACT_BROKER_PORT: '9292'
21
+ PACT_BROKER_DATABASE_URL: "postgres://postgres:password@postgres/postgres"
22
+ PACT_BROKER_LOG_LEVEL: INFO
23
+ PACT_BROKER_SQL_LOG_LEVEL: DEBUG
24
+
25
+ repro-issue:
26
+ build: .
27
+ depends_on:
28
+ - pact-broker
29
+ command: dockerize -wait http://pact-broker:9292 -timeout 30s /home/script/reproduce-issue.rb
30
+ environment:
31
+ - PACT_BROKER_BASE_URL=http://pact-broker:9292
32
+ volumes:
33
+ - $PWD:/home
@@ -4,9 +4,14 @@ module PactBroker
4
4
  PACT_BADGE_PATH = %r{^/pacts/provider/[^/]+/consumer/.*/badge(?:\.[A-Za-z]+)?$}.freeze
5
5
  MATRIX_BADGE_PATH = %r{^/matrix/provider/[^/]+/latest/[^/]+/consumer/[^/]+/latest/[^/]+/badge(?:\.[A-Za-z]+)?$}.freeze
6
6
  CAN_I_DEPLOY_BADGE_PATH = %r{^/pacticipants/[^/]+/latest-version/[^/]+/can-i-deploy/to/[^/]+/badge(?:\.[A-Za-z]+)?$}.freeze
7
+ VERIFICATION_RESULTS = %r{^/pacts/provider/[^/]+/consumer/[^/]+/pact-version/[^/]+/verification-results/[^/]+}
7
8
 
8
9
  extend self
9
10
 
11
+ def is_verification_results_path?(path)
12
+ path.start_with?('/pacts') && (path =~ VERIFICATION_RESULTS)
13
+ end
14
+
10
15
  def is_badge_path?(path)
11
16
  # Optimise by checking include? first - regexp slow
12
17
  path.include?('/badge') && (path =~ PACT_BADGE_PATH || path =~ MATRIX_BADGE_PATH || path =~ CAN_I_DEPLOY_BADGE_PATH)
@@ -68,12 +68,12 @@ module PactBroker
68
68
  alias_method :path_info, :identifier_from_path
69
69
 
70
70
  def base_url
71
- request.env["pactbroker.base_url"] || PactBroker.configuration.base_url || request.base_uri.to_s.chomp('/')
71
+ request.env["pactbroker.base_url"] || request.base_uri.to_s.chomp('/')
72
72
  end
73
73
 
74
74
  # See comments for base_url in lib/pact_broker/doc/controllers/app.rb
75
75
  def ui_base_url
76
- request.env["pactbroker.base_url"] || PactBroker.configuration.base_url || ''
76
+ request.env["pactbroker.base_url"] || ''
77
77
  end
78
78
 
79
79
  def charsets_provided
@@ -5,6 +5,8 @@ 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
+ require 'rack/pact_broker/set_base_url'
8
10
  require 'rack/pact_broker/add_pact_broker_version_header'
9
11
  require 'rack/pact_broker/convert_file_extension_to_accept_header'
10
12
  require 'rack/pact_broker/database_transaction'
@@ -189,10 +191,13 @@ module PactBroker
189
191
  @app_builder.use Rack::Static, :urls => ["/stylesheets", "/css", "/fonts", "/js", "/javascripts", "/images"], :root => PactBroker.project_root.join("public")
190
192
  @app_builder.use Rack::Static, :urls => ["/favicon.ico"], :root => PactBroker.project_root.join("public/images"), header_rules: [[:all, {'Content-Type' => 'image/x-icon'}]]
191
193
  @app_builder.use Rack::PactBroker::ConvertFileExtensionToAcceptHeader
194
+ # Rack::PactBroker::SetBaseUrl needs to be before the Rack::PactBroker::HalBrowserRedirect
195
+ @app_builder.use Rack::PactBroker::SetBaseUrl, configuration.base_url
192
196
 
193
197
  if configuration.use_hal_browser
194
198
  logger.info "Mounting HAL browser"
195
199
  @app_builder.use Rack::HalBrowser::Redirect
200
+ @app_builder.use Rack::PactBroker::HalBrowserRedirect
196
201
  else
197
202
  logger.info "Not mounting HAL browser"
198
203
  end
@@ -51,7 +51,7 @@ module PactBroker
51
51
  # https://www.acunetix.com/blog/articles/automated-detection-of-host-header-attacks/
52
52
  # Either use the explicitly configured base url or an empty string,
53
53
  # rather than request.base_url, which uses the X-Forwarded headers.
54
- env["pactbroker.base_url"] || PactBroker.configuration.base_url || ''
54
+ env["pactbroker.base_url"] || ''
55
55
  end
56
56
  end
57
57
  end
@@ -10,7 +10,7 @@ module PactBroker
10
10
 
11
11
  attr_reader :client, :last_consumer_name, :last_provider_name, :last_consumer_version_number, :last_provider_version_number
12
12
 
13
- def initialize(pact_broker_base_url, auth)
13
+ def initialize(pact_broker_base_url, auth = {})
14
14
  @client = Faraday.new(url: pact_broker_base_url) do |faraday|
15
15
  faraday.request :json
16
16
  faraday.response :json, :content_type => /\bjson$/
@@ -42,7 +42,7 @@ module PactBroker
42
42
 
43
43
  def create_tag(pacticipant:, version:, tag:)
44
44
  puts "Creating tag '#{tag}' for #{pacticipant} version #{version}"
45
- client.put("/pacticipants/#{encode(pacticipant)}/versions/#{encode(version)}/tags/#{encode(tag)}", {}).tap { |response| check_for_error(response) }
45
+ client.put("pacticipants/#{encode(pacticipant)}/versions/#{encode(version)}/tags/#{encode(tag)}", {}).tap { |response| check_for_error(response) }
46
46
  self
47
47
  end
48
48
 
@@ -55,7 +55,7 @@ module PactBroker
55
55
 
56
56
  def create_pacticipant(name)
57
57
  puts "Creating pacticipant with name #{name}"
58
- client.post("/pacticipants", { name: name}).tap { |response| check_for_error(response) }
58
+ client.post("pacticipants", { name: name}).tap { |response| check_for_error(response) }
59
59
  separate
60
60
  self
61
61
  end
@@ -72,7 +72,7 @@ module PactBroker
72
72
 
73
73
  content = generate_content(consumer, provider, content_id)
74
74
  puts "Publishing pact for consumer #{consumer} version #{consumer_version} and provider #{provider}"
75
- pact_path = "/pacts/provider/#{encode(provider)}/consumer/#{encode(consumer)}/version/#{encode(consumer_version)}"
75
+ pact_path = "pacts/provider/#{encode(provider)}/consumer/#{encode(consumer)}/version/#{encode(consumer_version)}"
76
76
  @publish_pact_response = client.put(pact_path, content).tap { |response| check_for_error(response) }
77
77
  separate
78
78
  self
@@ -89,7 +89,7 @@ module PactBroker
89
89
  }.compact
90
90
  puts body.to_yaml
91
91
  puts ""
92
- @pacts_for_verification_response = client.post("/pacts/provider/#{encode(provider)}/for-verification", body).tap { |response| check_for_error(response) }
92
+ @pacts_for_verification_response = client.post("pacts/provider/#{encode(provider)}/for-verification", body).tap { |response| check_for_error(response) }
93
93
 
94
94
  print_pacts_for_verification
95
95
  separate
@@ -150,7 +150,7 @@ module PactBroker
150
150
  "url" => url
151
151
  }
152
152
  }
153
- path = "/webhooks/#{uuid}"
153
+ path = "webhooks/#{uuid}"
154
154
  response = client.put(path, request_body.to_json).tap { |response| check_for_error(response) }
155
155
  separate
156
156
  self
@@ -158,7 +158,7 @@ module PactBroker
158
158
 
159
159
  def delete_webhook(uuid:)
160
160
  puts "Deleting webhook with uuid #{uuid}"
161
- path = "/webhooks/#{uuid}"
161
+ path = "webhooks/#{uuid}"
162
162
  response = client.delete(path).tap { |response| check_for_error(response) }
163
163
  separate
164
164
  self
@@ -170,7 +170,7 @@ module PactBroker
170
170
  end
171
171
 
172
172
  def can_i_deploy(pacticipant:, version:, to:)
173
- can_i_deploy_response = client.get("/can-i-deploy", { pacticipant: pacticipant, version: version, to: to} ).tap { |response| check_for_error(response) }
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
176
  puts (can_i_deploy_response.body['summary'] || can_i_deploy_response.body).to_yaml
@@ -180,14 +180,14 @@ module PactBroker
180
180
 
181
181
  def delete_integration(consumer:, provider:)
182
182
  puts "Deleting all data for the integration between #{consumer} and #{provider}"
183
- client.delete("/integrations/provider/#{encode(provider)}/consumer/#{encode(consumer)}").tap { |response| check_for_error(response) }
183
+ client.delete("integrations/provider/#{encode(provider)}/consumer/#{encode(consumer)}").tap { |response| check_for_error(response) }
184
184
  separate
185
185
  self
186
186
  end
187
187
 
188
188
  def delete_pacticipant(name)
189
189
  puts "Deleting pacticipant #{name}"
190
- @publish_pact_response = client.delete("/pacticipants/#{encode(name)}").tap { |response| check_for_error(response) }
190
+ @publish_pact_response = client.delete("pacticipants/#{encode(name)}").tap { |response| check_for_error(response) }
191
191
  separate
192
192
  self
193
193
  end
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = '2.75.0'
2
+ VERSION = '2.76.0'
3
3
  end
@@ -0,0 +1,42 @@
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
@@ -0,0 +1,22 @@
1
+ module Rack
2
+ module PactBroker
3
+ class SetBaseUrl
4
+ def initialize app, base_url
5
+ @app = app
6
+ @base_url = base_url
7
+ end
8
+
9
+ def call env
10
+ if env["pactbroker.base_url"]
11
+ app.call(env)
12
+ else
13
+ app.call(env.merge("pactbroker.base_url" => base_url))
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :app, :base_url
20
+ end
21
+ end
22
+ end
@@ -1,28 +1,31 @@
1
1
  #!/usr/bin/env ruby
2
-
3
- $LOAD_PATH << "#{Dir.pwd}/lib"
4
-
5
2
  begin
6
3
 
4
+ $LOAD_PATH << "#{Dir.pwd}/lib"
7
5
  require 'pact_broker/test/http_test_data_builder'
8
6
  base_url = ENV['PACT_BROKER_BASE_URL'] || 'http://localhost:9292'
9
7
 
10
- td = PactBroker::Test::HttpTestDataBuilder.new(base_url, { })
11
- td.delete_integration(consumer: "MyConsumer", provider: "MyProvider")
12
- .create_pacticipant("MyConsumer")
13
- .create_pacticipant("MyProvider")
14
- .publish_pact(consumer: "MyConsumer", consumer_version: "1", provider: "MyProvider", content_id: "111", tag: "main")
15
- .publish_pact(consumer: "MyConsumer", consumer_version: "2", provider: "MyProvider", content_id: "222", tag: "main")
16
- .publish_pact(consumer: "MyConsumer", consumer_version: "3", provider: "MyProvider", content_id: "111", tag: "feat/a")
8
+ td = PactBroker::Test::HttpTestDataBuilder.new(base_url)
9
+ td.delete_integration(consumer: "foo-consumer", provider: "bar-provider")
10
+ .publish_pact(consumer: "foo-consumer", consumer_version: "1", provider: "bar-provider", content_id: "111", tag: "main")
17
11
  .get_pacts_for_verification(
12
+ enable_pending: true,
18
13
  provider_version_tag: "main",
19
- consumer_version_selectors: [{ tag: "main" }, { tag: "feat/a", latest: true }])
20
- .verify_pact(success: true, provider_version_tag: "main", provider_version: "2" )
21
-
14
+ include_wip_pacts_since: "2020-01-01",
15
+ consumer_version_selectors: [{ tag: "main", latest: true }])
16
+ .verify_pact(
17
+ index: 0,
18
+ provider_version_tag: "main",
19
+ provider_version: "1",
20
+ success: true
21
+ )
22
+ .can_i_deploy(pacticipant: "bar-provider", version: "1", to: "prod")
23
+ .deploy_to_prod(pacticipant: "bar-provider", version: "1")
24
+ .can_i_deploy(pacticipant: "foo-consumer", version: "1", to: "prod")
25
+ .deploy_to_prod(pacticipant: "foo-consumer", version: "1")
22
26
 
23
27
  rescue StandardError => e
24
28
  puts "#{e.class} #{e.message}"
25
29
  puts e.backtrace
26
30
  exit 1
27
31
  end
28
-
@@ -90,7 +90,6 @@ module PactBroker
90
90
  describe "base_url" do
91
91
  before do
92
92
  allow(env).to receive(:[]).with("pactbroker.base_url").and_return("http://rack")
93
- allow(PactBroker.configuration).to receive(:base_url).and_return("http://foo")
94
93
  end
95
94
 
96
95
  context "when pactbroker.base_url is set on the env" do
@@ -99,20 +98,10 @@ module PactBroker
99
98
  end
100
99
  end
101
100
 
102
- context "when PactBroker.configuration.base_url is not nil" do
101
+ context "when the rack env value is not set" do
103
102
  before do
104
103
  allow(env).to receive(:[]).with("pactbroker.base_url").and_return(nil)
105
104
  end
106
- it "returns the configured base URL" do
107
- expect(subject.base_url).to eq "http://foo"
108
- end
109
- end
110
-
111
- context "when PactBroker.configuration.base_url is nil and the rack env value is not set" do
112
- before do
113
- allow(env).to receive(:[]).with("pactbroker.base_url").and_return(nil)
114
- allow(PactBroker.configuration).to receive(:base_url).and_return(nil)
115
- end
116
105
 
117
106
  it "returns the base URL from the request" do
118
107
  expect(subject.base_url).to eq "http://example.org"
@@ -4,13 +4,13 @@ module PactBroker
4
4
  module Doc
5
5
  module Controllers
6
6
  describe App do
7
-
8
7
  describe "GET relation" do
9
8
 
10
9
  let(:app) { PactBroker::Doc::Controllers::App }
10
+ let(:rack_env) { {} }
11
11
 
12
12
  context "when the resource exists" do
13
- subject { get "/webhooks" }
13
+ subject { get "/webhooks", nil, rack_env }
14
14
 
15
15
  it "returns a 200 status" do
16
16
  subject
@@ -34,9 +34,7 @@ module PactBroker
34
34
  end
35
35
 
36
36
  context "with the base_url set" do
37
- before do
38
- allow(PactBroker.configuration).to receive(:base_url).and_return('http://example.org/pact-broker')
39
- end
37
+ let(:rack_env) { { "pactbroker.base_url" => "http://example.org/pact-broker"} }
40
38
 
41
39
  it "returns absolute links" do
42
40
  expect(subject.body).to include "href='http://example.org/pact-broker/css"
@@ -0,0 +1,27 @@
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
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.75.0
4
+ version: 2.76.0
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-20 00:00:00.000000000 Z
13
+ date: 2021-01-21 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: httparty
@@ -565,6 +565,7 @@ files:
565
565
  - db/test/change_migration_strategy/before/Gemfile
566
566
  - docker-compose-ci-mysql.yml
567
567
  - docker-compose-dev-postgres.yml
568
+ - docker-compose-issue-repro-with-pact-broker-docker-image.yml
568
569
  - docker-compose-issue-repro.yml
569
570
  - docker-compose-test.yml
570
571
  - docs/images/Pactflow logo - black small.png
@@ -970,10 +971,12 @@ files:
970
971
  - lib/rack/pact_broker/convert_404_to_hal.rb
971
972
  - lib/rack/pact_broker/convert_file_extension_to_accept_header.rb
972
973
  - lib/rack/pact_broker/database_transaction.rb
974
+ - lib/rack/pact_broker/hal_browser_redirect.rb
973
975
  - lib/rack/pact_broker/invalid_uri_protection.rb
974
976
  - lib/rack/pact_broker/no_auth.rb
975
977
  - lib/rack/pact_broker/request_target.rb
976
978
  - lib/rack/pact_broker/reset_thread_data.rb
979
+ - lib/rack/pact_broker/set_base_url.rb
977
980
  - lib/rack/pact_broker/ui_authentication.rb
978
981
  - lib/rack/pact_broker/ui_request_filter.rb
979
982
  - lib/rack/pact_broker/use_when.rb
@@ -1380,6 +1383,7 @@ files:
1380
1383
  - spec/lib/rack/hal_browser/redirect_spec.rb
1381
1384
  - spec/lib/rack/pact_broker/add_pact_broker_version_header_spec.rb
1382
1385
  - spec/lib/rack/pact_broker/database_transaction_spec.rb
1386
+ - spec/lib/rack/pact_broker/hal_browser_redirect_spec.rb
1383
1387
  - spec/lib/rack/pact_broker/invalid_uri_protection_spec.rb
1384
1388
  - spec/lib/rack/pact_broker/request_target_spec.rb
1385
1389
  - spec/lib/rack/pact_broker/use_when_spec.rb
@@ -1782,6 +1786,7 @@ test_files:
1782
1786
  - spec/lib/rack/hal_browser/redirect_spec.rb
1783
1787
  - spec/lib/rack/pact_broker/add_pact_broker_version_header_spec.rb
1784
1788
  - spec/lib/rack/pact_broker/database_transaction_spec.rb
1789
+ - spec/lib/rack/pact_broker/hal_browser_redirect_spec.rb
1785
1790
  - spec/lib/rack/pact_broker/invalid_uri_protection_spec.rb
1786
1791
  - spec/lib/rack/pact_broker/request_target_spec.rb
1787
1792
  - spec/lib/rack/pact_broker/use_when_spec.rb