pact_broker 2.85.0 → 2.88.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/trigger_pact_docs_update.yml +22 -0
  3. data/CHANGELOG.md +67 -0
  4. data/DEVELOPER_DOCUMENTATION.md +0 -2
  5. data/db/migrations/20210914_add_labels_to_webhooks.rb +14 -0
  6. data/db/migrations/20210915_add_verified_by_to_verification.rb +6 -0
  7. data/db/migrations/20210929_increase_event_context_column_size.rb +14 -0
  8. data/docker-compose-ci-mysql.yml +1 -0
  9. data/docker-compose-test.yml +2 -0
  10. data/docs/CONFIGURATION.md +255 -66
  11. data/docs/api/WEBHOOKS.md +789 -0
  12. data/docs/configuration.yml +166 -101
  13. data/lib/db.rb +0 -1
  14. data/lib/pact/doc/interaction_view_model.rb +2 -2
  15. data/lib/pact/doc/markdown/consumer_contract_renderer.rb +1 -1
  16. data/lib/pact_broker/api/contracts/configuration.rb +33 -0
  17. data/lib/pact_broker/api/contracts/publish_contracts_schema.rb +35 -16
  18. data/lib/pact_broker/api/contracts/webhook_contract.rb +24 -2
  19. data/lib/pact_broker/api/decorators/matrix_decorator.rb +3 -1
  20. data/lib/pact_broker/api/decorators/pact_decorator.rb +12 -0
  21. data/lib/pact_broker/api/decorators/verification_decorator.rb +9 -3
  22. data/lib/pact_broker/api/decorators/webhook_decorator.rb +27 -4
  23. data/lib/pact_broker/api/pact_broker_urls.rb +30 -6
  24. data/lib/pact_broker/api/resources/all_webhooks.rb +2 -2
  25. data/lib/pact_broker/api/resources/default_base_resource.rb +5 -1
  26. data/lib/pact_broker/api/resources/environment.rb +4 -4
  27. data/lib/pact_broker/api/resources/environments.rb +1 -1
  28. data/lib/pact_broker/api/resources/index.rb +7 -1
  29. data/lib/pact_broker/api/resources/metadata_resource_methods.rb +33 -3
  30. data/lib/pact_broker/api/resources/pact_version.rb +4 -0
  31. data/lib/pact_broker/api/resources/previous_distinct_pact_version.rb +1 -1
  32. data/lib/pact_broker/api/resources/publish_contracts.rb +1 -1
  33. data/lib/pact_broker/api/resources/verification.rb +5 -2
  34. data/lib/pact_broker/api/resources/webhook_execution.rb +7 -3
  35. data/lib/pact_broker/api/resources/webhook_execution_methods.rb +23 -17
  36. data/lib/pact_broker/api.rb +6 -0
  37. data/lib/pact_broker/application_context.rb +5 -0
  38. data/lib/pact_broker/config/runtime_configuration.rb +4 -0
  39. data/lib/pact_broker/config/runtime_configuration_database_methods.rb +1 -1
  40. data/lib/pact_broker/db/clean.rb +1 -2
  41. data/lib/pact_broker/db/delete_overwritten_data.rb +41 -23
  42. data/lib/pact_broker/deployments/deployed_version.rb +1 -0
  43. data/lib/pact_broker/deployments/deployed_version_service.rb +1 -0
  44. data/lib/pact_broker/deployments/environment_service.rb +7 -2
  45. data/lib/pact_broker/deployments/released_version_service.rb +1 -0
  46. data/lib/pact_broker/doc/controllers/app.rb +1 -0
  47. data/lib/pact_broker/doc/views/can-i-deploy.markdown +2 -1
  48. data/lib/pact_broker/doc/views/index/publish-contracts.markdown +38 -9
  49. data/lib/pact_broker/doc/views/pacticipant/label.markdown +12 -0
  50. data/lib/pact_broker/doc/views/provider-pacts-for-verification.markdown +7 -7
  51. data/lib/pact_broker/doc/views/webhooks.markdown +17 -0
  52. data/lib/pact_broker/domain/index_item.rb +9 -0
  53. data/lib/pact_broker/domain/pacticipant.rb +4 -0
  54. data/lib/pact_broker/domain/verification.rb +19 -4
  55. data/lib/pact_broker/domain/webhook.rb +5 -5
  56. data/lib/pact_broker/domain/webhook_pacticipant.rb +6 -0
  57. data/lib/pact_broker/index/service.rb +4 -4
  58. data/lib/pact_broker/locale/en.yml +4 -1
  59. data/lib/pact_broker/matrix/head_row.rb +1 -1
  60. data/lib/pact_broker/matrix/parse_can_i_deploy_query.rb +5 -3
  61. data/lib/pact_broker/matrix/quick_row.rb +0 -1
  62. data/lib/pact_broker/matrix/repository.rb +0 -1
  63. data/lib/pact_broker/matrix/row.rb +2 -2
  64. data/lib/pact_broker/pacticipants/repository.rb +1 -1
  65. data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +0 -1
  66. data/lib/pact_broker/pacts/metadata.rb +7 -1
  67. data/lib/pact_broker/pacts/pact_publication.rb +7 -0
  68. data/lib/pact_broker/pacts/pact_publication_clean_selector_dataset_module.rb +19 -0
  69. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +30 -2
  70. data/lib/pact_broker/pacts/pact_version.rb +24 -1
  71. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +5 -4
  72. data/lib/pact_broker/pacts/repository.rb +50 -47
  73. data/lib/pact_broker/pacts/service.rb +5 -5
  74. data/lib/pact_broker/string_refinements.rb +1 -1
  75. data/lib/pact_broker/test/http_test_data_builder.rb +40 -10
  76. data/lib/pact_broker/test/test_data_builder.rb +28 -5
  77. data/lib/pact_broker/ui/helpers/url_helper.rb +12 -0
  78. data/lib/pact_broker/ui/view_models/index_item.rb +15 -1
  79. data/lib/pact_broker/ui/view_models/index_item_branch_head.rb +39 -0
  80. data/lib/pact_broker/ui/view_models/index_item_provider_branch_head.rb +39 -0
  81. data/lib/pact_broker/ui/views/dashboard/show.haml +14 -7
  82. data/lib/pact_broker/verifications/repository.rb +5 -2
  83. data/lib/pact_broker/verifications/service.rb +7 -4
  84. data/lib/pact_broker/version.rb +1 -1
  85. data/lib/pact_broker/versions/abbreviate_number.rb +8 -4
  86. data/lib/pact_broker/versions/branch_head.rb +0 -2
  87. data/lib/pact_broker/versions/branch_version.rb +1 -0
  88. data/lib/pact_broker/versions/repository.rb +0 -1
  89. data/lib/pact_broker/webhooks/event_listener.rb +4 -2
  90. data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +18 -3
  91. data/lib/pact_broker/webhooks/repository.rb +10 -4
  92. data/lib/pact_broker/webhooks/trigger_service.rb +1 -1
  93. data/lib/pact_broker/webhooks/webhook.rb +71 -8
  94. data/lib/webmachine/describe_routes.rb +62 -0
  95. data/public/stylesheets/index.css +5 -0
  96. data/script/data/auto-create-things-for-tags.rb +1 -0
  97. data/script/data/branches.rb +1 -1
  98. data/script/data/contract-published-requiring-verification.rb +0 -1
  99. data/script/data/verify-pact-for-multiple-selectors.rb +30 -0
  100. data/script/docs/generate-api-docs.rb +117 -0
  101. data/script/docs/generate-configuration-docs.rb +24 -3
  102. data/script/docs/regenerate-api-docs.sh +11 -0
  103. data/script/generate-erd +55 -0
  104. data/spec/features/create_webhook_spec.rb +55 -10
  105. data/spec/features/get_pact_spec.rb +2 -3
  106. data/spec/fixtures/approvals/docs_webhooks_executing_a_saved_webhook_options.approved.json +20 -0
  107. data/spec/fixtures/approvals/docs_webhooks_executing_a_saved_webhook_post.approved.json +43 -0
  108. data/spec/fixtures/approvals/docs_webhooks_executing_an_unsaved_webhook_options.approved.json +20 -0
  109. data/spec/fixtures/approvals/docs_webhooks_executing_an_unsaved_webhook_post.approved.json +63 -0
  110. data/spec/fixtures/approvals/docs_webhooks_logs_of_triggered_webhook_get.approved.json +20 -0
  111. data/spec/fixtures/approvals/docs_webhooks_logs_of_triggered_webhook_options.approved.json +20 -0
  112. data/spec/fixtures/approvals/docs_webhooks_pact_webhooks_get.approved.json +45 -0
  113. data/spec/fixtures/approvals/docs_webhooks_pact_webhooks_options.approved.json +20 -0
  114. data/spec/fixtures/approvals/docs_webhooks_triggered_webhooks_for_pact_publication_get.approved.json +52 -0
  115. data/spec/fixtures/approvals/docs_webhooks_triggered_webhooks_for_pact_publication_options.approved.json +20 -0
  116. data/spec/fixtures/approvals/docs_webhooks_triggered_webhooks_for_verification_publication_get.approved.json +32 -0
  117. data/spec/fixtures/approvals/docs_webhooks_triggered_webhooks_for_verification_publication_options.approved.json +20 -0
  118. data/spec/fixtures/approvals/docs_webhooks_webhook_get.approved.json +74 -0
  119. data/spec/fixtures/approvals/docs_webhooks_webhook_options.approved.json +20 -0
  120. data/spec/fixtures/approvals/docs_webhooks_webhook_put.approved.json +77 -0
  121. data/spec/fixtures/approvals/docs_webhooks_webhooks_for_a_provider_get.approved.json +41 -0
  122. data/spec/fixtures/approvals/docs_webhooks_webhooks_for_a_provider_options.approved.json +20 -0
  123. data/spec/fixtures/approvals/docs_webhooks_webhooks_for_consumer_and_provider_get.approved.json +45 -0
  124. data/spec/fixtures/approvals/docs_webhooks_webhooks_for_consumer_and_provider_options.approved.json +20 -0
  125. data/spec/fixtures/approvals/docs_webhooks_webhooks_for_consumer_get.approved.json +41 -0
  126. data/spec/fixtures/approvals/docs_webhooks_webhooks_for_consumer_options.approved.json +20 -0
  127. data/spec/fixtures/approvals/docs_webhooks_webhooks_get.approved.json +45 -0
  128. data/spec/fixtures/approvals/docs_webhooks_webhooks_options.approved.json +20 -0
  129. data/spec/fixtures/approvals/docs_webhooks_webhooks_post.approved.json +78 -0
  130. data/spec/fixtures/approvals/docs_webhooks_webhooks_status_get.approved.json +79 -0
  131. data/spec/fixtures/approvals/docs_webhooks_webhooks_status_options.approved.json +20 -0
  132. data/spec/fixtures/approvals/get_provider_pacts_for_verification.approved.json +1 -2
  133. data/spec/fixtures/approvals/publish_contract_no_branch.approved.json +1 -2
  134. data/spec/fixtures/approvals/publish_contract_nothing_exists.approved.json +1 -2
  135. data/spec/fixtures/approvals/publish_contract_nothing_exists_with_webhook.approved.json +1 -2
  136. data/spec/fixtures/approvals/publish_contract_verification_already_exists.approved.json +1 -2
  137. data/spec/fixtures/approvals/publish_contract_with_validation_error.approved.json +1 -2
  138. data/spec/fixtures/invalid-publish-contract-body.json +38 -0
  139. data/spec/fixtures/verification.json +4 -0
  140. data/spec/integration/pact_metdata_spec.rb +105 -0
  141. data/spec/integration/webhooks/contract_publication_spec.rb +68 -0
  142. data/spec/integration/webhooks/contract_requiring_verification_published_spec.rb +67 -0
  143. data/spec/integration/webhooks/pact_publication_spec.rb +51 -0
  144. data/spec/integration/webhooks_documentation_spec.rb +348 -0
  145. data/spec/lib/pact/doc/markdown/consumer_contract_renderer_spec.rb +2 -2
  146. data/spec/lib/pact_broker/api/contracts/publish_contracts_schema_spec.rb +13 -0
  147. data/spec/lib/pact_broker/api/contracts/webhook_contract_spec.rb +50 -0
  148. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +1 -1
  149. data/spec/lib/pact_broker/api/decorators/verification_decorator_spec.rb +15 -7
  150. data/spec/lib/pact_broker/api/decorators/verification_summary_decorator_spec.rb +4 -2
  151. data/spec/lib/pact_broker/api/decorators/webhook_decorator_spec.rb +4 -4
  152. data/spec/lib/pact_broker/api/pact_broker_urls_spec.rb +18 -0
  153. data/spec/lib/pact_broker/api/resources/triggered_webhook_logs_spec.rb +6 -5
  154. data/spec/lib/pact_broker/config/runtime_configuration_documentation_spec.rb +30 -0
  155. data/spec/lib/pact_broker/deployments/environment_service_spec.rb +22 -1
  156. data/spec/lib/pact_broker/domain/webhook_spec.rb +35 -0
  157. data/spec/lib/pact_broker/matrix/head_row_spec.rb +9 -5
  158. data/spec/lib/pact_broker/matrix/parse_can_i_deploy_query_spec.rb +13 -0
  159. data/spec/lib/pact_broker/pacts/{latest_tagged_pact_publications_spec.rb → pact_publication_clean_selector_dataset_module_spec.rb} +7 -9
  160. data/spec/lib/pact_broker/pacts/pact_version_spec.rb +32 -0
  161. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +4 -5
  162. data/spec/lib/pact_broker/pacts/repository_spec.rb +33 -0
  163. data/spec/lib/pact_broker/ui/view_models/index_item_spec.rb +1 -1
  164. data/spec/lib/pact_broker/verifications/service_spec.rb +22 -8
  165. data/spec/lib/pact_broker/versions/abbreviate_number_spec.rb +2 -1
  166. data/spec/lib/pact_broker/webhooks/render_spec.rb +3 -2
  167. data/spec/lib/pact_broker/webhooks/repository_spec.rb +158 -15
  168. data/spec/lib/pact_broker/webhooks/webhook_spec.rb +8 -5
  169. data/spec/support/documentation.rb +64 -0
  170. data/spec/support/rack_helpers.rb +1 -1
  171. data/tasks/db.rake +4 -1
  172. data/tasks/development.rake +14 -13
  173. metadata +89 -12
  174. data/lib/pact_broker/pacts/all_pact_publications.rb +0 -158
  175. data/lib/pact_broker/pacts/latest_pact_publications.rb +0 -48
  176. data/lib/pact_broker/pacts/latest_pact_publications_by_consumer_version.rb +0 -26
  177. data/lib/pact_broker/pacts/latest_tagged_pact_publications.rb +0 -45
  178. data/lib/pact_broker/verifications/latest_verification_for_pact_version.rb +0 -39
  179. data/spec/lib/pact_broker/verifications/latest_verification_for_pact_version_spec.rb +0 -18
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env ruby
2
+ require "json"
3
+ require "pathname"
4
+ require "fileutils"
5
+
6
+ EXAMPLES_FILE_PATTERN = "spec/fixtures/approvals/docs_*"
7
+ API_DOCS_DIR = Pathname.new("docs/api")
8
+
9
+
10
+ class Category
11
+ attr_reader :name, :examples, :not_options_examples
12
+
13
+ def initialize(name, examples)
14
+ @name = name
15
+ @examples = examples
16
+ @options_example = examples.find { | example | example[:request][:method] == "OPTIONS" }
17
+ @not_options_examples = examples.select { | example | example[:request][:method] != "OPTIONS" }
18
+ end
19
+
20
+ def path_template
21
+ not_options_examples.first[:request][:path_template]
22
+ end
23
+
24
+ def allowed_methods
25
+ if options_example
26
+ options_example[:response][:headers][:'Access-Control-Allow-Methods'].split(",").collect(&:strip).reject { |m| m == "OPTIONS" }
27
+ else
28
+ []
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :other_examples, :options_example
35
+
36
+ end
37
+
38
+ def generate_example_markdown_for_examples(name, examples)
39
+ category = Category.new(name, examples)
40
+
41
+
42
+ not_options_docs = category.not_options_examples.collect { | example | generate_example_markdown(example) }
43
+
44
+ allowed_methods = category.allowed_methods.collect{ | meth| "`#{meth}`"}.join(", ")
45
+
46
+ "
47
+ ## #{name}
48
+
49
+ Path: `#{category.path_template}`<br/>
50
+ Allowed methods: #{allowed_methods}<br/>
51
+ #{not_options_docs.join("\n")}
52
+ "
53
+ end
54
+
55
+ def generate_example_markdown(hash)
56
+ body = nil
57
+ if hash[:request][:body]
58
+ body = "Body:
59
+
60
+ ```
61
+ #{JSON.pretty_generate(hash[:request][:body])}
62
+ ```
63
+ "
64
+ end
65
+
66
+ "
67
+ ### #{hash[:request][:method]}
68
+
69
+ #### Request
70
+
71
+ Headers: `#{hash[:request][:headers]&.to_json}`<br/>
72
+ #{body}
73
+
74
+ #### Response
75
+
76
+ Status: `#{hash[:response][:status]}`<br/>
77
+ Headers: `#{hash[:response][:headers]&.to_json}`<br/>
78
+ Body:
79
+
80
+ ```
81
+ #{body_markdown(hash[:response][:body])}
82
+ ```
83
+ "
84
+ end
85
+
86
+ def body_markdown(body)
87
+ body.is_a?(Hash) ? JSON.pretty_generate(body) : body
88
+ end
89
+
90
+ file_names = Dir.glob(EXAMPLES_FILE_PATTERN)
91
+
92
+ examples = file_names.collect do | file_name |
93
+ JSON.parse(File.read(file_name), symbolize_names: true)
94
+ end
95
+
96
+ examples_by_category = examples.group_by { | hash | hash[:category] }
97
+
98
+ FileUtils.rm_rf(API_DOCS_DIR)
99
+ FileUtils.mkdir_p(API_DOCS_DIR)
100
+
101
+ examples_by_category.each do | category, category_examples |
102
+
103
+ examples_by_name = category_examples.sort_by{ |hash| hash[:order] }.group_by { | hash | hash[:name] }
104
+
105
+ docs = examples_by_name.collect do | name, examples_for_name |
106
+ generate_example_markdown_for_examples(name, examples_for_name)
107
+ end
108
+
109
+ file_name = (API_DOCS_DIR / category.upcase).to_s + ".md"
110
+ contents = "
111
+ # #{category}
112
+
113
+ #{docs.join("\n")}
114
+ "
115
+
116
+ File.open(file_name, "w") { |file| file << contents }
117
+ end
@@ -1,7 +1,16 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "yaml"
3
+ INTRO = <<EOM
4
+ <!-- This is a generated file. Please do not edit it directly. -->
5
+
6
+ The Pact Broker supports configuration via environment variables or a YAML file.
4
7
 
