pact_broker 2.75.0 → 2.78.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +12 -0
  3. data/.github/workflows/test-ruby-3.yml +19 -0
  4. data/.github/workflows/test.yml +19 -4
  5. data/.gitignore +3 -1
  6. data/CHANGELOG.md +48 -0
  7. data/DEVELOPER_SETUP.md +62 -3
  8. data/Dockerfile +1 -0
  9. data/ISSUES.md +13 -5
  10. data/README.md +1 -1
  11. data/config.ru +1 -0
  12. data/db/ddl_statements/head_pact_tags.rb +24 -1
  13. data/db/ddl_statements/latest_tagged_pact_consumer_version_orders.rb +11 -0
  14. data/db/ddl_statements/latest_tagged_pact_publications.rb +6 -0
  15. data/db/ddl_statements/latest_verification_ids_for_consumer_version_tags.rb +13 -0
  16. data/db/migrations/20210117_add_branch_to_version.rb +9 -0
  17. data/db/migrations/20210202_add_created_at_to_head_pact_tags.rb +14 -0
  18. data/db/migrations/20210205_add_pacticipant_id_to_tag.rb +17 -0
  19. data/db/migrations/20210206_add_index_to_tags_and_versions.rb +27 -0
  20. data/db/migrations/20210207_optimise_latest_verification_ids_for_consumer_version_tags.rb +13 -0
  21. data/db/migrations/20210208_optimise_latest_tagged_pact_cv_orders.rb +13 -0
  22. data/db/migrations/20210210_create_environments_table.rb +16 -0
  23. data/docker-compose-issue-repro-with-pact-broker-docker-image.yml +44 -0
  24. data/lib/pact_broker/api.rb +7 -2
  25. data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +8 -0
  26. data/lib/pact_broker/api/contracts/environment_schema.rb +49 -0
  27. data/lib/pact_broker/api/decorators/base_decorator.rb +11 -0
  28. data/lib/pact_broker/api/decorators/dashboard_decorator.rb +5 -1
  29. data/lib/pact_broker/api/decorators/environment_decorator.rb +30 -0
  30. data/lib/pact_broker/api/decorators/environments_decorator.rb +21 -0
  31. data/lib/pact_broker/api/decorators/matrix_decorator.rb +8 -2
  32. data/lib/pact_broker/api/decorators/reason_decorator.rb +2 -2
  33. data/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb +2 -0
  34. data/lib/pact_broker/api/decorators/version_decorator.rb +15 -2
  35. data/lib/pact_broker/api/pact_broker_urls.rb +8 -0
  36. data/lib/pact_broker/api/paths.rb +5 -0
  37. data/lib/pact_broker/api/resources/default_base_resource.rb +15 -2
  38. data/lib/pact_broker/api/resources/environment.rb +76 -0
  39. data/lib/pact_broker/api/resources/environments.rb +75 -0
  40. data/lib/pact_broker/api/resources/index.rb +20 -0
  41. data/lib/pact_broker/api/resources/latest_version.rb +27 -0
  42. data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +1 -0
  43. data/lib/pact_broker/api/resources/verifications.rb +5 -2
  44. data/lib/pact_broker/api/resources/version.rb +15 -9
  45. data/lib/pact_broker/api/resources/webhook_execution.rb +1 -1
  46. data/lib/pact_broker/app.rb +3 -0
  47. data/lib/pact_broker/certificates/certificate.rb +1 -1
  48. data/lib/pact_broker/config/setting.rb +1 -1
  49. data/lib/pact_broker/config/space_delimited_integer_list.rb +25 -0
  50. data/lib/pact_broker/configuration.rb +18 -1
  51. data/lib/pact_broker/db/data_migrations/helpers.rb +4 -0
  52. data/lib/pact_broker/db/data_migrations/set_extra_columns_for_tags.rb +29 -0
  53. data/lib/pact_broker/db/migrate_data.rb +1 -0
  54. data/lib/pact_broker/db/seed_example_data.rb +13 -13
  55. data/lib/pact_broker/deployments/environment.rb +15 -0
  56. data/lib/pact_broker/deployments/environment_service.rb +39 -0
  57. data/lib/pact_broker/doc/controllers/app.rb +1 -1
  58. data/lib/pact_broker/doc/views/index/environment.markdown +37 -0
  59. data/lib/pact_broker/doc/views/index/environments.markdown +53 -0
  60. data/lib/pact_broker/doc/views/index/latest-pact-versions.markdown +1 -1
  61. data/lib/pact_broker/doc/views/index/pacticipant-version-tag.markdown +1 -0
  62. data/lib/pact_broker/doc/views/index/pacticipant-version.markdown +13 -0
  63. data/lib/pact_broker/domain/index_item.rb +18 -4
  64. data/lib/pact_broker/domain/pacticipant.rb +9 -5
  65. data/lib/pact_broker/domain/tag.rb +131 -71
  66. data/lib/pact_broker/domain/verification.rb +3 -2
  67. data/lib/pact_broker/domain/version.rb +58 -23
  68. data/lib/pact_broker/domain/webhook.rb +12 -9
  69. data/lib/pact_broker/hash_refinements.rb +4 -0
  70. data/lib/pact_broker/index/service.rb +55 -49
  71. data/lib/pact_broker/locale/en.yml +3 -1
  72. data/lib/pact_broker/matrix/quick_row.rb +8 -0
  73. data/lib/pact_broker/metrics/service.rb +1 -1
  74. data/lib/pact_broker/pacts/eager_loaders.rb +52 -0
  75. data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +18 -13
  76. data/lib/pact_broker/pacts/lazy_loaders.rb +14 -0
  77. data/lib/pact_broker/pacts/pact_publication.rb +38 -84
  78. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +297 -0
  79. data/lib/pact_broker/pacts/pact_version.rb +1 -2
  80. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +286 -0
  81. data/lib/pact_broker/pacts/repository.rb +5 -231
  82. data/lib/pact_broker/pacts/selected_pact.rb +4 -0
  83. data/lib/pact_broker/pacts/selector.rb +56 -1
  84. data/lib/pact_broker/pacts/selectors.rb +16 -0
  85. data/lib/pact_broker/pacts/service.rb +6 -8
  86. data/lib/pact_broker/pacts/squash_pacts_for_verification.rb +1 -4
  87. data/lib/pact_broker/pacts/verifiable_pact.rb +45 -2
  88. data/lib/pact_broker/pacts/verifiable_pact_messages.rb +56 -16
  89. data/lib/pact_broker/repositories/helpers.rb +4 -0
  90. data/lib/pact_broker/services.rb +9 -0
  91. data/lib/pact_broker/tags/eager_loaders.rb +47 -0
  92. data/lib/pact_broker/tags/repository.rb +3 -1
  93. data/lib/pact_broker/tags/service.rb +0 -3
  94. data/lib/pact_broker/tags/tag_with_latest_flag.rb +1 -0
  95. data/lib/pact_broker/test/http_test_data_builder.rb +101 -35
  96. data/lib/pact_broker/test/test_data_builder.rb +50 -3
  97. data/lib/pact_broker/ui/app.rb +6 -0
  98. data/lib/pact_broker/ui/controllers/base_controller.rb +5 -1
  99. data/lib/pact_broker/ui/controllers/pacts.rb +18 -0
  100. data/lib/pact_broker/ui/view_models/index_item.rb +9 -0
  101. data/lib/pact_broker/ui/view_models/matrix_line.rb +36 -0
  102. data/lib/pact_broker/ui/views/index/show-with-tags.haml +8 -0
  103. data/lib/pact_broker/ui/views/matrix/show.haml +10 -0
  104. data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +7 -5
  105. data/lib/pact_broker/verifications/service.rb +2 -1
  106. data/lib/pact_broker/version.rb +1 -1
  107. data/lib/pact_broker/versions/eager_loaders.rb +71 -0
  108. data/lib/pact_broker/versions/lazy_loaders.rb +13 -0
  109. data/lib/pact_broker/versions/repository.rb +22 -2
  110. data/lib/pact_broker/versions/service.rb +5 -1
  111. data/lib/pact_broker/webhooks/execution.rb +3 -2
  112. data/lib/pact_broker/webhooks/latest_triggered_webhook.rb +2 -0
  113. data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +10 -3
  114. data/lib/pact_broker/webhooks/service.rb +8 -7
  115. data/lib/pact_broker/webhooks/trigger_service.rb +56 -23
  116. data/lib/pact_broker/webhooks/triggered_webhook.rb +14 -5
  117. data/lib/pact_broker/webhooks/webhook.rb +1 -1
  118. data/lib/pact_broker/webhooks/webhook_event.rb +1 -1
  119. data/lib/pact_broker/webhooks/webhook_execution_result.rb +4 -1
  120. data/lib/pact_broker/webhooks/webhook_request_logger.rb +5 -1
  121. data/lib/rack/pact_broker/set_base_url.rb +22 -0
  122. data/lib/sequel/plugins/upsert.rb +18 -4
  123. data/public/stylesheets/index.css +22 -1
  124. data/public/stylesheets/matrix.css +0 -21
  125. data/regression/can_i_deploy_spec.rb +5 -4
  126. data/regression/index_spec.rb +26 -0
  127. data/regression/regression_helper.rb +29 -3
  128. data/regression/script/clear.sh +3 -0
  129. data/regression/script/run.sh +3 -0
  130. data/script/demonstrate-version-branches.rb +33 -0
  131. data/script/pry.rb +2 -2
  132. data/script/reproduce-issue-starting-up.rb +13 -23
  133. data/script/reproduce-issue.rb +18 -14
  134. data/script/trigger-release.sh +1 -1
  135. data/script/webhook-server.ru +5 -5
  136. data/spec/features/create_environment_spec.rb +47 -0
  137. data/spec/features/create_tag_spec.rb +32 -0
  138. data/spec/features/create_version_spec.rb +70 -0
  139. data/spec/features/delete_environment_spec.rb +16 -0
  140. data/spec/features/end_deployment_spec.rb +29 -0
  141. data/spec/features/get_environment_spec.rb +19 -0
  142. data/spec/features/get_environments_spec.rb +20 -0
  143. data/spec/features/record_deployment_spec.rb +28 -0
  144. data/spec/features/update_environment_spec.rb +44 -0
  145. data/spec/fixtures/approvals/modifiable_resources.approved.json +6 -0
  146. data/spec/fixtures/dashboard.json +4 -2
  147. data/spec/integration/ui/index_spec.rb +4 -4
  148. data/spec/lib/pact_broker/api/contracts/environment_schema_spec.rb +83 -0
  149. data/spec/lib/pact_broker/api/decorators/dashboard_decorator_spec.rb +4 -2
  150. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +11 -6
  151. data/spec/lib/pact_broker/api/decorators/reason_decorator_spec.rb +6 -6
  152. data/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb +6 -0
  153. data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +18 -0
  154. data/spec/lib/pact_broker/api/resources/default_base_resource_approval_spec.rb +1 -1
  155. data/spec/lib/pact_broker/api/resources/default_base_resource_spec.rb +1 -12
  156. data/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb +4 -0
  157. data/spec/lib/pact_broker/api/resources/verifications_spec.rb +2 -5
  158. data/spec/lib/pact_broker/api/resources/webhook_execution_result_spec.rb +56 -0
  159. data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +3 -2
  160. data/spec/lib/pact_broker/config/space_delimited_integer_list_spec.rb +47 -0
  161. data/spec/lib/pact_broker/configuration_spec.rb +12 -0
  162. data/spec/lib/pact_broker/doc/controllers/app_spec.rb +3 -5
  163. data/spec/lib/pact_broker/domain/tag_spec.rb +101 -27
  164. data/spec/lib/pact_broker/domain/version_spec.rb +103 -15
  165. data/spec/lib/pact_broker/domain/webhook_spec.rb +7 -7
  166. data/spec/lib/pact_broker/index/service_spec.rb +89 -15
  167. data/spec/lib/pact_broker/pacts/pact_publication_dataset_module_spec.rb +400 -0
  168. data/spec/lib/pact_broker/pacts/pact_publication_spec.rb +434 -14
  169. data/spec/lib/pact_broker/pacts/repository_find_for_verification_fallback_spec.rb +1 -1
  170. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +1 -1
  171. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_branch_spec.rb +224 -0
  172. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_spec.rb +46 -7
  173. data/spec/lib/pact_broker/pacts/selector_spec.rb +3 -2
  174. data/spec/lib/pact_broker/pacts/service_find_for_verification_spec.rb +2 -3
  175. data/spec/lib/pact_broker/pacts/service_spec.rb +9 -7
  176. data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +57 -10
  177. data/spec/lib/pact_broker/tags/repository_spec.rb +2 -0
  178. data/spec/lib/pact_broker/verifications/service_spec.rb +4 -1
  179. data/spec/lib/pact_broker/versions/repository_spec.rb +54 -0
  180. data/spec/lib/pact_broker/webhooks/render_spec.rb +6 -5
  181. data/spec/lib/pact_broker/webhooks/service_spec.rb +13 -9
  182. data/spec/lib/pact_broker/webhooks/trigger_service_spec.rb +60 -18
  183. data/spec/lib/pact_broker/webhooks/webhook_request_logger_spec.rb +8 -0
  184. data/spec/lib/sequel/plugins/upsert_spec.rb +31 -3
  185. data/spec/service_consumers/hal_relation_proxy_app.rb +3 -1
  186. data/spec/service_consumers/provider_states_for_pact_broker_client.rb +16 -0
  187. data/spec/spec_helper.rb +17 -5
  188. data/spec/support/approvals.rb +24 -0
  189. data/spec/support/shared_examples_for_responses.rb +11 -0
  190. data/tasks/db.rake +1 -0
  191. data/tasks/rspec.rake +1 -1
  192. metadata +69 -4
  193. data/docker-compose-issue-repro.yml +0 -22
