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 +4 -4
- data/CHANGELOG.md +20 -0
- data/Gemfile +7 -6
- data/docs/developer/business_domain_models.md +9 -0
- data/lib/pact_broker/api/decorators/provider_states_decorator.rb +19 -0
- data/lib/pact_broker/api/resources/provider_states.rb +38 -0
- data/lib/pact_broker/api.rb +5 -0
- data/lib/pact_broker/db/data_migrations/set_interactions_counts.rb +2 -0
- data/lib/pact_broker/db/migrate_data.rb +28 -16
- data/lib/pact_broker/diagnostic/app.rb +2 -2
- data/lib/pact_broker/doc/views/pact/provider-states.markdown +28 -0
- data/lib/pact_broker/matrix/matrix_row_instance_methods.rb +7 -1
- data/lib/pact_broker/pacticipants/repository.rb +4 -1
- data/lib/pact_broker/pacts/content.rb +24 -7
- data/lib/pact_broker/pacts/provider_state_service.rb +22 -0
- data/lib/pact_broker/pacts/selector.rb +4 -0
- data/lib/pact_broker/pacts/selectors.rb +4 -0
- data/lib/pact_broker/services.rb +9 -0
- data/lib/pact_broker/ui/controllers/base_controller.rb +1 -0
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/webhooks/webhook_request_template.rb +4 -3
- data/lib/pact_broker/webmachine.rb +2 -3
- data/lib/sequel/extensions/pg_advisory_lock.rb +2 -2
- data/lib/webmachine/adapters/rack3_adapter.rb +178 -0
- data/lib/webmachine/describe_routes.rb +4 -4
- data/pact_broker.gemspec +3 -6
- metadata +23 -68
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aae45f50ce42ed60ea96c782c5cea44a8c3398d28aabdb705e0941e87690f59f
|
4
|
+
data.tar.gz: a27c8cbf72dd52c2d75a7c06319029c115d4b6c284033fa5487b4e6eefe6f565
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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", "~>
|
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.
|
14
|
-
gem "rubocop-performance", "~> 1.
|
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", "~>
|
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", "
|
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
|
+

|
6
|
+
|
7
|
+

|
8
|
+
|
9
|
+

|
@@ -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
|
data/lib/pact_broker/api.rb
CHANGED
@@ -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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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/
|
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 = :
|
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)
|
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
|
38
|
-
|
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
|
-
|
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
|
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
|
124
|
-
|
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
|
data/lib/pact_broker/services.rb
CHANGED
@@ -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
|
data/lib/pact_broker/version.rb
CHANGED
@@ -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::
|
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
|
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::
|
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/
|
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 = :
|
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
|
-
|
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/
|
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::
|
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::
|
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::
|
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", "
|
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" , "
|
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", "~>
|
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.
|
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:
|
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: '
|
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: '
|
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.
|
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.
|
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:
|
188
|
+
version: 1.21.2
|
224
189
|
- - "~>"
|
225
190
|
- !ruby/object:Gem::Version
|
226
|
-
version: '
|
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: '
|
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: '
|
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
|
1273
|
-
signing_key:
|
1228
|
+
rubygems_version: 3.6.5
|
1274
1229
|
specification_version: 4
|
1275
1230
|
summary: See description
|
1276
1231
|
test_files: []
|