pact_broker 2.112.0 → 2.113.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c7da30c01ac5c3b656df24282a63fe7d18e42d83ed7ffdda14d3919481497f39
4
- data.tar.gz: 71c525bd8ac9ed56c8d15f3f2d6c274a32c925be65e75f889d351033d759c400
3
+ metadata.gz: aae45f50ce42ed60ea96c782c5cea44a8c3398d28aabdb705e0941e87690f59f
4
+ data.tar.gz: a27c8cbf72dd52c2d75a7c06319029c115d4b6c284033fa5487b4e6eefe6f565
5
5
  SHA512:
6
- metadata.gz: 95f5eed3bcda08ad27274d0bf858ea78319455ca45f783b0cd21a3709ee1ac3a1956325713466b8f1438cda86f83f51a35cccb875c81f864d2f53b054f7c0807
7
- data.tar.gz: e51971781ce0679309cd60a8bb0eb281b2fc9a01872db91a4cd6f3f00b575805e7b5244d2b0f4d68a699140799e8cf50fca9940ddd72c77b207ca749de468fda
6
+ metadata.gz: 76ad626f57a946907f476c41a17ededfdcb27352a85196e640bbe228a49300f3a6efbc74b32576a3d76b778544c2ee8c2f3255182be90985db4a0683bc06fa34
7
+ data.tar.gz: 21aa4ec4d72413459dc670f896e5a5c2d9dfd7b3ac6635685fce9d91b1d8ee0e41d73ed4a0e46ae75a8a88eb9069267b762f110d5cb5fcd9b7c2c8aa6519b20a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ <a name="v2.113.1"></a>
2
+ ### v2.113.1 (2025-02-20)
3
+
4
+ #### Bug Fixes
5
+
6
+ * Update openapi_first and use it's coverage thing (#783) ([b3da850b](/../../commit/b3da850b))
7
+ * incorrect ProviderStates policy name. (#782) ([bddfd2d0](/../../commit/bddfd2d0))
8
+
9
+ <a name="v2.113.0"></a>
10
+ ### v2.113.0 (2025-02-13)
11
+
12
+ #### Features
13
+
14
+ * aggregated provider state endpoint (#734) ([108d11a7](/../../commit/108d11a7))
15
+ * add more logging to data migrations ([9482d44d](/../../commit/9482d44d))
16
+
17
+ #### Bug Fixes
18
+
19
+ * make sure last_action_date always returns a DateTime object ([d60c264e](/../../commit/d60c264e))
20
+
1
21
  <a name="v2.112.0"></a>
2
22
  ### v2.112.0 (2024-09-09)
3
23
 
data/Gemfile CHANGED
@@ -3,15 +3,17 @@ source "https://rubygems.org"
3
3
  gemspec
4
4
 
5
5
 
6
- gem "rake", "~>12.3.3"
6
+ gem "rake", "~>13.0"
7
7
  gem "sqlite3", ">=2.0.0"
8
8
  gem "conventional-changelog", "~>1.3"
9
9
  gem "bump", "~> 0.5"
10
+ gem "padrino-core", ">= 0.16.0.pre3", require: false
11
+ gem "rackup", "~> 2.2"
10
12
 
11
13
  group :development do
12
14
  gem "pry-byebug"
13
- gem "rubocop", "~>1.1"
14
- gem "rubocop-performance", "~> 1.11"
15
+ gem "rubocop", "~>1.7"
16
+ gem "rubocop-performance", "~> 1.23"
15
17
  gem "sequel-annotate", "~>1.3"
16
18
  gem "yard", "~> 0.9"
17
19
  end
@@ -21,18 +23,17 @@ group :test do
21
23
  gem "pact", "~>1.14"
22
24
  gem "rspec-pact-matchers", "~>0.1"
23
25
  gem "bundler-audit", "~>0.4"
24
- gem "fakefs", "~>0.4"
25
26
  gem "webmock", "~>3.9"
26
27
  gem "rspec", "~>3.0"
27
28
  gem "rspec-its", "~>1.2"
28
29
  gem "database_cleaner", "~>1.8", ">= 1.8.1"
29
30
  gem "timecop", "~> 0.9"
30
31
  gem "faraday", "~>2.0"
31
- gem "docker-api", "~>1.34"
32
+ gem "docker-api", "~>2.0"
32
33
  gem "approvals", ">=0.0.24", "<1.0.0"
33
34
  gem "tzinfo", "~>2.0"
34
35
  gem "faraday-retry", "~>2.0"
35
- gem "openapi_first", "~>0.20"
36
+ gem "openapi_first", ">= 2.3", "< 3"
36
37
  end
37
38
 
38
39
  group :pg, optional: true do
@@ -0,0 +1,9 @@
1
+ # Business Domain Models
2
+
3
+ Sorry this is so scarce. I'm in a hurry, and this is better than nothing.
4
+
5
+ ![Pact Publication](./images/domain-model-of-pact-publication.png)
6
+
7
+ ![Pact Publication with verification](./images/domain-model-of-pact-publication-with-verification.png)
8
+
9
+ ![Technically more correct but harder to understand diagram](./images/domain-model-of-pact-publication-with-verification-technically-more-correct-but-harder-to-understand.png)
@@ -0,0 +1,19 @@
1
+ require "pact_broker/api/decorators/base_decorator"
2
+
3
+ module PactBroker
4
+ module Api
5
+ module Decorators
6
+ class ProviderStateDecorator < BaseDecorator
7
+ camelize_property_names
8
+
9
+ property :name
10
+ property :params
11
+
12
+ end
13
+
14
+ class ProviderStatesDecorator < BaseDecorator
15
+ collection :providerStates, getter: -> (context) { context[:represented].sort_by(&:name) }, :extend => PactBroker::Api::Decorators::ProviderStateDecorator
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,38 @@
1
+ require "pact_broker/api/resources/base_resource"
2
+ require "pact_broker/api/decorators/provider_states_decorator"
3
+
4
+ module PactBroker
5
+ module Api
6
+ module Resources
7
+ class ProviderStates < BaseResource
8
+ def content_types_provided
9
+ [["application/hal+json", :to_json]]
10
+ end
11
+
12
+ def allowed_methods
13
+ ["GET", "OPTIONS"]
14
+ end
15
+
16
+ def resource_exists?
17
+ !!provider
18
+ end
19
+
20
+ def to_json
21
+ decorator_class(:provider_states_decorator).new(provider_states).to_json(decorator_options)
22
+ end
23
+
24
+ def policy_name
25
+ :'pacts::pact'
26
+ end
27
+
28
+ private
29
+
30
+ # attr_reader :provider_states
31
+
32
+ def provider_states
33
+ @provider_states ||= provider_state_service.list_provider_states(provider)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -44,6 +44,11 @@ module PactBroker
44
44
  add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "version", :consumer_version_number, "diff", "version", :comparison_consumer_version], Api::Resources::PactContentDiff, {resource_name: "pact_version_diff_by_consumer_version"}
45
45
  add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "pact-version", :pact_version_sha, "diff", "pact-version", :comparison_pact_version_sha], Api::Resources::PactContentDiff, {resource_name: "pact_version_diff_by_pact_version_sha"}