8
+ To configure the application using a YAML file, place it in the location `config/pact_broker.yml`,
9
+ relative to the working directory of the application, or set the environment
10
+ variable `PACT_BROKER_CONF` to the full path to the configuration file.
11
+ EOM
12
+
13
+ require "yaml"
5
14
  $stream = StringIO.new
6
15
 
7
16
  def write string
@@ -25,6 +34,7 @@ def in_backticks value
25
34
  end
26
35
 
27
36
  docs_dir = File.expand_path("../../../docs", __FILE__)
37
+ configuration_doc_path = File.join(docs_dir, "CONFIGURATION.md")
28
38
  environment_variable_file = File.join(docs_dir, "configuration.yml")
29
39
  doc = YAML.load(File.read(environment_variable_file))
30
40
 
@@ -42,6 +52,8 @@ write "# Pact Broker Configuration\n\n"
42
52
 
43
53
  write "\n"
44
54
 
55
+ write INTRO
56
+
45
57
  doc["groups"].each do | group |
46
58
  write "<br/>\n\n"
47
59
  write "## #{group["title"]}\n\n<hr/>\n"
@@ -55,9 +67,17 @@ doc["groups"].each do | group |
55
67
  write "### #{name}\n\n"
56
68
  write "#{metadata["description"]}\n\n"
