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,348 @@
|
|
1
|
+
require "timecop"
|
2
|
+
|
3
|
+
WEBHOOK_TESTED_PATHS = []
|
4
|
+
WEBHOOKS_NO_DOCUMENTATION = %w[
|
5
|
+
]
|
6
|
+
WEBHOOK_ROUTES_REQURING_A_TEST = PactBroker.routes
|
7
|
+
.select { | route | route[:path].include?("webhook") }
|
8
|
+
.reject { | route | WEBHOOKS_NO_DOCUMENTATION.include?(route[:path]) }
|
9
|
+
|
10
|
+
# Fails on Github Actions
|
11
|
+
RSpec.describe "webhook routes", skip: true do
|
12
|
+
before do
|
13
|
+
Timecop.freeze(Time.new(2021, 9, 1, 10, 7, 21))
|
14
|
+
td.create_consumer("Foo")
|
15
|
+
.create_provider("Bar")
|
16
|
+
.create_consumer_version("2")
|
17
|
+
.create_pact(json_content: { integrations: [] }.to_json )
|
18
|
+
.create_verification(provider_version: "3")
|
19
|
+
.create_webhook(
|
20
|
+
uuid: "d2181b32-8b03-4daf-8cc0-d9168b2f6fac",
|
21
|
+
url: "https://example.org/example",
|
22
|
+
description: "an example webhook",
|
23
|
+
body: webhook_body
|
24
|
+
)
|
25
|
+
.create_triggered_webhook(uuid: "6cd5cc48-db3c-4a4c-a36d-e9bedeb9d91e")
|
26
|
+
.create_webhook_execution
|
27
|
+
end
|
28
|
+
|
29
|
+
after do
|
30
|
+
Timecop.return
|
31
|
+
end
|
32
|
+
|
33
|
+
let(:webhook_body) do
|
34
|
+
{ "pactUrl" =>"${pactbroker.pactUrl}" }
|
35
|
+
end
|
36
|
+
|
37
|
+
before do
|
38
|
+
if ENV["DEBUG"] == "true"
|
39
|
+
PactBroker.routes.find{ | route| route[:path] == path_template }
|
40
|
+
end
|
41
|
+
WEBHOOK_TESTED_PATHS << path_template
|
42
|
+
end
|
43
|
+
|
44
|
+
after(:all) do
|
45
|
+
missed_routes = WEBHOOK_ROUTES_REQURING_A_TEST.reject { | route | WEBHOOK_TESTED_PATHS.include?(route[:path]) }
|
46
|
+
|
47
|
+
if missed_routes.any? && ENV["DEBUG"] != "true"
|
48
|
+
puts "WEBHOOK ROUTES MISSING COVERAGE:"
|
49
|
+
puts missed_routes.to_yaml
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
let(:category) { "Webhooks" }
|
54
|
+
let(:pact_version_sha) { PactBroker::Pacts::PactVersion.last.sha }
|
55
|
+
let(:triggered_webhook_uuid) { PactBroker::Webhooks::TriggeredWebhook.last.trigger_uuid }
|
56
|
+
let(:webhook_uuid) { PactBroker::Webhooks::TriggeredWebhook.last.webhook.uuid }
|
57
|
+
|
58
|
+
let(:webhook_hash) do
|
59
|
+
{
|
60
|
+
"description" => "an example webhook",
|
61
|
+
"events" => [{
|
62
|
+
"name" => "contract_content_changed"
|
63
|
+
}],
|
64
|
+
"request" =>{
|
65
|
+
"method" =>"POST",
|
66
|
+
"url" =>"https://example.org/example",
|
67
|
+
"username" =>"username",
|
68
|
+
"password" =>"password",
|
69
|
+
"headers" =>{
|
70
|
+
"Accept" =>"application/json"
|
71
|
+
},
|
72
|
+
"body" => webhook_body
|
73
|
+
}
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
let(:parameter_values) do
|
78
|
+
{
|
79
|
+
pact_version_sha: pact_version_sha,
|
80
|
+
provider_name: "Bar",
|
81
|
+
consumer_name: "Foo",
|
82
|
+
consumer_version_number: "2",
|
83
|
+
provider_version_number: "3",
|
84
|
+
trigger_uuid: triggered_webhook_uuid,
|
85
|
+
verification_number: "1"
|
86
|
+
}
|
87
|
+
end
|
88
|
+
|
89
|
+
let(:custom_parameter_values) do
|
90
|
+
{
|
91
|
+
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
let(:rack_headers) do
|
96
|
+
{
|
97
|
+
"ACCEPT" => "application/hal+json"
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
let(:http_params) { {} }
|
102
|
+
let(:http_method) { "GET" }
|
103
|
+
|
104
|
+
let(:path) do
|
105
|
+
build_path(path_template, parameter_values, custom_parameter_values)
|
106
|
+
end
|
107
|
+
|
108
|
+
let(:approval_request_example_name) do
|
109
|
+
build_approval_name(category, pact_broker_example_name, http_method)
|
110
|
+
end
|
111
|
+
|
112
|
+
let(:pact_broker_example_name) do | example |
|
113
|
+
example.example_group.parent_groups[-2].description
|
114
|
+
end
|
115
|
+
|
116
|
+
subject { send(http_method.downcase, path, http_params, rack_headers) }
|
117
|
+
|
118
|
+
shared_examples "request" do
|
119
|
+
it "returns a body" do
|
120
|
+
subject
|
121
|
+
Approvals.verify(expected_interaction(subject, WEBHOOK_TESTED_PATHS.size), :name => approval_request_example_name, format: :json)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
shared_examples "supports GET" do
|
126
|
+
its(:status) { is_expected.to eq 200 }
|
127
|
+
include_examples "request"
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
shared_examples "supports POST" do
|
132
|
+
let(:http_method) { "POST" }
|
133
|
+
let(:rack_headers) do
|
134
|
+
{
|
135
|
+
"CONTENT_TYPE" => "application/json",
|
136
|
+
"ACCEPT" => "application/hal+json"
|
137
|
+
}
|
138
|
+
end
|
139
|
+
|
140
|
+
its(:status) { is_expected.to be_between(200, 201) }
|
141
|
+
include_examples "request"
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
shared_examples "supports PUT" do
|
146
|
+
describe "PUT" do
|
147
|
+
let(:http_method) { "PUT" }
|
148
|
+
let(:rack_headers) do
|
149
|
+
{
|
150
|
+
"CONTENT_TYPE" => "application/json",
|
151
|
+
"ACCEPT" => "application/hal+json"
|
152
|
+
}
|
153
|
+
end
|
154
|
+
|
155
|
+
its(:status) { is_expected.to be_between(200, 201) }
|
156
|
+
|
157
|
+
include_examples "request"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
shared_examples "supports OPTIONS" do
|
162
|
+
let(:http_method) { "OPTIONS" }
|
163
|
+
|
164
|
+
its(:status) { is_expected.to eq 200 }
|
165
|
+
include_examples "request"
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "Webhook" do
|
169
|
+
let(:path_template) { "/webhooks/:uuid" }
|
170
|
+
let(:custom_parameter_values) { { uuid: webhook_uuid } }
|
171
|
+
|
172
|
+
describe "GET" do
|
173
|
+
include_examples "supports GET"
|
174
|
+
end
|
175
|
+
|
176
|
+
describe "PUT" do
|
177
|
+
let(:http_params) { webhook_hash.to_json }
|
178
|
+
include_examples "supports PUT"
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "OPTIONS" do
|
182
|
+
include_examples "supports OPTIONS"
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe "Webhooks" do
|
187
|
+
let(:path_template) { "/webhooks" }
|
188
|
+
|
189
|
+
describe "GET" do
|
190
|
+
include_examples "supports GET"
|
191
|
+
end
|
192
|
+
|
193
|
+
describe "POST" do
|
194
|
+
before do
|
195
|
+
allow(PactBroker::Webhooks::Service).to receive(:next_uuid).and_return("dCGCl-Ba3PqEFJ_iE9mJkQ")
|
196
|
+
end
|
197
|
+
|
198
|
+
let(:http_params) { webhook_hash.to_json }
|
199
|
+
include_examples "supports POST"
|
200
|
+
end
|
201
|
+
|
202
|
+
describe "OPTIONS" do
|
203
|
+
include_examples "supports OPTIONS"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "Webhooks for consumer" do
|
208
|
+
let(:path_template) { "/webhooks/consumer/:consumer_name" }
|
209
|
+
|
210
|
+
describe "GET" do
|
211
|
+
include_examples "supports GET"
|
212
|
+
end
|
213
|
+
|
214
|
+
describe "OPTIONS" do
|
215
|
+
include_examples "supports OPTIONS"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
describe "Webhooks for a provider" do
|
220
|
+
let(:path_template) { "/webhooks/provider/:provider_name" }
|
221
|
+
|
222
|
+
describe "GET" do
|
223
|
+
include_examples "supports GET"
|
224
|
+
end
|
225
|
+
|
226
|
+
describe "OPTIONS" do
|
227
|
+
include_examples "supports OPTIONS"
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
describe "Webhooks for consumer and provider" do
|
232
|
+
let(:path_template) { "/webhooks/provider/:provider_name/consumer/:consumer_name" }
|
233
|
+
|
234
|
+
describe "GET" do
|
235
|
+
include_examples "supports GET"
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "OPTIONS" do
|
239
|
+
include_examples "supports OPTIONS"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe "Pact webhooks" do
|
244
|
+
let(:path_template) do
|
245
|
+
"/pacts/provider/:provider_name/consumer/:consumer_name/webhooks"
|
246
|
+
end
|
247
|
+
|
248
|
+
describe "GET" do
|
249
|
+
include_examples "supports GET"
|
250
|
+
end
|
251
|
+
|
252
|
+
describe "OPTIONS" do
|
253
|
+
include_examples "supports OPTIONS"
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
describe "Webhooks status" do
|
258
|
+
let(:path_template) do
|
259
|
+
"/pacts/provider/:provider_name/consumer/:consumer_name/webhooks/status"
|
260
|
+
end
|
261
|
+
|
262
|
+
describe "GET" do
|
263
|
+
include_examples "supports GET"
|
264
|
+
end
|
265
|
+
|
266
|
+
describe "OPTIONS" do
|
267
|
+
include_examples "supports OPTIONS"
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
describe "Executing a saved webhook" do
|
272
|
+
let(:path_template) { "/webhooks/:uuid/execute" }
|
273
|
+
let(:custom_parameter_values) { { uuid: webhook_uuid } }
|
274
|
+
|
275
|
+
include_examples "supports OPTIONS"
|
276
|
+
|
277
|
+
describe "POST" do
|
278
|
+
before do
|
279
|
+
stub_request(:post, /http/).to_return(:status => 200)
|
280
|
+
allow(PactBroker.configuration).to receive(:webhook_host_whitelist).and_return([/.*/])
|
281
|
+
end
|
282
|
+
|
283
|
+
include_examples "supports POST"
|
284
|
+
end
|
285
|
+
|
286
|
+
end
|
287
|
+
|
288
|
+
describe "Executing an unsaved webhook" do
|
289
|
+
let(:path_template) { "/webhooks/execute" }
|
290
|
+
|
291
|
+
describe "OPTIONS" do
|
292
|
+
include_examples "supports OPTIONS"
|
293
|
+
end
|
294
|
+
|
295
|
+
describe "POST" do
|
296
|
+
before do
|
297
|
+
stub_request(:post, /http/).to_return(:status => 200)
|
298
|
+
allow(PactBroker.configuration).to receive(:webhook_host_whitelist).and_return([/.*/])
|
299
|
+
end
|
300
|
+
|
301
|
+
let(:http_params) do
|
302
|
+
webhook_hash.to_json
|
303
|
+
end
|
304
|
+
include_examples "supports POST"
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
describe "Triggered webhooks for pact publication" do
|
309
|
+
let(:path_template) do
|
310
|
+
"/pacts/provider/:provider_name/consumer/:consumer_name/version/:consumer_version_number/triggered-webhooks"
|
311
|
+
end
|
312
|
+
|
313
|
+
describe "GET" do
|
314
|
+
include_examples "supports GET"
|
315
|
+
end
|
316
|
+
|
317
|
+
describe "OPTIONS" do
|
318
|
+
include_examples "supports OPTIONS"
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
describe "Triggered webhooks for verification publication" do
|
323
|
+
let(:path_template) do
|
324
|
+
"/pacts/provider/:provider_name/consumer/:consumer_name/pact-version/:pact_version_sha/verification-results/:verification_number/triggered-webhooks"
|
325
|
+
end
|
326
|
+
|
327
|
+
describe "GET" do
|
328
|
+
include_examples "supports GET"
|
329
|
+
end
|
330
|
+
|
331
|
+
describe "OPTIONS" do
|
332
|
+
include_examples "supports OPTIONS"
|
333
|
+
end
|
334
|
+
end
|
335
|
+
|
336
|
+
describe "Logs of triggered webhook" do
|
337
|
+
let(:path_template) { "/triggered-webhooks/:uuid/logs" }
|
338
|
+
let(:custom_parameter_values) { { uuid: triggered_webhook_uuid } }
|
339
|
+
|
340
|
+
describe "GET" do
|
341
|
+
include_examples "supports GET"
|
342
|
+
end
|
343
|
+
|
344
|
+
describe "OPTIONS" do
|
345
|
+
include_examples "supports OPTIONS"
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
@@ -27,8 +27,8 @@ module Pact
|
|
27
27
|
let(:consumer_contract) { Pact::ConsumerContract.from_uri "./spec/support/markdown_pact_with_markdown_chars_in_names.json" }
|
28
28
|
|
29
29
|
it "escapes the markdown characters" do
|
30
|
-
expect(subject.call).to include
|
31
|
-
expect(subject.call).to include
|
30
|
+
expect(subject.call).to include "# A pact between Some\\*Consumer\\*App and Some\\_Provider\\_App"
|
31
|
+
expect(subject.call).to include "### Requests from Some\\*Consumer\\*App to Some\\_Provider\\_App"
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
@@ -108,6 +108,19 @@ module PactBroker
|
|
108
108
|
|
109
109
|
its([:contracts, 0]) { is_expected.to include "provider name in contract content ('WRONG') must match providerName ('Bar') in contracts at index 0" }
|
110
110
|
end
|
111
|
+
|
112
|
+
context "when the consumer name is missing and there is a validation error with the content" do
|
113
|
+
let(:params) do
|
114
|
+
JSON.parse(File.read("spec/fixtures/invalid-publish-contract-body.json"), symbolize_names: true)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "handles multiple errors" do
|
118
|
+
expect(subject[:contracts]).to include "consumerName is missing at index 0"
|
119
|
+
expect(subject[:contracts]).to include "providerName is missing at index 0"
|
120
|
+
expect(subject[:contracts]).to include "contentType is missing at index 0"
|
121
|
+
expect(subject[:contracts]).to include "specification is missing at index 0"
|
122
|
+
end
|
123
|
+
end
|
111
124
|
end
|
112
125
|
end
|
113
126
|
end
|
@@ -85,6 +85,31 @@ module PactBroker
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
+
context "with a consumer label" do
|
89
|
+
let(:json) do
|
90
|
+
valid_webhook_with do |hash|
|
91
|
+
hash["consumer"].delete("name")
|
92
|
+
hash["consumer"]["label"] = "my_label"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it "contains no errors" do
|
97
|
+
expect(subject.errors).to be_empty
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context "with a consumer label and name provided" do
|
102
|
+
let(:json) do
|
103
|
+
valid_webhook_with do |hash|
|
104
|
+
hash["consumer"]["label"] = "my_label"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
it "contains consumer.label error" do
|
109
|
+
expect(subject.errors.messages).to eq({:'consumer.label' => ["cannot be provided"]})
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
88
113
|
context "with a nil provider name" do
|
89
114
|
let(:json) do
|
90
115
|
valid_webhook_with do |hash|
|
@@ -131,6 +156,31 @@ module PactBroker
|
|
131
156
|
end
|
132
157
|
end
|
133
158
|
|
159
|
+
context "with provider label" do
|
160
|
+
let(:json) do
|
161
|
+
valid_webhook_with do |hash|
|
162
|
+
hash["provider"].delete("name")
|
163
|
+
hash["provider"]["label"] = "my_label"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
it "contains no errors" do
|
168
|
+
expect(subject.errors).to be_empty
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context "with a provider label and name" do
|
173
|
+
let(:json) do
|
174
|
+
valid_webhook_with do |hash|
|
175
|
+
hash["provider"]["label"] = "my_label"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
it "contains provider.label error" do
|
180
|
+
expect(subject.errors.messages).to eq({:'provider.label' => ["cannot be provided"]})
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
134
184
|
context "with no request defined" do
|
135
185
|
let(:json) { {}.to_json }
|
136
186
|
|
@@ -129,7 +129,7 @@ module PactBroker
|
|
129
129
|
verifiedAt: "2017-12-31T00:00:00+00:00",
|
130
130
|
_links: {
|
131
131
|
self: {
|
132
|
-
href: "http://example.org/pacts/provider/Provider/consumer/Consumer/pact-version/1234/verification-results/1"
|
132
|
+
href: "http://example.org/pacts/provider/Provider/consumer/Consumer/pact-version/1234/metadata/Y3ZuPTEuMC4w/verification-results/1"
|
133
133
|
}
|
134
134
|
}
|
135
135
|
}
|
@@ -6,6 +6,7 @@ module PactBroker
|
|
6
6
|
describe VerificationDecorator do
|
7
7
|
before do
|
8
8
|
allow_any_instance_of(VerificationDecorator).to receive(:verification_triggered_webhooks_url).and_return("http://triggered-webhooks")
|
9
|
+
allow_any_instance_of(VerificationDecorator).to receive(:pact_version_with_consumer_version_metadata_url).and_return("http://pact")
|
9
10
|
end
|
10
11
|
|
11
12
|
let(:verification) do
|
@@ -18,23 +19,25 @@ module PactBroker
|
|
18
19
|
test_results: { "arbitrary" => "json" },
|
19
20
|
build_url: "http://build-url",
|
20
21
|
pact_version_sha: "1234",
|
21
|
-
latest_pact_publication: pact_publication,
|
22
22
|
execution_date: DateTime.now,
|
23
|
-
provider_version_tags: provider_version_tags
|
23
|
+
provider_version_tags: provider_version_tags,
|
24
|
+
verified_by_implementation: "Ruby",
|
25
|
+
verified_by_version: "1234")
|
24
26
|
end
|
25
27
|
|
26
|
-
let(:
|
27
|
-
instance_double("PactBroker::
|
28
|
+
let(:pact) do
|
29
|
+
instance_double("PactBroker::Domain::Pact",
|
28
30
|
name: "A name",
|
29
31
|
provider_name: "Provider",
|
30
32
|
consumer_name: "Consumer",
|
31
|
-
consumer_version_number: "1.2.3"
|
33
|
+
consumer_version_number: "1.2.3",
|
34
|
+
pact_version_sha: "1234",
|
32
35
|
)
|
33
36
|
end
|
34
37
|
|
35
38
|
let(:provider_version_tags) { [instance_double(PactBroker::Tags::TagWithLatestFlag, name: "prod", latest?: true)] }
|
36
39
|
|
37
|
-
let(:options) { { user_options: { base_url: "http://example.org" } } }
|
40
|
+
let(:options) { { user_options: { base_url: "http://example.org", pact: pact } } }
|
38
41
|
|
39
42
|
let(:json) { VerificationDecorator.new(verification).to_json(options) }
|
40
43
|
|
@@ -61,12 +64,17 @@ module PactBroker
|
|
61
64
|
end
|
62
65
|
|
63
66
|
it "includes a link to its pact" do
|
64
|
-
expect(subject[:_links][:'pb:pact-version'][:href]).to
|
67
|
+
expect(subject[:_links][:'pb:pact-version'][:href]).to eq "http://pact"
|
65
68
|
end
|
66
69
|
|
67
70
|
it "includes a link to the triggered webhooks" do
|
68
71
|
expect(subject[:_links][:'pb:triggered-webhooks'][:href]).to eq "http://triggered-webhooks"
|
69
72
|
end
|
73
|
+
|
74
|
+
it "includes the framework that did the verification" do
|
75
|
+
expect(subject[:verifiedBy][:implementation]).to eq "Ruby"
|
76
|
+
expect(subject[:verifiedBy][:version]).to eq "1234"
|
77
|
+
end
|
70
78
|
end
|
71
79
|
end
|
72
80
|
end
|
@@ -21,7 +21,9 @@ module PactBroker
|
|
21
21
|
latest_pact_publication: pact,
|
22
22
|
test_results: nil,
|
23
23
|
execution_date: DateTime.now,
|
24
|
-
provider_version_tags: provider_version_tags
|
24
|
+
provider_version_tags: provider_version_tags,
|
25
|
+
verified_by_implementation: "Ruby",
|
26
|
+
verified_by_version: "1234")
|
25
27
|
end
|
26
28
|
|
27
29
|
let(:pact_version) do
|
@@ -29,7 +31,7 @@ module PactBroker
|
|
29
31
|
end
|
30
32
|
|
31
33
|
let(:provider_version_tags) { [instance_double(PactBroker::Tags::TagWithLatestFlag, name: "prod", latest?: true)] }
|
32
|
-
let(:pact) { instance_double("PactBroker::Domain::Pact", name: "Some pact", consumer_name: "Foo", provider_name: "Bar", consumer_version_number: "1.2.3") }
|
34
|
+
let(:pact) { instance_double("PactBroker::Domain::Pact", name: "Some pact", consumer_name: "Foo", provider_name: "Bar", consumer_version_number: "1.2.3", pact_version_sha: "1234") }
|
33
35
|
let(:is_pending) { true }
|
34
36
|
let(:options) { {base_url: "http://example.org", consumer_name: "Foo", consumer_version_number: "1.2.3", resource_url: "http://self"} }
|
35
37
|
|
@@ -20,8 +20,8 @@ module PactBroker
|
|
20
20
|
Webhooks::WebhookRequestTemplate.new(request)
|
21
21
|
end
|
22
22
|
|
23
|
-
let(:consumer) { Domain::
|
24
|
-
let(:provider) { Domain::
|
23
|
+
let(:consumer) { Domain::WebhookPacticipant.new(name: "Consumer") }
|
24
|
+
let(:provider) { Domain::WebhookPacticipant.new(name: "Provider") }
|
25
25
|
let(:event) { Webhooks::WebhookEvent.new(name: "something_happened") }
|
26
26
|
let(:created_at) { DateTime.now }
|
27
27
|
let(:updated_at) { created_at + 1 }
|
@@ -193,8 +193,8 @@ module PactBroker
|
|
193
193
|
context "when the decorated object has a consumer/provider but the incoming JSON does not" do
|
194
194
|
let(:webhook) do
|
195
195
|
Domain::Webhook.new(
|
196
|
-
consumer: Domain::
|
197
|
-
provider: Domain::
|
196
|
+
consumer: Domain::WebhookPacticipant.new(name: "consumer"),
|
197
|
+
provider: Domain::WebhookPacticipant.new(name: "provider")
|
198
198
|
)
|
199
199
|
end
|
200
200
|
|
@@ -100,6 +100,24 @@ module PactBroker
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
+
describe "verification_url_from_params" do
|
104
|
+
context "with consumer_version_number" do
|
105
|
+
let(:params) do
|
106
|
+
{
|
107
|
+
consumer_name: consumer_name,
|
108
|
+
provider_name: provider_name,
|
109
|
+
pact_version_sha: "1234",
|
110
|
+
consumer_version_number: "2",
|
111
|
+
verification_number: "1"
|
112
|
+
}
|
113
|
+
end
|
114
|
+
|
115
|
+
subject { PactBrokerUrls.verification_url_from_params(params, base_url)}
|
116
|
+
|
117
|
+
it { is_expected.to eq "http://example.org/pacts/provider/Bar%2FBar/consumer/Foo%2FFoo/pact-version/1234/metadata/Y3ZuPTI/verification-results/1" }
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
103
121
|
describe "templated_diff_url" do
|
104
122
|
subject { PactBrokerUrls.templated_diff_url(pact, base_url) }
|
105
123
|
|
@@ -15,15 +15,16 @@ module PactBroker
|
|
15
15
|
.create_webhook_execution(logs: "waffle")
|
16
16
|
end
|
17
17
|
|
18
|
-
let(:path) { "/webhooks/5432/trigger/1234/logs" }
|
19
|
-
|
20
18
|
subject { get(path) }
|
21
19
|
|
22
20
|
let(:triggered_webhook_uuid) { PactBroker::Webhooks::TriggeredWebhook.first.uuid }
|
23
|
-
let(:path) { "/triggered-webhooks/#{triggered_webhook_uuid}/logs" }
|
24
21
|
|
25
|
-
|
26
|
-
|
22
|
+
describe "by triggered webhook uuid" do
|
23
|
+
let(:path) { "/triggered-webhooks/1234/logs" }
|
24
|
+
|
25
|
+
it "returns the concatenated webhook execution logs" do
|
26
|
+
expect(subject.body).to eq "foo\nbar"
|
27
|
+
end
|
27
28
|
end
|
28
29
|
end
|
29
30
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "pact_broker/config/runtime_configuration"
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Config
|
5
|
+
describe RuntimeConfiguration do
|
6
|
+
ATTRIBUTES = RuntimeConfiguration.config_attributes
|
7
|
+
DOCUMENTATION = File.read("docs/configuration.yml")
|
8
|
+
DOCUMENTED_ATTRIBUTES = YAML.load(DOCUMENTATION)["groups"].flat_map{ | group | group["vars"].keys.collect(&:to_sym) }
|
9
|
+
DELIBERATELY_UNDOCUMENTED_ATTRIBUTES = [
|
10
|
+
:warning_error_class_names,
|
11
|
+
:log_configuration_on_startup,
|
12
|
+
:use_hal_browser,
|
13
|
+
:use_rack_protection,
|
14
|
+
:use_case_sensitive_resource_names,
|
15
|
+
:order_versions_by_date,
|
16
|
+
:base_equality_only_on_content_that_affects_verification_results,
|
17
|
+
:semver_formats,
|
18
|
+
:seed_example_data,
|
19
|
+
:use_first_tag_as_branch_time_limit,
|
20
|
+
:validate_database_connection_config
|
21
|
+
]
|
22
|
+
|
23
|
+
(ATTRIBUTES - DELIBERATELY_UNDOCUMENTED_ATTRIBUTES).each do | attribute_name |
|
24
|
+
it "has documentation for #{attribute_name}" do
|
25
|
+
expect(DOCUMENTED_ATTRIBUTES & [attribute_name]).to include(attribute_name)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -2,7 +2,7 @@ require "pact_broker/deployments/environment_service"
|
|
2
2
|
|
3
3
|
module PactBroker
|
4
4
|
module Deployments
|
5
|
-
|
5
|
+
describe EnvironmentService do
|
6
6
|
describe ".create" do
|
7
7
|
let(:environment) do
|
8
8
|
Environment.new(
|
@@ -32,6 +32,27 @@ module PactBroker
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
35
|
+
|
36
|
+
describe ".replace" do
|
37
|
+
before do
|
38
|
+
td.create_environment("foo", uuid: "1", display_name: "bar", production: false)
|
39
|
+
end
|
40
|
+
|
41
|
+
subject { EnvironmentService.replace("1", Environment.new(name: "bar", display_name: "bar-2", production: true) ) }
|
42
|
+
|
43
|
+
it "replaces the attributes" do
|
44
|
+
subject
|
45
|
+
expect(Environment.first).to have_attributes(name: "bar", display_name: "bar-2", production: true)
|
46
|
+
end
|
47
|
+
|
48
|
+
context "with missing attributes" do
|
49
|
+
subject { EnvironmentService.replace("1", Environment.new ) }
|
50
|
+
|
51
|
+
it "raises an error" do
|
52
|
+
expect { subject }.to raise_error Sequel::DatabaseError
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
35
56
|
end
|
36
57
|
end
|
37
58
|
end
|