@@ -43,6 +43,10 @@ module PactBroker
43
43
  select(Sequel[model.table_name].*)
44
44
  end
45
45
 
46
+ def select_append_all_qualified
47
+ select_append(Sequel[model.table_name].*)
48
+ end
49
+
46
50
  def select_for_subquery column
47
51
  if mysql? #stoopid mysql doesn't allow you to modify datasets with subqueries
48
52
  column_name = column.respond_to?(:alias) ? column.alias : column
@@ -73,6 +73,10 @@ module PactBroker
73
73
  get(:metrics_service)
74
74
  end
75
75
 
76
+ def environment_service
77
+ get(:environment_service)
78
+ end
79
+
76
80
  def register_default_services
77
81
  register_service(:index_service) do
78
82
  require 'pact_broker/index/service'
@@ -148,6 +152,11 @@ module PactBroker
148
152
  require 'pact_broker/webhooks/trigger_service'
149
153
  Webhooks::TriggerService
150
154
  end
155
+
156
+ register_service(:environment_service) do
157
+ require 'pact_broker/deployments/environment_service'
158
+ Deployments::EnvironmentService
159
+ end
151
160
  end
152
161
  end
153
162
  end
@@ -0,0 +1,47 @@
1
+ module PactBroker
2
+ module Tags
3
+ module EagerLoaders
4
+ class HeadTag
5
+ def self.call(eo, **_other)
6
+ initialize_association(eo[:rows])
7
+ populate_associations(eo[:rows])
8
+ end
9
+
10
+ def self.initialize_association(tags)
11
+ tags.each{|tag| tag.associations[:head_tag] = nil }
12
+ end
13
+
14
+ def self.populate_associations(tags)
15
+ group_by_pacticipant_id(tags).each do | pacticipant_id, tags |
16
+ populate_associations_by_pacticipant(pacticipant_id, tags)
17
+ end
18
+ end
19
+
20
+ def self.group_by_pacticipant_id(tags)
21
+ tags.to_a.group_by(&:pacticipant_id)
22
+ end
23
+
24
+ def self.populate_associations_by_pacticipant(pacticipant_id, tags)
25
+ latest_tags_for_tags = latest_tags_for_pacticipant_id(
26
+ pacticipant_id,
27
+ tags.collect(&:name).uniq.compact,
28
+ tags.first.class
29
+ )
30
+ self.populate_tags(tags, latest_tags_for_tags)
31
+ end
32
+
33
+ def self.populate_tags(tags, latest_tags_for_tags)
34
+ tags.each do | tag |
35
+ tag.associations[:head_tag] = latest_tags_for_tags[[tag.pacticipant_id, tag.name]]
36
+ end
37
+ end
38
+
39
+ def self.latest_tags_for_pacticipant_id(pacticipant_id, tag_names, tag_class)
40
+ tag_class.latest_tags_for_pacticipant_ids_and_tag_names(pacticipant_id, tag_names).each_with_object({}) do | tag, hash |
41
+ hash[[tag.pacticipant_id, tag.name]] = tag
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -10,7 +10,9 @@ module PactBroker
10
10
  def create args