57
69
 
70
+ write "**YAML configuration key name:** #{in_backticks(name)}<br/>"
71
+ write "**Environment variable name:** `PACT_BROKER_#{name.upcase}`<br/>"
72
+ write "**Supported versions:** #{metadata["supported_versions"]}<br/>" if metadata["supported_versions"]
58
73
  write "**Required:** #{metadata["required"] || "false"}<br/>" if metadata["required"]
59
74
  write "**Format:** #{metadata["format"]}<br/>" if metadata["format"]
60
- write "**Default:** #{in_backticks(metadata["default"])}<br/>" if !metadata["default"].nil?
75
+
76
+ write "**Default:** #{in_backticks(metadata["default_value"])}<br/>" if !metadata["default_value"].nil?
77
+ write "**Default:** #{metadata["default_description"]}<br/>" if !metadata["default_description"].nil?
78
+ if metadata["allowed_values_description"]
79
+ write "**Allowed values:** #{metadata["allowed_values_description"]}<br/>"
80
+ end
61
81
  if metadata["allowed_values"]
62
82
  allowed_values = metadata["allowed_values"].collect{ |val| in_backticks(val) }.join(", ")
63
83
  write "**Allowed values:** #{allowed_values}<br/>"
@@ -72,7 +92,7 @@ doc["groups"].each do | group |
72
92
  end