46
46
 
47
+ # Provider states
48
+
49
+ add ["pacts", "provider", :provider_name, "provider-states"], Api::Resources::ProviderStates, { resource_name: "provider_states" }
50
+
51
+
47
52
  # Verifications
48
53
  add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "pact-version", :pact_version_sha, "verification-results"], Api::Resources::Verifications, {resource_name: "verification_results"}
49
54
  add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "pact-version", :pact_version_sha, "metadata", :metadata, "verification-results"], Api::Resources::Verifications, {resource_name: "verification_results"}
@@ -4,6 +4,8 @@ module PactBroker
4
4
  module DB
5
5
  module DataMigrations
6
6
  class SetInteractionsCounts
7
+ # This was never included in PactBroker::DB::MigrateData::MIGRATIONS
8
+
7
9
  def self.call(connection)
8
10
  self_join = {
9
11
  Sequel[:pact_publications][:consumer_id] => Sequel[:pp2][:consumer_id],
@@ -13,23 +13,35 @@ end
13
13
  module PactBroker
14
14
  module DB
15
15
  class MigrateData
16
+ include PactBroker::Logging
17
+
18
+ MIGRATIONS = [
19
+ DataMigrations::SetPacticipantIdsForVerifications,
20
+ DataMigrations::SetConsumerIdsForPactPublications,
21
+ DataMigrations::SetLatestVersionSequenceValue,
22
+ DataMigrations::SetWebhooksEnabled,
23
+ DataMigrations::DeleteDeprecatedWebhookExecutions,
24
+ DataMigrations::SetCreatedAtForLatestPactPublications,
25
+ DataMigrations::SetCreatedAtForLatestVerifications,
26
+ DataMigrations::SetExtraColumnsForTags,
27
+ DataMigrations::SetPacticipantDisplayName,
28
+ DataMigrations::SetWebhookUuid,
29
+ DataMigrations::SetConsumerVersionOrderForPactPublications,
30
+ DataMigrations::CreateBranches,
31
+ DataMigrations::MigrateIntegrations,
32
+ DataMigrations::MigratePactVersionProviderTagSuccessfulVerifications,
33
+ DataMigrations::SetContractDataUpdatedAtForIntegrations
34
+ ].freeze
35
+
36
+ def self.registered_migrations
37
+ MIGRATIONS
38
+ end
39
+
16
40
  def self.call database_connection, _options = {}
17
- DataMigrations::SetPacticipantIdsForVerifications.call(database_connection)
18
- DataMigrations::SetConsumerIdsForPactPublications.call(database_connection)
19
- DataMigrations::SetLatestVersionSequenceValue.call(database_connection)
20
- DataMigrations::SetWebhooksEnabled.call(database_connection)
21
- DataMigrations::DeleteDeprecatedWebhookExecutions.call(database_connection)
22
- DataMigrations::SetCreatedAtForLatestPactPublications.call(database_connection)
23
- DataMigrations::SetCreatedAtForLatestVerifications.call(database_connection)
24
- DataMigrations::SetExtraColumnsForTags.call(database_connection)
25
- DataMigrations::SetPacticipantDisplayName.call(database_connection)
26
- DataMigrations::SetWebhookUuid.call(database_connection)
27
- DataMigrations::SetConsumerVersionOrderForPactPublications.call(database_connection)
28
- DataMigrations::SetExtraColumnsForTags.call(database_connection)
29
- DataMigrations::CreateBranches.call(database_connection)
30
- DataMigrations::MigrateIntegrations.call(database_connection)
31
- DataMigrations::MigratePactVersionProviderTagSuccessfulVerifications.call(database_connection)
32
- DataMigrations::SetContractDataUpdatedAtForIntegrations.call(database_connection)
41
+ registered_migrations.each do | migration |
42
+ logger.debug "Running data migration #{migration.to_s.split("::").last.gsub(/([a-z\d])([A-Z])/, '\1 \2').split.join("-")}"
43
+ migration.call(database_connection)
44
+ end
33
45
  end
34
46
  end
35
47
  end
@@ -1,6 +1,6 @@
1
1
  require "pact_broker/diagnostic/resources/heartbeat"
2
2
  require "pact_broker/diagnostic/resources/dependencies"
3
- require "webmachine/adapters/rack_mapped"
3
+ require "webmachine/adapters/rack3_adapter"
4
4
 
5
5
  module PactBroker
6
6
  module Diagnostic
@@ -27,7 +27,7 @@ module PactBroker
27
27
  end
28
28
 
29
29
  app.configure do |config|
30
- config.adapter = :RackMapped
30
+ config.adapter = :Rack3Mapped
31
31
  end
32
32
 
33
33
  app.adapter
@@ -0,0 +1,28 @@
1
+ # Provider States - Aggregated view by provider
2
+
3
+ Allowed methods: `GET`
4
+
5
+ Path: `/pacts/provider/{provider}/provider-states`
6
+
7
+ This resource returns a aggregated de-duplicated list of all provider states for a given provider.
8
+
9
+ Provider states are collected from the latest pact on the main branch for any dependant consumers.
10
+
11
+ Example response
12
+
13
+ ```json
14
+ {
15
+ "providerStates": [
16
+ {
17
+ "name": "an error occurs retrieving an alligator"
18
+ },
19
+ {
20
+ "name": "there is an alligator named Mary"
21
+ },
22
+ {
23
+ "name": "there is not an alligator named Mary"
24
+ }
25
+ ]
26
+ }
27
+ ```
28
+
@@ -129,7 +129,13 @@ module PactBroker
129
129
  end
130
130
 
131
131
  def last_action_date
132
- return_or_raise_if_not_set(:last_action_date)
132
+ date = return_or_raise_if_not_set(:last_action_date)
133
+
134
+ if date.class == String
135
+ DateTime.parse(date)
136
+ else
137
+ date
138
+ end
133
139
  end
134
140
 
135
141
  def has_verification?
@@ -37,7 +37,10 @@ module PactBroker
37
37
  end
38
38
 
39
39
  def find(options = {}, pagination_options = {}, eager_load_associations = [])
40
- query = scope_for(PactBroker::Domain::Pacticipant).select_all_qualified
40
+ query = scope_for(PactBroker::Domain::Pacticipant)
41
+ return [] if query.empty?
42
+
43
+ query = query.select_all_qualified
41
44
  query = query.filter(:name, options[:query_string]) if options[:query_string]
42
45
  query = query.label(options[:label_name]) if options[:label_name]
43
46
  query.order_ignore_case(Sequel[:pacticipants][:name]).eager(*eager_load_associations).all_with_pagination_options(pagination_options)
@@ -5,7 +5,10 @@ require "pact_broker/hash_refinements"
5
5
 
6
6
  module PactBroker
7
7
  module Pacts
8
+ ProviderState = Struct.new(:name, :params)
8
9
  class Content
10
+
11
+
9
12
  include GenerateInteractionSha
10
13
  using PactBroker::HashRefinements
11
14
 
@@ -33,9 +36,21 @@ module PactBroker
33
36
  Content.from_hash(SortContent.call(pact_hash))
34
37
  end
35
38
 
39
+ def provider_states
40
+ messages_and_or_interactions_or_empty_array.flat_map do | interaction |
41
+ if interaction["providerState"].is_a?(String)
42
+ [ProviderState.new(interaction["providerState"])]
43
+ elsif interaction["providerStates"].is_a?(Array)
44
+ interaction["providerStates"].collect do | provider_state |
45
+ ProviderState.new(provider_state["name"], provider_state["params"])
46
+ end
47
+ end
48
+ end.compact
49
+ end
50
+
36
51
  def interactions_missing_test_results
37
- return [] unless messages_or_interactions
38
- messages_or_interactions.reject do | interaction |
52
+ return [] unless messages_and_or_interactions
53
+ messages_and_or_interactions.reject do | interaction |
39
54
  interaction["tests"]&.any?
40
55
  end
41
56
  end
@@ -90,7 +105,7 @@ module PactBroker
90
105
  end
91
106
 
92
107
  def interaction_ids
93
- messages_or_interaction_or_empty_array.collect do | interaction |
108
+ messages_and_or_interactions_or_empty_array.collect do | interaction |
94
109
  interaction["_id"]
95
110
  end.compact
96
111
  end
@@ -116,12 +131,14 @@ module PactBroker
116
131
  pact_hash.is_a?(Hash) && pact_hash["interactions"].is_a?(Array) ? pact_hash["interactions"] : nil
117
132
  end
118
133
 
119
- def messages_or_interactions
120
- messages || interactions
134
+ def messages_and_or_interactions
135
+ if messages || interactions
136
+ (messages || []) + (interactions || [])
137
+ end
121
138
  end
122
139
 
123
- def messages_or_interaction_or_empty_array
124
- messages_or_interactions || []
140
+ def messages_and_or_interactions_or_empty_array
141
+ messages_and_or_interactions || []
125
142
  end
126
143
 
127
144
  def pact_specification_version
@@ -0,0 +1,22 @@
1
+ require "pact_broker/services"
2
+ require "pact_broker/pacts/selectors"
3
+ require "pact_broker/pacts/pact_publication"
4
+ require "pact_broker/repositories"
5
+
6
+
7
+ module PactBroker
8
+ module Pacts
9
+ class ProviderStateService
10
+ # extend self
11
+ extend PactBroker::Services
12
+ extend PactBroker::Repositories::Scopes
13
+
14
+ def self.list_provider_states(provider)
15
+ query = scope_for(PactPublication).eager_for_domain_with_content.for_provider_and_consumer_version_selector(provider, PactBroker::Pacts::Selector.latest_for_main_branch)
16
+ query.all.flat_map do | pact_publication |
17
+ pact_publication.to_domain.content_object.provider_states
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -155,6 +155,10 @@ module PactBroker
155
155
  new(latest: true, branch: branch)
156
156
  end
157
157
 
158
+ def self.latest_for_main_branch
159
+ new(latest: true, main_branch: true)
160
+ end
161
+
158
162
  def self.latest_for_tag_with_fallback(tag, fallback_tag)
159
163
  new(latest: true, tag: tag, fallback_tag: fallback_tag)
160
164
  end
@@ -27,6 +27,10 @@ module PactBroker
27
27
  Selectors.new([Selector.latest_for_branch(branch)])
28
28
  end
29
29
 
30
+ def self.create_for_latest_from_main_branch
31
+ Selectors.new([Selector.latest_for_main_branch])
32
+ end
33
+
30
34
  def self.create_for_overall_latest
31
35
  Selectors.new([Selector.overall_latest])
32
36
  end
@@ -93,6 +93,10 @@ module PactBroker
93
93
  get_service(:branch_service)
94
94
  end
95
95
 
96
+ def provider_state_service
97
+ get_service(:provider_state_service)
98
+ end
99
+
96
100
  # rubocop: disable Metrics/MethodLength
97
101
  def register_default_services
98
102
  register_service(:index_service) do
@@ -194,6 +198,11 @@ module PactBroker
194
198
  require "pact_broker/versions/branch_service"
195
199
  PactBroker::Versions::BranchService
196
200
  end
201
+
202
+ register_service(:provider_state_service) do
203
+ require "pact_broker/pacts/provider_state_service"
204
+ PactBroker::Pacts::ProviderStateService
205
+ end
197
206
  end
198
207
  # rubocop: enable Metrics/MethodLength
199
208
  end
@@ -1,3 +1,4 @@
1
+ require "rackup"
1
2
  require "padrino-core"
2
3
  require "haml"
3
4
  require "pact_broker/services"
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = "2.112.0"
2
+ VERSION = "2.113.1"
3
3
  end
@@ -24,7 +24,8 @@ module PactBroker
24
24
  attributes.each do | (name, value) |
25
25
  instance_variable_set("@#{name}", value) if respond_to?(name)
26
26
  end
27
- @headers = Rack::Utils::HeaderHash.new(attributes[:headers] || {})
27
+ @headers = Rack::Headers.new
28
+ @headers.merge!(attributes[:headers]) if attributes[:headers]
28
29
  end
29
30
 
30
31
  def build(template_params, user_agent: nil, disable_ssl_verification: false, cert_store: nil)
@@ -59,7 +60,7 @@ module PactBroker
59
60
  end
60
61
 
61
62
  def headers= headers
62
- @headers = Rack::Utils::HeaderHash.new(headers)
63
+ @headers.replace(headers)
63
64
  end
64
65
 
65
66
  def uses_parameter?(parameter_name)
@@ -114,7 +115,7 @@ module PactBroker
114
115
  end
115
116
 
116
117
  def build_headers(template_params)
117
- headers.each_with_object(Rack::Utils::HeaderHash.new) do | (key, value), new_headers |
118
+ headers.each_with_object(Rack::Headers.new) do | (key, value), new_headers |
118
119
  new_headers[key] = build_string(value, template_params)
119
120
  end
120
121
  end
@@ -1,10 +1,9 @@
1
1
  require "webmachine"
2
2
  require "webmachine/application_monkey_patch"
3
- require "webmachine/adapters/rack_mapped"
3
+ require "webmachine/adapters/rack3_adapter"
4
4
  require "webmachine/application_monkey_patch"
5
5
  require "webmachine/render_error_monkey_patch"
6
6
 
7
-
8
7
  module Webmachine
9
8
  def self.build_rack_api(application_context)
10
9
  api = Webmachine::Application.new do |app|
@@ -14,7 +13,7 @@ module Webmachine
14
13
  api.application_context = application_context
15
14
 
16
15
  api.configure do |config|
17
- config.adapter = :RackMapped
16
+ config.adapter = :Rack3Mapped
18
17
  end
19
18
 
20
19
  api.adapter
@@ -3,6 +3,7 @@
3
3
  # locks to be registered because different threads running the same code
4
4
  # should not cause a Sequel::Error to be raised.
5
5
  # Also, I wanted it to use Concurrent::Hash for multi-threaded environments.
6
+ # Made minor change in begin ensure block in with_advisory_lock method.
6
7
 
7
8
  require "sequel"
8
9
  require "zlib"
@@ -57,10 +58,9 @@ module Sequel
57
58
  synchronize do
58
59
  if get(Sequel.function(lock_function, *function_params))
59
60
  begin
60
- result = yield
61
+ yield
61
62
  ensure
62
63
  get(Sequel.function(UNLOCK_FUNCTION, *function_params))
63
- result
64
64
  end
65
65
  end
66
66
  end
@@ -0,0 +1,178 @@
1
+ # Taken from https://github.com/webmachine/webmachine-ruby/blob/master/lib/webmachine/adapters/rack.rb
2
+
3
+ require "webmachine/adapter"
4
+ require "rack"
5
+ require "webmachine/constants"
6
+ require "webmachine/headers"
7
+ require "webmachine/request"
8
+ require "webmachine/response"
9
+ require "webmachine/version"
10
+ require "webmachine/chunked_body"
11
+
12
+ module Webmachine
13
+ module Adapters
14
+ class Rack3 < Adapter
15
+ # Used to override default Rack server options (useful in testing)
16
+ DEFAULT_OPTIONS = {}
17
+
18
+ REQUEST_URI = "REQUEST_URI".freeze
19
+ RACK_VERSION = ::Rack::RELEASE.match(/^(\d+\.\d+)/)[1]
20
+ VERSION_STRING = "#{Webmachine::SERVER_STRING} Rack/#{RACK_VERSION}".freeze
21
+ NEWLINE = "\n".freeze
22
+
23
+ # Start the Rack adapter
24
+ def run
25
+ options = DEFAULT_OPTIONS.merge({
26
+ app: self,
27
+ Port: application.configuration.port,
28
+ Host: application.configuration.ip
29
+ }).merge(application.configuration.adapter_options)
30
+
31
+ @server = ::Rack::Server.new(options)
32
+ @server.start
33
+ end
34
+
35
+ # Handles a Rack-based request.
36
+ # @param [Hash] env the Rack environment
37
+ def call(env)
38
+ headers = Webmachine::Headers.from_cgi(env)
39
+
40
+ rack_req = ::Rack::Request.new env
41
+ request = build_webmachine_request(rack_req, headers)
42
+
43
+ response = Webmachine::Response.new
44
+ application.dispatcher.dispatch(request, response)
45
+
46
+ response.headers[SERVER] = VERSION_STRING
47
+
48
+ rack_body =
49
+ case response.body
50
+ when String # Strings are enumerable in ruby 1.8
51
+ [response.body]
52
+ else
53
+ if (io_body = IO.try_convert(response.body))
54
+ io_body
55
+ elsif response.body.respond_to?(:call)
56
+ response.body
57
+ elsif response.body.respond_to?(:each)
58
+ response.body
59
+ else
60
+ [response.body.to_s]
61
+ end
62
+ end
63
+
64
+ rack_res = ::Rack::Response.new(rack_body, response.code, response.headers)
65
+ rack_res.finish
66
+ end
67
+
68
+ protected
69
+
70
+ def routing_tokens(_rack_req)
71
+ nil # no-op for default, un-mapped rack adapter
72
+ end
73
+
74
+ def base_uri(_rack_req)
75
+ nil # no-op for default, un-mapped rack adapter
76
+ end
77
+
78
+ private
79
+
80
+ def build_webmachine_request(rack_req, headers)
81
+ RackRequest.new(rack_req.request_method,
82
+ rack_req.url,
83
+ headers,
84
+ RequestBody.new(rack_req),
85
+ routing_tokens(rack_req),
86
+ base_uri(rack_req),
87
+ rack_req.env)
88
+ end
89
+
90
+ class RackRequest < Webmachine::Request
91
+ attr_reader :env
92
+
93
+ # Yeah, Rubocop, piss off!
94
+ # rubocop:disable ParameterLists
95
+ def initialize(method, uri, headers, body, routing_tokens, base_uri, env)
96
+ super(method, uri, headers, body, routing_tokens, base_uri)
97
+ @env = env
98
+ end
99
+ end
100
+
101
+ # Wraps the Rack input so it can be treated like a String or
102
+ # Enumerable.
103
+ # @api private
104
+ class RequestBody
105
+ # @param [Rack::Request] request the Rack request
106
+ def initialize(request)
107
+ @request = request
108
+ end
109
+
110
+ # Rack Servers differ in the way you can access their request bodys.
111
+ # While some allow you to directly get a Ruby IO object others don't.
112
+ # You have to check the methods they expose, like #gets, #read, #each, #rewind and maybe others.
113
+ # See: https://github.com/rack/rack/blob/rack-1.5/lib/rack/lint.rb#L296
114
+ # @return [IO] the request body
115
+ def to_io
116
+ @request.body
117
+ end
118
+
119
+ # Converts the body to a String so you can work with the entire
120
+ # thing.
121
+ # @return [String] the request body as a string
122
+ def to_s
123
+ if @value
124
+ @value.join
125
+ elsif @request.body.respond_to?(:to_ary)
126
+ @request.body.to_ary.join
127
+ elsif @request.body.respond_to?(:read)
128
+ @request.body.rewind if @request.body.respond_to?(:rewind)
129
+ @request.body.read
130
+ else
131
+ @request.body&.to_s || ""
132
+ end
133
+ end
134
+
135
+ # Iterates over the body in chunks. If the body has previously
136
+ # been read, this method can be called again and get the same
137
+ # sequence of chunks.
138
+ # @yield [chunk]
139
+ # @yieldparam [String] chunk a chunk of the request body
140
+ def each
141
+ if @value
142
+ @value.each { |chunk| yield chunk }
143
+ elsif @request.body.respond_to?(:each)
144
+ @value = []
145
+ @request.body.each { |chunk|
146
+ @value << chunk
147
+ yield chunk
148
+ }
149
+ elsif @request.body.respond_to?(:to_ary)
150
+ @value = @request.body.to_ary
151
+ @value.each { |chunk| yield chunk }
152
+ else
153
+ yield @request.body
154
+ end
155
+ end
156
+ end # class RequestBody
157
+ end # class Rack
158
+
159
+ class Rack3Mapped < Rack3
160
+ protected
161
+
162
+ def routing_tokens(rack_req)
163
+ routing_match = rack_req.path_info.match(Webmachine::Request::ROUTING_PATH_MATCH)
164
+ routing_path = routing_match ? routing_match[1] : ""
165
+ routing_path.split(SLASH)
166
+ end
167
+
168
+ def base_uri(rack_req)
169
+ # rack SCRIPT_NAME env var doesn't end with "/". This causes weird
170
+ # behavour when URI.join concatenates URI components in
171
+ # Webmachine::Decision::Flow#n11
172
+ script_name = rack_req.script_name + SLASH
173
+ URI.join(rack_req.base_url, script_name)
174
+ end
175
+ end # class RackMapped
176
+
177
+ end # module Adapters
178
+ end # module Webmachine
@@ -1,4 +1,4 @@
1
- require "webmachine/adapters/rack_mapped"
1
+ require "webmachine/adapters/rack3_adapter"
2
2
  require "pact_broker/string_refinements"
3
3
 
4
4
  # Code to describe the routes in a Webmachine API, including
@@ -44,11 +44,11 @@ module Webmachine
44
44
  }.merge(path_params)
