pact_broker 2.115.0 → 2.117.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +41 -0
  3. data/Gemfile +4 -3
  4. data/lib/pact/doc/interaction_view_model.rb +25 -5
  5. data/lib/pact/doc/markdown/interaction_async.erb +10 -0
  6. data/lib/pact/doc/markdown/interaction_renderer.rb +5 -1
  7. data/lib/pact_broker/api/contracts/dry_validation_errors_formatter.rb +3 -0
  8. data/lib/pact_broker/api/decorators/integration_decorator.rb +7 -0
  9. data/lib/pact_broker/api/decorators/pacticipant_decorator.rb +11 -0
  10. data/lib/pact_broker/api/decorators/version_decorator.rb +16 -0
  11. data/lib/pact_broker/api/pact_broker_urls.rb +4 -0
  12. data/lib/pact_broker/api/renderers/html_pact_renderer.rb +55 -1
  13. data/lib/pact_broker/api/resources/branch_versions.rb +5 -1
  14. data/lib/pact_broker/api/resources/index.rb +48 -0
  15. data/lib/pact_broker/api/resources/latest_provider_pacts_for_branch.rb +26 -0
  16. data/lib/pact_broker/api/resources/pact_versions_for_branch.rb +15 -1
  17. data/lib/pact_broker/api/resources/pacticipant.rb +6 -1
  18. data/lib/pact_broker/api/resources/provider_pacts_for_consumer_branch.rb +47 -0
  19. data/lib/pact_broker/api/resources/provider_states.rb +9 -3
  20. data/lib/pact_broker/api/resources/tag_versions.rb +58 -0
  21. data/lib/pact_broker/api/resources/version.rb +5 -1
  22. data/lib/pact_broker/api/resources/versions.rb +5 -1
  23. data/lib/pact_broker/api.rb +11 -0
  24. data/lib/pact_broker/deployments/deployed_version_service.rb +21 -0
  25. data/lib/pact_broker/doc/views/index/branch-pact-versions.markdown +7 -0
  26. data/lib/pact_broker/doc/views/index/latest-branch-pact-versions.markdown +7 -0
  27. data/lib/pact_broker/doc/views/index/latest-main-branch-pact-versions.markdown +7 -0
  28. data/lib/pact_broker/doc/views/index/latest-provider-pacts-with-branch.markdown +7 -0
  29. data/lib/pact_broker/doc/views/index/latest-provider-pacts-with-main-branch.markdown +7 -0
  30. data/lib/pact_broker/doc/views/index/latest-provider-pacts-with-tag.markdown +3 -1
  31. data/lib/pact_broker/doc/views/index/main-branch-pact-versions.markdown +7 -0
  32. data/lib/pact_broker/doc/views/index/provider-pacts-with-branch.markdown +7 -0
  33. data/lib/pact_broker/doc/views/index/provider-pacts-with-main-branch.markdown +7 -0
  34. data/lib/pact_broker/doc/views/index/provider-pacts-with-tag.markdown +2 -0
  35. data/lib/pact_broker/doc/views/integrations.markdown +8 -2
  36. data/lib/pact_broker/doc/views/pact/provider-states.markdown +10 -3
  37. data/lib/pact_broker/integrations/integration.rb +3 -3
  38. data/lib/pact_broker/integrations/repository.rb +1 -0
  39. data/lib/pact_broker/json.rb +4 -1
  40. data/lib/pact_broker/pacts/pact_publication_selector_dataset_module.rb +8 -0
  41. data/lib/pact_broker/pacts/provider_state_service.rb +10 -2
  42. data/lib/pact_broker/pacts/repository.rb +30 -0
  43. data/lib/pact_broker/pacts/service.rb +20 -0
  44. data/lib/pact_broker/tags/repository.rb +11 -0
  45. data/lib/pact_broker/tags/service.rb +4 -0
  46. data/lib/pact_broker/test/test_data_builder.rb +3 -2
  47. data/lib/pact_broker/version.rb +1 -1
  48. data/lib/pact_broker/versions/repository.rb +9 -0
  49. data/lib/pact_broker/versions/service.rb +5 -0
  50. data/pact_broker.gemspec +8 -2
  51. metadata +74 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5d60c3b6a432bf6499e5167d6c1b06a6799ef58fb3cf5464000ebe6712352653
