pact_broker 2.108.0 → 2.109.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/Gemfile +0 -2
- data/README.md +1 -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/locale/en.yml +1 -1
- data/lib/pact_broker/logging.rb +10 -0
- data/lib/pact_broker/matrix/matrix_row.rb +0 -1
- data/lib/pact_broker/matrix/resolved_selector.rb +0 -1
- 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/pact_publication_dataset_module.rb +1 -0
- data/lib/pact_broker/pacts/pact_publication_wip_dataset_module.rb +59 -79
- data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +1 -0
- 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/lib/pact_broker/versions/branch_service.rb +1 -0
- 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: a4c49978b4312049fd2e394ce46bcf90f64125ff50556f9bb01f9610e1310546
|
4
|
+
data.tar.gz: 43f24ab98f5ce7bd757a52a085d653668d83395b6889921e8dc0d4aac5982b73
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3211f2cc4b2e9fbae7dd8a07bd1c49dc9d672fa46f6f4c83b6652b2266dc9498d4858a9a7714f91b09914d872e522affc5e96753cf3317e39228fecc620404c1
|
7
|
+
data.tar.gz: 36a5bc3f3ecc827cd6e24fa21b4d4bc9f943ec75bfdb3db8cdcdd1399533739bf0a2c15c68df816ae995fa58987fa43d4da45dcb72a2d68fff12f7594a69906a
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,24 @@
|
|
1
|
+
<a name="v2.109.1"></a>
|
2
|
+
### v2.109.1 (2024-02-21)
|
3
|
+
|
4
|
+
#### Bug Fixes
|
5
|
+
|
6
|
+
* improve performance for 'pacts for verification' queries ([299a6abe](/../../commit/299a6abe))
|
7
|
+
* correct spelling in message when pact is modified ([ae62ae7a](/../../commit/ae62ae7a))
|
8
|
+
|
9
|
+
<a name="v2.109.0"></a>
|
10
|
+
### v2.109.0 (2024-02-01)
|
11
|
+
|
12
|
+
#### Features
|
13
|
+
|
14
|
+
* use SemanticLogger for Padrino (#662) ([5d9d7002](/../../commit/5d9d7002))
|
15
|
+
* improve performance of publication for very large pacts by calculating the content SHA only once per request ([a947e409](/../../commit/a947e409))
|
16
|
+
|
17
|
+
#### Bug Fixes
|
18
|
+
|
19
|
+
* pass in environment to environment policy when getting an individual environment ([5c386a43](/../../commit/5c386a43))
|
20
|
+
* Dockerfile to reduce vulnerabilities (#650) ([9aaa3484](/../../commit/9aaa3484))
|
21
|
+
|
1
22
|
<a name="v2.108.0"></a>
|
2
23
|
### v2.108.0 (2024-01-05)
|
3
24
|
|
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"
|
data/README.md
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/pact_broker.svg)](http://badge.fury.io/rb/pact_broker)
|
3
3
|
![Build status](https://github.com/pact-foundation/pact_broker/workflows/Test/badge.svg)
|
4
4
|
[![Join the chat at https://pact-foundation.slack.com/](https://img.shields.io/badge/chat-on%20slack-blue.svg?logo=slack)](https://slack.pact.io)
|
5
|
-
[![security](https://hakiri.io/github/pact-foundation/pact_broker/master.svg)](https://hakiri.io/github/pact-foundation/pact_broker/master)
|
6
5
|
|
7
6
|
The Pact Broker is an application for sharing of consumer driven contracts and verification results. It is optimised for use with "pacts" (contracts created by the [Pact][pact-docs] framework), but can be used for any type of contract that can be serialized to JSON.
|
8
7
|
|
@@ -151,7 +150,7 @@ You can use the [Pact Broker Docker image][docker] or [Terraform on AWS][terrafo
|
|
151
150
|
|
152
151
|
* Are you sure you don't just want to use the [Pact Broker Docker image][docker]? No Docker at your company yet? Ah well, keep reading.
|
153
152
|
* Create a PostgreSQL database.
|
154
|
-
* To ensure you're on a supported version of the database that you choose, check the [
|
153
|
+
* To ensure you're on a supported version of the database that you choose, check the [.github/workflows/test.yml](.github/workflows/test.yml) file to see which versions we're currently running our tests against.
|
155
154
|
* MySQL was supported for the native Ruby application until around 2021, but the official `pactfoundation/pact-broker` Docker image does not support it. New features will not be optimised for MySQL, and some new features may not even be supported on it (eg. the database clean feature).
|
156
155
|
* You'll find a sample database creation script in the [example/config.ru](https://github.com/pact-foundation/pact_broker/blob/master/example/config.ru).
|
157
156
|
* Install ruby 2.7 and the latest version of bundler (if you've come this far, I'm assuming you know how to do both of these. Did I mention there was a [Docker][docker] image?)
|
@@ -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
|
@@ -50,7 +50,7 @@ en:
|
|
50
50
|
contract:
|
51
51
|
pact_published: Pact successfully published for %{consumer_name} version %{consumer_version_number} and provider %{provider_name}.
|
52
52
|
same_pact_content_published: Pact successfully republished for %{consumer_name} version %{consumer_version_number} and provider %{provider_name} with no content changes.
|
53
|
-
pact_modified_for_same_version: Pact with changed content published over existing content for %{consumer_name} version %{consumer_version_number} and provider %{provider_name}. This is not recommended in normal
|
53
|
+
pact_modified_for_same_version: Pact with changed content published over existing content for %{consumer_name} version %{consumer_version_number} and provider %{provider_name}. This is not recommended in normal circumstances and may indicate that you have not configured your Pact pipeline correctly. For more information see https://docs.pact.io/go/versioning
|
54
54
|
pact_merged: Pact content merged with existing content for %{consumer_name} version %{consumer_version_number} and provider %{provider_name}.
|
55
55
|
events:
|
56
56
|
pact_published_unchanged_with_single_tag: pact content is the same as previous version with tag %{tag_name} and no new tags were applied
|
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
|
@@ -1,35 +1,76 @@
|
|
1
1
|
module PactBroker
|
2
2
|
module Pacts
|
3
3
|
module PactPublicationWipDatasetModule
|
4
|
+
|
5
|
+
# Use a cut down model of the verifications table just for the WIP calculations.
|
6
|
+
# Don't need all the associations and normal domain methods.
|
7
|
+
class VerificationForWipCalculations < Sequel::Model(:verifications)
|
8
|
+
dataset_module do
|
9
|
+
def successful_non_wip_by_provider(provider_id)
|
10
|
+
distinct.where(success: true, wip: false, provider_id: provider_id)
|
11
|
+
end
|
12
|
+
|
13
|
+
def verified_before_creation_date_of(record)
|
14
|
+
if record
|
15
|
+
verified_before_date(record.created_at)
|
16
|
+
else
|
17
|
+
self
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def join_branch_versions_excluding_branch(provider_id, branch_name)
|
22
|
+
branch_versions_join = {
|
23
|
+
Sequel[:verifications][:provider_version_id] => Sequel[:branch_versions][:version_id],
|
24
|
+
Sequel[:branch_versions][:pacticipant_id] => provider_id
|
25
|
+
}
|
26
|
+
join(:branch_versions, branch_versions_join) do
|
27
|
+
Sequel.lit("branch_versions.branch_name != ?", branch_name)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def join_provider_versions_for_provider_id_and_branch(provider_id, provider_version_branch)
|
32
|
+
branch_versions_join = {
|
33
|
+
Sequel[:verifications][:provider_version_id] => Sequel[:branch_versions][:version_id],
|
34
|
+
Sequel[:branch_versions][:pacticipant_id] => provider_id,
|
35
|
+
Sequel[:branch_versions][:branch_name] => provider_version_branch
|
36
|
+
}
|
37
|
+
|
38
|
+
join(:branch_versions, branch_versions_join)
|
39
|
+
end
|
40
|
+
|
41
|
+
def verified_before_date(date)
|
42
|
+
where { Sequel[:verifications][:execution_date] < date }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
4
47
|
def successfully_verified_by_provider_branch_when_not_wip(provider_id, provider_version_branch)
|
48
|
+
successful_verifications = VerificationForWipCalculations
|
49
|
+
.select(:pact_version_id)
|
50
|
+
.distinct
|
51
|
+
.successful_non_wip_by_provider(provider_id)
|
52
|
+
.join_provider_versions_for_provider_id_and_branch(provider_id, provider_version_branch)
|
53
|
+
|
54
|
+
|
5
55
|
from_self(alias: :pp)
|
6
56
|
.select(Sequel[:pp].*)
|
7
|
-
.where(Sequel[:pp][:provider_id] => provider_id)
|
8
|
-
.join_successful_non_wip_verifications_for_provider_id(provider_id)
|
9
|
-
.join_provider_versions_for_provider_id_and_branch(provider_id, provider_version_branch)
|
10
57
|
.distinct
|
58
|
+
.join(successful_verifications, { Sequel[:pp][:pact_version_id] => Sequel[:v][:pact_version_id] }, { table_alias: :v })
|
11
59
|
end
|
12
60
|
|
13
61
|
def successfully_verified_by_provider_another_branch_before_this_branch_first_created(provider_id, provider_version_branch)
|
14
62
|
first_version_for_branch = PactBroker::Domain::Version.first_for_pacticipant_id_and_branch(provider_id, provider_version_branch)
|
15
63
|
|
64
|
+
successful_verifications = VerificationForWipCalculations
|
65
|
+
.select(:pact_version_id)
|
66
|
+
.distinct
|
67
|
+
.successful_non_wip_by_provider(provider_id)
|
68
|
+
.join_branch_versions_excluding_branch(provider_id, provider_version_branch)
|
69
|
+
.verified_before_creation_date_of(first_version_for_branch)
|
70
|
+
|
16
71
|
from_self(alias: :pp)
|
17
72
|
.select(Sequel[:pp].*)
|
18
|
-
.
|
19
|
-
.join_provider_versions_for_provider_id(provider_id)
|
20
|
-
.join_branch_versions_excluding_branch(provider_version_branch)
|
21
|
-
.where(Sequel[:pp][:provider_id] => provider_id)
|
22
|
-
.verified_before_creation_date_of(first_version_for_branch)
|
23
|
-
.distinct
|
24
|
-
end
|
25
|
-
|
26
|
-
def join_branch_versions_excluding_branch(branch_name)
|
27
|
-
branch_versions_join = {
|
28
|
-
Sequel[:provider_versions][:id] => Sequel[:branch_versions][:version_id]
|
29
|
-
}
|
30
|
-
join(:branch_versions, branch_versions_join) do
|
31
|
-
Sequel.lit("branch_versions.branch_name != ?", branch_name)
|
32
|
-
end
|
73
|
+
.join(successful_verifications, { Sequel[:pp][:pact_version_id] => Sequel[:v][:pact_version_id] }, { table_alias: :v })
|
33
74
|
end
|
34
75
|
|
35
76
|
def successfully_verified_by_provider_tag_when_not_wip(provider_tag)
|
@@ -43,7 +84,6 @@ module PactBroker
|
|
43
84
|
.select(Sequel[:pp].*)
|
44
85
|
.join(:pact_version_provider_tag_successful_verifications, pact_version_provider_tag_verifications_join, { table_alias: :sv })
|
45
86
|
.distinct
|
46
|
-
|
47
87
|
end
|
48
88
|
|
49
89
|
def successfully_verified_by_provider_another_tag_before_this_tag_first_created(provider_id, provider_tag)
|
@@ -71,66 +111,6 @@ module PactBroker
|
|
71
111
|
end
|
72
112
|
.distinct
|
73
113
|
end
|
74
|
-
|
75
|
-
protected
|
76
|
-
|
77
|
-
def verified_before_date(date)
|
78
|
-
where { Sequel[:verifications][:execution_date] < date }
|
79
|
-
end
|
80
|
-
|
81
|
-
def join_successful_non_wip_verifications_for_provider_id(provider_id, &block)
|
82
|
-
verifications_join = {
|
83
|
-
pact_version_id: :pact_version_id,
|
84
|
-
Sequel[:verifications][:success] => true,
|
85
|
-
Sequel[:verifications][:wip] => false,
|
86
|
-
Sequel[:verifications][:provider_id] => provider_id
|
87
|
-
}
|
88
|
-
join(:verifications, verifications_join, {}, &block)
|
89
|
-
end
|
90
|
-
|
91
|
-
def join_provider_version_tags &block
|
92
|
-
tags_join = {
|
93
|
-
Sequel[:verifications][:provider_version_id] => Sequel[:provider_tags][:version_id],
|
94
|
-
}
|
95
|
-
join(:tags, tags_join, { table_alias: :provider_tags }, &block)
|
96
|
-
end
|
97
|
-
|
98
|
-
def join_provider_version_tags_for_tag(tag)
|
99
|
-
tags_join = {
|
100
|
-
Sequel[:verifications][:provider_version_id] => Sequel[:provider_tags][:version_id],
|
101
|
-
Sequel[:provider_tags][:name] => tag
|
102
|
-
}
|
103
|
-
join(:tags, tags_join, { table_alias: :provider_tags } )
|
104
|
-
end
|
105
|
-
|
106
|
-
def join_provider_versions_for_provider_id_and_branch(provider_id, provider_version_branch)
|
107
|
-
versions_join = {
|
108
|
-
Sequel[:verifications][:provider_version_id] => Sequel[:provider_versions][:id],
|
109
|
-
Sequel[:provider_versions][:pacticipant_id] => provider_id
|
110
|
-
}
|
111
|
-
branch_versions_join = {
|
112
|
-
Sequel[:provider_versions][:id] => Sequel[:branch_versions][:version_id],
|
113
|
-
Sequel[:branch_versions][:branch_name] => provider_version_branch
|
114
|
-
}
|
115
|
-
join(:versions, versions_join, { table_alias: :provider_versions } )
|
116
|
-
.join(:branch_versions, branch_versions_join)
|
117
|
-
end
|
118
|
-
|
119
|
-
def join_provider_versions_for_provider_id(provider_id, &block)
|
120
|
-
versions_join = {
|
121
|
-
Sequel[:verifications][:provider_version_id] => Sequel[:provider_versions][:id],
|
122
|
-
Sequel[:provider_versions][:pacticipant_id] => provider_id
|
123
|
-
}
|
124
|
-
join(:versions, versions_join, { table_alias: :provider_versions }, &block)
|
125
|
-
end
|
126
|
-
|
127
|
-
def verified_before_creation_date_of(record)
|
128
|
-
if record
|
129
|
-
verified_before_date(record.created_at)
|
130
|
-
else
|
131
|
-
self
|
132
|
-
end
|
133
|
-
end
|
134
114
|
end
|
135
115
|
end
|
136
116
|
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.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bethany Skurrie
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2024-
|
13
|
+
date: 2024-02-21 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.6
|
1264
1264
|
signing_key:
|
1265
1265
|
specification_version: 4
|
1266
1266
|
summary: See description
|