73
93
  end
74
94
 
75
- File.open(File.join(docs_dir, "CONFIGURATION.md"), "w") { |file| file << $stream.string }
95
+ File.open(configuration_doc_path, "w") { |file| file << $stream.string }
76
96
 
77
97
  required_env_vars = []
78
98
 
@@ -84,3 +104,4 @@ end
84
104
 
85
105
  puts "Required:"
86
106
  puts required_env_vars
107
+ puts configuration_doc_path
@@ -0,0 +1,11 @@
1
+ #!/bin/sh
2
+ rm spec/fixtures/approvals/docs_webhooks*
3
+ bundle exec rspec spec/integration/webhooks_documentation_spec.rb
4
+ script/test/approval-all.sh
5
+ bundle exec rspec spec/integration/webhooks_documentation_spec.rb
6
+ script/docs/generate-api-docs.rb
7
+
8
+ git add spec/integration/webhooks_documentation_spec.rb
9
+ git add spec/fixtures/approvals
10
+ git add docs/api
11
+ git add script/docs/generate-api-docs.rb
@@ -0,0 +1,55 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require "sequel"
4
+ Sequel::Model.plugin :subclasses
5
+
6
+ DATABASE_CREDENTIALS = {
7
+ adapter: "postgres",
8
+ database: ENV["DATABASE"] || "postgres",
9
+ username: ENV["DATABASE_USERNAME"] || "postgres",
10
+ password: ENV["DATABASE_PASSWORD"] || "postgres",
11
+ host: "localhost",
12
+ :encoding => "utf8"
13
+ }
14
+ Sequel.connect(DATABASE_CREDENTIALS)
15
+
16
+ $LOAD_PATH.unshift "./lib"
17
+ $LOAD_PATH.unshift "./tasks"
18
+ ENV["RACK_ENV"] = "development"
19
+ require "pact_broker/db/models"
20
+
21
+ def generate_erd_graphviz()
22
+ associations = []
23
+ Sequel::Model.descendents.each do |model|
24
+ next if model.name.nil?
25
+ model.associations.each do |a|
26
+ ar = model.association_reflection(a)
27
+ associations << [model.name, ar[:type], ar.associated_class.name]
28
+ end
29
+ end
30
+ styles = {
31
+ :many_to_one=>:bold,
32
+ :one_to_many=>:solid,
33
+ :many_to_many=>:dashed,
34
+ :one_to_one=>:dotted
35
+ }
36
+
37
+ graph = "digraph G {\n"
38
+ graph += associations.uniq.map{|c, t, ac| " \"#{c}\" -> \"#{ac}\" [style=#{styles[t]}];"}.sort.join("\n")
39
+ graph += "\n}"
40
+
41
+ graph
42
+ end
43
+
44
+ puts "Usage:"
45
+ puts "generate-erd [erd-filename]"
46
+ puts "CAUTION: Please make sure that you have graphviz installed"
47
+ puts
48
+
49
+ GRAPHVIZ_FILENAME = ARGV[0] || "erd"
50
+
51
+ puts "Generating graphviz file ..."
52
+ File.write("#{GRAPHVIZ_FILENAME}.dot", generate_erd_graphviz())
53
+
54
+ puts "Converting graphviz file to a pdf"
55
+ `dot -Tpdf "#{GRAPHVIZ_FILENAME}.dot" > "#{GRAPHVIZ_FILENAME}.pdf"`
@@ -6,10 +6,14 @@ describe "Creating a webhook" do
6
6
  let(:headers) { {"CONTENT_TYPE" => "application/json"} }