11
11
  params = {
12
12
  name: args.fetch(:name),
13
- version_id: args.fetch(:version).id
13
+ version_id: args.fetch(:version).id,
14
+ version_order: args.fetch(:version).order,
15
+ pacticipant_id: args.fetch(:version).pacticipant_id
14
16
  }
15
17
  Domain::Tag.new(params).insert_ignore
16
18
  end
@@ -1,12 +1,9 @@
1
1
  require 'pact_broker/repositories'
2
2
 
3
3
  module PactBroker
4
-
5
4
  module Tags
6
5
  module Service
7
-
8
6
  extend self
9
-
10
7
  extend PactBroker::Repositories
11
8
 
12
9
  def create args
@@ -4,6 +4,7 @@ require 'pact_broker/repositories/helpers'
4
4
  module PactBroker
5
5
  module Tags
6
6
  # The tag associated with the latest verification for a given tag
7
+ # TODO remove this class now we have eager loaders for head_tag
7
8
  class TagWithLatestFlag < Sequel::Model(:tags_with_latest_flag)
8
9
  associate(:many_to_one, :version, :class => "PactBroker::Domain::Version", :key => :version_id, :primary_key => :id)
9
10
 
@@ -8,9 +8,9 @@ module PactBroker
8
8
  module Test
9
9
  class HttpTestDataBuilder
