pact_broker 2.15.0 → 2.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +7 -3
- data/CHANGELOG.md +53 -0
- data/DEVELOPER_DOCUMENTATION.md +28 -1
- data/DEVELOPER_SETUP.md +1 -1
- data/README.md +8 -5
- data/db/migrations/000004_create_tags_table.rb +1 -1
- data/db/migrations/000050_create_latest_matrix.rb +1 -0
- data/db/migrations/20180122_create_head_pact_publications.rb +21 -0
- data/db/migrations/20180123_create_tags_with_latest_flag.rb +28 -0
- data/db/migrations/20180129_create_latest_matrix_for_cv_and_pv.rb +91 -0
- data/db/migrations/20180130_create_materialized_matrix.rb +35 -0
- data/db/migrations/20180131_create_materialized_latest_matrix.rb +35 -0
- data/db/migrations/20180201_create_head_matrix.rb +33 -0
- data/db/migrations/20180202_create_materialized_head_matrix.rb +34 -0
- data/db/migrations/20180203_fix_head_matrix.rb +36 -0
- data/db/migrations/20180204_fix_latest_matrix_for_cv_and_pv.rb +57 -0
- data/db/migrations/20180205_drop_materialized_latest_matrix.rb +36 -0
- data/db/migrations/20180206_recreate_head_matrix_rename_consumer_tag_name.rb +68 -0
- data/db/migrations/20180207_recreate_head_matrix_union_all.rb +60 -0
- data/db/migrations/20180208_add_cv_tag_name_index_to_mat_head_matrix.rb +7 -0
- data/db/migrations/20180209_recreate_latest_matrix_for_cv_and_pv_union_all.rb +54 -0
- data/db/migrations/20180210_fix_latest_matrix_for_cv_and_pv_again.rb +53 -0
- data/db/migrations/migration_helper.rb +8 -0
- data/db/test/backwards_compatibility/Rakefile +1 -1
- data/example/pact_broker_database.sqlite3 +0 -0
- data/lib/pact_broker/api.rb +1 -0
- data/lib/pact_broker/api/decorators/dashboard_decorator.rb +163 -0
- data/lib/pact_broker/api/decorators/dashboard_text_decorator.rb +50 -0
- data/lib/pact_broker/api/decorators/matrix_decorator.rb +21 -16
- data/lib/pact_broker/api/decorators/pacticipant_decorator.rb +1 -0
- data/lib/pact_broker/api/pact_broker_urls.rb +29 -0
- data/lib/pact_broker/api/resources/base_resource.rb +3 -0
- data/lib/pact_broker/api/resources/dashboard.rb +38 -0
- data/lib/pact_broker/api/resources/label.rb +0 -1
- data/lib/pact_broker/api/resources/tag.rb +0 -1
- data/lib/pact_broker/dashboard/service.rb +0 -0
- data/lib/pact_broker/domain/index_item.rb +16 -5
- data/lib/pact_broker/index/service.rb +69 -4
- data/lib/pact_broker/matrix/head_row.rb +11 -0
- data/lib/pact_broker/matrix/latest_row.rb +2 -16
- data/lib/pact_broker/matrix/repository.rb +56 -11
- data/lib/pact_broker/matrix/row.rb +166 -6
- data/lib/pact_broker/matrix/service.rb +5 -0
- data/lib/pact_broker/tags/tag_with_latest_flag.rb +18 -0
- data/lib/pact_broker/ui/controllers/index.rb +5 -2
- data/lib/pact_broker/ui/controllers/matrix.rb +3 -3
- data/lib/pact_broker/ui/view_models/index_item.rb +13 -5
- data/lib/pact_broker/ui/view_models/matrix_line.rb +77 -8
- data/lib/pact_broker/ui/view_models/matrix_lines.rb +17 -0
- data/lib/pact_broker/ui/view_models/matrix_tag.rb +42 -0
- data/lib/pact_broker/ui/views/index/show-with-tags.haml +26 -14
- data/lib/pact_broker/ui/views/index/show.haml +9 -8
- data/lib/pact_broker/ui/views/matrix/show.haml +46 -15
- data/lib/pact_broker/verifications/latest_verifications_by_consumer_version.rb +1 -0
- data/lib/pact_broker/verifications/repository.rb +4 -4
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/abbreviate_number.rb +14 -0
- data/pact_broker.gemspec +3 -2
- data/public/images/logo@2x.png +0 -0
- data/public/javascripts/matrix.js +5 -0
- data/public/stylesheets/index.css +33 -1
- data/public/stylesheets/matrix.css +9 -0
- data/script/db-spec.sh +1 -1
- data/spec/features/get_dashboard_spec.rb +29 -0
- data/spec/fixtures/dashboard.json +83 -0
- data/spec/lib/pact_broker/api/decorators/dashboard_decorator_spec.rb +89 -0
- data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +30 -26
- data/spec/lib/pact_broker/api/resources/dashboard_spec.rb +16 -0
- data/spec/lib/pact_broker/api/resources/group_spec.rb +1 -0
- data/spec/lib/pact_broker/index/service_spec.rb +146 -32
- data/spec/lib/pact_broker/matrix/repository_spec.rb +48 -1
- data/spec/lib/pact_broker/matrix/row_spec.rb +59 -0
- data/spec/lib/pact_broker/ui/view_models/index_item_spec.rb +17 -12
- data/spec/lib/pact_broker/versions/abbreviate_number_spec.rb +22 -0
- data/spec/migrations/20180201_create_head_matrix_spec.rb +132 -0
- data/spec/migrations/23_pact_versions_spec.rb +2 -2
- data/spec/migrations/50_create_latest_matrix_spec.rb +84 -16
- data/spec/migrations/change_migration_strategy_spec.rb +1 -1
- data/spec/service_consumers/pact_helper.rb +4 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/support/migration_helpers.rb +1 -1
- data/spec/support/rspec_match_hash.rb +6 -2
- data/spec/support/shared_examples_for_responses.rb +1 -1
- data/spec/support/test_data_builder.rb +61 -11
- metadata +57 -6
data/lib/pact_broker/api.rb
CHANGED
@@ -66,6 +66,7 @@ module PactBroker
|
|
66
66
|
add ['matrix', 'provider', :provider_name, 'latest', :provider_tag, 'consumer', :consumer_name, 'latest', :tag, 'badge'], Api::Resources::MatrixBadge, {resource_name: "matrix_tag_badge"}
|
67
67
|
add ['matrix'], Api::Resources::Matrix, {resource_name: "matrix"}
|
68
68
|
|
69
|
+
add ['dashboard'], Api::Resources::Dashboard, {resource_name: "dashboard"}
|
69
70
|
add [], Api::Resources::Index, {resource_name: "index"}
|
70
71
|
end
|
71
72
|
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'pact_broker/api/pact_broker_urls'
|
3
|
+
|
4
|
+
module PactBroker
|
5
|
+
module Api
|
6
|
+
module Decorators
|
7
|
+
class DashboardDecorator
|
8
|
+
include PactBroker::Api::PactBrokerUrls
|
9
|
+
|
10
|
+
def initialize(index_items)
|
11
|
+
@index_items = index_items
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_json(options)
|
15
|
+
to_hash(options).to_json
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_hash(options)
|
19
|
+
{
|
20
|
+
items: items(index_items, options[:user_options][:base_url])
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :index_items
|
27
|
+
|
28
|
+
def items(index_items, base_url)
|
29
|
+
index_items.collect do | index_item |
|
30
|
+
index_item_hash(index_item.consumer, index_item.provider, index_item.consumer_version, index_item, base_url)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def index_item_hash(consumer, provider, consumer_version, index_item, base_url)
|
35
|
+
{
|
36
|
+
consumer: consumer_hash(index_item, consumer, consumer_version, base_url),
|
37
|
+
provider: provider_hash(index_item, provider, base_url),
|
38
|
+
pact: pact_hash(index_item, base_url),
|
39
|
+
pactTags: pact_tags(index_item, base_url),
|
40
|
+
latestVerificationResult: verification_hash(index_item, base_url),
|
41
|
+
latestVerificationResultTags: verification_tags(index_item, base_url),
|
42
|
+
verificationStatus: index_item.verification_status.to_s,
|
43
|
+
webhookStatus: index_item.webhook_status.to_s,
|
44
|
+
latestWebhookExecution: latest_webhook_execution(index_item, base_url),
|
45
|
+
_links: links(index_item, base_url)
|
46
|
+
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def consumer_hash(index_item, consumer, consumer_version, base_url)
|
51
|
+
{
|
52
|
+
name: index_item.consumer_name,
|
53
|
+
version: {
|
54
|
+
number: index_item.consumer_version_number,
|
55
|
+
_links: {
|
56
|
+
self: {
|
57
|
+
href: version_url(base_url, index_item.consumer_version)
|
58
|
+
}
|
59
|
+
}
|
60
|
+
},
|
61
|
+
_links: {
|
62
|
+
self: {
|
63
|
+
href: pacticipant_url(base_url, index_item.consumer)
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def provider_hash(index_item, provider, base_url)
|
70
|
+
hash = {
|
71
|
+
name: index_item.provider_name,
|
72
|
+
version: nil,
|
73
|
+
_links: {
|
74
|
+
self: {
|
75
|
+
href: pacticipant_url(base_url, index_item.provider)
|
76
|
+
}
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
if index_item.latest_verification
|
81
|
+
hash[:version] = { number: index_item.provider_version_number }
|
82
|
+
end
|
83
|
+
|
84
|
+
hash
|
85
|
+
end
|
86
|
+
|
87
|
+
def pact_hash(index_item, base_url)
|
88
|
+
{
|
89
|
+
createdAt: index_item.latest_pact.created_at.to_datetime.xmlschema,
|
90
|
+
_links: {
|
91
|
+
self: {
|
92
|
+
href: pact_url(base_url, index_item.latest_pact)
|
93
|
+
}
|
94
|
+
}
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
def verification_hash(index_item, base_url)
|
99
|
+
if index_item.latest_verification
|
100
|
+
{
|
101
|
+
success: index_item.latest_verification.success,
|
102
|
+
verifiedAt: index_item.latest_verification.created_at.to_datetime.xmlschema,
|
103
|
+
_links: {
|
104
|
+
self: {
|
105
|
+
href: verification_url(index_item.latest_verification, base_url)
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
else
|
110
|
+
nil
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def pact_tags(index_item, base_url)
|
115
|
+
index_item.tag_names.collect do | tag_name |
|
116
|
+
fake_tag = OpenStruct.new(name: tag_name, version: index_item.consumer_version)
|
117
|
+
{
|
118
|
+
name: tag_name,
|
119
|
+
latest: true,
|
120
|
+
_links: {
|
121
|
+
self: {
|
122
|
+
href: tag_url(base_url, fake_tag)
|
123
|
+
}
|
124
|
+
}
|
125
|
+
}
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def verification_tags(index_item, base_url)
|
130
|
+
index_item.latest_verification_latest_tags.collect do | tag |
|
131
|
+
fake_tag = OpenStruct.new(name: tag.name, version: index_item.provider_version)
|
132
|
+
{
|
133
|
+
name: tag.name,
|
134
|
+
latest: tag.latest?,
|
135
|
+
_links: {
|
136
|
+
self: {
|
137
|
+
href: tag_url(base_url, fake_tag)
|
138
|
+
}
|
139
|
+
}
|
140
|
+
}
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def latest_webhook_execution(index_item, base_url)
|
145
|
+
if index_item.last_webhook_execution_date
|
146
|
+
{
|
147
|
+
triggeredAt: index_item.last_webhook_execution_date.to_datetime.xmlschema
|
148
|
+
}
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def links(index_item, base_url)
|
153
|
+
{
|
154
|
+
'pb:webhook-status' => {
|
155
|
+
title: "Status of webhooks for #{index_item.consumer_name}/#{index_item.provider_name} pact",
|
156
|
+
href: webhooks_status_url(index_item.consumer, index_item.provider, base_url)
|
157
|
+
}
|
158
|
+
}
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
require 'pact_broker/api/pact_broker_urls'
|
3
|
+
|
4
|
+
module PactBroker
|
5
|
+
module Api
|
6
|
+
module Decorators
|
7
|
+
class DashboardTextDecorator
|
8
|
+
include PactBroker::Api::PactBrokerUrls
|
9
|
+
|
10
|
+
Line = Struct.new(:consumer_name, :c_version, :c_tags , :provider_name, :p_version, :p_tags, :success)
|
11
|
+
|
12
|
+
def initialize(index_items)
|
13
|
+
@index_items = index_items
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_json(options)
|
17
|
+
to_hash(options).to_json
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_text(options)
|
21
|
+
data = items(index_items, options[:user_options][:base_url])
|
22
|
+
printer = TablePrint::Printer.new(data)
|
23
|
+
printer.table_print + "\n"
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :index_items
|
29
|
+
|
30
|
+
def items(index_items, base_url)
|
31
|
+
index_items.collect do | index_item |
|
32
|
+
index_item_object(index_item)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def index_item_object(index_item)
|
37
|
+
Line.new(
|
38
|
+
index_item.consumer_name,
|
39
|
+
index_item.consumer_version_number,
|
40
|
+
index_item.tag_names.join(", "),
|
41
|
+
index_item.provider_name,
|
42
|
+
index_item.provider_version_number,
|
43
|
+
index_item.latest_verification_latest_tags.collect(&:name).join(", "),
|
44
|
+
index_item.verification_status.to_s
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -27,8 +27,8 @@ module PactBroker
|
|
27
27
|
|
28
28
|
def deployable
|
29
29
|
return nil if lines.empty?
|
30
|
-
return nil if lines.any?{ |line| line
|
31
|
-
lines.any? && lines.all?{ |line| line
|
30
|
+
return nil if lines.any?{ |line| line.success.nil? }
|
31
|
+
lines.any? && lines.all?{ |line| line.success }
|
32
32
|
end
|
33
33
|
|
34
34
|
def reason
|
@@ -47,9 +47,9 @@ module PactBroker
|
|
47
47
|
|
48
48
|
def matrix(lines, base_url)
|
49
49
|
lines.collect do | line |
|
50
|
-
provider = OpenStruct.new(name: line
|
51
|
-
consumer = OpenStruct.new(name: line
|
52
|
-
consumer_version = OpenStruct.new(number: line
|
50
|
+
provider = OpenStruct.new(name: line.provider_name)
|
51
|
+
consumer = OpenStruct.new(name: line.consumer_name)
|
52
|
+
consumer_version = OpenStruct.new(number: line.consumer_version_number, pacticipant: consumer)
|
53
53
|
line_hash(consumer, provider, consumer_version, line, base_url)
|
54
54
|
end
|
55
55
|
end
|
@@ -65,9 +65,9 @@ module PactBroker
|
|
65
65
|
|
66
66
|
def consumer_hash(line, consumer, consumer_version, base_url)
|
67
67
|
{
|
68
|
-
name: line
|
68
|
+
name: line.consumer_name,
|
69
69
|
version: {
|
70
|
-
number: line
|
70
|
+
number: line.consumer_version_number,
|
71
71
|
_links: {
|
72
72
|
self: {
|
73
73
|
href: version_url(base_url, consumer_version)
|
@@ -84,7 +84,7 @@ module PactBroker
|
|
84
84
|
|
85
85
|
def provider_hash(line, provider, base_url)
|
86
86
|
hash = {
|
87
|
-
name: line
|
87
|
+
name: line.provider_name,
|
88
88
|
version: nil,
|
89
89
|
_links: {
|
90
90
|
self: {
|
@@ -93,8 +93,8 @@ module PactBroker
|
|
93
93
|
}
|
94
94
|
}
|
95
95
|
|
96
|
-
if !line
|
97
|
-
hash[:version] = { number: line
|
96
|
+
if !line.provider_version_number.nil?
|
97
|
+
hash[:version] = { number: line.provider_version_number }
|
98
98
|
end
|
99
99
|
|
100
100
|
hash
|
@@ -102,23 +102,28 @@ module PactBroker
|
|
102
102
|
|
103
103
|
def pact_hash(line, base_url)
|
104
104
|
{
|
105
|
-
createdAt: line
|
105
|
+
createdAt: line.pact_created_at.to_datetime.xmlschema,
|
106
106
|
_links: {
|
107
107
|
self: {
|
108
|
-
href:
|
108
|
+
href: pact_url(base_url, line)
|
109
109
|
}
|
110
110
|
}
|
111
111
|
}
|
112
112
|
end
|
113
113
|
|
114
114
|
def verification_hash(line, base_url)
|
115
|
-
if !line
|
115
|
+
if !line.success.nil?
|
116
|
+
url_params = { consumer_name: line.consumer_name,
|
117
|
+
provider_name: line.provider_name,
|
118
|
+
pact_version_sha: line.pact_version_sha,
|
119
|
+
verification_number: line.verification_number
|
120
|
+
}
|
116
121
|
{
|
117
|
-
success: line
|
118
|
-
verifiedAt: line
|
122
|
+
success: line.success,
|
123
|
+
verifiedAt: line.verification_executed_at.to_datetime.xmlschema,
|
119
124
|
_links: {
|
120
125
|
self: {
|
121
|
-
href:
|
126
|
+
href: verification_url_from_params(url_params, base_url)
|
122
127
|
}
|
123
128
|
}
|
124
129
|
}
|
@@ -48,6 +48,7 @@ module PactBroker
|
|
48
48
|
if dasherized['_embedded']
|
49
49
|
if dasherized['_embedded']['latest-version']
|
50
50
|
dasherized['_embedded']['latest-version']['title'] = 'DEPRECATED - please use latestVersion'
|
51
|
+
dasherized['_embedded']['latest-version']['name'] = 'DEPRECATED - please use latestVersion'
|
51
52
|
end
|
52
53
|
h['_embedded'] ||= {}
|
53
54
|
h['_embedded'].merge!(dasherized['_embedded'])
|
@@ -4,6 +4,8 @@ module PactBroker
|
|
4
4
|
module Api
|
5
5
|
module PactBrokerUrls
|
6
6
|
|
7
|
+
# TODO make base_url the last and optional argument for all methods, defaulting to ''
|
8
|
+
|
7
9
|
extend self
|
8
10
|
|
9
11
|
def pacticipants_url base_url
|
@@ -14,6 +16,14 @@ module PactBroker
|
|
14
16
|
"#{pacticipants_url(base_url)}/#{url_encode(pacticipant.name)}"
|
15
17
|
end
|
16
18
|
|
19
|
+
def pacticipant_url_from_params params, base_url = ''
|
20
|
+
[
|
21
|
+
base_url,
|
22
|
+
'pacticipants',
|
23
|
+
url_encode(params.fetch(:pacticipant_name))
|
24
|
+
].join("/")
|
25
|
+
end
|
26
|
+
|
17
27
|
def latest_version_url base_url, pacticipant
|
18
28
|
"#{pacticipant_url(base_url, pacticipant)}/versions/latest"
|
19
29
|
end
|
@@ -26,6 +36,16 @@ module PactBroker
|
|
26
36
|
"#{pacticipant_url(base_url, version.pacticipant)}/versions/#{version.number}"
|
27
37
|
end
|
28
38
|
|
39
|
+
def version_url_from_params params, base_url = ''
|
40
|
+
[
|
41
|
+
base_url,
|
42
|
+
'pacticipants',
|
43
|
+
url_encode(params.fetch(:pacticipant_name)),
|
44
|
+
'versions',
|
45
|
+
url_encode(params.fetch(:version_number)),
|
46
|
+
].join("/")
|
47
|
+
end
|
48
|
+
|
29
49
|
def pact_url base_url, pact
|
30
50
|
"#{pactigration_base_url(base_url, pact)}/version/#{pact.consumer_version_number}"
|
31
51
|
end
|
@@ -87,6 +107,15 @@ module PactBroker
|
|
87
107
|
].join('/')
|
88
108
|
end
|
89
109
|
|
110
|
+
def verification_url_from_params params, base_url = ''
|
111
|
+
[ base_url, 'pacts',
|
112
|
+
'provider', url_encode(params.fetch(:provider_name)),
|
113
|
+
'consumer', url_encode(params.fetch(:consumer_name)),
|
114
|
+
'pact-version', params.fetch(:pact_version_sha),
|
115
|
+
'verification-results', params.fetch(:verification_number)
|
116
|
+
].join('/')
|
117
|
+
end
|
118
|
+
|
90
119
|
def latest_verifications_for_consumer_version_url version, base_url
|
91
120
|
"#{base_url}/verification-results/consumer/#{url_encode(version.pacticipant.name)}/version/#{version.number}/latest"
|
92
121
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'pact_broker/api/resources/base_resource'
|
2
|
+
require 'pact_broker/api/decorators/dashboard_decorator'
|
3
|
+
require 'pact_broker/api/decorators/dashboard_text_decorator'
|
4
|
+
|
5
|
+
module PactBroker
|
6
|
+
module Api
|
7
|
+
module Resources
|
8
|
+
|
9
|
+
class Dashboard < BaseResource
|
10
|
+
|
11
|
+
def content_types_provided
|
12
|
+
[
|
13
|
+
["application/hal+json", :to_json],
|
14
|
+
["text/plain", :to_text],
|
15
|
+
]
|
16
|
+
end
|
17
|
+
|
18
|
+
def allowed_methods
|
19
|
+
["GET"]
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_json
|
23
|
+
PactBroker::Api::Decorators::DashboardDecorator.new(index_items).to_json(user_options: decorator_context)
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_text
|
27
|
+
PactBroker::Api::Decorators::DashboardTextDecorator.new(index_items).to_text(user_options: decorator_context)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def index_items
|
33
|
+
index_service.find_index_items(tags: true)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|