pact_broker 2.108.0 → 2.109.0
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 +13 -0
- data/Gemfile +0 -2
- data/lib/pact_broker/api/decorators/publish_contract_decorator.rb +6 -1
- data/lib/pact_broker/api/decorators/webhook_decorator.rb +1 -1
- data/lib/pact_broker/api/resources/environment.rb +4 -0
- data/lib/pact_broker/api/resources/pact.rb +7 -3
- data/lib/pact_broker/api/resources/publish_contracts.rb +1 -1
- data/lib/pact_broker/app.rb +0 -5
- data/lib/pact_broker/contracts/contract_to_publish.rb +4 -5
- data/lib/pact_broker/contracts/service.rb +2 -2
- data/lib/pact_broker/logging.rb +10 -0
- data/lib/pact_broker/pacts/generate_sha.rb +9 -4
- data/lib/pact_broker/pacts/pact_params.rb +1 -1
- data/lib/pact_broker/pacts/service.rb +11 -12
- data/lib/pact_broker/test/test_data_builder.rb +7 -1
- data/lib/pact_broker/ui/controllers/base_controller.rb +4 -2
- data/lib/pact_broker/ui.rb +20 -9
- data/lib/pact_broker/version.rb +1 -1
- data/pact_broker.gemspec +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a915f7f2cb962cfc2d315338305f170cc875746ce0567826b54a8245dc06afa9
|
4
|
+
data.tar.gz: 3f2db5d2e4c1a5ece6b6b5fef712f3bbcaf85eae49856b9309632ff525d23173
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4cc5845f6611967e5a33865b05da2a214d8fa2d28762943ea4f112bab8a02163830acde551342486cb2b03690564b8a33eb3e5242afd93bc5e70249c1416ca56
|
7
|
+
data.tar.gz: 12f531f2a74c399bc48a26b7afb82e68453b35764c3f5aca5434a1fc55c9f377590508ea6ee41840547652ce240cce2dc4d244d88e4fc2b4074b8c8a8f441dfb
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
<a name="v2.109.0"></a>
|
2
|
+
### v2.109.0 (2024-02-01)
|
3
|
+
|
4
|
+
#### Features
|
5
|
+
|
6
|
+
* use SemanticLogger for Padrino (#662) ([5d9d7002](/../../commit/5d9d7002))
|
7
|
+
* improve performance of publication for very large pacts by calculating the content SHA only once per request ([a947e409](/../../commit/a947e409))
|
8
|
+
|
9
|
+
#### Bug Fixes
|
10
|
+
|
11
|
+
* pass in environment to environment policy when getting an individual environment ([5c386a43](/../../commit/5c386a43))
|
12
|
+
* Dockerfile to reduce vulnerabilities (#650) ([9aaa3484](/../../commit/9aaa3484))
|
13
|
+
|
1
14
|
<a name="v2.108.0"></a>
|
2
15
|
### v2.108.0 (2024-01-05)
|
3
16
|
|
data/Gemfile
CHANGED
@@ -2,8 +2,6 @@ source "https://rubygems.org"
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
# While https://github.com/brandonhilkert/sucker_punch/pull/253 is outstanding
|
6
|
-
gem "sucker_punch", git: "https://github.com/pact-foundation/sucker_punch.git", ref: "fix/rename-is-singleton-class-method-2"
|
7
5
|
|
8
6
|
gem "rake", "~>12.3.3"
|
9
7
|
gem "sqlite3", "~>1.3"
|
@@ -11,8 +11,13 @@ module PactBroker
|
|
11
11
|
property :provider_name
|
12
12
|
property :specification
|
13
13
|
property :content_type
|
14
|
-
property :decoded_content
|
14
|
+
property :decoded_content, setter: -> (fragment:, represented:, user_options:, **) {
|
15
|
+
represented.decoded_content = fragment
|
16
|
+
# Set the pact version sha when we set the content
|
17
|
+
represented.pact_version_sha = user_options.fetch(:sha_generator).call(fragment)
|
18
|
+
}
|
15
19
|
property :on_conflict, default: "overwrite"
|
20
|
+
|
16
21
|
end
|
17
22
|
end
|
18
23
|
end
|
@@ -71,9 +71,9 @@ module PactBroker
|
|
71
71
|
subscribe(PactBroker::Integrations::EventListener.new) do
|
72
72
|
handle_webhook_events do
|
73
73
|
if request.patch? && resource_exists?
|
74
|
-
@pact = pact_service.merge_pact(pact_params)
|
74
|
+
@pact = pact_service.merge_pact(pact_params.merge(pact_version_sha: pact_version_sha))
|
75
75
|
else
|
76
|
-
@pact = pact_service.create_or_update_pact(pact_params)
|
76
|
+
@pact = pact_service.create_or_update_pact(pact_params.merge(pact_version_sha: pact_version_sha))
|
77
77
|
end
|
78
78
|
end
|
79
79
|
end
|
@@ -114,7 +114,7 @@ module PactBroker
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def disallowed_modification?
|
117
|
-
if request.really_put? && pact_service.disallowed_modification?(pact,
|
117
|
+
if request.really_put? && pact_service.disallowed_modification?(pact, pact_version_sha)
|
118
118
|
message_params = { consumer_name: pact_params.consumer_name, consumer_version_number: pact_params.consumer_version_number, provider_name: pact_params.provider_name }
|
119
119
|
set_json_error_message(message("errors.validation.pact_content_modification_not_allowed", message_params))
|
120
120
|
true
|
@@ -126,6 +126,10 @@ module PactBroker
|
|
126
126
|
def schema
|
127
127
|
api_contract_class(:put_pact_params_contract)
|
128
128
|
end
|
129
|
+
|
130
|
+
def pact_version_sha
|
131
|
+
@pact_version_sha ||= pact_service.generate_sha(pact_params.json_content)
|
132
|
+
end
|
129
133
|
end
|
130
134
|
end
|
131
135
|
end
|
@@ -53,7 +53,7 @@ module PactBroker
|
|
53
53
|
private
|
54
54
|
|
55
55
|
def parsed_contracts
|
56
|
-
@parsed_contracts ||= decorator_class(:publish_contracts_decorator).new(PactBroker::Contracts::ContractsToPublish.new).from_hash(params)
|
56
|
+
@parsed_contracts ||= decorator_class(:publish_contracts_decorator).new(PactBroker::Contracts::ContractsToPublish.new).from_hash(params, { user_options: { sha_generator: PactBroker.configuration.sha_generator } } )
|
57
57
|
end
|
58
58
|
|
59
59
|
def params
|
data/lib/pact_broker/app.rb
CHANGED
@@ -1,8 +1,3 @@
|
|
1
|
-
# Must be defined before loading Padrino
|
2
|
-
PADRINO_LOGGER ||= {
|
3
|
-
ENV.fetch("RACK_ENV", "production").to_sym => { log_level: :error, stream: :stdout, format_datetime: "%Y-%m-%dT%H:%M:%S.000%:z" }
|
4
|
-
}
|
5
|
-
|
6
1
|
require "pact_broker/configuration"
|
7
2
|
require "pact_broker/db"
|
8
3
|
require "pact_broker/initializers/database_connection"
|
@@ -1,11 +1,10 @@
|
|
1
1
|
module PactBroker
|
2
2
|
module Contracts
|
3
|
-
ContractToPublish = Struct.new(:consumer_name, :provider_name, :decoded_content, :content_type, :specification, :on_conflict) do
|
4
|
-
|
5
|
-
def self.from_hash(
|
6
|
-
new(
|
3
|
+
ContractToPublish = Struct.new(:consumer_name, :provider_name, :decoded_content, :content_type, :specification, :on_conflict, :pact_version_sha, keyword_init: true) do
|
4
|
+
|
5
|
+
def self.from_hash(hash)
|
6
|
+
new(**hash)
|
7
7
|
end
|
8
|
-
# rubocop: enable Metrics/ParameterLists
|
9
8
|
|
10
9
|
def pact?
|
11
10
|
specification == "pact"
|
@@ -57,7 +57,7 @@ module PactBroker
|
|
57
57
|
parsed_contracts.contracts.collect do | contract_to_publish |
|
58
58
|
pact_params = create_pact_params(parsed_contracts, contract_to_publish)
|
59
59
|
existing_pact = pact_service.find_pact(pact_params)
|
60
|
-
if existing_pact && pact_service.disallowed_modification?(existing_pact, contract_to_publish.
|
60
|
+
if existing_pact && pact_service.disallowed_modification?(existing_pact, contract_to_publish.pact_version_sha)
|
61
61
|
add_pact_conflict_notice(notices, parsed_contracts, contract_to_publish, existing_pact.json_content, contract_to_publish.decoded_content)
|
62
62
|
end
|
63
63
|
end
|
@@ -134,7 +134,7 @@ module PactBroker
|
|
134
134
|
pact_params = create_pact_params(parsed_contracts, contract_to_publish)
|
135
135
|
existing_pact = pact_service.find_pact(pact_params)
|
136
136
|
listener = TriggeredWebhooksCreatedListener.new
|
137
|
-
created_pact = create_or_merge_pact(contract_to_publish.merge?, existing_pact, pact_params, listener)
|
137
|
+
created_pact = create_or_merge_pact(contract_to_publish.merge?, existing_pact, pact_params.merge(pact_version_sha: contract_to_publish.pact_version_sha), listener)
|
138
138
|
notices.concat(notices_for_pact(parsed_contracts, contract_to_publish, existing_pact, created_pact, listener, base_url))
|
139
139
|
created_pact
|
140
140
|
end
|
data/lib/pact_broker/logging.rb
CHANGED
@@ -42,6 +42,16 @@ module PactBroker
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
def measure_info(message, payload: {})
|
46
|
+
if logger.respond_to?(:measure_info)
|
47
|
+
logger.measure_info(message, payload: payload) do
|
48
|
+
yield
|
49
|
+
end
|
50
|
+
else
|
51
|
+
yield
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
45
55
|
def log_error e, description = nil
|
46
56
|
if logger.instance_of?(SemanticLogger::Logger)
|
47
57
|
if description
|
@@ -3,22 +3,27 @@ require "pact_broker/configuration"
|
|
3
3
|
require "pact_broker/pacts/sort_content"
|
4
4
|
require "pact_broker/pacts/parse"
|
5
5
|
require "pact_broker/pacts/content"
|
6
|
+
require "pact_broker/logging"
|
6
7
|
|
7
8
|
module PactBroker
|
8
9
|
module Pacts
|
9
10
|
class GenerateSha
|
11
|
+
include PactBroker::Logging
|
12
|
+
|
10
13
|
# @param [String] json_content
|
11
|
-
def self.call
|
14
|
+
def self.call(json_content, _options = {})
|
12
15
|
content_for_sha = if PactBroker.configuration.base_equality_only_on_content_that_affects_verification_results
|
13
16
|
extract_verifiable_content_for_sha(json_content)
|
14
17
|
else
|
15
18
|
json_content
|
16
19
|
end
|
17
|
-
Digest::SHA1.hexdigest(content_for_sha)
|
20
|
+
measure_info("Generating SHA1 hexdigest for pact", payload: { length: content_for_sha.length } ){ Digest::SHA1.hexdigest(content_for_sha) }
|
18
21
|
end
|
19
22
|
|
20
|
-
def self.extract_verifiable_content_for_sha
|
21
|
-
Content.from_json(json_content)
|
23
|
+
def self.extract_verifiable_content_for_sha(json_content)
|
24
|
+
objects = Content.from_json(json_content)
|
25
|
+
sorted_content = measure_info("Sorting content", payload: { length: json_content.length }){ objects.sort }
|
26
|
+
sorted_content.content_that_affects_verification_results.to_json
|
22
27
|
end
|
23
28
|
end
|
24
29
|
end
|
@@ -22,6 +22,10 @@ module PactBroker
|
|
22
22
|
extend PactBroker::Messages
|
23
23
|
extend SquashPactsForVerification
|
24
24
|
|
25
|
+
def generate_sha(json_content)
|
26
|
+
PactBroker.configuration.sha_generator.call(json_content)
|
27
|
+
end
|
28
|
+
|
25
29
|
def find_latest_pact params
|
26
30
|
pact_repository.find_latest_pact(params[:consumer_name], params[:provider_name], params[:tag], params[:branch_name])
|
27
31
|
end
|
@@ -154,10 +158,12 @@ module PactBroker
|
|
154
158
|
end
|
155
159
|
|
156
160
|
# Overwriting an existing pact with the same consumer/provider/consumer version number
|
161
|
+
# by creating a new revision (that is, a new PactPublication with an incremented revision number)
|
162
|
+
# Modifing pacts is strongly discouraged now, and support for it will be dropped in the next major version of the Pact Broker
|
157
163
|
def create_pact_revision params, existing_pact
|
158
164
|
logger.info("Updating existing pact publication", params.without(:json_content))
|
159
165
|
logger.debug("Content #{params[:json_content]}")
|
160
|
-
pact_version_sha =
|
166
|
+
pact_version_sha = params.fetch(:pact_version_sha)
|
161
167
|
json_content = add_interaction_ids(params[:json_content])
|
162
168
|
update_params = { pact_version_sha: pact_version_sha, json_content: json_content }
|
163
169
|
updated_pact = pact_repository.update(existing_pact.id, update_params)
|
@@ -178,21 +184,20 @@ module PactBroker
|
|
178
184
|
|
179
185
|
private :create_pact_revision
|
180
186
|
|
181
|
-
def disallowed_modification?(existing_pact,
|
182
|
-
!PactBroker.configuration.allow_dangerous_contract_modification && existing_pact && existing_pact.pact_version_sha !=
|
187
|
+
def disallowed_modification?(existing_pact, new_pact_version_sha)
|
188
|
+
!PactBroker.configuration.allow_dangerous_contract_modification && existing_pact && existing_pact.pact_version_sha != new_pact_version_sha
|
183
189
|
end
|
184
190
|
|
185
191
|
# When no publication for the given consumer/provider/consumer version number exists
|
186
|
-
def create_pact
|
192
|
+
def create_pact(params, version, provider)
|
187
193
|
logger.info("Creating new pact publication", params.without(:json_content))
|
188
194
|
logger.debug("Content #{params[:json_content]}")
|
189
|
-
pact_version_sha = generate_sha(params[:json_content])
|
190
195
|
json_content = add_interaction_ids(params[:json_content])
|
191
196
|
pact = pact_repository.create(
|
192
197
|
version_id: version.id,
|
193
198
|
provider_id: provider.id,
|
194
199
|
consumer_id: version.pacticipant_id,
|
195
|
-
pact_version_sha: pact_version_sha,
|
200
|
+
pact_version_sha: params.fetch(:pact_version_sha),
|
196
201
|
json_content: json_content,
|
197
202
|
version: version
|
198
203
|
)
|
@@ -212,12 +217,6 @@ module PactBroker
|
|
212
217
|
|
213
218
|
private :create_pact
|
214
219
|
|
215
|
-
def generate_sha(json_content)
|
216
|
-
PactBroker.configuration.sha_generator.call(json_content)
|
217
|
-
end
|
218
|
-
|
219
|
-
private :generate_sha
|
220
|
-
|
221
220
|
def add_interaction_ids(json_content)
|
222
221
|
Content.from_json(json_content).with_ids.to_json
|
223
222
|
end
|
@@ -256,7 +256,13 @@ module PactBroker
|
|
256
256
|
def publish_pact(consumer_name:, provider_name:, consumer_version_number: , tags: nil, branch: nil, build_url: nil, json_content: nil)
|
257
257
|
json_content = json_content || random_json_content(consumer_name, provider_name)
|
258
258
|
contracts = [
|
259
|
-
PactBroker::Contracts::ContractToPublish.from_hash(
|
259
|
+
PactBroker::Contracts::ContractToPublish.from_hash(
|
260
|
+
consumer_name: consumer_name,
|
261
|
+
provider_name: provider_name,
|
262
|
+
decoded_content: json_content,
|
263
|
+
content_type: "application/json",
|
264
|
+
specification: "pact",
|
265
|
+
pact_version_sha: PactBroker::Pacts::GenerateSha.call(json_content))
|
260
266
|
]
|
261
267
|
contracts_to_publish = PactBroker::Contracts::ContractsToPublish.from_hash(
|
262
268
|
pacticipant_name: consumer_name,
|
@@ -10,8 +10,10 @@ module PactBroker
|
|
10
10
|
using PactBroker::StringRefinements
|
11
11
|
|
12
12
|
set :root, File.join(File.dirname(__FILE__), "..")
|
13
|
-
set :show_exceptions, ENV["RACK_ENV"]
|
14
|
-
|
13
|
+
set :show_exceptions, ENV["RACK_ENV"] == "development"
|
14
|
+
# The padrino logger logs these for us, but only in production. If this is enabled we get duplicate logging.
|
15
|
+
set :dump_errors, ENV["RACK_ENV"] != "production"
|
16
|
+
set :raise_errors, ENV["RACK_ENV"] == "test"
|
15
17
|
|
16
18
|
def base_url
|
17
19
|
# Using the X-Forwarded headers in the UI can leave the app vulnerable
|
data/lib/pact_broker/ui.rb
CHANGED
@@ -1,14 +1,25 @@
|
|
1
|
-
|
1
|
+
# Must be defined before loading Padrino
|
2
2
|
# Stop Padrino creating a log file, as it will try to create it in the gems directory
|
3
3
|
# http://www.padrinorb.com/api/Padrino/Logger.html
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
# This configuration will be replaced by the SemanticLogger later on.
|
5
|
+
PADRINO_LOGGER ||= {
|
6
|
+
ENV.fetch("RACK_ENV", "production").to_sym => { stream: :stdout }
|
7
|
+
}
|
8
|
+
|
9
|
+
require "padrino-core"
|
10
|
+
|
11
|
+
class PactBrokerPadrinoLogger < SemanticLogger::Logger
|
12
|
+
include Padrino::Logger::Extensions
|
13
|
+
|
14
|
+
# Padrino expects level to return an integer, not a symbol
|
15
|
+
def level
|
16
|
+
Padrino::Logger::Levels[SemanticLogger.default_level]
|
17
|
+
end
|
12
18
|
end
|
13
19
|
|
20
|
+
Padrino.logger = PactBrokerPadrinoLogger.new("Padrino")
|
21
|
+
# Log a test message to ensure that the logger works properly, as it only
|
22
|
+
# seems to be used in production.
|
23
|
+
Padrino.logger.info("Padrino has been configured with SemanticLogger")
|
24
|
+
|
14
25
|
require "pact_broker/ui/app"
|
data/lib/pact_broker/version.rb
CHANGED
data/pact_broker.gemspec
CHANGED
@@ -64,7 +64,7 @@ Gem::Specification.new do |gem|
|
|
64
64
|
gem.add_runtime_dependency "padrino-core", ">= 0.14.3", "~> 0.14"
|
65
65
|
gem.add_runtime_dependency "sinatra", "~> 3.0"
|
66
66
|
gem.add_runtime_dependency "haml", "~>5.0"
|
67
|
-
gem.add_runtime_dependency "sucker_punch", "~>
|
67
|
+
gem.add_runtime_dependency "sucker_punch", "~>3.0"
|
68
68
|
gem.add_runtime_dependency "rack-protection", "~> 3.0"
|
69
69
|
gem.add_runtime_dependency "table_print", "~> 1.5"
|
70
70
|
gem.add_runtime_dependency "semantic_logger", "~> 4.11"
|
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.
|
4
|
+
version: 2.109.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: 2024-
|
13
|
+
date: 2024-02-05 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: json
|
@@ -258,14 +258,14 @@ dependencies:
|
|
258
258
|
requirements:
|
259
259
|
- - "~>"
|
260
260
|
- !ruby/object:Gem::Version
|
261
|
-
version: '
|
261
|
+
version: '3.0'
|
262
262
|
type: :runtime
|
263
263
|
prerelease: false
|
264
264
|
version_requirements: !ruby/object:Gem::Requirement
|
265
265
|
requirements:
|
266
266
|
- - "~>"
|
267
267
|
- !ruby/object:Gem::Version
|
268
|
-
version: '
|
268
|
+
version: '3.0'
|
269
269
|
- !ruby/object:Gem::Dependency
|
270
270
|
name: rack-protection
|
271
271
|
requirement: !ruby/object:Gem::Requirement
|
@@ -1260,7 +1260,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1260
1260
|
- !ruby/object:Gem::Version
|
1261
1261
|
version: '0'
|
1262
1262
|
requirements: []
|
1263
|
-
rubygems_version: 3.5.
|
1263
|
+
rubygems_version: 3.5.5
|
1264
1264
|
signing_key:
|
1265
1265
|
specification_version: 4
|
1266
1266
|
summary: See description
|