10
10
 
11
- attr_reader :client, :last_consumer_name, :last_provider_name, :last_consumer_version_number, :last_provider_version_number
11
+ attr_reader :client, :last_consumer_name, :last_provider_name, :last_consumer_version_number, :last_provider_version_number, :last_provider_version_tag, :last_provider_version_branch
12
12
 
13
- def initialize(pact_broker_base_url, auth)
13
+ def initialize(pact_broker_base_url, auth = {})
14
14
  @client = Faraday.new(url: pact_broker_base_url) do |faraday|
15
15
  faraday.request :json
16
16
  faraday.response :json, :content_type => /\bjson$/
@@ -24,8 +24,8 @@ module PactBroker
24
24
  end
25
25
  end
26
26
 
27
- def sleep
28
- Kernel.sleep 0.5
27
+ def sleep(seconds = 0.5)
28
+ Kernel.sleep(seconds)
29
29
  self
30
30
  end
31
31
 
@@ -42,10 +42,17 @@ module PactBroker
42
42
 
43
43
  def create_tag(pacticipant:, version:, tag:)
44
44
  puts "Creating tag '#{tag}' for #{pacticipant} version #{version}"
45
- client.put("/pacticipants/#{encode(pacticipant)}/versions/#{encode(version)}/tags/#{encode(tag)}", {}).tap { |response| check_for_error(response) }
45
+ client.put("pacticipants/#{encode(pacticipant)}/versions/#{encode(version)}/tags/#{encode(tag)}", {}).tap { |response| check_for_error(response) }
46
46
  self