4
- data.tar.gz: e8b326e736249b6de4cf47baca16f0551e4a45de24d61a9839ba91b077577959
3
+ metadata.gz: 66a321653a387b5b79c1929494938563e608901abf69bdf97c99062e6b97570d
4
+ data.tar.gz: b3b33dee60c7a5cdf1ad8471929821ad4f5c8ee07c9c8e54d147c0cc590b7492
5
5
  SHA512:
6
- metadata.gz: b1973fc6c1f1b44ab6fa5ea7c7986cb588f7e69cd6bc3a25c5abca52675c5cfeb453c1ee2db261ebeb4d53ffdf5d6d7e4985010c7a89dc8a162521f13728af3e
7
- data.tar.gz: 06c0d372bc3f97fa958d74e064033d89e3dd096a835290c44c59fa7b7331deeb2b50653b5b4be23f194db933250520696feba15b8e24bac5ef3669ca53f52289
6
+ metadata.gz: afb8062161928832aa645ca3f9b611e7d5969a7ee23de3987f3c4eda24f0efe4bfd0a393894225ac1836e4da4bee4d05fe3d3ada1f898292e3269ca8259e8675
7
+ data.tar.gz: 80da5823d947745d6c165bd744693886e8e744f32bbe218bd2fe61b328b0bcd95712c8f7140cdc6ce73db6293e3c6ebfdb3ed5d229a704b6299c188806d95b9e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,44 @@
1
+ <a name="v2.117.0"></a>
2
+ ### v2.117.0 (2025-10-28)
3
+
4
+ #### Features
5
+
6
+ * add provider pacts by branch endpoints ([0ccff2ec](/../../commit/0ccff2ec))
7
+ * PACT-4511/updated matrix decorator to return app instance for an env if present (#838) ([8bc24e72](/../../commit/8bc24e72))
8
+ * support provider states by branch/env ([f4db396f](/../../commit/f4db396f))
9
+
10
+ #### Bug Fixes
11
+
12
+ * update hal relations for provider pacts ([b6e8e8e3](/../../commit/b6e8e8e3))
13
+ * drop pact-support pin ([3c7eb4c5](/../../commit/3c7eb4c5))
14
+ * fixed the text fixtures (#826) ([28035c27](/../../commit/28035c27))
15
+
16
+ * **test**
17
+ * update expectation of webhook_certificates source format dependant on rb version ([5364c1b1](/../../commit/5364c1b1))
18
+
19
+ * **deps**
20
+ * add mutex_m/csv/ostruct/pstore ([075d2522](/../../commit/075d2522))
21
+
22
+ <a name="v2.116.0"></a>
23
+ ### v2.116.0 (2025-07-04)
24
+
25
+ #### Features
26
+
27
+ * render sync messages ([c0ad9f5b](/../../commit/c0ad9f5b))
28
+ * render async messages mixed v4 and v3 ([d727d950](/../../commit/d727d950))
29
+ * add deployed-environments to pacticipant response and tag versions (#804) ([d8c7ee65](/../../commit/d8c7ee65))
30
+ * show deployed-environments in branch versions response (#803) ([cc346010](/../../commit/cc346010))
31
+ * add tag_versions endpoint ([42bf5203](/../../commit/42bf5203))
32
+ * added deployed-environments to `/parcticipants/$name/versions` abd (#801) ([af66f6a3](/../../commit/af66f6a3))
33
+
34
+ #### Bug Fixes
35
+
36
+ * rubocop errors ([e311422c](/../../commit/e311422c))
37
+ * refactored long consumer_contract method ([7d8af4d5](/../../commit/7d8af4d5))
38
+ * remove unsupported Pact::Term from test example ([1a4056bd](/../../commit/1a4056bd))
39
+ * rename interaction_async.erb filename ([77ddcb59](/../../commit/77ddcb59))
40
+ * refactored the query to filter out duplicate integration rows (#806) ([7bff0f0d](/../../commit/7bff0f0d))
41
+
1
42
  <a name="v2.115.0"></a>
2
43
  ### v2.115.0 (2025-03-17)
3
44
 
data/Gemfile CHANGED
@@ -3,12 +3,13 @@ source "https://rubygems.org"
3
3
  gemspec
4
4
 
5
5
 
6
- gem "rake", "~>13.0"
6
+ gem "rake", "~> 13.3"
7
7
  gem "sqlite3", ">=2.0.0"
8
8
  gem "conventional-changelog", "~>1.3"
9
9
  gem "bump", "~> 0.5"
10
10
  gem "padrino-core", ">= 0.16.0.pre3", require: false
11
11
  gem "rackup", "~> 2.2"
12
+ gem "thor", "~> 1.4" # thor is secondary dependency but bumping here to avoid CVEs
12
13
 
13
14
  group :development do
14
15
  gem "pry-byebug"
@@ -33,11 +34,11 @@ group :test do
33
34
  gem "approvals", ">=0.0.24", "<1.0.0"
34
35
  gem "tzinfo", "~>2.0"
35
36
  gem "faraday-retry", "~>2.0"
36
- gem "openapi_first", ">= 2.3", "< 3"
37
+ gem "openapi_first", "~>2.0"
37
38
  end
38
39
 
39
40
  group :pg, optional: true do
40
- gem "pg", "~>1.2"
41
+ gem "pg", "~>1.6"
41
42
  end
42
43
 
43
44
  group :mysql, optional: true do
@@ -70,7 +70,12 @@ module Pact
70
70
  end
71
71
 
72
72
  def request
73
- fix_json_formatting JSON.pretty_generate(clean_request)
73
+ the_clean_request = clean_request
74
+ if the_clean_request == "ASYNC_REQUEST"
75
+ "ASYNC_REQUEST"
76
+ else
77
+ fix_json_formatting JSON.pretty_generate(clean_request)
78
+ end
74
79
  end
75
80
 
76
81
  def response
@@ -82,14 +87,29 @@ module Pact
82
87
  attr_reader :interaction, :consumer_contract
83
88
 
84
89
  def clean_request
85
- reified_request = Reification.from_term(interaction.request)
86
- ordered_clean_hash(reified_request).tap do | hash |
87
- hash[:body] = reified_request[:body] if reified_request[:body]
90
+ reified = Reification.from_term(interaction.request)
91
+ return "ASYNC_REQUEST" if reified[:method] == "FAKE_ASYNC_METHOD"
92
+
93
+ ordered = ordered_clean_hash(reified).tap do |h|
94
+ h[:body] = reified[:body] if reified[:body]
88
95
  end
96
+
97
+ return ordered[:body].to_h.slice("contents", "metadata") if ordered[:method] == "FAKE_SYNC_METHOD"
98
+
99
+ ordered
89
100
  end
90
101
 
91
102
  def clean_response
92
- ordered_clean_hash Reification.from_term(interaction.response)
103
+ raw = Reification.from_term(interaction.response)
104
+
105
+ case raw[:status]
106
+ when "FAKE_ASYNC_METHOD"
107
+ raw[:body] || {}
108
+ when "FAKE_SYNC_METHOD"
109
+ Array(raw.dig(:body, "contents")).map { |item| item.slice("contents", "metadata") }
110
+ else
111
+ ordered_clean_hash(raw)
112
+ end
93
113
  end
94
114
 
95
115
  # Remove empty body and headers hashes from response, and empty headers from request,
@@ -0,0 +1,10 @@
1
+ <a name="<%= interaction.id %>"></a><% formatted_provider_states = h(interaction.formatted_provider_states mark_bold: true) %>
2
+ <%= if !formatted_provider_states.empty?
3
+ "Given #{formatted_provider_states}"
4
+ end
5
+ %>
6
+
7
+ <%= h(interaction.provider_name) %> will **asyncronously** send **<%= h(interaction.description) %>**:
8
+ ```json
9
+ <%= interaction.response %>
10
+ ```
@@ -19,7 +19,11 @@ module Pact
19
19
  end
20
20
 
21
21
  def render_full_interaction
22
- render("/interaction.erb")
22
+ if interaction.request == "ASYNC_REQUEST"
23
+ render("/interaction_async.erb")
24
+ else
25
+ render("/interaction.erb")
26
+ end
23
27
  end
24
28
 
25
29
  def render template_file
@@ -41,6 +41,9 @@ module PactBroker
41
41
  add_error(errors_hash, error.path.first, "#{error.path.last} #{error.text} (at index #{error.path[1]})")
42
42
  elsif error_path_classes == [Symbol, Integer]
43
43
  add_error(errors_hash, error.path.first, "#{error.text} (at index #{error.path[1]})")
44
+ elsif error_path_classes == [Symbol, Symbol, Integer]
45
+ # this should be refactored to dynamically handle patterns instead of hardcoding the patterns
46
+ add_error(errors_hash, error.path.first, "#{error.path[1]} #{error.text} (at index #{error.path[2]})")
44
47
  else
45
48
  # Don't have any usecases for this - will deal with it when it happens
46
49
  raise PactBroker::Error, "Cannot currently format an error message with path classes #{error_path_classes}"
@@ -36,6 +36,13 @@ module PactBroker
36
36
  href: group_url(represented.consumer.name, options.fetch(:base_url))
37
37
  }
38
38
  end
39
+
40
+ link "pb:delete_integration" do | options |
41
+ {
42
+ title: "Delete the integration between #{represented.consumer.name} and #{represented.provider.name}",
43
+ href: integration_url(represented.consumer.name, represented.provider.name, options.fetch(:base_url))
44
+ }
45
+ end
39
46
  end
40
47
  end
41
48
  end
@@ -43,6 +43,17 @@ module PactBroker
43
43
  pacticipant_branches_url(represented, options[:base_url])
44
44
  end
45
45
 
46
+ links :'pb:deployed-environments' do | context |
47
+ context[:deployed_versions]&.collect do | deployed_version |
48
+ {
49
+ title: "Version deployed to #{deployed_version.environment.display_name}",
50
+ name: deployed_version.environment.display_name,
51
+ href: deployed_version_url(deployed_version, context.fetch(:base_url)),
52
+ currently_deployed: deployed_version.currently_deployed
53
+ }
54
+ end
55
+ end
56
+
46
57
  link :'pb:version' do | options |
47
58
  {
48
59
  title: "Get, create or delete a pacticipant version",
@@ -73,6 +73,22 @@ module PactBroker
73
73
  end
74
74
  end
75
75
 
76
+ links :'pb:deployed-environments' do | context |
77
+ # I couldn't another way to check if call is from a collection or a single item 🤷‍♂️
78
+ # Also not sure why the heck .to_a?(Hash) doesn't work, I mean what...
79
+ deployed_versions = context[:deployed_versions].class.to_s == "Hash" ? context[:deployed_versions][represented.id] : context[:deployed_versions]
80
+ deployed_versions&.collect do | deployed_version |
81
+ {
82
+ title: "Version deployed to #{deployed_version.environment.display_name}",
83
+ name: deployed_version.environment.display_name,
84
+ href: deployed_version_url(deployed_version, context.fetch(:base_url)),
85
+ currently_deployed: deployed_version.currently_deployed
86
+ }.tap do |hash|
87
+ hash[:application_instance] = deployed_version.application_instance unless deployed_version.application_instance.nil?
88
+ end
89
+ end
90
+ end
91
+
76
92
  links :'pb:record-deployment' do | context |
77
93
  context[:environments]&.collect do | environment |
78
94
  {
@@ -414,6 +414,10 @@ module PactBroker
414
414
  end
415
415
  end
416
416
 
417
+ def tag_versions_url(tag, base_url = "")
418
+ "#{pacticipant_url(base_url, tag.pacticipant)}/tags/#{tag.name}/versions"
419
+ end
420
+
417
421
  private
418
422
 
419
423
  def representable_pact pact
@@ -195,12 +195,66 @@ module PactBroker
195
195
  end
196
196
 
197
197
  def consumer_contract
198
- Pact::ConsumerContract.from_json(@json_content)
198
+ pact_object = JSON.parse(@json_content, quirks_mode: true)
199
+ convert_v3_messages_to_interactions(pact_object)
200
+
201
+ pact_object["interactions"]&.each do |interaction|
202
+ add_dummy_html_request_response_to_asynchronous_message(interaction)
203
+ add_dummy_html_request_response_to_synchronous_message(interaction)
204
+ end
205
+
206
+ new_json_content = pact_object.to_json
207
+
208
+ Pact::ConsumerContract.from_json(new_json_content)
199
209
  rescue => e
200
210
  logger.info "Could not parse the following content to a Pact due to #{e.class} #{e.message}, showing raw content instead: #{@json_content}"
201
211
  raise NotAPactError
202
212
  end
203
213
 
214
+ def convert_v3_messages_to_interactions(pact_object)
215
+ return unless pact_object.key?("messages")
216
+
217
+ logger.warn "Detected a v3 Pact, converting 'messages' to 'interactions'."
218
+ pact_object["interactions"] = pact_object.delete("messages")
219
+ end
220
+
221
+ def add_dummy_html_request_response_to_asynchronous_message(interaction)
222
+ if !interaction["request"] || !interaction["response"]
223
+ logger.warn "Interaction '#{interaction['description']}' does not have a request or response, adding dummy request and response so that they can be parsed and appear on the UI."
224
+ end
225
+
226
+ interaction["request"] ||= {
227
+ method: "FAKE_ASYNC_METHOD",
228
+ path: interaction["description"]
229
+ }
230
+
231
+ unless interaction.key?("response")
232
+ interaction["response"] = {
233
+ status: "FAKE_ASYNC_METHOD",
234
+ body: {
235
+ contents: interaction.delete("contents"),
236
+ metadata: interaction.delete("metadata")
237
+ }
238
+ }
239
+ end
240
+ end
241
+
242
+ def add_dummy_html_request_response_to_synchronous_message(interaction)
243
+ if interaction["type"] == "Synchronous/Messages"
244
+ interaction["request"] = {
245
+ method: "FAKE_SYNC_METHOD",
246
+ path: interaction["description"],
247
+ body: interaction.delete("request"),
248
+ }
249
+ interaction["response"] = {
250
+ status: "FAKE_SYNC_METHOD",
251
+ body: {
252
+ contents: interaction.delete("response"),
253
+ }
254
+ }
255
+ end
256
+ end
257
+
204
258
  def h string
205
259
  Rack::Utils.escape_html(string)
206
260
  end
@@ -27,13 +27,17 @@ module PactBroker
27
27
  end
28
28
 
29
29
  def to_json
30
- decorator_class(:versions_decorator).new(versions).to_json(**decorator_options(identifier_from_path.merge(resource_title: resource_title)))
30
+ decorator_class(:versions_decorator).new(versions).to_json(**decorator_options(identifier_from_path.merge(resource_title: resource_title, deployed_versions: deployed_versions)))
31
31
  end
32
32
 
33
33
  def versions
34
34
  @versions ||= version_service.find_pacticipant_versions_in_reverse_order(pacticipant_name, { branch_name: identifier_from_path[:branch_name] }, pagination_options, decorator_class(:versions_decorator).eager_load_associations)
35
35
  end
36
36
 
37
+ def deployed_versions
38
+ @deployed_versions ||= deployed_version_service.find_deployed_versions_for_versions(versions)
39
+ end
40
+
37
41
  def policy_name
38
42
  :'versions::versions'
39
43
  end
@@ -49,6 +49,54 @@ module PactBroker
49
49
  title: "All versions of a pact for a given consumer, provider and consumer version tag",
50
50
  templated: false
51
51
  },
52
+ "pb:branch-pact-versions" =>
53
+ {
54
+ href: base_url + "/pacts/provider/{provider}/consumer/{consumer}/branch/{branch}",
55
+ title: "All versions of pacts for a provider, for a named consumers branch",
56
+ templated: true
57
+ },
58
+ "pb:latest-branch-pact-versions" =>
59
+ {
60
+ href: base_url + "/pacts/provider/{provider}/consumer/{consumer}/branch/{branch}/latest",
61
+ title: "Latest version of pact for a provider, for a named consumers branch",
62
+ templated: true
63
+ },
64
+ "pb:main-branch-pact-versions" =>
65
+ {
66
+ href: base_url + "/pacts/provider/{provider}/consumer/{consumer}/branch",
67
+ title: "All versions of pacts for a provider, for a named consumers main branch",
68
+ templated: true
69
+ },
70
+ "pb:latest-main-branch-pact-versions" =>
71
+ {
72
+ href: base_url + "/pacts/provider/{provider}/consumer/{consumer}/branch/latest",
73
+ title: "Latest version of pact for a provider, for a named consumers main branch",
74
+ templated: true
75
+ },
76
+ "pb:provider-pacts-with-main-branch" =>
77
+ {
78
+ href: base_url + "/pacts/provider/{provider}/branch",
79
+ title: "All pacts for a provider, for any consumers main branch",
80
+ templated: true
81
+ },
82
+ "pb:provider-pacts-with-branch" =>
83
+ {
84
+ href: base_url + "/pacts/provider/{provider}/branch/{branch}",
85
+ title: "All pacts for a provider, for any consumers named branch",
86
+ templated: true
87
+ },
88
+ "pb:latest-provider-pacts-with-main-branch" =>
89
+ {
90
+ href: base_url + "/pacts/provider/{provider}/branch/latest",
91
+ title: "Latest pact for a provider, for any consumers main branch",
92
+ templated: true
93
+ },
94
+ "pb:latest-provider-pacts-with-branch" =>
95
+ {
96
+ href: base_url + "/pacts/provider/{provider}/branch/{branch}/latest",
97
+ title: "Latest pacts for a provider, for any consumers named branch",
98
+ templated: true
99
+ },
52
100
  "pb:pacticipants" =>
53
101
  {
54
102
  href: base_url + "/pacticipants",
@@ -0,0 +1,26 @@
1
+ require "pact_broker/api/resources/provider_pacts"
2
+ require "pact_broker/configuration"
3
+ require "pact_broker/api/decorators/provider_pacts_decorator"
4
+
5
+ module PactBroker
6
+ module Api
7
+ module Resources
8
+ class LatestProviderPactsForBranch < ProviderPacts
9
+ private
10
+
11
+ def pacts
12
+ pact_service.find_latest_pacts_for_provider_by_consumer_branch(
13
+ provider_name,
14
+ branch_name: identifier_from_path[:branch_name],
15
+ main_branch: identifier_from_path[:branch_name].nil?,
16
+ )
17
+ end
18
+
19
+ def resource_title
20
+ suffix = identifier_from_path[:branch_name] ? " with consumer version branch '#{identifier_from_path[:branch_name]}'" : ""
21
+ "Latest pact versions for the provider #{identifier_from_path[:provider_name]}#{suffix}#{!!identifier_from_path[:main_branch] ? ' for main branch' : ''}"
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -14,13 +14,27 @@ module PactBroker
14
14
  end
15
15
 
16
16
  def allowed_methods
17
- ["DELETE", "OPTIONS"]
17
+ ["GET", "DELETE", "OPTIONS"]
18
18
  end
19
19
 
20
20
  def resource_exists?
21
21
  consumer && provider
22
22
  end
23
23
 
24
+ def to_json
25
+ decorator_class(:pact_versions_decorator).new(pacts).to_json(**decorator_options(identifier_from_path))
26
+ end
27
+
28
+ def pacts
29
+ @pacts ||= pact_service.find_pacts_for_provider_and_consumer_by_consumer_branch(
30
+ provider_name,
31
+ consumer_name,
32
+ branch_name: identifier_from_path[:branch_name],
33
+ main_branch: identifier_from_path[:branch_name].nil?,
34
+ latest: identifier_from_path[:resource_name] == "latest_pact_publications_for_main_branch" || identifier_from_path[:resource_name] == "latest_pact_publications_for_branch"
35
+ )
36
+ end
37
+
24
38
  def delete_resource
25
39
  pact_service.delete_all_pact_publications_between consumer_name, and: provider_name, branch_name: identifier_from_path[:branch_name]
26
40
  set_post_deletion_response
@@ -71,7 +71,12 @@ module PactBroker
71
71
  end
72
72
 
73
73
  def to_json
74
- decorator_class(:pacticipant_decorator).new(pacticipant).to_json(**decorator_options)
74
+ decorator_class(:pacticipant_decorator).new(pacticipant)
75
+ .to_json(**decorator_options(deployed_versions: deployed_versions))
76
+ end
77
+
78
+ def deployed_versions
79
+ @deployed_versions ||= deployed_version_service.find_all_deployed_versions_for_pacticipant(pacticipant)
75
80
  end
76
81
 
77
82
  def parsed_pacticipant(pacticipant)
@@ -0,0 +1,47 @@
1
+ require "pact_broker/api/resources/base_resource"
2
+ require "pact_broker/configuration"
3
+ require "pact_broker/api/decorators/provider_pacts_decorator"
4
+
5
+ module PactBroker
6
+ module Api
7
+ module Resources
8
+ class ProviderPactsForConsumerBranch < BaseResource
9
+
10
+ def content_types_provided
11
+ [["application/hal+json", :to_json]]
12
+ end
13
+
14
+ def allowed_methods
15
+ ["GET", "OPTIONS"]
16
+ end
17
+
18
+ def resource_exists?
19
+ !!provider
20
+ end
21
+
22
+ def policy_name
23
+ :'pacts::provider_pacts'
24
+ end
25
+
26
+ def to_json
27
+ decorator_class(:provider_pacts_decorator).new(pacts).to_json(**decorator_options(identifier_from_path.merge(title: resource_title)))
28
+ end
29
+
30
+ private
31
+
32
+ def pacts
33
+ pact_service.find_pacts_for_provider_by_consumer_branch(
34
+ provider_name,
35
+ branch_name: identifier_from_path[:branch_name],
36
+ main_branch: identifier_from_path[:branch_name].nil?,
37
+ )
38
+ end
39
+
40
+ def resource_title
41
+ suffix = identifier_from_path[:branch_name] ? " with consumer version branch '#{identifier_from_path[:branch_name]}'" : ""
42
+ "All pact versions for the provider #{identifier_from_path[:provider_name]}#{suffix}#{!!identifier_from_path[:main_branch] ? ' for main branch' : ''}"
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -25,12 +25,18 @@ module PactBroker
25
25
  :'pacts::pact'
26
26
  end
27
27
 
28
- private
28
+ def environment_uuid
29
+ identifier_from_path[:environment_uuid]
30
+ end
29
31
 
30
- # attr_reader :provider_states
32
+ def branch_name
33
+ identifier_from_path[:branch_name]
34
+ end
35
+
36
+ private
31
37
 
32
38
  def provider_states
33
- @provider_states ||= provider_state_service.list_provider_states(provider)
39
+ @provider_states ||= provider_state_service.list_provider_states(provider, branch_name, environment_uuid)
34
40
  end
35
41
  end
36
42
  end
@@ -0,0 +1,58 @@
1
+ require "pact_broker/api/resources/base_resource"
2
+ require "pact_broker/api/decorators/versions_decorator"
3
+ require "pact_broker/api/resources/pagination_methods"
4
+
5
+ module PactBroker
6
+ module Api
7
+ module Resources
8
+ class TagVersions < BaseResource
9
+ include PactBroker::Api::Resources::PaginationMethods
10
+
11
+ def allowed_methods
12
+ ["GET", "OPTIONS"]
13
+ end
14
+
15
+ def malformed_request?
16
+ super || request.get? && validation_errors_for_schema?(schema, request.query)
17
+ end
18
+
19
+ def content_types_provided
20
+ [["application/hal+json", :to_json]]
21
+ end
22
+
23
+ def policy_name
24
+ :'versions::versions'
25
+ end
26
+
27
+ def resource_exists?
28
+ !tags.empty?
29
+ end
30
+
31
+ def to_json
32
+ decorator_class(:versions_decorator).new(tag_versions)
33
+ .to_json(**decorator_options(deployed_versions: deployed_versions))
34
+ end
35
+
36
+ private
37
+
38
+ def deployed_versions
39
+ @deployed_versions ||= deployed_version_service.find_deployed_versions_for_versions(tag_versions)
40
+ end
41
+
42
+ def tag_versions
43
+ @versions ||= version_service.find_by_ids_in_reverse_order(@tags.select_map(:version_id), pagination_options, decorator_class(:versions_decorator).eager_load_associations)
44
+ end
45
+
46
+ def tags
47
+ @tags ||= tag_service.find_all_by_pacticipant_name_and_tag(**identifier_from_path.slice(:pacticipant_name, :tag_name))
48
+ end
49
+
50
+ def schema
51
+ if request.get?
52
+ PactBroker::Api::Contracts::PaginationQueryParamsSchema
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -54,7 +54,7 @@ module PactBroker
54
54
  end
55
55
 
56
56
  def to_json
57
- decorator_class(:version_decorator).new(version).to_json(**decorator_options(environments: environments))
57
+ decorator_class(:version_decorator).new(version).to_json(**decorator_options(environments: environments, deployed_versions: deployed_versions))
58
58
  end
59
59
 
60
60
  def delete_resource
@@ -83,6 +83,10 @@ module PactBroker
83
83
  @environments ||= environment_service.find_for_pacticipant(version.pacticipant)
84
84
  end
85
85
 
86
+ def deployed_versions
87
+ @deployed_versions ||= deployed_version_service.find_deployed_versions_for_version(version)
88
+ end
89
+
86
90
  def version
87
91
  @version ||= version_service.find_by_pacticipant_name_and_number(identifier_from_path)
88
92
  end
@@ -27,13 +27,17 @@ module PactBroker
27
27
  end
28
28
 
29
29
  def to_json
30
- decorator_class(:versions_decorator).new(versions).to_json(**decorator_options(identifier_from_path))
30
+ decorator_class(:versions_decorator).new(versions).to_json(**decorator_options(identifier_from_path.merge(deployed_versions: deployed_versions)))
31
31
  end
32
32
 
33
33
  def versions
34
34
  @versions ||= version_service.find_pacticipant_versions_in_reverse_order(pacticipant_name, {}, pagination_options, decorator_class(:versions_decorator).eager_load_associations)
35
35
  end
36
36
 
37
+ def deployed_versions
38
+ @deployed_versions ||= deployed_version_service.find_deployed_versions_for_versions(versions)
39
+ end
40
+
37
41
  def policy_name
38
42
  :'versions::versions'
39
43
  end