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.
- checksums.yaml +4 -4
- data/.github/workflows/trigger_pact_docs_update.yml +22 -0
- data/CHANGELOG.md +67 -0
- data/DEVELOPER_DOCUMENTATION.md +0 -2
- data/db/migrations/20210914_add_labels_to_webhooks.rb +14 -0
- data/db/migrations/20210915_add_verified_by_to_verification.rb +6 -0
- data/db/migrations/20210929_increase_event_context_column_size.rb +14 -0
- data/docker-compose-ci-mysql.yml +1 -0
- data/docker-compose-test.yml +2 -0
- data/docs/CONFIGURATION.md +255 -66
- data/docs/api/WEBHOOKS.md +789 -0
- data/docs/configuration.yml +166 -101
- data/lib/db.rb +0 -1
- data/lib/pact/doc/interaction_view_model.rb +2 -2
- data/lib/pact/doc/markdown/consumer_contract_renderer.rb +1 -1
- data/lib/pact_broker/api/contracts/configuration.rb +33 -0
- data/lib/pact_broker/api/contracts/publish_contracts_schema.rb +35 -16
- data/lib/pact_broker/api/contracts/webhook_contract.rb +24 -2
- data/lib/pact_broker/api/decorators/matrix_decorator.rb +3 -1
- data/lib/pact_broker/api/decorators/pact_decorator.rb +12 -0
- data/lib/pact_broker/api/decorators/verification_decorator.rb +9 -3
- data/lib/pact_broker/api/decorators/webhook_decorator.rb +27 -4
- data/lib/pact_broker/api/pact_broker_urls.rb +30 -6
- data/lib/pact_broker/api/resources/all_webhooks.rb +2 -2
- data/lib/pact_broker/api/resources/default_base_resource.rb +5 -1
- data/lib/pact_broker/api/resources/environment.rb +4 -4
- data/lib/pact_broker/api/resources/environments.rb +1 -1
- data/lib/pact_broker/api/resources/index.rb +7 -1
- data/lib/pact_broker/api/resources/metadata_resource_methods.rb +33 -3
- data/lib/pact_broker/api/resources/pact_version.rb +4 -0
- data/lib/pact_broker/api/resources/previous_distinct_pact_version.rb +1 -1
- data/lib/pact_broker/api/resources/publish_contracts.rb +1 -1
- data/lib/pact_broker/api/resources/verification.rb +5 -2
- data/lib/pact_broker/api/resources/webhook_execution.rb +7 -3
- data/lib/pact_broker/api/resources/webhook_execution_methods.rb +23 -17
- data/lib/pact_broker/api.rb +6 -0
- data/lib/pact_broker/application_context.rb +5 -0
- data/lib/pact_broker/config/runtime_configuration.rb +4 -0
- data/lib/pact_broker/config/runtime_configuration_database_methods.rb +1 -1
- data/lib/pact_broker/db/clean.rb +1 -2
- data/lib/pact_broker/db/delete_overwritten_data.rb +41 -23
- data/lib/pact_broker/deployments/deployed_version.rb +1 -0
- data/lib/pact_broker/deployments/deployed_version_service.rb +1 -0
- data/lib/pact_broker/deployments/environment_service.rb +7 -2
- data/lib/pact_broker/deployments/released_version_service.rb +1 -0
- data/lib/pact_broker/doc/controllers/app.rb +1 -0
- data/lib/pact_broker/doc/views/can-i-deploy.markdown +2 -1
- data/lib/pact_broker/doc/views/index/publish-contracts.markdown +38 -9
- data/lib/pact_broker/doc/views/pacticipant/label.markdown +12 -0
- data/lib/pact_broker/doc/views/provider-pacts-for-verification.markdown +7 -7
- data/lib/pact_broker/doc/views/webhooks.markdown +17 -0
- data/lib/pact_broker/domain/index_item.rb +9 -0
- data/lib/pact_broker/domain/pacticipant.rb +4 -0
- data/lib/pact_broker/domain/verification.rb +19 -4
- data/lib/pact_broker/domain/webhook.rb +5 -5
- data/lib/pact_broker/domain/webhook_pacticipant.rb +6 -0
- data/lib/pact_broker/index/service.rb +4 -4
- data/lib/pact_broker/locale/en.yml +4 -1
- data/lib/pact_broker/matrix/head_row.rb +1 -1
- data/lib/pact_broker/matrix/parse_can_i_deploy_query.rb +5 -3
- data/lib/pact_broker/matrix/quick_row.rb +0 -1
- data/lib/pact_broker/matrix/repository.rb +0 -1
- data/lib/pact_broker/matrix/row.rb +2 -2
- data/lib/pact_broker/pacticipants/repository.rb +1 -1
- data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +0 -1
- data/lib/pact_broker/pacts/metadata.rb +7 -1
- data/lib/pact_broker/pacts/pact_publication.rb +7 -0
- data/lib/pact_broker/pacts/pact_publication_clean_selector_dataset_module.rb +19 -0
- data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +30 -2
- data/lib/pact_broker/pacts/pact_version.rb +24 -1
- data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +5 -4
- data/lib/pact_broker/pacts/repository.rb +50 -47
- data/lib/pact_broker/pacts/service.rb +5 -5
- data/lib/pact_broker/string_refinements.rb +1 -1
- data/lib/pact_broker/test/http_test_data_builder.rb +40 -10
- data/lib/pact_broker/test/test_data_builder.rb +28 -5
- data/lib/pact_broker/ui/helpers/url_helper.rb +12 -0
- data/lib/pact_broker/ui/view_models/index_item.rb +15 -1
- data/lib/pact_broker/ui/view_models/index_item_branch_head.rb +39 -0
- data/lib/pact_broker/ui/view_models/index_item_provider_branch_head.rb +39 -0
- data/lib/pact_broker/ui/views/dashboard/show.haml +14 -7
- data/lib/pact_broker/verifications/repository.rb +5 -2
- data/lib/pact_broker/verifications/service.rb +7 -4
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/abbreviate_number.rb +8 -4
- data/lib/pact_broker/versions/branch_head.rb +0 -2
- data/lib/pact_broker/versions/branch_version.rb +1 -0
- data/lib/pact_broker/versions/repository.rb +0 -1
- data/lib/pact_broker/webhooks/event_listener.rb +4 -2
- data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +18 -3
- data/lib/pact_broker/webhooks/repository.rb +10 -4
- data/lib/pact_broker/webhooks/trigger_service.rb +1 -1
- data/lib/pact_broker/webhooks/webhook.rb +71 -8
- data/lib/webmachine/describe_routes.rb +62 -0
- data/public/stylesheets/index.css +5 -0
- data/script/data/auto-create-things-for-tags.rb +1 -0
- data/script/data/branches.rb +1 -1
- data/script/data/contract-published-requiring-verification.rb +0 -1
- data/script/data/verify-pact-for-multiple-selectors.rb +30 -0
- data/script/docs/generate-api-docs.rb +117 -0
- data/script/docs/generate-configuration-docs.rb +24 -3
- data/script/docs/regenerate-api-docs.sh +11 -0
- data/script/generate-erd +55 -0
- data/spec/features/create_webhook_spec.rb +55 -10
- data/spec/features/get_pact_spec.rb +2 -3
- data/spec/fixtures/approvals/docs_webhooks_executing_a_saved_webhook_options.approved.json +20 -0
- data/spec/fixtures/approvals/docs_webhooks_executing_a_saved_webhook_post.approved.json +43 -0
- data/spec/fixtures/approvals/docs_webhooks_executing_an_unsaved_webhook_options.approved.json +20 -0
- data/spec/fixtures/approvals/docs_webhooks_executing_an_unsaved_webhook_post.approved.json +63 -0
- data/spec/fixtures/approvals/docs_webhooks_logs_of_triggered_webhook_get.approved.json +20 -0
- data/spec/fixtures/approvals/docs_webhooks_logs_of_triggered_webhook_options.approved.json +20 -0
- data/spec/fixtures/approvals/docs_webhooks_pact_webhooks_get.approved.json +45 -0
- data/spec/fixtures/approvals/docs_webhooks_pact_webhooks_options.approved.json +20 -0
- data/spec/fixtures/approvals/docs_webhooks_triggered_webhooks_for_pact_publication_get.approved.json +52 -0
- data/spec/fixtures/approvals/docs_webhooks_triggered_webhooks_for_pact_publication_options.approved.json +20 -0
- data/spec/fixtures/approvals/docs_webhooks_triggered_webhooks_for_verification_publication_get.approved.json +32 -0
- data/spec/fixtures/approvals/docs_webhooks_triggered_webhooks_for_verification_publication_options.approved.json +20 -0
- data/spec/fixtures/approvals/docs_webhooks_webhook_get.approved.json +74 -0
- data/spec/fixtures/approvals/docs_webhooks_webhook_options.approved.json +20 -0
- data/spec/fixtures/approvals/docs_webhooks_webhook_put.approved.json +77 -0
- data/spec/fixtures/approvals/docs_webhooks_webhooks_for_a_provider_get.approved.json +41 -0
- data/spec/fixtures/approvals/docs_webhooks_webhooks_for_a_provider_options.approved.json +20 -0
- data/spec/fixtures/approvals/docs_webhooks_webhooks_for_consumer_and_provider_get.approved.json +45 -0
- data/spec/fixtures/approvals/docs_webhooks_webhooks_for_consumer_and_provider_options.approved.json +20 -0
- data/spec/fixtures/approvals/docs_webhooks_webhooks_for_consumer_get.approved.json +41 -0
- data/spec/fixtures/approvals/docs_webhooks_webhooks_for_consumer_options.approved.json +20 -0
- data/spec/fixtures/approvals/docs_webhooks_webhooks_get.approved.json +45 -0
- data/spec/fixtures/approvals/docs_webhooks_webhooks_options.approved.json +20 -0
- data/spec/fixtures/approvals/docs_webhooks_webhooks_post.approved.json +78 -0
- data/spec/fixtures/approvals/docs_webhooks_webhooks_status_get.approved.json +79 -0
- data/spec/fixtures/approvals/docs_webhooks_webhooks_status_options.approved.json +20 -0
- data/spec/fixtures/approvals/get_provider_pacts_for_verification.approved.json +1 -2
- data/spec/fixtures/approvals/publish_contract_no_branch.approved.json +1 -2
- data/spec/fixtures/approvals/publish_contract_nothing_exists.approved.json +1 -2
- data/spec/fixtures/approvals/publish_contract_nothing_exists_with_webhook.approved.json +1 -2
- data/spec/fixtures/approvals/publish_contract_verification_already_exists.approved.json +1 -2
- data/spec/fixtures/approvals/publish_contract_with_validation_error.approved.json +1 -2
- data/spec/fixtures/invalid-publish-contract-body.json +38 -0
- data/spec/fixtures/verification.json +4 -0
- data/spec/integration/pact_metdata_spec.rb +105 -0
- data/spec/integration/webhooks/contract_publication_spec.rb +68 -0
- data/spec/integration/webhooks/contract_requiring_verification_published_spec.rb +67 -0
- data/spec/integration/webhooks/pact_publication_spec.rb +51 -0
- data/spec/integration/webhooks_documentation_spec.rb +348 -0
- data/spec/lib/pact/doc/markdown/consumer_contract_renderer_spec.rb +2 -2
- data/spec/lib/pact_broker/api/contracts/publish_contracts_schema_spec.rb +13 -0
- data/spec/lib/pact_broker/api/contracts/webhook_contract_spec.rb +50 -0
- data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +1 -1
- data/spec/lib/pact_broker/api/decorators/verification_decorator_spec.rb +15 -7
- data/spec/lib/pact_broker/api/decorators/verification_summary_decorator_spec.rb +4 -2
- data/spec/lib/pact_broker/api/decorators/webhook_decorator_spec.rb +4 -4
- data/spec/lib/pact_broker/api/pact_broker_urls_spec.rb +18 -0
- data/spec/lib/pact_broker/api/resources/triggered_webhook_logs_spec.rb +6 -5
- data/spec/lib/pact_broker/config/runtime_configuration_documentation_spec.rb +30 -0
- data/spec/lib/pact_broker/deployments/environment_service_spec.rb +22 -1
- data/spec/lib/pact_broker/domain/webhook_spec.rb +35 -0
- data/spec/lib/pact_broker/matrix/head_row_spec.rb +9 -5
- data/spec/lib/pact_broker/matrix/parse_can_i_deploy_query_spec.rb +13 -0
- data/spec/lib/pact_broker/pacts/{latest_tagged_pact_publications_spec.rb → pact_publication_clean_selector_dataset_module_spec.rb} +7 -9
- data/spec/lib/pact_broker/pacts/pact_version_spec.rb +32 -0
- data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +4 -5
- data/spec/lib/pact_broker/pacts/repository_spec.rb +33 -0
- data/spec/lib/pact_broker/ui/view_models/index_item_spec.rb +1 -1
- data/spec/lib/pact_broker/verifications/service_spec.rb +22 -8
- data/spec/lib/pact_broker/versions/abbreviate_number_spec.rb +2 -1
- data/spec/lib/pact_broker/webhooks/render_spec.rb +3 -2
- data/spec/lib/pact_broker/webhooks/repository_spec.rb +158 -15
- data/spec/lib/pact_broker/webhooks/webhook_spec.rb +8 -5
- data/spec/support/documentation.rb +64 -0
- data/spec/support/rack_helpers.rb +1 -1
- data/tasks/db.rake +4 -1
- data/tasks/development.rake +14 -13
- metadata +89 -12
- data/lib/pact_broker/pacts/all_pact_publications.rb +0 -158
- data/lib/pact_broker/pacts/latest_pact_publications.rb +0 -48
- data/lib/pact_broker/pacts/latest_pact_publications_by_consumer_version.rb +0 -26
- data/lib/pact_broker/pacts/latest_tagged_pact_publications.rb +0 -45
- data/lib/pact_broker/verifications/latest_verification_for_pact_version.rb +0 -39
- 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
|
-
|
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
|
-
|
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(
|
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
|
data/script/generate-erd
ADDED
@@ -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
|
-
|
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
|
-
|
84
|
-
webhook_hash[:consumer] = { name: "Some Consumer" }
|
85
|
-
end
|
107
|
+
let(:consumer) { { name: "Some Consumer" } }
|
86
108
|
|
87
|
-
its(:status) { is_expected.to
|
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
|
-
|
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
|
-
|
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
|
+
}
|