47
47
  end
48
48
 
49
+ def create_version(pacticipant:, version:, branch:)
50
+ request_body = {
51
+ branch: branch
52
+ }
53
+ client.put("pacticipants/#{encode(pacticipant)}/versions/#{encode(version)}", request_body).tap { |response| check_for_error(response) }
54
+ end
55
+
49
56
  def deploy_to_prod(pacticipant:, version:)
50
57
  puts "Deploying #{pacticipant} version #{version} to prod"
51
58
  create_tag(pacticipant: pacticipant, version: version, tag: "prod")
@@ -55,16 +62,18 @@ module PactBroker
55
62
 
56
63
  def create_pacticipant(name)
57
64
  puts "Creating pacticipant with name #{name}"
58
- client.post("/pacticipants", { name: name}).tap { |response| check_for_error(response) }
65
+ client.post("pacticipants", { name: name}).tap { |response| check_for_error(response) }
59
66
  separate
60
67
  self
61
68
  end
62
69
 
63
- def publish_pact(consumer: last_consumer_name, consumer_version:, provider: last_provider_name, content_id:, tag:)
70
+ def publish_pact(consumer: last_consumer_name, consumer_version:, provider: last_provider_name, content_id:, tag: nil, branch: nil)
64
71
  @last_consumer_name = consumer
65
72
  @last_provider_name = provider
66
73
  @last_consumer_version_number = consumer_version
67
74
 
75
+ create_version(pacticipant: consumer, version: consumer_version, branch: branch) if branch
76
+
68
77
  [*tag].each do | tag |
69
78
  create_tag(pacticipant: consumer, version: consumer_version, tag: tag)
70
79
  end
@@ -72,24 +81,27 @@ module PactBroker
72
81
 
73
82
  content = generate_content(consumer, provider, content_id)
74
83
  puts "Publishing pact for consumer #{consumer} version #{consumer_version} and provider #{provider}"
75
- pact_path = "/pacts/provider/#{encode(provider)}/consumer/#{encode(consumer)}/version/#{encode(consumer_version)}"
84
+ pact_path = "pacts/provider/#{encode(provider)}/consumer/#{encode(consumer)}/version/#{encode(consumer_version)}"
76
85
  @publish_pact_response = client.put(pact_path, content).tap { |response| check_for_error(response) }
77
86
  separate
78
87
  self
79
88
  end
80
89
 
81
- def get_pacts_for_verification(provider: last_provider_name, provider_version_tag: , consumer_version_selectors:, enable_pending: false, include_wip_pacts_since: nil)
90
+ def get_pacts_for_verification(provider: last_provider_name, provider_version_tag: nil, provider_version_branch: nil, consumer_version_selectors:, enable_pending: false, include_wip_pacts_since: nil)
82
91
  @last_provider_name = provider
92
+ @last_provider_version_tag = provider_version_tag
93
+ @last_provder_version_branch = provider_version_branch
83
94
  puts "Fetching pacts for verification for #{provider}"