7
7
  let(:response_body) { JSON.parse(subject.body, symbolize_names: true)}
8
8
  let(:webhook_json) { webhook_hash.to_json }
9
+ let(:provider) { nil }
10
+ let(:consumer) { nil }
9
11
  let(:webhook_hash) do
10
12
  {
11
13
  description: "trigger build",
12
14
  enabled: false,
15
+ provider: provider,
16
+ consumer: consumer,
13
17
  events: [{
14
18
  name: "contract_content_changed"
15
19
  }],
@@ -23,7 +27,7 @@ describe "Creating a webhook" do
23
27
  a: "body"
24
28
  }
25
29
  }
26
- }
30
+ }.compact
27
31
  end
28
32
 
29
33
  subject { post(path, webhook_json, headers) }
@@ -64,33 +68,74 @@ describe "Creating a webhook" do
64
68
 
65
69
  context "for a provider" do
66
70
  let(:path) { "/webhooks" }
71
+ let(:provider) { { name: "Some Provider" } }
67
72
 
68
- before do
69
- webhook_hash[:provider] = { name: "Some Provider" }
70
- end
71
-
72
- its(:status) { is_expected.to be 201 }
73
+ its(:status) { is_expected.to eq 201 }
73
74
 
74
75
  it "creates a webhook without a consumer" do
