pact_broker 2.85.1 → 2.86.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/release_gem.yml +1 -1
- data/.github/workflows/trigger_pact_docs_update.yml +22 -0
- data/CHANGELOG.md +10 -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/docker-compose-ci-mysql.yml +1 -0
- data/docs/CONFIGURATION.md +255 -66
- data/docs/configuration.yml +166 -101
- data/lib/db.rb +0 -1
- data/lib/pact_broker/api/contracts/webhook_contract.rb +24 -2
- data/lib/pact_broker/api/decorators/verification_decorator.rb +4 -0
- data/lib/pact_broker/api/decorators/webhook_decorator.rb +27 -4
- data/lib/pact_broker/api/pact_broker_urls.rb +4 -0
- data/lib/pact_broker/api/resources/all_webhooks.rb +2 -2
- 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/doc/views/pacticipant/label.markdown +12 -0
- data/lib/pact_broker/doc/views/webhooks.markdown +17 -0
- data/lib/pact_broker/domain/pacticipant.rb +4 -0
- data/lib/pact_broker/domain/verification.rb +16 -4
- data/lib/pact_broker/domain/webhook.rb +5 -5
- data/lib/pact_broker/domain/webhook_pacticipant.rb +6 -0
- data/lib/pact_broker/locale/en.yml +1 -0
- data/lib/pact_broker/matrix/head_row.rb +1 -1
- 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/pacts/latest_pact_publication_id_for_consumer_version.rb +0 -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 +2 -2
- data/lib/pact_broker/pacts/repository.rb +50 -47
- data/lib/pact_broker/test/http_test_data_builder.rb +37 -10
- data/lib/pact_broker/test/test_data_builder.rb +22 -5
- data/lib/pact_broker/verifications/repository.rb +5 -2
- data/lib/pact_broker/verifications/service.rb +4 -1
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/webhooks/event_listener.rb +4 -2
- data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +1 -0
- data/lib/pact_broker/webhooks/repository.rb +10 -4
- data/lib/pact_broker/webhooks/webhook.rb +66 -8
- data/script/data/verify-pact-for-multiple-selectors.rb +30 -0
- data/script/docs/generate-configuration-docs.rb +24 -3
- 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/verification.json +4 -0
- data/spec/integration/webhooks/pact_publication_spec.rb +51 -0
- data/spec/lib/pact_broker/api/contracts/webhook_contract_spec.rb +50 -0
- data/spec/lib/pact_broker/api/decorators/verification_decorator_spec.rb +8 -1
- data/spec/lib/pact_broker/api/decorators/verification_summary_decorator_spec.rb +3 -1
- data/spec/lib/pact_broker/api/decorators/webhook_decorator_spec.rb +4 -4
- data/spec/lib/pact_broker/config/runtime_configuration_documentation_spec.rb +30 -0
- data/spec/lib/pact_broker/deployments/environment_service_spec.rb +1 -1
- data/spec/lib/pact_broker/matrix/head_row_spec.rb +9 -5
- 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_spec.rb +33 -0
- data/spec/lib/pact_broker/verifications/service_spec.rb +16 -2
- data/spec/lib/pact_broker/webhooks/repository_spec.rb +158 -15
- data/spec/lib/pact_broker/webhooks/webhook_spec.rb +8 -5
- metadata +16 -11
- 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
@@ -30,12 +30,14 @@ module PactBroker
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def find_by_consumer_and_or_provider consumer, provider
|
33
|
+
|
33
34
|
where(
|
34
35
|
Sequel.|(
|
35
36
|
{ consumer_id: consumer.id, provider_id: provider.id },
|
36
|
-
{ consumer_id: nil, provider_id: provider.id },
|
37
|
-
{ consumer_id: consumer.id, provider_id: nil },
|
38
|
-
{ consumer_id: nil, provider_id: nil}
|
37
|
+
{ consumer_id: nil, provider_id: provider.id, consumer_label: nil },
|
38
|
+
{ consumer_id: consumer.id, provider_id: nil, provider_label: nil },
|
39
|
+
{ consumer_id: nil, provider_id: nil, consumer_label: nil, provider_label: nil },
|
40
|
+
*labels_criteria_for_consumer_or_provider(consumer, provider)
|
39
41
|
)
|
40
42
|
)
|
41
43
|
end
|
@@ -51,6 +53,32 @@ module PactBroker
|
|
51
53
|
def enabled
|
52
54
|
where(enabled: true)
|
53
55
|
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def labels_criteria_for_consumer_or_provider(consumer, provider)
|
60
|
+
consumer_labels = consumer.labels.map(&:name)
|
61
|
+
provider_labels = provider.labels.map(&:name)
|
62
|
+
|
63
|
+
[].then do |criteria|
|
64
|
+
next criteria if consumer_labels.empty?
|
65
|
+
criteria + [
|
66
|
+
{ consumer_label: consumer_labels, provider_label: nil, provider_id: nil },
|
67
|
+
{ consumer_label: consumer_labels, provider_label: nil, provider_id: provider.id }
|
68
|
+
]
|
69
|
+
end.then do |criteria|
|
70
|
+
next criteria if provider_labels.empty?
|
71
|
+
criteria + [
|
72
|
+
{ provider_label: provider_labels, consumer_label: nil, consumer_id: nil },
|
73
|
+
{ provider_label: provider_labels, consumer_label: nil, consumer_id: consumer.id }
|
74
|
+
]
|
75
|
+
end.then do |criteria|
|
76
|
+
next criteria if consumer_labels.empty? || provider_labels.empty?
|
77
|
+
criteria + [
|
78
|
+
{ consumer_label: consumer_labels, provider_label: provider_labels }
|
79
|
+
]
|
80
|
+
end
|
81
|
+
end
|
54
82
|
end
|
55
83
|
|
56
84
|
def update_from_domain webhook
|
@@ -74,8 +102,8 @@ module PactBroker
|
|
74
102
|
Domain::Webhook.new(
|
75
103
|
uuid: uuid,
|
76
104
|
description: description,
|
77
|
-
consumer:
|
78
|
-
provider:
|
105
|
+
consumer: webhook_consumer,
|
106
|
+
provider: webhook_provider,
|
79
107
|
events: events,
|
80
108
|
request: Webhooks::WebhookRequestTemplate.new(request_attributes),
|
81
109
|
enabled: enabled,
|
@@ -100,7 +128,15 @@ module PactBroker
|
|
100
128
|
end
|
101
129
|
|
102
130
|
def is_for? integration
|
103
|
-
(
|
131
|
+
(
|
132
|
+
consumer_id == integration.consumer_id ||
|
133
|
+
match_label?(:consumer, integration) ||
|
134
|
+
match_all?(:consumer)
|
135
|
+
) && (
|
136
|
+
provider_id == integration.provider_id ||
|
137
|
+
match_label?(:provider, integration) ||
|
138
|
+
match_all?(:provider)
|
139
|
+
)
|
104
140
|
end
|
105
141
|
|
106
142
|
# Keep the triggered webhooks after the webhook has been deleted
|
@@ -110,7 +146,6 @@ module PactBroker
|
|
110
146
|
super
|
111
147
|
end
|
112
148
|
|
113
|
-
|
114
149
|
def self.properties_hash_from_domain webhook
|
115
150
|
is_json_request_body = !(String === webhook.request.body || webhook.request.body.nil?) # Can't rely on people to set content type
|
116
151
|
{
|
@@ -122,9 +157,32 @@ module PactBroker
|
|
122
157
|
enabled: webhook.enabled.nil? ? true : webhook.enabled,
|
123
158
|
body: (is_json_request_body ? webhook.request.body.to_json : webhook.request.body),
|
124
159
|
is_json_request_body: is_json_request_body,
|
125
|
-
headers: webhook.request.headers
|
160
|
+
headers: webhook.request.headers,
|
161
|
+
consumer_label: webhook.consumer&.label,
|
162
|
+
provider_label: webhook.provider&.label
|
126
163
|
}
|
127
164
|
end
|
165
|
+
|
166
|
+
def webhook_consumer
|
167
|
+
return if consumer.nil? && consumer_label.nil?
|
168
|
+
|
169
|
+
Domain::WebhookPacticipant.new(name: consumer&.name, label: consumer_label)
|
170
|
+
end
|
171
|
+
|
172
|
+
def webhook_provider
|
173
|
+
return if provider.nil? && provider_label.nil?
|
174
|
+
|
175
|
+
Domain::WebhookPacticipant.new(name: provider&.name, label: provider_label)
|
176
|
+
end
|
177
|
+
|
178
|
+
def match_all?(name)
|
179
|
+
public_send(:"#{name}_id").nil? && public_send(:"#{name}_label").nil?
|
180
|
+
end
|
181
|
+
|
182
|
+
def match_label?(name, integration)
|
183
|
+
label = public_send(:"#{name}_label")
|
184
|
+
public_send(:"#{name}_id").nil? && integration.public_send(name).label?(label)
|
185
|
+
end
|
128
186
|
end
|
129
187
|
end
|
130
188
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
begin
|
3
|
+
|
4
|
+
$LOAD_PATH << "#{Dir.pwd}/lib"
|
5
|
+
require "pact_broker/test/http_test_data_builder"
|
6
|
+
base_url = ENV["PACT_BROKER_BASE_URL"] || "http://localhost:9292"
|
7
|
+
|
8
|
+
td = PactBroker::Test::HttpTestDataBuilder.new(base_url)
|
9
|
+
td.delete_pacticipant("some-consumer")
|
10
|
+
.delete_pacticipant("some-provider")
|
11
|
+
.create_pacticipant("some-consumer")
|
12
|
+
.create_pacticipant("some-provider")
|
13
|
+
.publish_pact(consumer: "some-consumer", consumer_version: "1", provider: "some-provider", content_id: "111", branch: "main")
|
14
|
+
.publish_pact(consumer: "some-consumer", consumer_version: "2", provider: "some-provider", content_id: "111", branch: "feat/x")
|
15
|
+
.get_pacts_for_verification(
|
16
|
+
provider_version_tag: "main",
|
17
|
+
consumer_version_selectors: [{ branch: "main" }, { branch: "feat/x" }]
|
18
|
+
)
|
19
|
+
.verify_pact(
|
20
|
+
index: 0,
|
21
|
+
provider_version_tag: "main",
|
22
|
+
provider_version: "1",
|
23
|
+
success: true
|
24
|
+
)
|
25
|
+
|
26
|
+
rescue StandardError => e
|
27
|
+
puts "#{e.class} #{e.message}"
|
28
|
+
puts e.backtrace
|
29
|
+
exit 1
|
30
|
+
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
|
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,51 @@
|
|
1
|
+
RSpec.describe "triggering a webhook for a pact publication" do
|
2
|
+
before do
|
3
|
+
td.create_global_webhook(event_names: ["contract_published"], body: { "provider_version" => "${pactbroker.providerVersionNumber}"})
|
4
|
+
end
|
5
|
+
|
6
|
+
let(:pact_content) { td.random_json_content("Foo", "Bar") }
|
7
|
+
|
8
|
+
let!(:request) do
|
9
|
+
stub_request(:post, /http/).with(body: expected_webhook_body).to_return(:status => 200)
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:database_connector) { ->(&block) { block.call } }
|
13
|
+
|
14
|
+
subject { put("/pacts/provider/Bar/consumer/Foo/version/2", pact_content, { "CONTENT_TYPE" => "application/json", "pactbroker.database_connector" => database_connector}) }
|
15
|
+
|
16
|
+
context "when there is a verification from the main branch of the provider" do
|
17
|
+
before do
|
18
|
+
td.create_consumer("Foo")
|
19
|
+
.create_provider("Bar", main_branch: "main")
|
20
|
+
.create_consumer_version("1")
|
21
|
+
.create_pact(json_content: pact_content)
|
22
|
+
.create_verification(provider_version: "1", branch: "main")
|
23
|
+
.create_verification(provider_version: "2", branch: "feat/x", number: 2)
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:expected_webhook_body) { { provider_version: "1"}.to_json }
|
27
|
+
|
28
|
+
it "uses that in the webhook" do
|
29
|
+
subject
|
30
|
+
expect(request).to have_been_made
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "when there is not a verification from the main branch of the provider" do
|
35
|
+
before do
|
36
|
+
td.create_consumer("Foo")
|
37
|
+
.create_provider("Bar", main_branch: "main")
|
38
|
+
.create_consumer_version("1")
|
39
|
+
.create_pact(json_content: pact_content)
|
40
|
+
.create_verification(provider_version: "1", branch: "feat/y")
|
41
|
+
.create_verification(provider_version: "2", branch: "feat/x", number: 2)
|
42
|
+
end
|
43
|
+
|
44
|
+
let(:expected_webhook_body) { { provider_version: "2"}.to_json }
|
45
|
+
|
46
|
+
it "uses the latest verification in the webhook" do
|
47
|
+
subject
|
48
|
+
expect(request).to have_been_made
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|