84
- body = {
95
+ request_body = {
85
96
  providerVersionTags: [*provider_version_tag],
97
+ providerVersionBranch: provider_version_branch,
86
98
  consumerVersionSelectors: consumer_version_selectors,
87
99
  includePendingStatus: enable_pending,
88
100
  includeWipPactsSince: include_wip_pacts_since
89
101
  }.compact
90
- puts body.to_yaml
102
+ puts request_body.to_yaml
91
103
  puts ""
92
- @pacts_for_verification_response = client.post("/pacts/provider/#{encode(provider)}/for-verification", body).tap { |response| check_for_error(response) }
104
+ @pacts_for_verification_response = client.post("pacts/provider/#{encode(provider)}/for-verification", request_body).tap { |response| check_for_error(response) }
93
105
 
94
106
  print_pacts_for_verification
95
107
  separate
@@ -111,28 +123,26 @@ module PactBroker
111
123
  self
112
124
  end
113
125
 
114
- def verify_pact(index: 0, success:, provider: last_provider_name, provider_version_tag: , provider_version: )
126
+ def verify_latest_pact_for_tag(success: true, provider: last_provider_name, consumer: last_consumer_name, consumer_version_tag: , provider_version:, provider_version_tag: nil)
115
127
  @last_provider_name = provider
128
+ @last_consumer_name = consumer
129
+
130
+ url_of_pact_to_verify = "pacts/provider/#{encode(provider)}/consumer/#{encode(consumer)}/latest/#{encode(consumer_version_tag)}"
131
+ publish_verification_results(url_of_pact_to_verify, provider, provider_version, provider_version_tag, success)
132
+ separate
133
+ self
134
+ end
135
+
136
+ def verify_pact(index: 0, success:, provider: last_provider_name, provider_version_tag: last_provider_version_tag, provider_version_branch: last_provider_version_branch, provider_version: )
137
+ @last_provider_name = provider
138
+ @last_provider_version_tag = provider_version_tag
139
+ @last_provider_version_branch = provider_version_branch
140
+
116
141
  pact_to_verify = @pacts_for_verification_response.body["_embedded"]["pacts"][index]
117
142
  raise "No pact found to verify at index #{index}" unless pact_to_verify
118
143
  url_of_pact_to_verify = pact_to_verify["_links"]["self"]["href"]
119
144
 
120
- [*provider_version_tag].each do | tag |
121
- create_tag(pacticipant: provider, version: provider_version, tag: tag)
122
- end
123
- puts "" if [*provider_version_tag].any?
124
-
125
- pact_response = client.get(url_of_pact_to_verify).tap { |response| check_for_error(response) }
126
- verification_results_url = pact_response.body["_links"]["pb:publish-verification-results"]["href"]
127
-
128
- results = {
129
- success: success,
130
- testResults: [],
131
- providerApplicationVersion: provider_version
132
- }
133
- puts "Publishing verification"
134
- puts results.to_yaml
135
- response = client.post(verification_results_url, results.to_json).tap { |response| check_for_error(response) }
145
+ publish_verification_results(url_of_pact_to_verify, provider, provider_version, provider_version_tag, success)
136
146
  separate
137
147
  self
138
148
  end
@@ -150,7 +160,37 @@ module PactBroker
150
160
  "url" => url
151
161
  }
152
162
  }
153
- path = "/webhooks/#{uuid}"
163
+ path = "webhooks/#{uuid}"
164
+ response = client.put(path, request_body.to_json).tap { |response| check_for_error(response) }
165
+ separate
166
+ self
167
+ end
168
+
169
+ def create_global_webhook_for_verification_published(uuid: nil, url: "https://postman-echo.com/post")
170
+ puts "Creating global webhook for contract changed event with uuid #{uuid}"
171
+ uuid ||= SecureRandom.uuid
172
+ request_body = {
173
+ "description" => "A webhook for all consumers and providers",
174
+ "events" => [{
175
+ "name" => "contract_published"
176
+ },{
177
+ "name" => "provider_verification_published"
178
+ }],
179
+ "request" => {
180
+ "method" => "POST",
181
+ "url" => url,
182
+ "headers" => { "Content-Type" => "application/json"},
183
+ "body" => {
184
+ "eventName" => "${pactbroker.eventName}",
185
+ "consumerVersionNumber" => "${pactbroker.consumerVersionNumber}",
186
+ "consumerVersionTags" => "${pactbroker.consumerVersionTags}",
187
+ "githubVerificationStatus" => "${pactbroker.githubVerificationStatus}",
188
+ "providerVersionNumber" => "${pactbroker.providerVersionNumber}",
189
+ "providerVersionTags" => "${pactbroker.providerVersionTags}"
190
+ }
191
+ }
192
+ }
193
+ path = "webhooks/#{uuid}"
154
194
  response = client.put(path, request_body.to_json).tap { |response| check_for_error(response) }
155
195
  separate
156
196
  self
@@ -158,7 +198,7 @@ module PactBroker
158
198
 
159
199
  def delete_webhook(uuid:)
160
200
  puts "Deleting webhook with uuid #{uuid}"
161
- path = "/webhooks/#{uuid}"
201
+ path = "webhooks/#{uuid}"
162
202
  response = client.delete(path).tap { |response| check_for_error(response) }