75
76
  subject
76
77
  expect(PactBroker::Webhooks::Webhook.first.provider).to_not be nil
77
78
  expect(PactBroker::Webhooks::Webhook.first.consumer).to be nil
78
79
  end
80
+
81
+ context "with label" do
82
+ let(:provider) { { label: "my_label" } }
83
+
84
+ its(:status) { is_expected.to eq 201 }
85
+
86
+ it "creates a webhook without explicit consumer and provider with provider label" do
87
+ subject
88
+ expect(PactBroker::Webhooks::Webhook.first.provider).to be nil
89
+ expect(PactBroker::Webhooks::Webhook.first.consumer).to be nil
90
+ expect(PactBroker::Webhooks::Webhook.first.provider_label).to eq "my_label"
91
+ end
92
+ end
93
+
94
+ context "with both label and name" do
95
+ let(:provider) { { name: "Some Provider", label: "my_label" } }
96
+
97
+ its(:status) { is_expected.to eq 400 }
98
+
99
+ it "returns the validation errors" do
100
+ expect(response_body[:errors]).to_not be_empty
101
+ end
102
+ end
79
103
  end
80
104
 
81
105
  context "for a consumer" do
82
106
  let(:path) { "/webhooks" }
83
- before do
84
- webhook_hash[:consumer] = { name: "Some Consumer" }
85
- end
107
+ let(:consumer) { { name: "Some Consumer" } }
86
108
 
87
- its(:status) { is_expected.to be 201 }
109
+ its(:status) { is_expected.to eq 201 }
88
110
 
89
111
  it "creates a webhook without a provider" do
90
112
  subject
91
113
  expect(PactBroker::Webhooks::Webhook.first.consumer).to_not be nil
92
114
  expect(PactBroker::Webhooks::Webhook.first.provider).to be nil
93
115
  end
116
+
117
+ context "with label" do
118
+ let(:consumer) { { label: "my_label" } }
119
+
120
+ its(:status) { is_expected.to eq 201 }
121
+
122
+ it "creates a webhook without explicit consumer and provider with consumer label" do
123
+ subject
124
+ expect(PactBroker::Webhooks::Webhook.first.provider).to be nil
125
+ expect(PactBroker::Webhooks::Webhook.first.consumer).to be nil
126
+ expect(PactBroker::Webhooks::Webhook.first.consumer_label).to eq "my_label"
127
+ end
128
+ end
129
+
130
+ context "with both label and name" do
131
+ let(:consumer) { { name: "Some Consumer", label: "my_label" } }
132
+
133
+ its(:status) { is_expected.to eq 400 }
134
+
135
+ it "returns the validation errors" do
136
+ expect(response_body[:errors]).to_not be_empty
137
+ end
138
+ end
94
139
  end
95
140
 
96
141
  context "with no consumer or provider" do
@@ -6,7 +6,7 @@ describe "retrieving a pact" do
6
6
  let(:path) { "/pacts/provider/a%20provider/consumer/a%20consumer/version/1.2.3A" }
7
7
 
8
8
  before do
9
- TestDataBuilder.new.create_pact_with_hierarchy("A Consumer", "1.2.3a", "A Provider").and_return(:pact)
9
+ td.create_pact_with_hierarchy("A Consumer", "1.2.3a", "A Provider").and_return(:pact)
10
10
  end
11
11
 
12
12
  context "when case sensitivity is turned on" do
@@ -35,8 +35,7 @@ describe "retrieving a pact" do
35
35
  let(:path) { "/pacts/provider/a%20provider/consumer/a%20consumer/latest/PROD" }
36
36
 
37
37
  before do
38
- TestDataBuilder.new
39
- .create_consumer("A Consumer")
38
+ td.create_consumer("A Consumer")
40
39
  .create_consumer_version("1.2.3")
