pact_broker 2.58.0 → 2.58.2
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 +25 -0
- data/.travis.yml +5 -3
- data/CHANGELOG.md +8 -0
- data/DEVELOPER_SETUP.md +46 -16
- data/Dockerfile +23 -2
- data/Gemfile +29 -2
- data/config.ru +32 -12
- data/config/database.yml +7 -0
- data/docker-compose-dev-postgres.yml +35 -0
- data/docker-compose-test.yml +100 -0
- data/lib/pact_broker/api/decorators/decorator_context.rb +1 -1
- data/lib/pact_broker/api/pact_broker_urls.rb +4 -4
- data/lib/pact_broker/api/paths.rb +15 -0
- data/lib/pact_broker/api/resources/all_webhooks.rb +3 -3
- data/lib/pact_broker/api/resources/base_resource.rb +2 -174
- data/lib/pact_broker/api/resources/default_base_resource.rb +211 -0
- data/lib/pact_broker/api/resources/error_handler.rb +1 -1
- data/lib/pact_broker/api/resources/group.rb +1 -13
- data/lib/pact_broker/api/resources/label.rb +5 -2
- data/lib/pact_broker/api/resources/latest_pact.rb +4 -0
- data/lib/pact_broker/api/resources/latest_pacts.rb +1 -4
- data/lib/pact_broker/api/resources/latest_verifications_for_consumer_version.rb +8 -2
- data/lib/pact_broker/api/resources/matrix.rb +2 -2
- data/lib/pact_broker/api/resources/matrix_for_consumer_and_provider.rb +1 -1
- data/lib/pact_broker/api/resources/pact.rb +5 -1
- data/lib/pact_broker/api/resources/pact_content_diff.rb +1 -2
- data/lib/pact_broker/api/resources/pact_triggered_webhooks.rb +1 -7
- data/lib/pact_broker/api/resources/pact_versions.rb +1 -3
- data/lib/pact_broker/api/resources/pact_webhooks.rb +2 -5
- data/lib/pact_broker/api/resources/pact_webhooks_status.rb +1 -17
- data/lib/pact_broker/api/resources/pacticipant.rb +7 -14
- data/lib/pact_broker/api/resources/pacticipants.rb +1 -1
- data/lib/pact_broker/api/resources/pacticipants_for_label.rb +1 -1
- data/lib/pact_broker/api/resources/previous_distinct_pact_version.rb +4 -0
- data/lib/pact_broker/api/resources/provider_pacts.rb +5 -1
- data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +1 -1
- data/lib/pact_broker/api/resources/tag.rb +5 -1
- data/lib/pact_broker/api/resources/tagged_pact_versions.rb +1 -2
- data/lib/pact_broker/api/resources/triggered_webhook_logs.rb +4 -0
- data/lib/pact_broker/api/resources/verification.rb +7 -3
- data/lib/pact_broker/api/resources/verification_triggered_webhooks.rb +5 -1
- data/lib/pact_broker/api/resources/verifications.rb +7 -3
- data/lib/pact_broker/api/resources/version.rb +4 -1
- data/lib/pact_broker/api/resources/versions.rb +1 -3
- data/lib/pact_broker/api/resources/webhook.rb +6 -2
- data/lib/pact_broker/api/resources/webhook_execution.rb +4 -0
- data/lib/pact_broker/api/resources/webhooks.rb +3 -18
- data/lib/pact_broker/app.rb +1 -0
- data/lib/pact_broker/configuration.rb +8 -1
- data/lib/pact_broker/db/clean.rb +0 -6
- data/lib/pact_broker/domain/pacticipant.rb +7 -2
- data/lib/pact_broker/domain/version.rb +3 -0
- data/lib/pact_broker/index/service.rb +5 -45
- data/lib/pact_broker/pacticipants/repository.rb +2 -2
- data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +2 -5
- data/lib/pact_broker/pacts/pact_publication.rb +11 -9
- data/lib/pact_broker/pacts/pact_version.rb +3 -4
- data/lib/pact_broker/pacts/repository.rb +53 -39
- data/lib/pact_broker/pacts/verifiable_pact.rb +8 -0
- data/lib/pact_broker/policies.rb +53 -0
- data/lib/pact_broker/repositories/helpers.rb +3 -20
- data/lib/pact_broker/ui/controllers/index.rb +0 -2
- data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +3 -5
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/repository.rb +2 -4
- data/lib/rack/pact_broker/request_target.rb +6 -1
- data/lib/sequel/plugins/insert_ignore.rb +69 -0
- data/lib/sequel/plugins/upsert.rb +103 -0
- data/pact_broker.gemspec +22 -41
- data/script/docker/db-execute-sql-file.sh +2 -0
- data/script/issues/consumer-version-selectors-docs/issue-text.txt +11 -0
- data/script/issues/consumer-version-selectors-docs/issues.txt +6 -0
- data/script/issues/consumer-version-selectors-docs/raise-issue-in-client-repos.sh +10 -0
- data/script/prod/redact-data.sql +1 -0
- data/script/release-via-github-action.sh +7 -0
- data/script/trigger-release.sh +30 -0
- data/spec/features/get_versions_spec.rb +1 -6
- data/spec/lib/pact_broker/api/pact_broker_urls_spec.rb +2 -2
- data/spec/lib/pact_broker/api/resources/all_webhooks_spec.rb +1 -1
- data/spec/lib/pact_broker/api/resources/default_base_resource_spec.rb +158 -0
- data/spec/lib/pact_broker/api/resources/tag_spec.rb +2 -2
- data/spec/lib/pact_broker/api/resources/webhook_spec.rb +1 -1
- data/spec/lib/pact_broker/api/resources/webhooks_spec.rb +1 -1
- data/spec/lib/pact_broker/db/clean_old_spec.rb +125 -0
- data/spec/lib/pact_broker/db/clean_spec.rb +45 -11
- data/spec/lib/pact_broker/index/service_spec.rb +2 -3
- data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_spec.rb +36 -0
- data/spec/lib/pact_broker/versions/repository_spec.rb +8 -0
- data/spec/lib/rack/pact_broker/request_target_spec.rb +7 -0
- data/spec/lib/sequel/plugins/insert_ignore_spec.rb +82 -0
- data/spec/lib/sequel/plugins/upsert_spec.rb +125 -0
- data/spec/spec_helper.rb +1 -0
- data/tasks/audit.rake +6 -2
- data/tasks/development.rake +2 -2
- metadata +46 -284
- data/spec/lib/pact_broker/api/resources/base_resource_spec.rb +0 -78
@@ -125,7 +125,7 @@ module PactBroker
|
|
125
125
|
end
|
126
126
|
|
127
127
|
it "renders the tag" do
|
128
|
-
expect(tag_decorator).to receive(:to_json).with(user_options:
|
128
|
+
expect(tag_decorator).to receive(:to_json).with(user_options: hash_including(base_url: "http://example.org"))
|
129
129
|
subject
|
130
130
|
expect(last_response.body).to eq tag_json
|
131
131
|
end
|
@@ -149,7 +149,7 @@ module PactBroker
|
|
149
149
|
end
|
150
150
|
|
151
151
|
it "renders the tag" do
|
152
|
-
expect(tag_decorator).to receive(:to_json).with(user_options:
|
152
|
+
expect(tag_decorator).to receive(:to_json).with(user_options: hash_including(base_url: "http://example.org"))
|
153
153
|
subject
|
154
154
|
expect(last_response.body).to eq tag_json
|
155
155
|
end
|
@@ -40,7 +40,7 @@ module PactBroker::Api
|
|
40
40
|
|
41
41
|
it "generates a JSON representation of the webhook" do
|
42
42
|
expect(Decorators::WebhookDecorator).to receive(:new).with(webhook)
|
43
|
-
expect(decorator).to receive(:to_json).with(user_options:
|
43
|
+
expect(decorator).to receive(:to_json).with(user_options: hash_including(base_url: 'http://example.org'))
|
44
44
|
subject
|
45
45
|
end
|
46
46
|
|
@@ -223,7 +223,7 @@ module PactBroker::Api
|
|
223
223
|
|
224
224
|
it "generates the JSON response body" do
|
225
225
|
expect(Decorators::WebhookDecorator).to receive(:new).with(saved_webhook).and_return(webhook_decorator)
|
226
|
-
expect(webhook_decorator).to receive(:to_json).with(user_options:
|
226
|
+
expect(webhook_decorator).to receive(:to_json).with(user_options: hash_including(base_url: 'http://example.org'))
|
227
227
|
subject
|
228
228
|
end
|
229
229
|
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'pact_broker/db/clean'
|
2
|
+
|
3
|
+
IS_MYSQL = !!DB.mysql?
|
4
|
+
|
5
|
+
module PactBroker
|
6
|
+
module DB
|
7
|
+
# Inner queries don't work on MySQL. Seriously, MySQL???
|
8
|
+
describe Clean, skip: true, pending: IS_MYSQL do
|
9
|
+
let(:options) { {} }
|
10
|
+
let(:db) { PactBroker::DB.connection }
|
11
|
+
|
12
|
+
subject { Clean.call(PactBroker::DB.connection, options) }
|
13
|
+
|
14
|
+
describe ".call"do
|
15
|
+
|
16
|
+
before do
|
17
|
+
td.create_pact_with_hierarchy("Foo", "0", "Bar")
|
18
|
+
.create_consumer_version_tag("prod")
|
19
|
+
.create_consumer_version("1")
|
20
|
+
.create_pact
|
21
|
+
.create_consumer_version_tag("prod")
|
22
|
+
.comment("keep")
|
23
|
+
.create_verification(provider_version: "20")
|
24
|
+
.create_consumer_version("2")
|
25
|
+
.create_pact
|
26
|
+
.comment("don't keep")
|
27
|
+
.create_webhook
|
28
|
+
.create_triggered_webhook
|
29
|
+
.create_webhook_execution
|
30
|
+
.create_verification(provider_version: "30")
|
31
|
+
.create_verification_webhook
|
32
|
+
.create_triggered_webhook
|
33
|
+
.create_webhook_execution
|
34
|
+
.create_consumer_version("3")
|
35
|
+
.create_pact
|
36
|
+
.comment("keep")
|
37
|
+
.create_verification(provider_version: "40")
|
38
|
+
.create_verification(provider_version: "40", number: 2)
|
39
|
+
.create_verification(provider_version: "50", number: 3)
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
it "does not delete any rows in the head matrix" do
|
44
|
+
head_matrix_before = db[:head_matrix].select_all
|
45
|
+
subject
|
46
|
+
head_matrix_after = db[:head_matrix].select_all
|
47
|
+
expect(head_matrix_before).to eq head_matrix_after
|
48
|
+
end
|
49
|
+
|
50
|
+
it "deletes rows that aren't the latest or latest tagged" do
|
51
|
+
subject
|
52
|
+
expect(db[:matrix].where(consumer_version_number: "2").count).to eq 0
|
53
|
+
end
|
54
|
+
|
55
|
+
it "deletes orphan pact_versions" do
|
56
|
+
subject
|
57
|
+
expect(db[:pact_versions].count).to eq 2
|
58
|
+
end
|
59
|
+
|
60
|
+
it "deletes orphan versions" do
|
61
|
+
subject
|
62
|
+
expect(db[:versions].where(number: "20").count).to be 1
|
63
|
+
expect(db[:versions].where(number: "30").count).to be 0
|
64
|
+
expect(db[:versions].where(number: "40").count).to be 1
|
65
|
+
expect(db[:versions].where(number: "50").count).to be 1
|
66
|
+
end
|
67
|
+
|
68
|
+
it "deletes overwritten verifications" do
|
69
|
+
expect(db[:matrix].where(provider_version_number: "40").count).to eq 2
|
70
|
+
subject
|
71
|
+
expect(db[:matrix].where(provider_version_number: "40", verification_number: 2).count).to eq 1
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe ".call with a date" do
|
76
|
+
before do
|
77
|
+
td.set_now(DateTime.new(2019, 1, 1))
|
78
|
+
.create_pact_with_hierarchy
|
79
|
+
.create_verification
|
80
|
+
end
|
81
|
+
let(:options) { { date: date } }
|
82
|
+
|
83
|
+
context "when the data is older than the given date" do
|
84
|
+
let(:date) { DateTime.new(2019, 1, 2) }
|
85
|
+
let(:expected_report) do
|
86
|
+
{
|
87
|
+
kept: { pact_publications: 0, verification_results: 0 },
|
88
|
+
deleted: { pact_publications: 1, verification_results: 1 }
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
it "is deleted" do
|
93
|
+
subject
|
94
|
+
expect(db[:head_matrix].count).to be 0
|
95
|
+
end
|
96
|
+
|
97
|
+
it "returns a report" do
|
98
|
+
expect(subject).to include(expected_report)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "when the data is not older than the given date" do
|
103
|
+
let(:date) { DateTime.new(2019, 1, 1) }
|
104
|
+
let(:expected_report) do
|
105
|
+
{
|
106
|
+
kept: { pact_publications: 1, verification_results: 1 },
|
107
|
+
deleted: { pact_publications: 0, verification_results: 0 }
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
it "is not deleted" do
|
112
|
+
subject
|
113
|
+
expect(db[:head_matrix].count).to be 1
|
114
|
+
expect(db[:pact_publications].count).to be 1
|
115
|
+
expect(db[:verifications].count).to be 1
|
116
|
+
end
|
117
|
+
|
118
|
+
it "returns a report" do
|
119
|
+
expect(subject).to include(expected_report)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -11,31 +11,26 @@ module PactBroker
|
|
11
11
|
let(:db) { PactBroker::DB.connection }
|
12
12
|
|
13
13
|
subject { Clean.call(PactBroker::DB.connection, options) }
|
14
|
+
let(:latest_dev_selector) { PactBroker::Matrix::UnresolvedSelector.new(tag: "dev", latest: true) }
|
15
|
+
let(:all_prod_selector) { PactBroker::Matrix::UnresolvedSelector.new(tag: "prod") }
|
14
16
|
|
15
17
|
describe ".call"do
|
16
18
|
context "when there are specified versions to keep" do
|
17
19
|
before do
|
18
20
|
td.create_pact_with_hierarchy("Foo", "1", "Bar")
|
19
21
|
.create_consumer_version_tag("prod")
|
20
|
-
.create_consumer_version_tag("
|
22
|
+
.create_consumer_version_tag("dev")
|
21
23
|
.create_consumer_version("3", tag_names: %w{prod})
|
22
24
|
.create_pact
|
23
|
-
.create_consumer_version("4", tag_names: %w{
|
25
|
+
.create_consumer_version("4", tag_names: %w{dev})
|
24
26
|
.create_pact
|
25
|
-
.create_consumer_version("5", tag_names: %w{
|
27
|
+
.create_consumer_version("5", tag_names: %w{dev})
|
26
28
|
.create_pact
|
27
29
|
.create_consumer_version("6", tag_names: %w{foo})
|
28
30
|
.create_pact
|
29
31
|
end
|
30
32
|
|
31
|
-
let(:options)
|
32
|
-
{
|
33
|
-
keep: [
|
34
|
-
PactBroker::Matrix::UnresolvedSelector.new(tag: "prod"),
|
35
|
-
PactBroker::Matrix::UnresolvedSelector.new(tag: "master", latest: true)
|
36
|
-
]
|
37
|
-
}
|
38
|
-
end
|
33
|
+
let(:options) { { keep: [all_prod_selector, latest_dev_selector] } }
|
39
34
|
|
40
35
|
it "does not delete the consumer versions specified" do
|
41
36
|
expect(PactBroker::Domain::Version.where(number: "1").count).to be 1
|
@@ -51,6 +46,45 @@ module PactBroker
|
|
51
46
|
expect(PactBroker::Domain::Version.where(number: "6").count).to be 0
|
52
47
|
end
|
53
48
|
end
|
49
|
+
|
50
|
+
context "with orphan pact versions" do
|
51
|
+
before do
|
52
|
+
# Create a pact that will not be deleted
|
53
|
+
td.create_pact_with_hierarchy("Foo", "0", "Bar", json_content_1)
|
54
|
+
.create_consumer_version_tag("dev")
|
55
|
+
# Create an orphan pact version
|
56
|
+
pact_version_params = PactBroker::Pacts::PactVersion.first.to_hash
|
57
|
+
pact_version_params.delete(:id)
|
58
|
+
pact_version_params[:sha] = "1234"
|
59
|
+
PactBroker::Pacts::PactVersion.create(pact_version_params)
|
60
|
+
end
|
61
|
+
|
62
|
+
let(:json_content_1) { { interactions: ['a', 'b']}.to_json }
|
63
|
+
let(:json_content_2) { { interactions: ['a', 'c']}.to_json }
|
64
|
+
|
65
|
+
let(:options) { { keep: [latest_dev_selector] } }
|
66
|
+
|
67
|
+
it "deletes them" do
|
68
|
+
expect { subject }.to change { PactBroker::Pacts::PactVersion.count }.by(-1)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "with triggered and executed" do
|
73
|
+
before do
|
74
|
+
td.create_pact_with_hierarchy("Foo", "1", "Bar")
|
75
|
+
.create_consumer_version_tag("dev").comment("keep")
|
76
|
+
.create_webhook
|
77
|
+
.create_triggered_webhook
|
78
|
+
.create_webhook_execution
|
79
|
+
.add_day
|
80
|
+
.create_triggered_webhook
|
81
|
+
.create_webhook_execution
|
82
|
+
end
|
83
|
+
|
84
|
+
xit "deletes all but the most recent triggered webhook" do
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
54
88
|
end
|
55
89
|
end
|
56
90
|
end
|
@@ -8,17 +8,16 @@ module PactBroker
|
|
8
8
|
describe Service do
|
9
9
|
let(:td) { TestDataBuilder.new }
|
10
10
|
let(:tags) { ['prod', 'production'] }
|
11
|
-
let(:options) { { tags: tags,
|
11
|
+
let(:options) { { tags: tags, page_size: page_size, page_number: page_number } }
|
12
12
|
let(:page_number) { nil }
|
13
13
|
let(:page_size) { nil }
|
14
14
|
let(:rows) { subject.find_index_items(options) }
|
15
|
-
let(:optimised) { true }
|
16
15
|
|
17
16
|
before do
|
18
17
|
td.create_global_webhook
|
19
18
|
end
|
20
19
|
|
21
|
-
subject{ Service }
|
20
|
+
subject { Service }
|
22
21
|
|
23
22
|
describe "find_relationships integration test" do
|
24
23
|
context "when a prod pact exists and is not the latest version" do
|
@@ -20,6 +20,42 @@ module PactBroker
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
+
context "when there are multiple wip pacts" do
|
24
|
+
before do
|
25
|
+
td.create_provider("bar")
|
26
|
+
.create_provider_version("333")
|
27
|
+
.create_provider_version_tag("dev")
|
28
|
+
.add_day
|
29
|
+
.create_pact_with_hierarchy("foo", "1", "bar")
|
30
|
+
.create_consumer_version_tag("feat-1")
|
31
|
+
.add_day
|
32
|
+
.create_pact_with_hierarchy("meep", "2", "bar")
|
33
|
+
.create_consumer_version_tag("feat-2")
|
34
|
+
.add_day
|
35
|
+
.create_pact_with_hierarchy("foo", "2", "bar")
|
36
|
+
.create_consumer_version_tag("feat-2")
|
37
|
+
.add_day
|
38
|
+
.create_pact_with_hierarchy("meep", "1", "bar")
|
39
|
+
.create_consumer_version_tag("feat-1")
|
40
|
+
end
|
41
|
+
|
42
|
+
let(:provider_tags) { %w[dev] }
|
43
|
+
|
44
|
+
it "sorts them" do
|
45
|
+
expect(subject[0].consumer_name).to eq "foo"
|
46
|
+
expect(subject[0].consumer_version_number).to eq "1"
|
47
|
+
|
48
|
+
expect(subject[1].consumer_name).to eq "foo"
|
49
|
+
expect(subject[1].consumer_version_number).to eq "2"
|
50
|
+
|
51
|
+
expect(subject[2].consumer_name).to eq "meep"
|
52
|
+
expect(subject[2].consumer_version_number).to eq "2"
|
53
|
+
|
54
|
+
expect(subject[3].consumer_name).to eq "meep"
|
55
|
+
expect(subject[3].consumer_version_number).to eq "1"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
23
59
|
context "when the latest pact for a tag has been successfully verified by the given provider tag" do
|
24
60
|
before do
|
25
61
|
td.create_pact_with_hierarchy("foo", "1", "bar")
|
@@ -39,6 +39,10 @@ module PactBroker
|
|
39
39
|
|
40
40
|
subject { Repository.new.create pacticipant_id: existing_version.pacticipant_id, number: "1.2.4" }
|
41
41
|
|
42
|
+
it "creates a new version" do
|
43
|
+
expect { subject }.to change { PactBroker::Domain::Version.count }.by(1)
|
44
|
+
end
|
45
|
+
|
42
46
|
it "sets the order to the previous version's order plus one" do
|
43
47
|
expect(subject.order).to eq existing_version.order + 1
|
44
48
|
end
|
@@ -49,6 +53,10 @@ module PactBroker
|
|
49
53
|
|
50
54
|
subject { Repository.new.create pacticipant_id: existing_version.pacticipant_id, number: version_number }
|
51
55
|
|
56
|
+
it "does not create a new version" do
|
57
|
+
expect { subject }.to_not change { PactBroker::Domain::Version.count }
|
58
|
+
end
|
59
|
+
|
52
60
|
it "returns the pre-existing version" do
|
53
61
|
expect(subject.id).to eq existing_version.id
|
54
62
|
end
|
@@ -56,6 +56,13 @@ module Rack
|
|
56
56
|
|
57
57
|
it { is_expected.to be false }
|
58
58
|
end
|
59
|
+
|
60
|
+
context "when the request is for a badge resource with a svg content type" do
|
61
|
+
let(:accept) { "image/svg+xml;charset=utf-8" }
|
62
|
+
let(:path) { "/pacts/provider/foo/consumer/bar/latest/badge" }
|
63
|
+
|
64
|
+
it { is_expected.to be false }
|
65
|
+
end
|
59
66
|
end
|
60
67
|
end
|
61
68
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'sequel/plugins/insert_ignore'
|
2
|
+
require 'sequel'
|
3
|
+
|
4
|
+
module Sequel
|
5
|
+
module Plugins
|
6
|
+
module InsertIgnore
|
7
|
+
class PacticipantNoInsertIgnore < Sequel::Model(:pacticipants)
|
8
|
+
plugin :timestamps, update_on_create: true
|
9
|
+
end
|
10
|
+
|
11
|
+
class Pacticipant < Sequel::Model
|
12
|
+
plugin :insert_ignore, identifying_columns: [:name]
|
13
|
+
plugin :timestamps, update_on_create: true
|
14
|
+
end
|
15
|
+
|
16
|
+
class Version < Sequel::Model
|
17
|
+
plugin :insert_ignore, identifying_columns: [:pacticipant_id, :number]
|
18
|
+
plugin :timestamps, update_on_create: true
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when a duplicate is inserted with no insert_ignore" do
|
22
|
+
before do
|
23
|
+
PacticipantNoInsertIgnore.new(name: "Foo").save
|
24
|
+
end
|
25
|
+
|
26
|
+
subject do
|
27
|
+
PacticipantNoInsertIgnore.new(name: "Foo").save
|
28
|
+
end
|
29
|
+
|
30
|
+
it "raises an error" do
|
31
|
+
expect { subject }.to raise_error Sequel::UniqueConstraintViolation
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# This doesn't work on MSQL because the _insert_raw method
|
36
|
+
# does not return the row ID of the duplicated row when insert_ignore is used
|
37
|
+
# May have to go back to the old method of doing this
|
38
|
+
context "when a duplicate Pacticipant is inserted with insert_ignore" do
|
39
|
+
before do
|
40
|
+
Pacticipant.new(name: "Foo", repository_url: "http://foo").insert_ignore
|
41
|
+
end
|
42
|
+
|
43
|
+
subject do
|
44
|
+
Pacticipant.new(name: "Foo").insert_ignore
|
45
|
+
end
|
46
|
+
|
47
|
+
it "does not raise an error" do
|
48
|
+
expect { subject }.to_not raise_error
|
49
|
+
end
|
50
|
+
|
51
|
+
it "sets the values on the object" do
|
52
|
+
expect(subject.repository_url).to eq "http://foo"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "does not insert another row" do
|
56
|
+
expect { subject }.to_not change { Pacticipant.count }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "when a duplicate Version is inserted with insert_ignore" do
|
61
|
+
let!(:pacticipant) { Pacticipant.new(name: "Foo").save }
|
62
|
+
let!(:original_version) { Version.new(number: "1", pacticipant_id: pacticipant.id).insert_ignore }
|
63
|
+
|
64
|
+
subject do
|
65
|
+
Version.new(number: "1", pacticipant_id: pacticipant.id).insert_ignore
|
66
|
+
end
|
67
|
+
|
68
|
+
it "does not raise an error" do
|
69
|
+
expect { subject }.to_not raise_error
|
70
|
+
end
|
71
|
+
|
72
|
+
it "sets the values on the object" do
|
73
|
+
expect(subject.id).to eq original_version.id
|
74
|
+
end
|
75
|
+
|
76
|
+
it "does not insert another row" do
|
77
|
+
expect { subject }.to_not change { Version.count }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'sequel/plugins/upsert'
|
2
|
+
require 'sequel'
|
3
|
+
|
4
|
+
module Sequel
|
5
|
+
module Plugins
|
6
|
+
module Upsert
|
7
|
+
class PacticipantNoUpsert < Sequel::Model(:pacticipants)
|
8
|
+
plugin :timestamps, update_on_create: true
|
9
|
+
end
|
10
|
+
|
11
|
+
class Pacticipant < Sequel::Model
|
12
|
+
plugin :upsert, identifying_columns: [:name]
|
13
|
+
plugin :timestamps, update_on_create: true
|
14
|
+
end
|
15
|
+
|
16
|
+
class Version < Sequel::Model
|
17
|
+
plugin :upsert, identifying_columns: [:pacticipant_id, :number]
|
18
|
+
plugin :timestamps, update_on_create: true
|
19
|
+
end
|
20
|
+
|
21
|
+
class LatestPactPublicationIdForConsumerVersion < Sequel::Model(:latest_pact_publication_ids_for_consumer_versions)
|
22
|
+
set_primary_key [:provider_id, :consumer_version_id]
|
23
|
+
unrestrict_primary_key
|
24
|
+
plugin :upsert, identifying_columns: [:provider_id, :consumer_version_id]
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "LatestPactPublicationIdForConsumerVersion" do
|
28
|
+
before do
|
29
|
+
td.create_pact_with_hierarchy("Foo", "1", "Bar")
|
30
|
+
.create_consumer_version("2")
|
31
|
+
end
|
32
|
+
|
33
|
+
let!(:new_pact_publication) do
|
34
|
+
pact_publication_values = PactBroker::Pacts::PactPublication.first.values.dup
|
35
|
+
pact_publication_values.delete(:id)
|
36
|
+
pact_publication_values.delete(:created_at)
|
37
|
+
pact_publication_values.delete(:updated_at)
|
38
|
+
pact_publication_values[:revision_number] = 2
|
39
|
+
PactBroker::Pacts::PactPublication.new(pact_publication_values).save
|
40
|
+
end
|
41
|
+
|
42
|
+
let(:new_latest_pact_publication_id_for_consumer_version) do
|
43
|
+
values = LatestPactPublicationIdForConsumerVersion.first.values
|
44
|
+
LatestPactPublicationIdForConsumerVersion.new(values.merge(pact_publication_id: new_pact_publication.id))
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "save" do
|
48
|
+
subject { new_latest_pact_publication_id_for_consumer_version.save }
|
49
|
+
|
50
|
+
it "raises an error" do
|
51
|
+
expect { subject }.to raise_error Sequel::UniqueConstraintViolation
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "upsert" do
|
56
|
+
subject { new_latest_pact_publication_id_for_consumer_version.upsert }
|
57
|
+
|
58
|
+
it "updates the new object with the values from the existing object" do
|
59
|
+
expect(subject.pact_publication_id).to eq new_pact_publication.id
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when a duplicate is inserted with no upsert" do
|
65
|
+
before do
|
66
|
+
PacticipantNoUpsert.new(name: "Foo").save
|
67
|
+
end
|
68
|
+
|
69
|
+
subject do
|
70
|
+
PacticipantNoUpsert.new(name: "Foo").save
|
71
|
+
end
|
72
|
+
|
73
|
+
it "raises an error" do
|
74
|
+
expect { subject }.to raise_error Sequel::UniqueConstraintViolation
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# This doesn't work on MSQL because the _insert_raw method
|
79
|
+
# does not return the row ID of the duplicated row when upsert is used
|
80
|
+
# May have to go back to the old method of doing this
|
81
|
+
context "when a duplicate Pacticipant is inserted with upsert" do
|
82
|
+
before do
|
83
|
+
Pacticipant.new(name: "Foo", repository_url: "http://foo").upsert
|
84
|
+
end
|
85
|
+
|
86
|
+
subject do
|
87
|
+
Pacticipant.new(name: "Foo", repository_url: "http://bar").upsert
|
88
|
+
end
|
89
|
+
|
90
|
+
it "does not raise an error" do
|
91
|
+
expect { subject }.to_not raise_error
|
92
|
+
end
|
93
|
+
|
94
|
+
it "sets the values on the object" do
|
95
|
+
expect(subject.repository_url).to eq "http://bar"
|
96
|
+
end
|
97
|
+
|
98
|
+
it "does not insert another row" do
|
99
|
+
expect { subject }.to_not change { Pacticipant.count }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "when a duplicate Version is inserted with upsert" do
|
104
|
+
let!(:pacticipant) { Pacticipant.new(name: "Foo").save }
|
105
|
+
let!(:original_version) { Version.new(number: "1", pacticipant_id: pacticipant.id).upsert }
|
106
|
+
|
107
|
+
subject do
|
108
|
+
Version.new(number: "1", pacticipant_id: pacticipant.id).upsert
|
109
|
+
end
|
110
|
+
|
111
|
+
it "does not raise an error" do
|
112
|
+
expect { subject }.to_not raise_error
|
113
|
+
end
|
114
|
+
|
115
|
+
it "sets the values on the object" do
|
116
|
+
expect(subject.id).to eq original_version.id
|
117
|
+
end
|
118
|
+
|
119
|
+
it "does not insert another row" do
|
120
|
+
expect { subject }.to_not change { Version.count }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|