163
203
  separate
164
204
  self
@@ -170,24 +210,29 @@ module PactBroker
170
210
  end
171
211
 
172
212
  def can_i_deploy(pacticipant:, version:, to:)
173
- can_i_deploy_response = client.get("/can-i-deploy", { pacticipant: pacticipant, version: version, to: to} ).tap { |response| check_for_error(response) }
213
+ can_i_deploy_response = client.get("can-i-deploy", { pacticipant: pacticipant, version: version, to: to} ).tap { |response| check_for_error(response) }
174
214
  can = !!(can_i_deploy_response.body['summary'] || {})['deployable']
175
215
  puts "can-i-deploy #{pacticipant} version #{version} to #{to}: #{can ? 'yes' : 'no'}"
176
- puts (can_i_deploy_response.body['summary'] || can_i_deploy_response.body).to_yaml
216
+ summary = can_i_deploy_response.body['summary']
217
+ verification_result_urls = (can_i_deploy_response.body['matrix'] || []).collect do | row |
218
+ row.dig("verificationResult", "_links", "self", "href")
219
+ end.compact
220
+ summary.merge!("verification_result_urls" => verification_result_urls)
221
+ puts summary.to_yaml
177
222
  separate
178
223
  self
179
224
  end
180
225
 
181
226
  def delete_integration(consumer:, provider:)
182
227
  puts "Deleting all data for the integration between #{consumer} and #{provider}"
183
- client.delete("/integrations/provider/#{encode(provider)}/consumer/#{encode(consumer)}").tap { |response| check_for_error(response) }
228
+ client.delete("integrations/provider/#{encode(provider)}/consumer/#{encode(consumer)}").tap { |response| check_for_error(response) }
184
229
  separate
185
230
  self
186
231
  end
187
232
 
188
233
  def delete_pacticipant(name)
189
234
  puts "Deleting pacticipant #{name}"
190
- @publish_pact_response = client.delete("/pacticipants/#{encode(name)}").tap { |response| check_for_error(response) }
235
+ @publish_pact_response = client.delete("pacticipants/#{encode(name)}").tap { |response| check_for_error(response) }
191
236
  separate
192
237
  self
193
238
  end
@@ -215,6 +260,27 @@ module PactBroker
215
260
  }
216
261
  end
217
262
 
263
+ private
264
+
265
+ def publish_verification_results(url_of_pact_to_verify, provider, provider_version, provider_version_tag, success)
266
+ [*provider_version_tag].each do | tag |
267
+ create_tag(pacticipant: provider, version: provider_version, tag: tag)
268
+ end
269
+ puts "" if [*provider_version_tag].any?
270
+
271
+ pact_response = client.get(url_of_pact_to_verify).tap { |response| check_for_error(response) }
272
+ verification_results_url = pact_response.body["_links"]["pb:publish-verification-results"]["href"]
273
+
274
+ results = {
275
+ success: success,
276
+ testResults: [],
277
+ providerApplicationVersion: provider_version
278
+ }
279
+ puts "Publishing verification"
280
+ puts results.to_yaml
281
+ response = client.post(verification_results_url, results.to_json).tap { |response| check_for_error(response) }
282
+ end
283
+
218
284
  def encode string
219
285
  ERB::Util.url_encode(string)
220
286
  end
@@ -24,6 +24,7 @@ require 'pact_broker/tags/repository'
24
24
  require 'pact_broker/webhooks/repository'
25
25
  require 'pact_broker/certificates/certificate'
26
26
  require 'pact_broker/matrix/row'
27
+ require 'pact_broker/deployments/environment_service'
27
28
  require 'ostruct'
28
29
 
29
30
  module PactBroker
@@ -45,6 +46,7 @@ module PactBroker
45
46
  attr_reader :webhook
46
47
  attr_reader :webhook_execution
47
48
  attr_reader :triggered_webhook
49
+ attr_reader :environment
48
50
 
49
51
  def initialize(params = {})
50
52
  @now = DateTime.now
@@ -159,18 +161,29 @@ module PactBroker
159
161
  def create_consumer_version version_number = "1.0.#{model_counter}", params = {}
160
162
  params.delete(:comment)
161
163
  tag_names = [params.delete(:tag_names), params.delete(:tag_name)].flatten.compact
162
- @consumer_version = PactBroker::Domain::Version.create(:number => version_number, :pacticipant => @consumer)
164
+ @consumer_version = PactBroker::Domain::Version.create(
165
+ number: version_number,
166
+ pacticipant: @consumer,
167
+ branch: params[:branch],
168
+ build_url: params[:build_url]
169
+ )
163
170
  set_created_at_if_set params[:created_at], :versions, { id: @consumer_version.id }
