pact_broker 2.121.2 → 2.123.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 +116 -0
- data/Gemfile +1 -4
- data/lib/pact_broker/api/contracts/consumer_version_selector_contract.rb +17 -1
- data/lib/pact_broker/api/contracts/utf_8_validation.rb +5 -1
- data/lib/pact_broker/api/decorators/pacts_for_verification_query_decorator.rb +1 -0
- data/lib/pact_broker/api/decorators/publish_contract_decorator.rb +4 -3
- data/lib/pact_broker/api/decorators/verification_decorator.rb +12 -2
- data/lib/pact_broker/api/decorators/verification_summary_decorator.rb +6 -0
- data/lib/pact_broker/api/renderers/html_pact_renderer.rb +6 -69
- data/lib/pact_broker/api/renderers/markdown/consumer_contract_renderer.rb +87 -0
- data/lib/pact_broker/api/renderers/markdown/interaction_renderer.rb +52 -0
- data/lib/pact_broker/api/renderers/markdown/interaction_view_model.rb +162 -0
- data/lib/pact_broker/api/renderers/markdown.rb +9 -0
- data/lib/pact_broker/api/resources/publish_contracts.rb +10 -6
- data/lib/pact_broker/doc/views/provider-pacts-for-verification.markdown +10 -2
- data/lib/pact_broker/hash_refinements.rb +2 -2
- data/lib/pact_broker/locale/en.yml +3 -0
- data/lib/pact_broker/pacts/create_formatted_diff.rb +2 -7
- data/lib/pact_broker/pacts/generate_sha.rb +7 -4
- data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +41 -21
- data/lib/pact_broker/pacts/repository.rb +2 -2
- data/lib/pact_broker/pacts/selected_pact.rb +4 -0
- data/lib/pact_broker/pacts/selector.rb +20 -2
- data/lib/pact_broker/pacts/selectors.rb +4 -0
- data/lib/pact_broker/unified_diff.rb +26 -0
- data/lib/pact_broker/verifications/repository.rb +1 -1
- data/lib/pact_broker/verifications/summary_for_consumer_version.rb +4 -0
- data/lib/pact_broker/version.rb +1 -1
- data/pact_broker.gemspec +2 -2
- metadata +25 -30
- data/lib/pact/doc/doc_file.rb +0 -38
- data/lib/pact/doc/generate.rb +0 -11
- data/lib/pact/doc/generator.rb +0 -82
- data/lib/pact/doc/interaction_view_model.rb +0 -157
- data/lib/pact/doc/markdown/consumer_contract_renderer.rb +0 -74
- data/lib/pact/doc/markdown/generator.rb +0 -24
- data/lib/pact/doc/markdown/index_renderer.rb +0 -40
- data/lib/pact/doc/markdown/interaction_renderer.rb +0 -51
- data/lib/pact/doc/sort_interactions.rb +0 -14
- data/lib/pact/doc.rb +0 -5
- /data/lib/{pact/doc → pact_broker/api/renderers}/markdown/interaction.erb +0 -0
- /data/lib/{pact/doc → pact_broker/api/renderers}/markdown/interaction_async.erb +0 -0
|
@@ -56,16 +56,20 @@ module PactBroker
|
|
|
56
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
|
+
# Memoized because decoding and parsing very large contracts is expensive,
|
|
60
|
+
# and this is called multiple times per request (validation, authorization and publication)
|
|
59
61
|
def params
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
p["contracts"].
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
@params_with_decoded_contracts ||= begin
|
|
63
|
+
p = super(default: {}, symbolize_names: false)
|
|
64
|
+
if p["contracts"].is_a?(Array)
|
|
65
|
+
p["contracts"].each do | contract |
|
|
66
|
+
if contract.is_a?(Hash)
|
|
67
|
+
decode_and_parse_content(contract)
|
|
68
|
+
end
|
|
65
69
|
end
|
|
66
70
|
end
|
|
71
|
+
p
|
|
67
72
|
end
|
|
68
|
-
p
|
|
69
73
|
end
|
|
70
74
|
|
|
71
75
|
def schema
|
|
@@ -32,7 +32,15 @@ Example: This data structure represents the way a user might specify "I want to
|
|
|
32
32
|
|
|
33
33
|
`consumerVersionSelectors.matchingBranch`: if the key is specified, can only be set to `true`. When true, returns the latest pact for any branch with the same name as the specified `providerVersionBranch`.
|
|
34
34
|
|
|
35
|
-
`consumerVersionSelectors.fallbackBranch`: the name of the branch to
|
|
35
|
+
`consumerVersionSelectors.fallbackBranch`: the name of the branch to fall back to for each consumer that has no pact from the specified `branch`. Use of this property is discouraged as it may allow a pact to pass on a feature branch while breaking backwards compatibility with the main branch, which is generally not desired. It is better to use two separate consumer version selectors, one with the main branch name, and one with the feature branch name, rather than use this property.
|
|
36
|
+
|
|
37
|
+
`consumerVersionSelectors.fallbackToMainBranch`: if the key is specified, can only be set to `true`. Used with `branch`. For each consumer that has no pact for the specified `branch`, returns the latest pact from that consumer's configured `mainBranch` instead. Consumers without a configured `mainBranch` have no fallback. Use this instead of `fallbackBranch` when the consumers have different main branch names, or when a main branch may be renamed, so the provider does not need to know the name. It cannot be used together with `fallbackBranch`. The same caveat as `fallbackBranch` applies.
|
|
38
|
+
|
|
39
|
+
{
|
|
40
|
+
"consumerVersionSelectors": [
|
|
41
|
+
{ "branch": "feat-x", "fallbackToMainBranch": true }
|
|
42
|
+
]
|
|
43
|
+
}
|
|
36
44
|
|
|
37
45
|
`consumerVersionSelectors.deployed`: if the key is specified, can only be set to `true`. Returns the pacts for all versions of the consumer that are currently deployed to any environment. Use of this selector requires that the deployment of the consumer application is recorded in the Pact Broker using the `pact-broker record-deployment` CLI.
|
|
38
46
|
|
|
@@ -48,7 +56,7 @@ Example: This data structure represents the way a user might specify "I want to
|
|
|
48
56
|
|
|
49
57
|
`consumerVersionSelectors.tag`: the tag name(s) of the consumer versions to get the pacts for. *This field is still supported but it is recommended to use the `branch` in preference now.*
|
|
50
58
|
|
|
51
|
-
`consumerVersionSelectors.fallbackTag`: the name of the tag to
|
|
59
|
+
`consumerVersionSelectors.fallbackTag`: the name of the tag to fall back to for each consumer that has no pact with the specified `tag`. This is useful when the consumer and provider use matching branch names to coordinate the development of new features. *This field is still supported but it is recommended to use two separate selectors - one with the main branch name and one with the feature branch name.*
|
|
52
60
|
|
|
53
61
|
`providerVersionBranch`: the repository branch name for the provider application version that will be published with the verification results. This is used by the Broker to determine whether or not a particular pact is in pending state or not.
|
|
54
62
|
|
|
@@ -80,8 +80,8 @@ module PactBroker
|
|
|
80
80
|
def symbolize_keys_private(params)
|
|
81
81
|
case params
|
|
82
82
|
when Hash
|
|
83
|
-
params.
|
|
84
|
-
result
|
|
83
|
+
params.each_with_object({}) do |(key, value), result|
|
|
84
|
+
result[key.to_sym] = symbolize_keys_private(value)
|
|
85
85
|
end
|
|
86
86
|
when Array
|
|
87
87
|
params.collect { |value| symbolize_keys_private(value) }
|
|
@@ -105,6 +105,9 @@ en:
|
|
|
105
105
|
pacts_for_verification_selector_branch_and_latest_false_disallowed: cannot specify a branch with latest=false
|
|
106
106
|
pacts_for_verification_selector_main_branch_and_latest_false_disallowed: cannot specify mainBranch=true with latest=false
|
|
107
107
|
pacts_for_verification_selector_fallback_branch_and_latest_false_disallowed: fallbackBranch can only be set if latest is true
|
|
108
|
+
pacts_for_verification_selector_fallback_to_main_branch_requires_branch: "a branch must be specified when fallbackToMainBranch=true is specified"
|
|
109
|
+
pacts_for_verification_selector_fallback_to_main_branch_and_fallback_branch_disallowed: cannot specify both fallbackBranch and fallbackToMainBranch=true
|
|
110
|
+
pacts_for_verification_selector_fallback_to_main_branch_and_latest_false_disallowed: fallbackToMainBranch can only be set if latest is true
|
|
108
111
|
pacts_for_verification_selector_required_params_missing: must specify a value for environment or tag or branch, or specify mainBranch=true, matchingBranch=true, latest=true, deployed=true, released=true or deployedOrReleased=true
|
|
109
112
|
pacts_for_verification_selector_main_branch_with_other_param_disallowed: cannot specify mainBranch=true with any other criteria apart from consumer
|
|
110
113
|
pacts_for_verification_selector_matching_branch_with_other_param_disallowed: cannot specify matchingBranch=true with any other criteria apart from consumer
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
require "pact/support/matchers"
|
|
2
1
|
require "pact_broker/json"
|
|
3
|
-
require "
|
|
2
|
+
require "pact_broker/unified_diff"
|
|
4
3
|
require "pact_broker/pacts/sort_content"
|
|
5
4
|
require "pact_broker/pacts/content"
|
|
6
5
|
|
|
7
6
|
module PactBroker
|
|
8
7
|
module Pacts
|
|
9
8
|
class CreateFormattedDiff
|
|
10
|
-
extend Pact::Matchers
|
|
11
|
-
|
|
12
9
|
def self.call pact_json_content, previous_pact_json_content, raw: false
|
|
13
10
|
pact_hash = JSON.parse(pact_json_content, **PactBroker::PACT_PARSING_OPTIONS)
|
|
14
11
|
previous_pact_hash = JSON.parse(previous_pact_json_content, **PactBroker::PACT_PARSING_OPTIONS)
|
|
@@ -18,9 +15,7 @@ module PactBroker
|
|
|
18
15
|
previous_pact_hash = SortContent.call(PactBroker::Pacts::Content.from_hash(previous_pact_hash).without_ids.to_hash)
|
|
19
16
|
end
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
Pact::Matchers::UnixDiffFormatter.call(difference, colour: false, include_explanation: false)
|
|
18
|
+
PactBroker::UnifiedDiff.call(JSON.pretty_generate(previous_pact_hash), JSON.pretty_generate(pact_hash))
|
|
24
19
|
end
|
|
25
20
|
end
|
|
26
21
|
end
|
|
@@ -11,17 +11,20 @@ module PactBroker
|
|
|
11
11
|
include PactBroker::Logging
|
|
12
12
|
|
|
13
13
|
# @param [String] json_content
|
|
14
|
-
|
|
14
|
+
# @param [Hash] options
|
|
15
|
+
# @option options [Hash] :parsed_content the result of parsing the json_content, if it has already been parsed.
|
|
16
|
+
# Used to avoid parsing very large pacts again. Must be the parsed json_content, or the sha will be wrong.
|
|
17
|
+
def self.call(json_content, options = {})
|
|
15
18
|
content_for_sha = if PactBroker.configuration.base_equality_only_on_content_that_affects_verification_results
|
|
16
|
-
extract_verifiable_content_for_sha(json_content)
|
|
19
|
+
extract_verifiable_content_for_sha(json_content, options[:parsed_content])
|
|
17
20
|
else
|
|
18
21
|
json_content
|
|
19
22
|
end
|
|
20
23
|
measure_info("Generating SHA1 hexdigest for pact", payload: { length: content_for_sha.length } ){ Digest::SHA1.hexdigest(content_for_sha) }
|
|
21
24
|
end
|
|
22
25
|
|
|
23
|
-
def self.extract_verifiable_content_for_sha(json_content)
|
|
24
|
-
objects = Content.from_json(json_content)
|
|
26
|
+
def self.extract_verifiable_content_for_sha(json_content, parsed_content = nil)
|
|
27
|
+
objects = parsed_content.is_a?(Hash) ? Content.from_hash(parsed_content) : Content.from_json(json_content)
|
|
25
28
|
sorted_content = measure_info("Sorting content", payload: { length: json_content.length }){ objects.sort }
|
|
26
29
|
sorted_content.content_that_affects_verification_results.to_json
|
|
27
30
|
end
|
|
@@ -28,7 +28,9 @@ module PactBroker
|
|
|
28
28
|
# @return [VerifiablePact] an array of VerifiablePact objects
|
|
29
29
|
def find(provider_name, consumer_version_selectors)
|
|
30
30
|
selected_pacts = find_pacts_by_selector(provider_name, consumer_version_selectors)
|
|
31
|
-
selected_pacts = selected_pacts +
|
|
31
|
+
selected_pacts = selected_pacts +
|
|
32
|
+
find_pacts_for_fallback_tags(selected_pacts, provider_name, consumer_version_selectors) +
|
|
33
|
+
find_pacts_for_fallback_branches(selected_pacts, provider_name, consumer_version_selectors)
|
|
32
34
|
merge_selected_pacts(selected_pacts)
|
|
33
35
|
end
|
|
34
36
|
|
|
@@ -178,22 +180,32 @@ module PactBroker
|
|
|
178
180
|
end
|
|
179
181
|
end
|
|
180
182
|
|
|
183
|
+
# The fallback is applied per consumer, so a consumer without a pact for the tag
|
|
184
|
+
# still gets its fallback pact when another consumer does have a pact for the tag.
|
|
181
185
|
def find_pacts_for_fallback_tags(selected_pacts, provider_name, consumer_version_selectors)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
selected_pact.latest_for_tag?(selector.tag)
|
|
186
|
+
consumer_version_selectors.select(&:fallback_tag?).flat_map do | selector |
|
|
187
|
+
consumer_ids_with_a_pact_for_the_tag = consumer_ids_of(selected_pacts.select { | selected_pact | selected_pact.latest_for_tag?(selector.tag) })
|
|
188
|
+
find_fallback_pacts(provider_name, selector, consumer_ids_with_a_pact_for_the_tag) do | query |
|
|
189
|
+
query.for_latest_consumer_versions_with_tag(selector.fallback_tag)
|
|
187
190
|
end
|
|
188
191
|
end
|
|
192
|
+
end
|
|
189
193
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
+
# The fallback is applied per consumer, so a consumer without a pact for the branch
|
|
195
|
+
# still gets its fallback pact when another consumer does have a pact for the branch.
|
|
196
|
+
def find_pacts_for_fallback_branches(selected_pacts, provider_name, consumer_version_selectors)
|
|
197
|
+
consumer_version_selectors.select { | selector | selector.fallback_branch? || selector.fallback_to_main_branch? }.flat_map do | selector |
|
|
198
|
+
consumer_ids_with_a_pact_for_the_branch = consumer_ids_of(selected_pacts.select { | selected_pact | selected_pact.latest_for_branch?(selector.branch) })
|
|
199
|
+
find_fallback_pacts(provider_name, selector, consumer_ids_with_a_pact_for_the_branch) do | query |
|
|
200
|
+
selector.fallback_to_main_branch? ? query.latest_for_main_branches : query.latest_for_consumer_branch(selector.fallback_branch)
|
|
201
|
+
end
|
|
194
202
|
end
|
|
195
203
|
end
|
|
196
204
|
|
|
205
|
+
def consumer_ids_of(selected_pacts)
|
|
206
|
+
selected_pacts.collect { | selected_pact | selected_pact.pact.consumer.id }.uniq
|
|
207
|
+
end
|
|
208
|
+
|
|
197
209
|
def find_pacts_by_selector(provider_name, consumer_version_selectors)
|
|
198
210
|
provider = pacticipant_repository.find_by_name(provider_name)
|
|
199
211
|
|
|
@@ -248,17 +260,25 @@ module PactBroker
|
|
|
248
260
|
selectors
|
|
249
261
|
end
|
|
250
262
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
)
|
|
260
|
-
|
|
261
|
-
end
|
|
263
|
+
# Yields the provider's pacts so the caller can narrow them to the latest for the fallback.
|
|
264
|
+
def find_fallback_pacts(provider_name, selector, consumer_ids_to_exclude)
|
|
265
|
+
query = yield scope_for(PactPublication).eager_for_domain_with_content.for_provider_name(provider_name)
|
|
266
|
+
query = query.for_consumer_name(selector.consumer) if selector.consumer
|
|
267
|
+
query = query.exclude(Sequel[:pact_publications][:consumer_id] => consumer_ids_to_exclude) if consumer_ids_to_exclude.any?
|
|
268
|
+
query.all.collect do | pact_publication |
|
|
269
|
+
SelectedPact.new(
|
|
270
|
+
pact_publication.to_domain,
|
|
271
|
+
Selectors.new(resolve_selector_for_fallback(selector, pact_publication))
|
|
272
|
+
)
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
def resolve_selector_for_fallback(selector, pact_publication)
|
|
277
|
+
if selector.fallback_to_main_branch?
|
|
278
|
+
selector.resolve_for_fallback_to_main_branch(pact_publication.consumer_version, pact_publication.consumer.main_branch)
|
|
279
|
+
else
|
|
280
|
+
selector.resolve_for_fallback(pact_publication.consumer_version)
|
|
281
|
+
end
|
|
262
282
|
end
|
|
263
283
|
|
|
264
284
|
def find_provider_tags_for_which_pact_publication_id_is_pending(pact_publication, successfully_verified_head_pact_publication_ids_for_each_provider_tag)
|
|
@@ -3,7 +3,6 @@ require "pact_broker/logging"
|
|
|
3
3
|
require "pact_broker/pacts/generate_sha"
|
|
4
4
|
require "pact_broker/pacts/pact_publication"
|
|
5
5
|
require "pact_broker/pacts/pact_version"
|
|
6
|
-
require "pact/shared/json_differ"
|
|
7
6
|
require "pact_broker/domain"
|
|
8
7
|
require "pact_broker/pacts/parse"
|
|
9
8
|
require "pact_broker/pacts/latest_pact_publication_id_for_consumer_version"
|
|
@@ -203,6 +202,7 @@ module PactBroker
|
|
|
203
202
|
def find_by_consumer_version consumer_name, consumer_version_number
|
|
204
203
|
scope_for(PactPublication)
|
|
205
204
|
.eager_for_domain_with_content
|
|
205
|
+
.eager(pact_version: :latest_verification)
|
|
206
206
|
.for_consumer_name_and_maybe_version_number(consumer_name, consumer_version_number)
|
|
207
207
|
.remove_overridden_revisions_from_complete_query
|
|
208
208
|
.all
|
|
@@ -386,7 +386,7 @@ module PactBroker
|
|
|
386
386
|
end
|
|
387
387
|
|
|
388
388
|
def different? pact, other_pact
|
|
389
|
-
|
|
389
|
+
pact.content_hash != other_pact.content_hash
|
|
390
390
|
end
|
|
391
391
|
|
|
392
392
|
def find_or_create_pact_version consumer_id, provider_id, pact_version_sha, json_content
|
|
@@ -6,7 +6,7 @@ module PactBroker
|
|
|
6
6
|
class Selector < Hash
|
|
7
7
|
using PactBroker::HashRefinements
|
|
8
8
|
|
|
9
|
-
PROPERTY_NAMES = [:latest, :tag, :branch, :consumer, :consumer_version, :environment_name, :fallback_tag, :fallback_branch, :main_branch, :matching_branch, :currently_supported, :currently_deployed]
|
|
9
|
+
PROPERTY_NAMES = [:latest, :tag, :branch, :consumer, :consumer_version, :environment_name, :fallback_tag, :fallback_branch, :fallback_to_main_branch, :main_branch, :matching_branch, :currently_supported, :currently_deployed]
|
|
10
10
|
|
|
11
11
|
def initialize(properties = {})
|
|
12
12
|
properties.without(*PROPERTY_NAMES).tap { |it| warn("WARN: Unsupported property for #{self.class.name}: #{it.keys.join(", ")} at #{caller[0..3]}") if it.any? }
|
|
@@ -14,13 +14,19 @@ module PactBroker
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def resolve(consumer_version)
|
|
17
|
-
ResolvedSelector.new(self.to_h.without(:fallback_tag, :fallback_branch), consumer_version)
|
|
17
|
+
ResolvedSelector.new(self.to_h.without(:fallback_tag, :fallback_branch, :fallback_to_main_branch), consumer_version)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def resolve_for_fallback(consumer_version)
|
|
21
21
|
ResolvedSelector.new(self.to_h, consumer_version)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
# Records the consumer's main branch as the fallback branch, so the verification
|
|
25
|
+
# notice names the branch that was actually used.
|
|
26
|
+
def resolve_for_fallback_to_main_branch(consumer_version, main_branch)
|
|
27
|
+
ResolvedSelector.new(self.to_h.without(:fallback_to_main_branch).merge(fallback_branch: main_branch), consumer_version)
|
|
28
|
+
end
|
|
29
|
+
|
|
24
30
|
def resolve_for_environment(consumer_version, environment, target = nil)
|
|
25
31
|
ResolvedSelector.new(self.to_h.merge({ environment: environment, target: target }.compact), consumer_version)
|
|
26
32
|
end
|
|
@@ -87,6 +93,10 @@ module PactBroker
|
|
|
87
93
|
self[:fallback_branch] = fallback_branch
|
|
88
94
|
end
|
|
89
95
|
|
|
96
|
+
def fallback_to_main_branch= fallback_to_main_branch
|
|
97
|
+
self[:fallback_to_main_branch] = fallback_to_main_branch
|
|
98
|
+
end
|
|
99
|
+
|
|
90
100
|
def fallback_tag
|
|
91
101
|
self[:fallback_tag]
|
|
92
102
|
end
|
|
@@ -95,6 +105,10 @@ module PactBroker
|
|
|
95
105
|
self[:fallback_branch]
|
|
96
106
|
end
|
|
97
107
|
|
|
108
|
+
def fallback_to_main_branch
|
|
109
|
+
self[:fallback_to_main_branch]
|
|
110
|
+
end
|
|
111
|
+
|
|
98
112
|
def consumer= consumer
|
|
99
113
|
self[:consumer] = consumer
|
|
100
114
|
end
|
|
@@ -235,6 +249,10 @@ module PactBroker
|
|
|
235
249
|
!!fallback_branch
|
|
236
250
|
end
|
|
237
251
|
|
|
252
|
+
def fallback_to_main_branch?
|
|
253
|
+
!!fallback_to_main_branch
|
|
254
|
+
end
|
|
255
|
+
|
|
238
256
|
def main_branch
|
|
239
257
|
self[:main_branch]
|
|
240
258
|
end
|
|
@@ -59,6 +59,10 @@ module PactBroker
|
|
|
59
59
|
any? { | selector | selector.latest_for_tag?(potential_tag) }
|
|
60
60
|
end
|
|
61
61
|
|
|
62
|
+
def latest_for_branch? potential_branch = nil
|
|
63
|
+
any? { | selector | selector.latest_for_branch?(potential_branch) }
|
|
64
|
+
end
|
|
65
|
+
|
|
62
66
|
def tag_names_of_selectors_for_all_pacts
|
|
63
67
|
select(&:all_for_tag?).collect(&:tag).uniq
|
|
64
68
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require "diff/lcs"
|
|
2
|
+
require "diff/lcs/hunk"
|
|
3
|
+
|
|
4
|
+
module PactBroker
|
|
5
|
+
# Renders the difference between two texts in unified diff format,
|
|
6
|
+
# without the file header lines.
|
|
7
|
+
class UnifiedDiff
|
|
8
|
+
def self.call(old_text, new_text, context: 3)
|
|
9
|
+
old_lines = old_text.split("\n")
|
|
10
|
+
new_lines = new_text.split("\n")
|
|
11
|
+
pieces = Diff::LCS.diff(old_lines, new_lines)
|
|
12
|
+
return "" if pieces.empty?
|
|
13
|
+
|
|
14
|
+
hunks = []
|
|
15
|
+
length_difference = 0
|
|
16
|
+
pieces.each do |piece|
|
|
17
|
+
hunk = Diff::LCS::Hunk.new(old_lines, new_lines, piece, context, length_difference)
|
|
18
|
+
length_difference = hunk.file_length_difference
|
|
19
|
+
hunk.merge(hunks.pop) if context.positive? && hunks.last && hunk.overlaps?(hunks.last)
|
|
20
|
+
hunks << hunk
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
hunks.collect { |hunk| hunk.diff(:unified) }.join("\n")
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -99,7 +99,7 @@ module PactBroker
|
|
|
99
99
|
.remove_verifications_for_overridden_consumer_versions
|
|
100
100
|
.for_consumer_name_and_consumer_version_number(consumer_name, consumer_version_number)
|
|
101
101
|
.latest_by_pact_version
|
|
102
|
-
.eager(:provider)
|
|
102
|
+
.eager(:provider, :consumer, :provider_version, :pact_version)
|
|
103
103
|
.all
|
|
104
104
|
.sort_by { | v | v.provider_name.downcase }
|
|
105
105
|
end
|
data/lib/pact_broker/version.rb
CHANGED
data/pact_broker.gemspec
CHANGED
|
@@ -59,17 +59,17 @@ Gem::Specification.new do |gem|
|
|
|
59
59
|
gem.add_runtime_dependency "semver2", "~> 3.4.2"
|
|
60
60
|
gem.add_runtime_dependency "rack", "~> 3.2"
|
|
61
61
|
gem.add_runtime_dependency "redcarpet", "~> 3.5"
|
|
62
|
-
gem.add_runtime_dependency "pact-support", "~> 2.0"
|
|
63
62
|
gem.add_runtime_dependency "haml", "~>5.0"
|
|
64
63
|
gem.add_runtime_dependency "sucker_punch", "~>3.0"
|
|
65
64
|
gem.add_runtime_dependency "rack-protection", "~> 4.1"
|
|
66
65
|
gem.add_runtime_dependency "table_print", "~> 1.5"
|
|
67
66
|
gem.add_runtime_dependency "semantic_logger", "~> 5.0"
|
|
68
|
-
gem.add_runtime_dependency "sanitize", "~>
|
|
67
|
+
gem.add_runtime_dependency "sanitize", "~> 7.0"
|
|
69
68
|
gem.add_runtime_dependency "wisper", "~> 2.0"
|
|
70
69
|
gem.add_runtime_dependency "anyway_config", "~> 2.1"
|
|
71
70
|
gem.add_runtime_dependency "request_store", "~> 1.5"
|
|
72
71
|
gem.add_runtime_dependency "moments", "~> 0.2"
|
|
72
|
+
gem.add_runtime_dependency "diff-lcs", "~> 1.5"
|
|
73
73
|
# dropped in ruby 3.4 stdlib
|
|
74
74
|
gem.add_runtime_dependency "mutex_m", "~> 0.3" # until as-notifications -> webmachine requires it
|
|
75
75
|
gem.add_runtime_dependency "csv", "~> 3.0" # lib/pact_broker/api/decorators/relationships_csv_decorator.rb
|
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.123.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: 2026-
|
|
13
|
+
date: 2026-11-11 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
16
|
name: json
|
|
@@ -152,20 +152,6 @@ dependencies:
|
|
|
152
152
|
- - "~>"
|
|
153
153
|
- !ruby/object:Gem::Version
|
|
154
154
|
version: '3.5'
|
|
155
|
-
- !ruby/object:Gem::Dependency
|
|
156
|
-
name: pact-support
|
|
157
|
-
requirement: !ruby/object:Gem::Requirement
|
|
158
|
-
requirements:
|
|
159
|
-
- - "~>"
|
|
160
|
-
- !ruby/object:Gem::Version
|
|
161
|
-
version: '2.0'
|
|
162
|
-
type: :runtime
|
|
163
|
-
prerelease: false
|
|
164
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
165
|
-
requirements:
|
|
166
|
-
- - "~>"
|
|
167
|
-
- !ruby/object:Gem::Version
|
|
168
|
-
version: '2.0'
|
|
169
155
|
- !ruby/object:Gem::Dependency
|
|
170
156
|
name: haml
|
|
171
157
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -242,14 +228,14 @@ dependencies:
|
|
|
242
228
|
requirements:
|
|
243
229
|
- - "~>"
|
|
244
230
|
- !ruby/object:Gem::Version
|
|
245
|
-
version: '
|
|
231
|
+
version: '7.0'
|
|
246
232
|
type: :runtime
|
|
247
233
|
prerelease: false
|
|
248
234
|
version_requirements: !ruby/object:Gem::Requirement
|
|
249
235
|
requirements:
|
|
250
236
|
- - "~>"
|
|
251
237
|
- !ruby/object:Gem::Version
|
|
252
|
-
version: '
|
|
238
|
+
version: '7.0'
|
|
253
239
|
- !ruby/object:Gem::Dependency
|
|
254
240
|
name: wisper
|
|
255
241
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -306,6 +292,20 @@ dependencies:
|
|
|
306
292
|
- - "~>"
|
|
307
293
|
- !ruby/object:Gem::Version
|
|
308
294
|
version: '0.2'
|
|
295
|
+
- !ruby/object:Gem::Dependency
|
|
296
|
+
name: diff-lcs
|
|
297
|
+
requirement: !ruby/object:Gem::Requirement
|
|
298
|
+
requirements:
|
|
299
|
+
- - "~>"
|
|
300
|
+
- !ruby/object:Gem::Version
|
|
301
|
+
version: '1.5'
|
|
302
|
+
type: :runtime
|
|
303
|
+
prerelease: false
|
|
304
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
305
|
+
requirements:
|
|
306
|
+
- - "~>"
|
|
307
|
+
- !ruby/object:Gem::Version
|
|
308
|
+
version: '1.5'
|
|
309
309
|
- !ruby/object:Gem::Dependency
|
|
310
310
|
name: mutex_m
|
|
311
311
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -593,18 +593,6 @@ files:
|
|
|
593
593
|
- docs/developer/matrix.md
|
|
594
594
|
- docs/developer/rack.md
|
|
595
595
|
- docs/matrix-optimisation/README.md
|
|
596
|
-
- lib/pact/doc.rb
|
|
597
|
-
- lib/pact/doc/doc_file.rb
|
|
598
|
-
- lib/pact/doc/generate.rb
|
|
599
|
-
- lib/pact/doc/generator.rb
|
|
600
|
-
- lib/pact/doc/interaction_view_model.rb
|
|
601
|
-
- lib/pact/doc/markdown/consumer_contract_renderer.rb
|
|
602
|
-
- lib/pact/doc/markdown/generator.rb
|
|
603
|
-
- lib/pact/doc/markdown/index_renderer.rb
|
|
604
|
-
- lib/pact/doc/markdown/interaction.erb
|
|
605
|
-
- lib/pact/doc/markdown/interaction_async.erb
|
|
606
|
-
- lib/pact/doc/markdown/interaction_renderer.rb
|
|
607
|
-
- lib/pact/doc/sort_interactions.rb
|
|
608
596
|
- lib/pact_broker.rb
|
|
609
597
|
- lib/pact_broker/api.rb
|
|
610
598
|
- lib/pact_broker/api/authorization/resource_access_policy.rb
|
|
@@ -717,6 +705,12 @@ files:
|
|
|
717
705
|
- lib/pact_broker/api/paths.rb
|
|
718
706
|
- lib/pact_broker/api/renderers/html_pact_renderer.rb
|
|
719
707
|
- lib/pact_broker/api/renderers/integrations_dot_renderer.rb
|
|
708
|
+
- lib/pact_broker/api/renderers/markdown.rb
|
|
709
|
+
- lib/pact_broker/api/renderers/markdown/consumer_contract_renderer.rb
|
|
710
|
+
- lib/pact_broker/api/renderers/markdown/interaction.erb
|
|
711
|
+
- lib/pact_broker/api/renderers/markdown/interaction_async.erb
|
|
712
|
+
- lib/pact_broker/api/renderers/markdown/interaction_renderer.rb
|
|
713
|
+
- lib/pact_broker/api/renderers/markdown/interaction_view_model.rb
|
|
720
714
|
- lib/pact_broker/api/resources.rb
|
|
721
715
|
- lib/pact_broker/api/resources/after_reply.rb
|
|
722
716
|
- lib/pact_broker/api/resources/all_webhooks.rb
|
|
@@ -1093,6 +1087,7 @@ files:
|
|
|
1093
1087
|
- lib/pact_broker/ui/views/index/show.haml
|
|
1094
1088
|
- lib/pact_broker/ui/views/layouts/main.haml
|
|
1095
1089
|
- lib/pact_broker/ui/views/matrix/show.haml
|
|
1090
|
+
- lib/pact_broker/unified_diff.rb
|
|
1096
1091
|
- lib/pact_broker/verifications/latest_verification_for_consumer_and_provider.rb
|
|
1097
1092
|
- lib/pact_broker/verifications/latest_verification_for_consumer_version_tag.rb
|
|
1098
1093
|
- lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb
|
data/lib/pact/doc/doc_file.rb
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
module Pact
|
|
2
|
-
module Doc
|
|
3
|
-
class DocFile
|
|
4
|
-
|
|
5
|
-
def initialize consumer_contract, dir, consumer_contract_renderer, file_extension
|
|
6
|
-
@dir = dir
|
|
7
|
-
@consumer_contract = consumer_contract
|
|
8
|
-
@consumer_contract_renderer = consumer_contract_renderer
|
|
9
|
-
@file_extension = file_extension
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def write
|
|
13
|
-
File.open(path, "w") { |io| io << doc_file_contents }
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def title
|
|
17
|
-
consumer_contract.provider.name
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def name
|
|
21
|
-
"#{consumer_contract.consumer.name} - #{consumer_contract.provider.name}#{file_extension}"
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
private
|
|
25
|
-
|
|
26
|
-
attr_reader :dir, :consumer_contract, :consumer_contract_renderer, :file_extension
|
|
27
|
-
|
|
28
|
-
def path
|
|
29
|
-
File.join(dir, name)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def doc_file_contents
|
|
33
|
-
consumer_contract_renderer.call(consumer_contract)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
data/lib/pact/doc/generate.rb
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
module Pact
|
|
2
|
-
module Doc
|
|
3
|
-
class Generate
|
|
4
|
-
|
|
5
|
-
def self.call pact_dir = Pact.configuration.pact_dir, doc_dir = Pact.configuration.doc_dir, doc_generators = Pact.configuration.doc_generators
|
|
6
|
-
doc_generators.each{| doc_generator| doc_generator.call pact_dir, doc_dir }
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
end
|