45
45
 
46
46
  rack_req = ::Rack::Request.new({ "REQUEST_METHOD" => "GET", "rack.input" => StringIO.new("") }.merge(env) )
47
- request = Webmachine::Adapters::Rack::RackRequest.new(
47
+ request = Webmachine::Adapters::Rack3::RackRequest.new(
48
48
  rack_req.env["REQUEST_METHOD"],
49
49
  path,
50
50
  Webmachine::Headers.from_cgi({"HTTP_HOST" => "example.org"}.merge(env)),
51
- Webmachine::Adapters::Rack::RequestBody.new(rack_req),
51
+ Webmachine::Adapters::Rack3::RequestBody.new(rack_req),
52
52
  {},
53
53
  {},
54
54
  rack_req.env
@@ -134,7 +134,7 @@ module Webmachine
134
134
  end
135
135
 
136
136
  def self.build_request(http_method: "GET", path_info: )
137
- request = Webmachine::Adapters::Rack::RackRequest.new(http_method, "/", Webmachine::Headers["host" => "example.org"], nil, {}, {}, { "REQUEST_METHOD" => http_method })
137
+ request = Webmachine::Adapters::Rack3::RackRequest.new(http_method, "/", Webmachine::Headers["host" => "example.org"], nil, {}, {}, { "REQUEST_METHOD" => http_method })
138
138
  request.path_info = path_info
139
139
  request
140
140
  end
data/pact_broker.gemspec CHANGED
@@ -56,16 +56,13 @@ Gem::Specification.new do |gem|
56
56
  gem.add_runtime_dependency "reform", "~> 2.6"
57
57
  gem.add_runtime_dependency "sequel", "~> 5.28"
58
58
  gem.add_runtime_dependency "webmachine", ">= 2.0.0.beta", "< 3.0"
59
- gem.add_runtime_dependency "webrick", "~> 1.8" # webmachine requires webrick, but doesn't declare it as a dependency :shrug:
60
59
  gem.add_runtime_dependency "semver2", "~> 3.4.2"
61
- gem.add_runtime_dependency "rack", ">= 2.2.3", "~> 2.2" # TODO update to 3
60
+ gem.add_runtime_dependency "rack", "~> 3.1", ">= 3.1.10"
62
61
  gem.add_runtime_dependency "redcarpet", ">= 3.5.1", "~>3.5"
63
- gem.add_runtime_dependency "pact-support" , "~> 1.16", ">= 1.16.4"
64
- gem.add_runtime_dependency "padrino-core", ">= 0.14.3", "~> 0.14"
65
- gem.add_runtime_dependency "sinatra", "~> 3.0"
62
+ gem.add_runtime_dependency "pact-support" , ">= 1.21.2", "~> 1.21"
66
63
  gem.add_runtime_dependency "haml", "~>5.0"
67
64
  gem.add_runtime_dependency "sucker_punch", "~>3.0"
68
- gem.add_runtime_dependency "rack-protection", "~> 3.0"
65
+ gem.add_runtime_dependency "rack-protection", "~> 4.1"
69
66
  gem.add_runtime_dependency "table_print", "~> 1.5"
70
67
  gem.add_runtime_dependency "semantic_logger", "~> 4.11"
71
68
  gem.add_runtime_dependency "sanitize", "~> 6.0"
metadata CHANGED
@@ -1,16 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pact_broker
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.112.0
4
+ version: 2.113.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bethany Skurrie
8
8
  - Sergei Matheson
9
9
  - Warner Godfrey
10
- autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
- date: 2024-09-17 00:00:00.000000000 Z
12
+ date: 2025-03-04 00:00:00.000000000 Z
14
13
  dependencies:
15
14
  - !ruby/object:Gem::Dependency
16
15
  name: json
@@ -116,20 +115,6 @@ dependencies:
116
115
  - - "<"
117
116
  - !ruby/object:Gem::Version
118
117
  version: '3.0'
119
- - !ruby/object:Gem::Dependency
120
- name: webrick
121
- requirement: !ruby/object:Gem::Requirement
122
- requirements:
123
- - - "~>"
124
- - !ruby/object:Gem::Version
125
- version: '1.8'
126
- type: :runtime
127
- prerelease: false
128
- version_requirements: !ruby/object:Gem::Requirement
129
- requirements:
130
- - - "~>"
131
- - !ruby/object:Gem::Version
132
- version: '1.8'
133
118
  - !ruby/object:Gem::Dependency
134
119
  name: semver2
135
120
  requirement: !ruby/object:Gem::Requirement
@@ -148,22 +133,22 @@ dependencies:
148
133
  name: rack
149
134
  requirement: !ruby/object:Gem::Requirement
150
135
  requirements:
151
- - - ">="
152
- - !ruby/object:Gem::Version
153
- version: 2.2.3
154
136
  - - "~>"
155
137
  - !ruby/object:Gem::Version
156
- version: '2.2'
138
+ version: '3.1'
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: 3.1.10
157
142
  type: :runtime
158
143
  prerelease: false
159
144
  version_requirements: !ruby/object:Gem::Requirement
160
145
  requirements:
161
- - - ">="
162
- - !ruby/object:Gem::Version
163
- version: 2.2.3
164
146
  - - "~>"
165
147
  - !ruby/object:Gem::Version
166
- version: '2.2'
148
+ version: '3.1'
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: 3.1.10
167
152
  - !ruby/object:Gem::Dependency
168
153
  name: redcarpet
169
154
  requirement: !ruby/object:Gem::Requirement
@@ -188,56 +173,22 @@ dependencies:
188
173
  name: pact-support
189
174
  requirement: !ruby/object:Gem::Requirement
190
175
  requirements:
191
- - - "~>"
192
- - !ruby/object:Gem::Version
193
- version: '1.16'
194
176
  - - ">="
195
177
  - !ruby/object:Gem::Version
196
- version: 1.16.4
197
- type: :runtime
198
- prerelease: false
199
- version_requirements: !ruby/object:Gem::Requirement
200
- requirements:
178
+ version: 1.21.2
201
179
  - - "~>"
202
180
  - !ruby/object:Gem::Version
203
- version: '1.16'
204
- - - ">="
205
- - !ruby/object:Gem::Version
206
- version: 1.16.4
207
- - !ruby/object:Gem::Dependency
208
- name: padrino-core
209
- requirement: !ruby/object:Gem::Requirement
210
- requirements:
211
- - - ">="
212
- - !ruby/object:Gem::Version
213
- version: 0.14.3
214
- - - "~>"
215
- - !ruby/object:Gem::Version
216
- version: '0.14'
181
+ version: '1.21'
217
182
  type: :runtime
218
183
  prerelease: false
219
184
  version_requirements: !ruby/object:Gem::Requirement
220
185
  requirements:
221
186
  - - ">="
222
187
  - !ruby/object:Gem::Version
223
- version: 0.14.3
188
+ version: 1.21.2
224
189
  - - "~>"
225
190
  - !ruby/object:Gem::Version
226
- version: '0.14'
227
- - !ruby/object:Gem::Dependency
228
- name: sinatra
229
- requirement: !ruby/object:Gem::Requirement
230
- requirements:
231
- - - "~>"
232
- - !ruby/object:Gem::Version
233
- version: '3.0'
234
- type: :runtime
235
- prerelease: false
236
- version_requirements: !ruby/object:Gem::Requirement
237
- requirements:
238
- - - "~>"
239
- - !ruby/object:Gem::Version
240
- version: '3.0'
191
+ version: '1.21'
241
192
  - !ruby/object:Gem::Dependency
242
193
  name: haml
243
194
  requirement: !ruby/object:Gem::Requirement
@@ -272,14 +223,14 @@ dependencies:
272
223
  requirements:
273
224
  - - "~>"
274
225
  - !ruby/object:Gem::Version
275
- version: '3.0'
226
+ version: '4.1'
276
227
  type: :runtime
277
228
  prerelease: false
278
229
  version_requirements: !ruby/object:Gem::Requirement
279
230
  requirements:
280
231
  - - "~>"
281
232
  - !ruby/object:Gem::Version
282
- version: '3.0'
233
+ version: '4.1'
283
234
  - !ruby/object:Gem::Dependency
284
235
  name: table_print
285
236
  requirement: !ruby/object:Gem::Requirement
@@ -582,6 +533,7 @@ files:
582
533
  - docs/api/PACTICIPANTS.md
583
534
  - docs/api/PAGINATION.md
584
535
  - docs/api/WEBHOOKS.md
536
+ - docs/developer/business_domain_models.md
585
537
  - docs/developer/design_pattern_for_eager_loading_collections.md
586
538
  - docs/developer/matrix.md
587
539
  - docs/developer/rack.md
@@ -672,6 +624,7 @@ files:
672
624
  - lib/pact_broker/api/decorators/pacts_for_verification_query_decorator.rb
673
625
  - lib/pact_broker/api/decorators/pagination_links.rb
674
626
  - lib/pact_broker/api/decorators/provider_pacts_decorator.rb
627
+ - lib/pact_broker/api/decorators/provider_states_decorator.rb
675
628
  - lib/pact_broker/api/decorators/publish_contract_decorator.rb
676
629
  - lib/pact_broker/api/decorators/publish_contracts_decorator.rb
677
630
  - lib/pact_broker/api/decorators/publish_contracts_results_decorator.rb
@@ -774,6 +727,7 @@ files:
774
727
  - lib/pact_broker/api/resources/previous_distinct_pact_version.rb
775
728
  - lib/pact_broker/api/resources/provider_pacts.rb
776
729
  - lib/pact_broker/api/resources/provider_pacts_for_verification.rb
730
+ - lib/pact_broker/api/resources/provider_states.rb
777
731
  - lib/pact_broker/api/resources/publish_contracts.rb
778
732
  - lib/pact_broker/api/resources/relationships.rb
779
733
  - lib/pact_broker/api/resources/released_version.rb
@@ -899,6 +853,7 @@ files:
899
853
  - lib/pact_broker/doc/views/pact/latest-pact-version.markdown
900
854
  - lib/pact_broker/doc/views/pact/matrix-for-consumer-version.markdown
901
855
  - lib/pact_broker/doc/views/pact/pact-webhooks.markdown
856
+ - lib/pact_broker/doc/views/pact/provider-states.markdown
902
857
  - lib/pact_broker/doc/views/pact/publish-verification-results.markdown
903
858
  - lib/pact_broker/doc/views/pact/tag-prod-version.markdown
904
859
  - lib/pact_broker/doc/views/pact/tag-version.markdown
@@ -1000,6 +955,7 @@ files:
1000
955
  - lib/pact_broker/pacts/pacts_for_verification_repository.rb
1001
956
  - lib/pact_broker/pacts/parse.rb
1002
957
  - lib/pact_broker/pacts/placeholder_pact.rb
958
+ - lib/pact_broker/pacts/provider_state_service.rb
1003
959
  - lib/pact_broker/pacts/repository.rb
1004
960
  - lib/pact_broker/pacts/selected_pact.rb
1005
961
  - lib/pact_broker/pacts/selector.rb
@@ -1137,6 +1093,7 @@ files:
1137
1093
  - lib/sequel/plugins/age.rb
1138
1094
  - lib/sequel/plugins/insert_ignore.rb
1139
1095
  - lib/sequel/plugins/upsert.rb
1096
+ - lib/webmachine/adapters/rack3_adapter.rb
1140
1097
  - lib/webmachine/application_monkey_patch.rb
1141
1098
  - lib/webmachine/describe_routes.rb
1142
1099
  - lib/webmachine/render_error_monkey_patch.rb
@@ -1254,7 +1211,6 @@ homepage: https://github.com/pact-foundation/pact_broker
1254
1211
  licenses:
1255
1212
  - MIT
1256
1213
  metadata: {}
1257
- post_install_message:
1258
1214
  rdoc_options: []
1259
1215
  require_paths:
1260
1216
  - lib
@@ -1269,8 +1225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1269
1225
  - !ruby/object:Gem::Version
1270
1226
  version: '0'
1271
1227
  requirements: []
1272
- rubygems_version: 3.5.18
1273
- signing_key:
1228
+ rubygems_version: 3.6.5
1274
1229
  specification_version: 4
1275
1230
  summary: See description
1276
1231
  test_files: []