164
171
  tag_names.each do | tag_name |
165
- PactBroker::Domain::Tag.create(name: tag_name, version: @consumer_version)
172
+ tag = PactBroker::Domain::Tag.create(name: tag_name, version: consumer_version)
173
+ set_created_at_if_set(params[:created_at], :tags, { name: tag.name, version_id: consumer_version.id })
166
174
  end
167
175
  self
168
176
  end
169
177
 
170
178
  def create_provider_version version_number = "1.0.#{model_counter}", params = {}
171
179
  params.delete(:comment)
180
+ tag_names = [params.delete(:tag_names), params.delete(:tag_name)].flatten.compact
172
181
  @version = PactBroker::Domain::Version.create(:number => version_number, :pacticipant => @provider)
173
182
  @provider_version = @version
183
+ tag_names.each do | tag_name |
184
+ tag = PactBroker::Domain::Tag.create(name: tag_name, version: provider_version)
185
+ set_created_at_if_set(params[:created_at], :tags, { name: tag.name, version_id: provider_version.id })
186
+ end
174
187
  self
175
188
  end
176
189
 
@@ -186,7 +199,7 @@ module PactBroker
186
199
 
187
200
  def create_tag tag_name, params = {}
188
201
  params.delete(:comment)
189
- @tag = PactBroker::Domain::Tag.create(name: tag_name, version: @version)
202
+ @tag = PactBroker::Domain::Tag.create(name: tag_name, version: @version, version_order: @version.order, pacticipant_id: @version.pacticipant_id)
190
203
  set_created_at_if_set params[:created_at], :tags, { name: @tag.name, version_id: @tag.version_id }
191
204
  self
192
205
  end
@@ -339,6 +352,7 @@ module PactBroker
339
352
 
340
353
  def create_verification parameters = {}
341
354
  parameters.delete(:comment)
355
+ branch = parameters.delete(:branch)
342
356
  tag_names = [parameters.delete(:tag_names), parameters.delete(:tag_name)].flatten.compact
343
357
  provider_version_number = parameters[:provider_version] || '4.5.6'
344
358
  default_parameters = { success: true, number: 1, test_results: {some: 'results'}, wip: false }
@@ -348,6 +362,7 @@ module PactBroker
348
362
  verification = PactBroker::Domain::Verification.new(parameters)
349
363
  @verification = PactBroker::Verifications::Repository.new.create(verification, provider_version_number, @pact)
350
364
  @provider_version = PactBroker::Domain::Version.where(pacticipant_id: @provider.id, number: provider_version_number).single_record
365
+ @provider_version.update(branch: branch) if branch
351
366
 
352
367
  set_created_at_if_set(parameters[:created_at], :verifications, id: @verification.id)
353
368
  set_created_at_if_set(parameters[:created_at], :versions, id: @provider_version.id)
@@ -368,6 +383,18 @@ module PactBroker
368
383
  self
369
384
  end
370
385
 
386
+ def create_environment(name, params = {})
387
+ uuid = params[:uuid] || PactBroker::Deployments::EnvironmentService.next_uuid
388
+ production = params[:production] || false
389
+ @environment = PactBroker::Deployments::EnvironmentService.create(uuid, PactBroker::Deployments::Environment.new(params.merge(name: name, production: production)))
390
+ set_created_at_if_set(params[:created_at], :environments, id: environment.id)
391
+ self
392
+ end
393
+
394
+ def create_deployment(_)
395
+ self
396
+ end
397
+
371
398
  def create_everything_for_an_integration
372
399
  create_pact_with_verification("Foo", "1", "Bar", "2")
373
400
  .create_label("label")
@@ -378,6 +405,26 @@ module PactBroker
378
405
  .create_webhook_execution
379
406
  end
380
407
 
408
+ def find_pacticipant(name)
409
+ PactBroker::Domain::Pacticipant.where(name: name).single_record
410
+ end
411
+
412
+ def find_version(pacticipant_name, version_number)
413
+ PactBroker::Domain::Version.for(pacticipant_name, version_number)
414
+ end
415
+
416
+ def find_pact(consumer_name, consumer_version_number, provider_name)
417
+ pact_repository.find_pact(consumer_name, consumer_version_number, provider_name)
418
+ end
419
+
420
+ def find_pact_publication(consumer_name, consumer_version_number, provider_name)
421
+ PactBroker::Pacts::PactPublication
422
+ .remove_overridden_revisions
423
+ .where(provider: find_pacticipant(provider_name))
424
+ .where(consumer_version: find_version(consumer_name, consumer_version_number))
425
+ .single_record
426
+ end
427
+
381
428
  def model_counter
382
429
  @@model_counter ||= 0
383
430
  @@model_counter += 1