pact_broker 2.58.0 → 2.59.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 +45 -0
- data/.travis.yml +5 -3
- data/CHANGELOG.md +37 -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/decorators/version_decorator.rb +2 -0
- 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/renderers/html_pact_renderer.rb +26 -8
- data/lib/pact_broker/api/resources/all_webhooks.rb +12 -3
- data/lib/pact_broker/api/resources/badge.rb +4 -0
- data/lib/pact_broker/api/resources/base_resource.rb +2 -174
- data/lib/pact_broker/api/resources/can_i_deploy.rb +8 -0
- data/lib/pact_broker/api/resources/dashboard.rb +4 -0
- data/lib/pact_broker/api/resources/default_base_resource.rb +211 -0
- data/lib/pact_broker/api/resources/error_handler.rb +3 -5
- data/lib/pact_broker/api/resources/group.rb +7 -11
- data/lib/pact_broker/api/resources/index.rb +4 -0
- data/lib/pact_broker/api/resources/integration.rb +12 -0
- data/lib/pact_broker/api/resources/integrations.rb +9 -1
- data/lib/pact_broker/api/resources/label.rb +16 -6
- data/lib/pact_broker/api/resources/latest_pact.rb +8 -0
- data/lib/pact_broker/api/resources/latest_pacts.rb +9 -4
- data/lib/pact_broker/api/resources/latest_verifications_for_consumer_version.rb +16 -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 +8 -0
- 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 +11 -14
- data/lib/pact_broker/api/resources/pacticipants.rb +15 -1
- data/lib/pact_broker/api/resources/pacticipants_for_label.rb +1 -1
- data/lib/pact_broker/api/resources/previous_distinct_pact_version.rb +8 -1
- data/lib/pact_broker/api/resources/provider_pacts.rb +9 -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/badges/service.rb +3 -2
- data/lib/pact_broker/configuration.rb +21 -2
- data/lib/pact_broker/db/clean.rb +0 -6
- data/lib/pact_broker/doc/views/layouts/main.haml +1 -1
- data/lib/pact_broker/domain/pacticipant.rb +7 -2
- data/lib/pact_broker/domain/version.rb +3 -0
- data/lib/pact_broker/groups/service.rb +1 -1
- data/lib/pact_broker/index/service.rb +9 -43
- data/lib/pact_broker/matrix/deployment_status_summary.rb +1 -1
- data/lib/pact_broker/pacticipants/repository.rb +2 -2
- data/lib/pact_broker/pacts/content.rb +2 -1
- 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/test/test_data_builder.rb +4 -4
- data/lib/pact_broker/ui/controllers/clusters.rb +1 -1
- data/lib/pact_broker/ui/controllers/groups.rb +2 -2
- data/lib/pact_broker/ui/controllers/index.rb +1 -3
- data/lib/pact_broker/ui/controllers/matrix.rb +2 -2
- data/lib/pact_broker/ui/views/groups/show.html.erb +3 -3
- data/lib/pact_broker/ui/views/index/show-with-tags.haml +10 -10
- data/lib/pact_broker/ui/views/index/show.haml +6 -6
- data/lib/pact_broker/ui/views/layouts/main.haml +1 -1
- data/lib/pact_broker/ui/views/matrix/show.haml +4 -5
- 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/public/javascripts/pact.js +6 -2
- 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/seed.rb +5 -7
- data/script/trigger-release.sh +30 -0
- data/spec/features/get_versions_spec.rb +1 -6
- data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +4 -0
- data/spec/lib/pact_broker/api/pact_broker_urls_spec.rb +2 -2
- data/spec/lib/pact_broker/api/renderers/html_pact_renderer_spec.rb +24 -6
- 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/error_handler_spec.rb +18 -1
- 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/badges/service_spec.rb +6 -6
- 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/content_spec.rb +8 -0
- 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
@@ -22,6 +22,14 @@ module PactBroker
|
|
22
22
|
def wip?
|
23
23
|
wip
|
24
24
|
end
|
25
|
+
|
26
|
+
def <=> other
|
27
|
+
if self.consumer_name != other.consumer_name
|
28
|
+
return self.consumer_name <=> other.consumer_name
|
29
|
+
else
|
30
|
+
return self.consumer_version.order <=> other.consumer_version.order
|
31
|
+
end
|
32
|
+
end
|
25
33
|
end
|
26
34
|
end
|
27
35
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'pact_broker/configuration'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
class DefaultPolicy
|
5
|
+
def initialize(current_user, resource)
|
6
|
+
@current_user = current_user
|
7
|
+
@resource = resource
|
8
|
+
end
|
9
|
+
|
10
|
+
def update?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def delete?
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
def create?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def view?
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :current_user, :resource
|
29
|
+
|
30
|
+
class Scope
|
31
|
+
def initialize(user, scope)
|
32
|
+
@user = user
|
33
|
+
@scope = scope
|
34
|
+
end
|
35
|
+
|
36
|
+
def resolve
|
37
|
+
scope
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
attr_reader :user, :scope
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.policy!(*args)
|
47
|
+
PactBroker.configuration.policy_builder.call(*args)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.policy_scope!(*args)
|
51
|
+
PactBroker.configuration.policy_scope_builder.call(*args)
|
52
|
+
end
|
53
|
+
end
|
@@ -44,30 +44,13 @@ module PactBroker
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def select_for_subquery column
|
47
|
-
if mysql? #stoopid mysql doesn't allow subqueries
|
48
|
-
|
47
|
+
if mysql? #stoopid mysql doesn't allow you to modify datasets with subqueries
|
48
|
+
column_name = column.respond_to?(:alias) ? column.alias : column
|
49
|
+
select(column).collect{ | it | it[column_name] }
|
49
50
|
else
|
50
51
|
select(column)
|
51
52
|
end
|
52
53
|
end
|
53
|
-
|
54
|
-
def upsert row, unique_key_names, columns_to_update = nil
|
55
|
-
if postgres?
|
56
|
-
insert_conflict(update: row, target: unique_key_names).insert(row)
|
57
|
-
elsif mysql?
|
58
|
-
update_cols = columns_to_update || (row.keys - unique_key_names)
|
59
|
-
on_duplicate_key_update(*update_cols).insert(row)
|
60
|
-
else
|
61
|
-
# Sqlite
|
62
|
-
key = row.reject{ |k, v| !unique_key_names.include?(k) }
|
63
|
-
if where(key).count == 0
|
64
|
-
insert(row)
|
65
|
-
else
|
66
|
-
where(key).update(row)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
model.where(row.select{ |key, _| unique_key_names.include?(key)}).single_record
|
70
|
-
end
|
71
54
|
end
|
72
55
|
end
|
73
56
|
end
|
@@ -73,14 +73,14 @@ module PactBroker
|
|
73
73
|
self
|
74
74
|
end
|
75
75
|
|
76
|
-
def create_pact_with_hierarchy consumer_name = "Consumer", consumer_version_number = "1.2.3", provider_name = "Provider", json_content =
|
76
|
+
def create_pact_with_hierarchy consumer_name = "Consumer", consumer_version_number = "1.2.3", provider_name = "Provider", json_content = nil
|
77
77
|
use_consumer(consumer_name)
|
78
78
|
create_consumer(consumer_name) if !consumer
|
79
79
|
use_provider(provider_name)
|
80
80
|
create_provider provider_name if !provider
|
81
81
|
use_consumer_version(consumer_version_number)
|
82
82
|
create_consumer_version(consumer_version_number) if !consumer_version
|
83
|
-
create_pact json_content: json_content
|
83
|
+
create_pact json_content: json_content || default_json_content
|
84
84
|
self
|
85
85
|
end
|
86
86
|
|
@@ -436,10 +436,10 @@ module PactBroker
|
|
436
436
|
def default_json_content
|
437
437
|
{
|
438
438
|
"consumer" => {
|
439
|
-
"name" =>
|
439
|
+
"name" => consumer.name
|
440
440
|
},
|
441
441
|
"provider" => {
|
442
|
-
"name" =>
|
442
|
+
"name" => provider.name
|
443
443
|
},
|
444
444
|
"interactions" => [],
|
445
445
|
"random" => rand
|
@@ -19,7 +19,7 @@ module PactBroker
|
|
19
19
|
|
20
20
|
get "/" do
|
21
21
|
view_model = ViewDomain::IndexItems.new(pacticipant_service.find_index_items, base_url: base_url)
|
22
|
-
haml 'clusters/show', locals: {relationships: view_model, base_url: base_url}
|
22
|
+
haml 'clusters/show', locals: { relationships: view_model, base_url: base_url }, escape_html: true
|
23
23
|
end
|
24
24
|
|
25
25
|
end
|
@@ -13,13 +13,13 @@ module PactBroker
|
|
13
13
|
pacticipant = pacticipant_service.find_pacticipant_by_name(params[:name])
|
14
14
|
erb :'groups/show.html', {
|
15
15
|
locals: {
|
16
|
-
csv_path: "#{base_url}/groups/#{params[:name]}.csv",
|
16
|
+
csv_path: "#{base_url}/groups/#{ERB::Util.url_encode(params[:name])}.csv",
|
17
17
|
pacticipant_name: params[:name],
|
18
18
|
repository_url: pacticipant&.repository_url,
|
19
19
|
base_url: base_url
|
20
20
|
}
|
21
21
|
}, {
|
22
|
-
layout: 'layouts/main'
|
22
|
+
layout: 'layouts/main',
|
23
23
|
}
|
24
24
|
end
|
25
25
|
|
@@ -23,8 +23,6 @@ module PactBroker
|
|
23
23
|
page_size: page_size
|
24
24
|
}
|
25
25
|
|
26
|
-
# TODO remove this code when verified
|
27
|
-
options[:optimised] = true unless params[:optimised] == 'false'
|
28
26
|
index_items = ViewDomain::IndexItems.new(index_service.find_index_items(options), base_url: base_url)
|
29
27
|
|
30
28
|
page = tags ? :'index/show-with-tags' : :'index/show'
|
@@ -38,7 +36,7 @@ module PactBroker
|
|
38
36
|
base_url: base_url
|
39
37
|
}
|
40
38
|
|
41
|
-
haml page, {locals: locals, layout: :'layouts/main'}
|
39
|
+
haml page, { locals: locals, layout: :'layouts/main', escape_html: true }
|
42
40
|
end
|
43
41
|
|
44
42
|
def set_headers
|
@@ -42,7 +42,7 @@ module PactBroker
|
|
42
42
|
Padrino.logger.exception(e) unless e.is_a?(PactBroker::Error)
|
43
43
|
locals[:errors] = [e.message]
|
44
44
|
end
|
45
|
-
haml :'matrix/show', {locals: locals, layout: :'layouts/main'}
|
45
|
+
haml :'matrix/show', { locals: locals, layout: :'layouts/main', escape_html: true }
|
46
46
|
end
|
47
47
|
|
48
48
|
get "/provider/:provider_name/consumer/:consumer_name" do
|
@@ -60,7 +60,7 @@ module PactBroker
|
|
60
60
|
badge_url: nil,
|
61
61
|
base_url: base_url
|
62
62
|
}
|
63
|
-
haml :'matrix/show', {locals: locals, layout: :'layouts/main'}
|
63
|
+
haml :'matrix/show', { locals: locals, layout: :'layouts/main', escape_html: true }
|
64
64
|
end
|
65
65
|
|
66
66
|
def create_selector_objects(selector_hashes)
|
@@ -31,13 +31,13 @@ body{
|
|
31
31
|
<!-- developed by Duncan Alexander - hypothete.com -->
|
32
32
|
</head>
|
33
33
|
<body>
|
34
|
-
<h1>Network graph of <%= pacticipant_name %> relationships</h1>
|
34
|
+
<h1>Network graph of <%= escape_html(pacticipant_name) %> relationships</h1>
|
35
35
|
|
36
36
|
<% if repository_url %>
|
37
37
|
<p>Repository URL:
|
38
38
|
|
39
39
|
<%
|
40
|
-
repository_link = "<a href
|
40
|
+
repository_link = "<a href=\"#{repository_url}\">#{repository_url}</a>"
|
41
41
|
%>
|
42
42
|
|
43
43
|
<%= Sanitize.fragment(repository_link, Sanitize::Config::BASIC) %>
|
@@ -105,7 +105,7 @@ var relationshipPath = function(relationship, nodeLocations, pacticipants) {
|
|
105
105
|
|
106
106
|
var latestPactUrl = function (consumerName, providerName) {
|
107
107
|
//TODO send this with the relationship data
|
108
|
-
return '<%= base_url
|
108
|
+
return '<%= base_url %>' + '/pacts/provider/' + encodeURIComponent(providerName) + '/consumer/' + encodeURIComponent(consumerName) + '/latest';
|
109
109
|
};
|
110
110
|
|
111
111
|
var relationshipData = function(pacticipant, relationships) {
|
@@ -1,9 +1,9 @@
|
|
1
1
|
%body
|
2
|
-
|
2
|
+
!= render :haml, :'index/_css_and_js', :layout => false
|
3
3
|
.container
|
4
|
-
|
4
|
+
!= render :haml, :'index/_navbar', :layout => false, locals: {tag_toggle: false, base_url: base_url}
|
5
5
|
- if index_items.empty?
|
6
|
-
|
6
|
+
!= render :haml, :'index/_getting-started', :layout => false
|
7
7
|
%h1.page-header
|
8
8
|
Pacts
|
9
9
|
%table.table.table-bordered.table-striped{ id: 'relationships' }
|
@@ -37,10 +37,10 @@
|
|
37
37
|
%tr{'data-pact-versions-url': index_item.pact_versions_url, 'data-consumer-name': index_item.consumer_name, 'data-provider-name': index_item.provider_name, 'data-integration-url': index_item.integration_url}
|
38
38
|
%td.consumer
|
39
39
|
%a{:href => index_item.consumer_group_url }
|
40
|
-
=
|
40
|
+
= index_item.consumer_name
|
41
41
|
%td.consumer-version-number{"data-text": index_item.consumer_version_order}
|
42
42
|
%div.clippable
|
43
|
-
=
|
43
|
+
= index_item.consumer_version_number
|
44
44
|
- if index_item.consumer_version_number
|
45
45
|
%button.clippy.invisible{ title: "Copy to clipboard" }
|
46
46
|
%span.glyphicon.glyphicon-copy
|
@@ -49,7 +49,7 @@
|
|
49
49
|
latest
|
50
50
|
- index_item.consumer_version_latest_tag_names.each do | tag_name |
|
51
51
|
.tag.label.label-primary
|
52
|
-
=
|
52
|
+
= tag_name
|
53
53
|
%td.pact
|
54
54
|
%span.pact
|
55
55
|
%a{ href: index_item.pact_url, title: "View pact" }
|
@@ -57,16 +57,16 @@
|
|
57
57
|
%a{ href: index_item.pact_matrix_url, title: "View pact matrix" }
|
58
58
|
%td.provider
|
59
59
|
%a{ href: index_item.provider_group_url }
|
60
|
-
=
|
60
|
+
= index_item.provider_name
|
61
61
|
%td.provider-version-number
|
62
62
|
%div.clippable
|
63
|
-
=
|
63
|
+
= index_item.provider_version_number
|
64
64
|
- if index_item.provider_version_number
|
65
65
|
%button.clippy.invisible{ title: "Copy to clipboard" }
|
66
66
|
%span.glyphicon.glyphicon-copy
|
67
67
|
- index_item.provider_version_latest_tag_names.each do | tag_name |
|
68
68
|
.tag.label.label-primary
|
69
|
-
=
|
69
|
+
= tag_name
|
70
70
|
%td{"data-text": index_item.publication_date_of_latest_pact_order}
|
71
71
|
= index_item.publication_date_of_latest_pact.gsub("about ", "")
|
72
72
|
%td{ class: index_item.webhook_status }
|
@@ -86,7 +86,7 @@
|
|
86
86
|
%div.pagination
|
87
87
|
|
88
88
|
- pagination_locals = { page_number: page_number, page_size: page_size, pagination_record_count: pagination_record_count, current_page_size: current_page_size }
|
89
|
-
|
89
|
+
!= render :haml, :'index/_pagination', :layout => false, locals: pagination_locals
|
90
90
|
|
91
91
|
:javascript
|
92
92
|
$(function(){
|
@@ -1,9 +1,9 @@
|
|
1
1
|
%body
|
2
|
-
|
2
|
+
!= render :haml, :'index/_css_and_js', :layout => false
|
3
3
|
.container
|
4
|
-
|
4
|
+
!= render :haml, :'index/_navbar', :layout => false, locals: {tag_toggle: true, base_url: base_url}
|
5
5
|
- if index_items.empty?
|
6
|
-
|
6
|
+
!= render :haml, :'index/_getting-started', :layout => false
|
7
7
|
%h1.page-header
|
8
8
|
Pacts
|
9
9
|
%table.table.table-bordered.table-striped{ id: 'relationships' }
|
@@ -32,7 +32,7 @@
|
|
32
32
|
%td
|
33
33
|
%td.consumer
|
34
34
|
%a{ href: index_item.consumer_group_url }
|
35
|
-
=
|
35
|
+
= index_item.consumer_name
|
36
36
|
%td.pact
|
37
37
|
%span.pact
|
38
38
|
%a{ href: index_item.latest_pact_url, :title => "View pact" }
|
@@ -40,7 +40,7 @@
|
|
40
40
|
%a{ href: index_item.pact_matrix_url, title: "View pact matrix" }
|
41
41
|
%td.provider
|
42
42
|
%a{ href: index_item.provider_group_url }
|
43
|
-
=
|
43
|
+
= index_item.provider_name
|
44
44
|
%td
|
45
45
|
%td{"data-text": index_item.publication_date_of_latest_pact_order}
|
46
46
|
= index_item.publication_date_of_latest_pact
|
@@ -58,7 +58,7 @@
|
|
58
58
|
%div.pagination
|
59
59
|
|
60
60
|
- pagination_locals = { page_number: page_number, page_size: page_size, pagination_record_count: pagination_record_count, current_page_size: current_page_size }
|
61
|
-
|
61
|
+
!= render :haml, :'index/_pagination', :layout => false, locals: pagination_locals
|
62
62
|
|
63
63
|
|
64
64
|
:javascript
|
@@ -20,15 +20,14 @@
|
|
20
20
|
- if defined?(errors) && errors.any?
|
21
21
|
- errors.each do | error |
|
22
22
|
%div.alert.alert-danger
|
23
|
-
=
|
24
|
-
|
23
|
+
= error
|
25
24
|
|
26
25
|
%form{action: "#{base_url}/matrix", onsubmit:'return onSubmit()'}
|
27
26
|
- selectors.each_with_index do | selector, index |
|
28
27
|
.selector
|
29
28
|
%label{for: "pacticipant#{index}"}
|
30
29
|
Pacticipant name
|
31
|
-
%input{name: 'q[]pacticipant', id: "pacticipant1#{index}", class: 'pacticipant_name', value:
|
30
|
+
%input{name: 'q[]pacticipant', id: "pacticipant1#{index}", class: 'pacticipant_name', value: selector.pacticipant_name}
|
32
31
|
|
33
32
|
.input-group
|
34
33
|
|
@@ -45,9 +44,9 @@
|
|
45
44
|
%option{ value: 'specify-all-tagged', selected: selector.specify_all_tagged }
|
46
45
|
All versions with tag...
|
47
46
|
|
48
|
-
%input{name: 'q[]version', type: 'text', id: "pacticipant#{index}_version", class: 'version', value:
|
47
|
+
%input{name: 'q[]version', type: 'text', id: "pacticipant#{index}_version", class: 'version', value: selector.pacticipant_version_number}
|
49
48
|
|
50
|
-
%input{name: 'q[]tag', type: 'text', id: "pacticipant#{index}_tag", class: 'tag', value:
|
49
|
+
%input{name: 'q[]tag', type: 'text', id: "pacticipant#{index}_tag", class: 'tag', value: selector.tag}
|
51
50
|
|
52
51
|
%input{name: 'q[]latest', value: 'true', hidden: true, class: 'latest-flag'}
|
53
52
|
|
data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb
CHANGED
@@ -3,16 +3,14 @@ require 'pact_broker/domain/verification'
|
|
3
3
|
module PactBroker
|
4
4
|
module Verifications
|
5
5
|
class LatestVerificationIdForPactVersionAndProviderVersion < Sequel::Model(:latest_verification_id_for_pact_version_and_provider_version)
|
6
|
-
|
7
6
|
unrestrict_primary_key
|
7
|
+
set_primary_key [:pact_version_id, :provider_version_id]
|
8
|
+
|
9
|
+
plugin :upsert, identifying_columns: [:pact_version_id, :provider_version_id]
|
8
10
|
|
9
11
|
dataset_module do
|
10
12
|
include PactBroker::Repositories::Helpers
|
11
13
|
end
|
12
|
-
|
13
|
-
def upsert
|
14
|
-
self.class.upsert(to_hash, [:pact_version_id, :provider_version_id])
|
15
|
-
end
|
16
14
|
end
|
17
15
|
end
|
18
16
|
end
|
data/lib/pact_broker/version.rb
CHANGED
@@ -56,10 +56,8 @@ module PactBroker
|
|
56
56
|
created_at: Sequel.datetime_class.now,
|
57
57
|
updated_at: Sequel.datetime_class.now
|
58
58
|
}
|
59
|
-
|
60
|
-
|
61
|
-
PactBroker::Domain::OrderVersions.(version)
|
62
|
-
version.refresh # reload with the populated order
|
59
|
+
|
60
|
+
PactBroker::Domain::Version.new(version_params).insert_ignore
|
63
61
|
end
|
64
62
|
|
65
63
|
def find_by_pacticipant_id_and_number_or_create pacticipant_id, number
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require 'pact_broker/api/paths'
|
2
3
|
|
3
4
|
module Rack
|
4
5
|
module PactBroker
|
@@ -13,7 +14,7 @@ module Rack
|
|
13
14
|
end
|
14
15
|
|
15
16
|
def request_for_api?(env)
|
16
|
-
explicit_request_for_api(env) || no_accept_header(env) || (accept_all(env) && !is_web_extension(env))
|
17
|
+
explicit_request_for_api(env) || no_accept_header(env) || is_badge_request?(env) || (accept_all(env) && !is_web_extension(env))
|
17
18
|
end
|
18
19
|
|
19
20
|
private
|
@@ -38,6 +39,10 @@ module Rack
|
|
38
39
|
API_CONTENT_TYPES.any?{ |content_type| header.include?(content_type) }
|
39
40
|
end
|
40
41
|
|
42
|
+
def is_badge_request?(env)
|
43
|
+
env['HTTP_ACCEPT'].include?('svg') && ::PactBroker::Api::Paths.is_badge_path?(env['PATH_INFO'])
|
44
|
+
end
|
45
|
+
|
41
46
|
# default curl Accept header
|
42
47
|
# Also used by browsers to request various web assets like woff files
|
43
48
|
def accept_all(env)
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# This plugin can be included into a Sequel model to allow the original record
|
2
|
+
# to be loaded into the model if a duplicate is inserted.
|
3
|
+
# This is to handle race conditions when two requests come in in parallel to create
|
4
|
+
# the same resource.
|
5
|
+
|
6
|
+
# Rather than re-writing the whole save method and all the hooks and validation logic in it,
|
7
|
+
# it naughtily overrides the private _insert_dataset.
|
8
|
+
|
9
|
+
module Sequel
|
10
|
+
module Plugins
|
11
|
+
module InsertIgnore
|
12
|
+
def self.configure(model, opts=OPTS)
|
13
|
+
model.instance_exec do
|
14
|
+
@insert_ignore_plugin_identifying_columns = opts.fetch(:identifying_columns)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
attr_reader :insert_ignore_plugin_identifying_columns
|
20
|
+
end
|
21
|
+
|
22
|
+
module InstanceMethods
|
23
|
+
def insert_ignore(opts = {})
|
24
|
+
save(opts)
|
25
|
+
load_values_from_previously_inserted_object unless id
|
26
|
+
self
|
27
|
+
rescue Sequel::NoExistingObject
|
28
|
+
load_values_from_previously_inserted_object
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def load_values_from_previously_inserted_object
|
34
|
+
set_primary_key_columns_from_previously_inserted_object
|
35
|
+
refresh
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_primary_key_columns_from_previously_inserted_object
|
39
|
+
if !primary_key_columns_are_same_as_identifying_columns
|
40
|
+
existing_record = find_previously_inserted_object
|
41
|
+
insert_ignore_primary_key_columns.each do | column |
|
42
|
+
self.send("#{column}=".to_sym, existing_record[column])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def find_previously_inserted_object
|
48
|
+
query = self.class.insert_ignore_plugin_identifying_columns.each_with_object({}) do | column_name, q |
|
49
|
+
q[column_name] = values[column_name]
|
50
|
+
end
|
51
|
+
model.where(query).single_record
|
52
|
+
end
|
53
|
+
|
54
|
+
def insert_ignore_primary_key_columns
|
55
|
+
@insert_ignore_primary_key_columns ||= [*primary_key].sort
|
56
|
+
end
|
57
|
+
|
58
|
+
def primary_key_columns_are_same_as_identifying_columns
|
59
|
+
insert_ignore_primary_key_columns == self.class.insert_ignore_plugin_identifying_columns.sort
|
60
|
+
end
|
61
|
+
|
62
|
+
# naughty override of Sequel private method
|
63
|
+
def _insert_dataset
|
64
|
+
super.insert_ignore
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|