41
40
  .create_consumer_version_tag("prod")
42
41
  .create_provider("A Provider")
@@ -0,0 +1,20 @@
1
+ {
2
+ "category": "Webhooks",
3
+ "name": "Executing a saved webhook",
4
+ "order": 33,
5
+ "request": {
6
+ "method": "OPTIONS",
7
+ "path_template": "/webhooks/:uuid/execute",
8
+ "path": "/webhooks/d2181b32-8b03-4daf-8cc0-d9168b2f6fac/execute",
9
+ "headers": {
10
+ "Accept": "application/hal+json"
11
+ }
12
+ },
13
+ "response": {
14
+ "status": 200,
15
+ "headers": {
16
+ "Access-Control-Allow-Methods": "POST, OPTIONS"
17
+ },
18
+ "body": ""
19
+ }
20
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "category": "Webhooks",
3
+ "name": "Executing a saved webhook",
4
+ "order": 35,
5
+ "request": {
6
+ "method": "POST",
7
+ "path_template": "/webhooks/:uuid/execute",
8
+ "path": "/webhooks/d2181b32-8b03-4daf-8cc0-d9168b2f6fac/execute",
9
+ "headers": {
10
+ "Content-Type": "application/json",
11
+ "Accept": "application/hal+json"
12
+ }
13
+ },
14
+ "response": {
15
+ "status": 200,
16
+ "headers": {
17
+ "Content-Type": "application/hal+json;charset=utf-8"
18
+ },
19
+ "body": {
20
+ "request": {
21
+ "headers": {
22
+ "accept": "*/*",
23
+ "user-agent": "Pact Broker v2.87.0",
24
+ "content-type": "application/json"
25
+ },
26
+ "body": {
27
+ "pactUrl": "http://example.org/pacts/provider/Bar/consumer/Foo/pact-version/3e193ecb37ad04b43ce974a38352c704b2e0ed6b/metadata/Y3ZuPTImdz10cnVl"
28
+ },
29
+ "url": "/example"
30
+ },
31
+ "response": {
32
+ "status": 200,
33
+ "headers": {
34
+ },
35
+ "body": ""
36
+ },
37
+ "logs": "[2021-09-01T10:07:21Z] DEBUG: Webhook context {\"base_url\":\"http://example.org\",\"event_name\":\"test\"}\n[2021-09-01T10:07:21Z] INFO: HTTP/1.1 POST https://example.org/example\n[2021-09-01T10:07:21Z] INFO: accept: */*\n[2021-09-01T10:07:21Z] INFO: user-agent: Pact Broker v2.87.0\n[2021-09-01T10:07:21Z] INFO: content-type: application/json\n[2021-09-01T10:07:21Z] INFO: {\"pactUrl\":\"http://example.org/pacts/provider/Bar/consumer/Foo/pact-version/3e193ecb37ad04b43ce974a38352c704b2e0ed6b/metadata/Y3ZuPTImdz10cnVl\"}\n[2021-09-01T10:07:21Z] INFO: HTTP/1.0 200 \n[2021-09-01T10:07:21Z] INFO: \n",
38
+ "success": true,
39
+ "_links": {
40
+ }
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "category": "Webhooks",
3
+ "name": "Executing an unsaved webhook",
4
+ "order": 37,
5
+ "request": {
6
+ "method": "OPTIONS",
7
+ "path_template": "/webhooks/execute",
8
+ "path": "/webhooks/execute",
9
+ "headers": {
10
+ "Accept": "application/hal+json"
11
+ }
12
+ },
13
+ "response": {
14
+ "status": 200,
15
+ "headers": {
16
+ "Access-Control-Allow-Methods": "POST, OPTIONS"
17
+ },
18
+ "body": ""
19
+ }
20
+ }
@@ -0,0 +1,63 @@
1
+ {
2
+ "category": "Webhooks",
3
+ "name": "Executing an unsaved webhook",
4
+ "order": 39,
5
+ "request": {
6
+ "method": "POST",
7
+ "path_template": "/webhooks/execute",
8
+ "path": "/webhooks/execute",
9
+ "headers": {
10
+ "Content-Type": "application/json",
11
+ "Accept": "application/hal+json"
12
+ },
13
+ "body": {
14
+ "description": "an example webhook",
15
+ "events": [
16
+ {
17
+ "name": "contract_content_changed"
18
+ }
19
+ ],
20
+ "request": {
21
+ "method": "POST",
22
+ "url": "https://example.org/example",
23
+ "username": "username",
24
+ "password": "password",
25
+ "headers": {
26
+ "Accept": "application/json"
27
+ },
28
+ "body": {
29
+ "pactUrl": "${pactbroker.pactUrl}"
30
+ }
31
+ }
32
+ }
33
+ },
34
+ "response": {
35
+ "status": 200,
36
+ "headers": {
37
+ "Content-Type": "application/hal+json;charset=utf-8"
38
+ },
39
+ "body": {
40
+ "request": {
41
+ "headers": {
42
+ "accept": "application/json",
43
+ "user-agent": "Pact Broker v2.87.0",
44
+ "authorization": "**********"
45
+ },
46
+ "body": {
47
+ "pactUrl": "http://example.org/pacts/provider/Bar/consumer/Foo/pact-version/3e193ecb37ad04b43ce974a38352c704b2e0ed6b/metadata/Y3ZuPTImdz10cnVl"
48
+ },
49
+ "url": "/example"
50
+ },
51
+ "response": {
52
+ "status": 200,
53
+ "headers": {
54
+ },
55
+ "body": ""
56
+ },
57
+ "logs": "[2021-09-01T10:07:21Z] DEBUG: Webhook context {\"base_url\":\"http://example.org\",\"event_name\":\"test\"}\n[2021-09-01T10:07:21Z] INFO: HTTP/1.1 POST https://example.org/example\n[2021-09-01T10:07:21Z] INFO: accept: application/json\n[2021-09-01T10:07:21Z] INFO: user-agent: Pact Broker v2.87.0\n[2021-09-01T10:07:21Z] INFO: authorization: **********\n[2021-09-01T10:07:21Z] INFO: {\"pactUrl\":\"http://example.org/pacts/provider/Bar/consumer/Foo/pact-version/3e193ecb37ad04b43ce974a38352c704b2e0ed6b/metadata/Y3ZuPTImdz10cnVl\"}\n[2021-09-01T10:07:21Z] INFO: HTTP/1.0 200 \n[2021-09-01T10:07:21Z] INFO: \n",
58
+ "success": true,
59
+ "_links": {
60
+ }
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "category": "Webhooks",
3
+ "name": "Logs of triggered webhook",
4
+ "order": 49,
5
+ "request": {
6
+ "method": "GET",
7
+ "path_template": "/triggered-webhooks/:uuid/logs",
8
+ "path": "/triggered-webhooks/6cd5cc48-db3c-4a4c-a36d-e9bedeb9d91e/logs",
9
+ "headers": {
10
+ "Accept": "application/hal+json"
11
+ }
12
+ },
13
+ "response": {
14
+ "status": 200,
15
+ "headers": {
16
+ "Content-Type": "text/plain;charset=utf-8"
17
+ },
18
+ "body": "logs"
19
+ }
20
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "category": "Webhooks",
3
+ "name": "Logs of triggered webhook",
4
+ "order": 51,
5
+ "request": {
6
+ "method": "OPTIONS",
7
+ "path_template": "/triggered-webhooks/:uuid/logs",
8
+ "path": "/triggered-webhooks/6cd5cc48-db3c-4a4c-a36d-e9bedeb9d91e/logs",
9
+ "headers": {
10
+ "Accept": "application/hal+json"
11
+ }
12
+ },
13
+ "response": {
14
+ "status": 200,
15
+ "headers": {
16
+ "Access-Control-Allow-Methods": "GET, OPTIONS"
17
+ },
18
+ "body": ""
19
+ }
20
+ }
@@ -0,0 +1,45 @@
1
+ {
2
+ "category": "Webhooks",
3
+ "name": "Pact webhooks",
4
+ "order": 25,
5
+ "request": {
6
+ "method": "GET",
7
+ "path_template": "/pacts/provider/:provider_name/consumer/:consumer_name/webhooks",
8
+ "path": "/pacts/provider/Bar/consumer/Foo/webhooks",
9
+ "headers": {
10
+ "Accept": "application/hal+json"
11
+ }
12
+ },
13
+ "response": {
14
+ "status": 200,
15
+ "headers": {
16
+ "Content-Type": "application/hal+json;charset=utf-8"
17
+ },
18
+ "body": {
19
+ "_links": {
20
+ "self": {
21
+ "title": "Pact webhooks",
22
+ "href": "http://example.org/pacts/provider/Bar/consumer/Foo/webhooks"
23
+ },
24
+ "pb:create": {
25
+ "title": "POST to create a webhook",
26
+ "href": "http://example.org/pacts/provider/Bar/consumer/Foo/webhooks"
27
+ },
28
+ "pb:webhooks": [
29
+ {
30
+ "title": "A webhook for the pact between Foo and Bar",
31
+ "name": "an example webhook",
32
+ "href": "http://example.org/webhooks/d2181b32-8b03-4daf-8cc0-d9168b2f6fac"
33
+ }
34
+ ],
35
+ "curies": [
36
+ {
37
+ "name": "pb",
38
+ "href": "http://example.org/doc/webhooks-{rel}",
39
+ "templated": true
40
+ }
41
+ ]
42
+ }
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "category": "Webhooks",
3
+ "name": "Pact webhooks",
4
+ "order": 27,
5
+ "request": {
6
+ "method": "OPTIONS",
7
+ "path_template": "/pacts/provider/:provider_name/consumer/:consumer_name/webhooks",
8
+ "path": "/pacts/provider/Bar/consumer/Foo/webhooks",
9
+ "headers": {
10
+ "Accept": "application/hal+json"
11
+ }
12
+ },
13
+ "response": {
14
+ "status": 200,
15
+ "headers": {
16
+ "Access-Control-Allow-Methods": "POST, GET, OPTIONS"
17
+ },
18
+ "body": ""
19
+ }
20
+ }