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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79ce9d64a823a800533d3312f75b9e008d621833683e1f1424827fdf146ae855
4
- data.tar.gz: 46c802480921553348daf0f3db5af2cbd94dd0a3b40de7db29f7137846768b93
3
+ metadata.gz: a4c49978b4312049fd2e394ce46bcf90f64125ff50556f9bb01f9610e1310546
4
+ data.tar.gz: 43f24ab98f5ce7bd757a52a085d653668d83395b6889921e8dc0d4aac5982b73
5
5
  SHA512:
6
- metadata.gz: 2fc7c186cd8b1174668c97724e9065bf417768ec854726d3651a1ad1c13908adaa6ad36979f17be05483208fab304dad25f19dc8e31c085c685fc73c9539192e
7
- data.tar.gz: bbb31b5fde13172358084bd35e3d52161a4440f91c2363ed337f7aa5512e8669cc39a323ae7f970016924a669de4eedb35d891a3ce95cadea850032a97c995dd
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 [travis.yml][travisyml] file to see which versions we're currently running our tests against.
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
@@ -16,7 +16,7 @@ module PactBroker
16
16
  property :name
17
17
  end
18
18
 
19
- property :uuid
19
+ property :uuid, writeable: false
20
20
 
21
21
  property :description, getter: lambda { |represented:, **| represented.display_description }
22
22
 
@@ -42,6 +42,10 @@ module PactBroker
42
42
  :'deployments::environment'
43
43
  end
44
44
 
45
+ def policy_record
46
+ environment
47
+ end
48
+
45
49
  def to_json
46
50
  decorator_class(:environment_decorator).new(environment).to_json(**decorator_options)
47
51
  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, pact_params.json_content)
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
@@ -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
- # rubocop: disable Metrics/ParameterLists
5
- def self.from_hash(consumer_name: nil, provider_name: nil, decoded_content: nil, content_type: nil, specification: nil, on_conflict: nil)
6
- new(consumer_name, provider_name, decoded_content, content_type, specification, on_conflict)
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.decoded_content)
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 cicumstances and may indicate that you have not configured your Pact pipeline correctly. For more information see https://docs.pact.io/go/versioning
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
@@ -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
@@ -55,7 +55,6 @@ module PactBroker
55
55
  Sequel[:v][:verification_id],
56
56
  Sequel[:v][:provider_version_id],
57
57
  Sequel[:v][:provider_version_created_at]
58
-
59
58
  ]
60
59
 
61
60
  # Must be kept in sync with PactBroker::Matrix::EveryRow
@@ -11,7 +11,6 @@ require "pact_broker/hash_refinements"
11
11
  module PactBroker
12
12
  module Matrix
13
13
  class ResolvedSelector < Hash
14
-
15
14
  using PactBroker::HashRefinements
16
15
 
17
16
  # A version ID of -1 will not match any rows, which is what we want to ensure that
@@ -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 json_content, _options = {}
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 json_content
21
- Content.from_json(json_content).sort.content_that_affects_verification_results.to_json
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
@@ -20,7 +20,7 @@ module PactBroker
20
20
  )
21
21
  end
22
22
 
23
- def self.from_request request, path_info
23
+ def self.from_request(request, path_info)
24
24
  json_content = request.body.to_s
25
25
  parsed_content = begin
26
26
  parsed = JSON.parse(json_content, PACT_PARSING_OPTIONS)
@@ -57,6 +57,7 @@ module PactBroker
57
57
  end
58
58
  end
59
59
 
60
+ # TODO use the branch heads here
60
61
  def latest_by_consumer_branch
61
62
  branch_versions_join = {
62
63
  Sequel[:pact_publications][:consumer_version_id] => Sequel[:branch_versions][:version_id]
@@ -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
- .join_successful_non_wip_verifications_for_provider_id(provider_id)
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
@@ -7,6 +7,7 @@ require "pact_broker/pacts/selector"
7
7
  require "pact_broker/pacts/selectors"
8
8
  require "pact_broker/feature_toggle"
9
9
  require "pact_broker/repositories/scopes"
10
+ require "pact_broker/matrix/unresolved_selector"
10
11
 
11
12
  module PactBroker
12
13
  module Pacts
@@ -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 = generate_sha(params[:json_content])
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, new_json_content)
182
- !PactBroker.configuration.allow_dangerous_contract_modification && existing_pact && existing_pact.pact_version_sha != generate_sha(new_json_content)
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 params, version, provider
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(consumer_name: consumer_name, provider_name: provider_name, decoded_content: json_content, content_type: "application/json", specification: "pact")
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"] != "production"
14
- set :dump_errors, false # The padrino logger logs these for us. If this is enabled we get duplicate logging.
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
@@ -1,14 +1,25 @@
1
- require "pact_broker/configuration"
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
- unless defined? PADRINO_LOGGER
5
- log_path = File.join(PactBroker.configuration.log_dir, "ui.log")
6
- PADRINO_LOGGER = {
7
- production: { log_level: :error, stream: :to_file, log_path: log_path },
8
- staging: { log_level: :error, stream: :to_file, log_path: log_path },
9
- test: { log_level: :warn, stream: :to_file, log_path: log_path },
10
- development: { log_level: :warn, stream: :to_file, log_path: log_path }
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"
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = "2.108.0"
2
+ VERSION = "2.109.1"
3
3
  end
@@ -2,6 +2,7 @@ require "forwardable"
2
2
  require "pact_broker/logging"
3
3
  require "pact_broker/repositories"
4
4
  require "pact_broker/messages"
5
+ require "pact_broker/contracts/notice"
5
6
 
6
7
  module PactBroker
7
8
  module Versions
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", "~>2.0"
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.108.0
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-01-05 00:00:00.000000000 Z
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: '2.0'
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: '2.0'
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.4
1263
+ rubygems_version: 3.5.6
1264
1264
  signing_key:
1265
1265
  specification_version: 4
1266
1266
  summary: See description