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.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +7 -3
  3. data/CHANGELOG.md +53 -0
  4. data/DEVELOPER_DOCUMENTATION.md +28 -1
  5. data/DEVELOPER_SETUP.md +1 -1
  6. data/README.md +8 -5
  7. data/db/migrations/000004_create_tags_table.rb +1 -1
  8. data/db/migrations/000050_create_latest_matrix.rb +1 -0
  9. data/db/migrations/20180122_create_head_pact_publications.rb +21 -0
  10. data/db/migrations/20180123_create_tags_with_latest_flag.rb +28 -0
  11. data/db/migrations/20180129_create_latest_matrix_for_cv_and_pv.rb +91 -0
  12. data/db/migrations/20180130_create_materialized_matrix.rb +35 -0
  13. data/db/migrations/20180131_create_materialized_latest_matrix.rb +35 -0
  14. data/db/migrations/20180201_create_head_matrix.rb +33 -0
  15. data/db/migrations/20180202_create_materialized_head_matrix.rb +34 -0
  16. data/db/migrations/20180203_fix_head_matrix.rb +36 -0
  17. data/db/migrations/20180204_fix_latest_matrix_for_cv_and_pv.rb +57 -0
  18. data/db/migrations/20180205_drop_materialized_latest_matrix.rb +36 -0
  19. data/db/migrations/20180206_recreate_head_matrix_rename_consumer_tag_name.rb +68 -0
  20. data/db/migrations/20180207_recreate_head_matrix_union_all.rb +60 -0
  21. data/db/migrations/20180208_add_cv_tag_name_index_to_mat_head_matrix.rb +7 -0
  22. data/db/migrations/20180209_recreate_latest_matrix_for_cv_and_pv_union_all.rb +54 -0
  23. data/db/migrations/20180210_fix_latest_matrix_for_cv_and_pv_again.rb +53 -0
  24. data/db/migrations/migration_helper.rb +8 -0
  25. data/db/test/backwards_compatibility/Rakefile +1 -1
  26. data/example/pact_broker_database.sqlite3 +0 -0
  27. data/lib/pact_broker/api.rb +1 -0
  28. data/lib/pact_broker/api/decorators/dashboard_decorator.rb +163 -0
  29. data/lib/pact_broker/api/decorators/dashboard_text_decorator.rb +50 -0
  30. data/lib/pact_broker/api/decorators/matrix_decorator.rb +21 -16
  31. data/lib/pact_broker/api/decorators/pacticipant_decorator.rb +1 -0
  32. data/lib/pact_broker/api/pact_broker_urls.rb +29 -0
  33. data/lib/pact_broker/api/resources/base_resource.rb +3 -0
  34. data/lib/pact_broker/api/resources/dashboard.rb +38 -0
  35. data/lib/pact_broker/api/resources/label.rb +0 -1
  36. data/lib/pact_broker/api/resources/tag.rb +0 -1
  37. data/lib/pact_broker/dashboard/service.rb +0 -0
  38. data/lib/pact_broker/domain/index_item.rb +16 -5
  39. data/lib/pact_broker/index/service.rb +69 -4
  40. data/lib/pact_broker/matrix/head_row.rb +11 -0
  41. data/lib/pact_broker/matrix/latest_row.rb +2 -16
  42. data/lib/pact_broker/matrix/repository.rb +56 -11
  43. data/lib/pact_broker/matrix/row.rb +166 -6
  44. data/lib/pact_broker/matrix/service.rb +5 -0
  45. data/lib/pact_broker/tags/tag_with_latest_flag.rb +18 -0
  46. data/lib/pact_broker/ui/controllers/index.rb +5 -2
  47. data/lib/pact_broker/ui/controllers/matrix.rb +3 -3
  48. data/lib/pact_broker/ui/view_models/index_item.rb +13 -5
  49. data/lib/pact_broker/ui/view_models/matrix_line.rb +77 -8
  50. data/lib/pact_broker/ui/view_models/matrix_lines.rb +17 -0
  51. data/lib/pact_broker/ui/view_models/matrix_tag.rb +42 -0
  52. data/lib/pact_broker/ui/views/index/show-with-tags.haml +26 -14
  53. data/lib/pact_broker/ui/views/index/show.haml +9 -8
  54. data/lib/pact_broker/ui/views/matrix/show.haml +46 -15
  55. data/lib/pact_broker/verifications/latest_verifications_by_consumer_version.rb +1 -0
  56. data/lib/pact_broker/verifications/repository.rb +4 -4
  57. data/lib/pact_broker/version.rb +1 -1
  58. data/lib/pact_broker/versions/abbreviate_number.rb +14 -0
  59. data/pact_broker.gemspec +3 -2
  60. data/public/images/logo@2x.png +0 -0
  61. data/public/javascripts/matrix.js +5 -0
  62. data/public/stylesheets/index.css +33 -1
  63. data/public/stylesheets/matrix.css +9 -0
  64. data/script/db-spec.sh +1 -1
  65. data/spec/features/get_dashboard_spec.rb +29 -0
  66. data/spec/fixtures/dashboard.json +83 -0
  67. data/spec/lib/pact_broker/api/decorators/dashboard_decorator_spec.rb +89 -0
  68. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +30 -26
  69. data/spec/lib/pact_broker/api/resources/dashboard_spec.rb +16 -0
  70. data/spec/lib/pact_broker/api/resources/group_spec.rb +1 -0
  71. data/spec/lib/pact_broker/index/service_spec.rb +146 -32
  72. data/spec/lib/pact_broker/matrix/repository_spec.rb +48 -1
  73. data/spec/lib/pact_broker/matrix/row_spec.rb +59 -0
  74. data/spec/lib/pact_broker/ui/view_models/index_item_spec.rb +17 -12
  75. data/spec/lib/pact_broker/versions/abbreviate_number_spec.rb +22 -0
  76. data/spec/migrations/20180201_create_head_matrix_spec.rb +132 -0
  77. data/spec/migrations/23_pact_versions_spec.rb +2 -2
  78. data/spec/migrations/50_create_latest_matrix_spec.rb +84 -16
  79. data/spec/migrations/change_migration_strategy_spec.rb +1 -1
  80. data/spec/service_consumers/pact_helper.rb +4 -1
  81. data/spec/spec_helper.rb +1 -0
  82. data/spec/support/migration_helpers.rb +1 -1
  83. data/spec/support/rspec_match_hash.rb +6 -2
  84. data/spec/support/shared_examples_for_responses.rb +1 -1
  85. data/spec/support/test_data_builder.rb +61 -11
  86. metadata +57 -6
File without changes
@@ -5,9 +5,9 @@ module PactBroker
5
5
  module Domain
6
6
  class IndexItem
7
7
 
8
- attr_reader :consumer, :provider, :latest_pact, :latest_verification, :webhooks
8
+ attr_reader :consumer, :provider, :latest_pact, :latest_verification, :webhooks, :triggered_webhooks, :latest_verification_latest_tags
9
9
 
10
- def initialize consumer, provider, latest_pact = nil, latest = true, latest_verification = nil, webhooks = [], triggered_webhooks = [], tags = []
10
+ def initialize consumer, provider, latest_pact = nil, latest = true, latest_verification = nil, webhooks = [], triggered_webhooks = [], tags = [], latest_verification_latest_tags = []
11
11
  @consumer = consumer
12
12
  @provider = provider
13
13
  @latest_pact = latest_pact
@@ -16,10 +16,11 @@ module PactBroker
16
16
  @webhooks = webhooks
17
17
  @triggered_webhooks = triggered_webhooks
18
18
  @tags = tags
19
+ @latest_verification_latest_tags = latest_verification_latest_tags
19
20
  end
20
21
 
21
- def self.create consumer, provider, latest_pact, latest, latest_verification, webhooks = [], triggered_webhooks = [], tags = []
22
- new consumer, provider, latest_pact, latest, latest_verification, webhooks, triggered_webhooks, tags
22
+ def self.create consumer, provider, latest_pact, latest, latest_verification, webhooks = [], triggered_webhooks = [], tags = [], latest_verification_latest_tags = []
23
+ new consumer, provider, latest_pact, latest, latest_verification, webhooks, triggered_webhooks, tags, latest_verification_latest_tags
23
24
  end
24
25
 
25
26
  def eq? other
@@ -54,10 +55,20 @@ module PactBroker
54
55
  @latest_pact.consumer_version_number
55
56
  end
56
57
 
58
+ def consumer_version
59
+ @latest_pact.consumer_version
60
+ end
61
+
62
+ def provider_version
63
+ @latest_verification ? @latest_verification.provider_version : nil
64
+ end
65
+
57
66
  def provider_version_number
58
67
  @latest_verification ? @latest_verification.provider_version_number : nil
59
68
  end
60
69
 
70
+ # these are the consumer tag names for which this pact publication
71
+ # is the latest with that tag
61
72
  def tag_names
62
73
  @tags
63
74
  end
@@ -117,7 +128,7 @@ module PactBroker
117
128
  end
118
129
 
119
130
  def to_s
120
- "Pact between #{consumer_name} and #{provider_name}"
131
+ "Pact between #{consumer_name} #{consumer_version_number} and #{provider_name} #{provider_version_number}"
121
132
  end
122
133
 
123
134
  def to_a
@@ -1,6 +1,8 @@
1
1
  require 'pact_broker/repositories'
2
2
  require 'pact_broker/logging'
3
3
  require 'pact_broker/domain/index_item'
4
+ require 'pact_broker/matrix/latest_row'
5
+ require 'pact_broker/matrix/head_row'
4
6
 
5
7
  module PactBroker
6
8
 
@@ -12,10 +14,73 @@ module PactBroker
12
14
  extend PactBroker::Logging
13
15
 
14
16
  def self.find_index_items options = {}
15
- pact_repository
16
- .find_latest_pacts
17
- .collect { | pact| build_index_item_rows(pact, tags_for(pact, options)) }
18
- .flatten
17
+ rows = []
18
+ overall_latest_publication_ids = nil
19
+
20
+ rows = PactBroker::Matrix::HeadRow
21
+ .select_all_qualified
22
+ .eager(:latest_triggered_webhooks)
23
+ .eager(:webhooks)
24
+ .order(:consumer_name, :provider_name)
25
+ .eager(:consumer_version_tags)
26
+ .eager(:provider_version_tags)
27
+
28
+ if !options[:tags]
29
+ rows = rows.where(consumer_version_tag_name: nil).all
30
+ overall_latest_publication_ids = rows.collect(&:pact_publication_id)
31
+ end
32
+
33
+ if options[:tags]
34
+ if options[:tags].is_a?(Array)
35
+ rows = rows.where(consumer_version_tag_name: options[:tags]).or(consumer_version_tag_name: nil)
36
+ end
37
+
38
+ rows = rows.all
39
+ overall_latest_publication_ids = rows.select{|r| !r[:consumer_version_tag_name] }.collect(&:pact_publication_id).uniq
40
+
41
+ # Smoosh all the rows with matching pact publications together
42
+ # and collect their consumer_head_tag_names
43
+ rows = rows
44
+ .group_by(&:pact_publication_id)
45
+ .values
46
+ .collect{|group| [group.last, group.collect{|r| r[:consumer_version_tag_name]}.compact] }
47
+ .collect{ |(row, tag_names)| row.consumer_head_tag_names = tag_names; row }
48
+ end
49
+
50
+ index_items = []
51
+ rows.sort.each do | row |
52
+ tag_names = []
53
+ if options[:tags]
54
+ tag_names = row.consumer_version_tags.collect(&:name)
55
+ end
56
+
57
+ overall_latest = overall_latest_publication_ids.include?(row.pact_publication_id)
58
+ latest_verification = if overall_latest
59
+ verification_repository.find_latest_verification_for row.consumer_name, row.provider_name
60
+ else
61
+ tag_names.collect do | tag_name |
62
+ verification_repository.find_latest_verification_for row.consumer_name, row.provider_name, tag_name
63
+ end.compact.sort do | v1, v2 |
64
+ # Some provider versions have nil orders, not sure why
65
+ # Sort by execution_date instead of order
66
+ v1.execution_date <=> v2.execution_date
67
+ end.last
68
+ end
69
+
70
+ index_items << PactBroker::Domain::IndexItem.create(
71
+ row.consumer,
72
+ row.provider,
73
+ row.pact,
74
+ overall_latest,
75
+ latest_verification,
76
+ row.webhooks,
77
+ row.latest_triggered_webhooks,
78
+ row.consumer_head_tag_names,
79
+ row.provider_version_tags.select(&:latest?)
80
+ )
81
+ end
82
+
83
+ index_items
19
84
  end
20
85
 
21
86
  def self.tags_for(pact, options)
@@ -0,0 +1,11 @@
1
+ require 'pact_broker/matrix/row'
2
+
3
+ module PactBroker
4
+ module Matrix
5
+ # A row for each of the overall latest pacts, and a row for each of the latest tagged pacts
6
+ # Rows with a nil consumer_tag_name are the overall latest
7
+ class HeadRow < Row
8
+ set_dataset(:materialized_head_matrix)
9
+ end
10
+ end
11
+ end
@@ -2,23 +2,9 @@ require 'pact_broker/matrix/row'
2
2
 
3
3
  module PactBroker
4
4
  module Matrix
5
- # Latest pact revision for each consumer version => latest verification
5
+ # Latest pact revision for each consumer version => latest verification for each provider version
6
6
  class LatestRow < Row
7
- set_dataset(:latest_matrix)
8
-
9
- # For some reason, with MySQL, the success column value
10
- # comes back as an integer rather than a boolean
11
- # for the latest_matrix view (but not the matrix view!)
12
- # Maybe something to do with the union?
13
- # Haven't investigated as this is an easy enough fix.
14
- def success
15
- value = super
16
- value.nil? ? nil : value == true || value == 1
17
- end
18
-
19
- def values
20
- super.merge(success: success)
21
- end
7
+ set_dataset(:latest_matrix_for_consumer_version_and_provider_version)
22
8
  end
23
9
  end
24
10
  end
@@ -1,8 +1,10 @@
1
1
  require 'pact_broker/repositories/helpers'
2
2
  require 'pact_broker/matrix/row'
3
3
  require 'pact_broker/matrix/latest_row'
4
+ require 'pact_broker/matrix/head_row'
4
5
  require 'pact_broker/error'
5
6
 
7
+
6
8
  module PactBroker
7
9
  module Matrix
8
10
 
@@ -14,56 +16,84 @@ module PactBroker
14
16
 
15
17
  # TODO move latest verification logic in to database
16
18
 
19
+ TP_COLS = PactBroker::Matrix::Row::TP_COLS
20
+
17
21
  GROUP_BY_PROVIDER_VERSION_NUMBER = [:consumer_name, :consumer_version_number, :provider_name, :provider_version_number]
18
22
  GROUP_BY_PROVIDER = [:consumer_name, :consumer_version_number, :provider_name]
19
23
  GROUP_BY_PACT = [:consumer_name, :provider_name]
20
24
 
25
+ def refresh params
26
+ PactBroker::Matrix::Row.refresh(params)
27
+ PactBroker::Matrix::HeadRow.refresh(params)
28
+ end
29
+
21
30
  # Return the latest matrix row (pact/verification) for each consumer_version_number/provider_version_number
22
31
  def find selectors, options = {}
23
- # The group with the nil provider_version_numbers will be the results of the left outer join
24
- # that don't have verifications, so we need to include them all.
25
32
  lines = query_matrix(resolve_selectors(selectors, options), options)
26
33
  lines = apply_latestby(options, selectors, lines)
27
34
 
35
+ # This needs to be done after the latestby, so can't be done in the db unless
36
+ # the latestby logic is moved to the db
28
37
  if options.key?(:success)
29
38
  lines = lines.select{ |l| options[:success].include?(l.success) }
30
39
  end
31
40
 
32
- lines.sort.collect(&:values)
41
+ lines.sort
33
42
  end
34
43
 
35
- def apply_latestby options, selectors, lines
36
- return lines unless options[:latestby] == 'cvp' || options[:latestby] == 'cp'
37
44
 
45
+
46
+ def apply_latestby options, selectors, lines
47
+ return lines unless options[:latestby]
38
48
  group_by_columns = case options[:latestby]
49
+ when 'cvpv' then GROUP_BY_PROVIDER_VERSION_NUMBER
39
50
  when 'cvp' then GROUP_BY_PROVIDER
40
51
  when 'cp' then GROUP_BY_PACT
41
52
  end
42
53
 
43
- lines.group_by{|line| group_by_columns.collect{|key| line.send(key) }}
54
+ # The group with the nil provider_version_numbers will be the results of the left outer join
55
+ # that don't have verifications, so we need to include them all.
56
+ remove_overwritten_revisions(lines).group_by{|line| group_by_columns.collect{|key| line.send(key) }}
44
57
  .values
45
58
  .collect{ | lines | lines.first.provider_version_number.nil? ? lines : lines.first }
46
59
  .flatten
47
60
  end
48
61
 
62
+ def remove_overwritten_revisions lines
63
+ latest_revisions_keys = {}
64
+ latest_revisions = []
65
+ lines.each do | line |
66
+ key = "#{line.consumer_name}-#{line.provider_name}-#{line.consumer_version_number}"
67
+ if !latest_revisions_keys.key?(key) || latest_revisions_keys[key] == line.pact_revision_number
68
+ latest_revisions << line
69
+ latest_revisions_keys[key] ||= line.pact_revision_number
70
+ end
71
+ end
72
+ latest_revisions
73
+ end
74
+
49
75
  def find_for_consumer_and_provider pacticipant_1_name, pacticipant_2_name
50
76
  selectors = [{ pacticipant_name: pacticipant_1_name }, { pacticipant_name: pacticipant_2_name }]
51
77
  options = { latestby: 'cvpv' }
52
- query_matrix(resolve_selectors(selectors, options), options).sort.collect(&:values)
78
+ find(selectors, options)
53
79
  end
54
80
 
55
81
  def find_compatible_pacticipant_versions selectors
56
- find(selectors, latestby: 'cvpv').select{|line| line[:success] }
82
+ find(selectors, latestby: 'cvpv').select{|line| line.success }
57
83
  end
58
84
 
59
85
  def query_matrix selectors, options
60
86
  query = view_for(options).select_all.matching_selectors(selectors)
61
87
  query = query.limit(options[:limit]) if options[:limit]
62
- query.order_by_names_ascending_most_recent_first.all
88
+ query
89
+ .order_by_names_ascending_most_recent_first
90
+ .eager(:consumer_version_tags)
91
+ .eager(:provider_version_tags)
92
+ .all
63
93
  end
64
94
 
65
95
  def view_for(options)
66
- options[:latestby] ? LatestRow : Row
96
+ Row
67
97
  end
68
98
 
69
99
  def resolve_selectors(selectors, options)
@@ -95,8 +125,23 @@ module PactBroker
95
125
  pacticipant_version_number: version.number
96
126
  }
97
127
  else
98
- selector
128
+ selector.dup
129
+ end
130
+ end.collect do | selector |
131
+ if selector[:pacticipant_name]
132
+ pacticipant = PactBroker::Domain::Pacticipant.find(name: selector[:pacticipant_name])
133
+ selector[:pacticipant_id] = pacticipant ? pacticipant.id : nil
134
+ end
135
+
136
+ if selector[:pacticipant_name] && selector[:pacticipant_version_number]
137
+ version = version_repository.find_by_pacticipant_name_and_number(selector[:pacticipant_name], selector[:pacticipant_version_number])
138
+ selector[:pacticipant_version_id] = version ? version.id : nil
139
+ end
140
+
141
+ if selector[:pacticipant_version_number].nil?
142
+ selector[:pacticipant_version_id] = nil
99
143
  end
144
+ selector
100
145
  end
101
146
  end
102
147
 
@@ -1,11 +1,61 @@
1
1
  require 'pact_broker/repositories/helpers'
2
+ require 'pact_broker/webhooks/latest_triggered_webhook'
3
+ require 'pact_broker/tags/tag_with_latest_flag'
4
+ require 'pact_broker/logging'
2
5
 
3
6
  module PactBroker
4
7
  module Matrix
5
- class Row < Sequel::Model(:matrix)
8
+ class Row < Sequel::Model(:materialized_matrix)
9
+
10
+ # Used when using table_print to output query results
11
+ TP_COLS = [ :consumer_version_number, :pact_revision_number, :provider_version_number, :verification_number]
12
+
13
+ associate(:one_to_many, :latest_triggered_webhooks, :class => "PactBroker::Webhooks::LatestTriggeredWebhook", primary_key: :pact_publication_id, key: :pact_publication_id)
14
+ associate(:one_to_many, :webhooks, :class => "PactBroker::Webhooks::Webhook", primary_key: [:consumer_id, :provider_id], key: [:consumer_id, :provider_id])
15
+ associate(:one_to_many, :consumer_version_tags, :class => "PactBroker::Tags::TagWithLatestFlag", primary_key: :consumer_version_id, key: :version_id)
16
+ associate(:one_to_many, :provider_version_tags, :class => "PactBroker::Tags::TagWithLatestFlag", primary_key: :provider_version_id, key: :version_id)
6
17
 
7
18
  dataset_module do
8
19
  include PactBroker::Repositories::Helpers
20
+ include PactBroker::Logging
21
+
22
+ def refresh params
23
+ logger.debug("Refreshing #{model.table_name} for #{params}")
24
+
25
+ db = model.db
26
+ table_name = model.table_name
27
+
28
+ source_view_name = model.table_name.to_s.gsub('materialized_', '').to_sym
29
+ if params[:consumer_name] || params[:provider_name]
30
+ criteria = {}
31
+ if params[:consumer_name]
32
+ pacticipant = PactBroker::Domain::Pacticipant.where(name_like(:name, params[:consumer_name])).single_record
33
+ criteria[:consumer_id] = pacticipant.id if pacticipant
34
+ end
35
+
36
+ if params[:provider_name]
37
+ pacticipant = PactBroker::Domain::Pacticipant.where(name_like(:name, params[:provider_name])).single_record
38
+ criteria[:provider_id] = pacticipant.id if pacticipant
39
+ end
40
+ if criteria.any?
41
+ db.transaction do
42
+ db[table_name].where(criteria).delete
43
+ db[table_name].insert(db[source_view_name].where(criteria).distinct)
44
+ end
45
+ end
46
+ end
47
+
48
+ if params[:pacticipant_name]
49
+ pacticipant = PactBroker::Domain::Pacticipant.where(name_like(:name, params[:pacticipant_name])).single_record
50
+ if pacticipant
51
+ db.transaction do
52
+ db[table_name].where(consumer_id: pacticipant.id).or(provider_id: pacticipant.id).delete
53
+ new_rows = db[source_view_name].where(consumer_id: pacticipant.id).or(provider_id: pacticipant.id).distinct
54
+ db[table_name].insert(new_rows)
55
+ end
56
+ end
57
+ end
58
+ end
9
59
 
10
60
  def matching_selectors selectors
11
61
  if selectors.size == 1
@@ -19,11 +69,24 @@ module PactBroker
19
69
  where{
20
70
  Sequel.&(
21
71
  Sequel.|(
22
- *selectors.collect{ |s| s[:pacticipant_version_number] ? Sequel.&(consumer_name: s[:pacticipant_name], consumer_version_number: s[:pacticipant_version_number]) : Sequel.&(consumer_name: s[:pacticipant_name]) }
72
+ *selectors.collect do |s|
73
+ if s[:pacticipant_version_id]
74
+ Sequel.&(consumer_id: s[:pacticipant_id], consumer_version_id: s[:pacticipant_version_id])
75
+ else
76
+ Sequel.&(consumer_id: s[:pacticipant_id])
77
+ end
78
+ end
23
79
  ),
24
80
  Sequel.|(
25
- *(selectors.collect{ |s| s[:pacticipant_version_number] ? Sequel.&(provider_name: s[:pacticipant_name], provider_version_number: s[:pacticipant_version_number]) : Sequel.&(provider_name: s[:pacticipant_name]) } +
26
- selectors.collect{ |s| Sequel.&(provider_name: s[:pacticipant_name], provider_version_number: nil) })
81
+ *(selectors.collect do |s|
82
+ if s[:pacticipant_version_id]
83
+ Sequel.&(provider_id: s[:pacticipant_id], provider_version_id: s[:pacticipant_version_id])
84
+ else
85
+ Sequel.&(provider_id: s[:pacticipant_id])
86
+ end
87
+ end + selectors.collect do |s|
88
+ Sequel.&(provider_id: s[:pacticipant_id], provider_version_id: nil)
89
+ end)
27
90
  )
28
91
  )
29
92
  }
@@ -32,8 +95,8 @@ module PactBroker
32
95
  def where_consumer_or_provider_is s
33
96
  where{
34
97
  Sequel.|(
35
- s[:pacticipant_version_number] ? Sequel.&(consumer_name: s[:pacticipant_name], consumer_version_number: s[:pacticipant_version_number]) : Sequel.&(consumer_name: s[:pacticipant_name]),
36
- s[:pacticipant_version_number] ? Sequel.&(provider_name: s[:pacticipant_name], provider_version_number: s[:pacticipant_version_number]) : Sequel.&(provider_name: s[:pacticipant_name])
98
+ s[:pacticipant_version_id] ? Sequel.&(consumer_id: s[:pacticipant_id], consumer_version_id: s[:pacticipant_version_id]) : Sequel.&(consumer_id: s[:pacticipant_id]),
99
+ s[:pacticipant_version_id] ? Sequel.&(provider_id: s[:pacticipant_id], provider_version_id: s[:pacticipant_version_id]) : Sequel.&(provider_id: s[:pacticipant_id])
37
100
  )
38
101
  }
39
102
  end
@@ -49,10 +112,81 @@ module PactBroker
49
112
  end
50
113
  end
51
114
 
115
+ # Temporary method while we transition from returning Hashes to return Matrix objects
116
+ # from the repository find methods
117
+ # Need to make the object act as a hash and an object
118
+ def [] key
119
+ if key == :provider_version_tags || key == :consumer_version_tags
120
+ send(key)
121
+ else
122
+ super
123
+ end
124
+ end
125
+
126
+ # tags for which this pact publication is the latest of that tag
127
+ # this is set in the code rather than the database
128
+ def consumer_head_tag_names
129
+ @consumer_head_tag_names ||= []
130
+ end
131
+
132
+ def consumer_head_tag_names= consumer_head_tag_names
133
+ @consumer_head_tag_names = consumer_head_tag_names
134
+ end
135
+
136
+ # def latest_triggered_webhooks
137
+ # @latest_triggered_webhooks ||= []
138
+ # end
139
+
52
140
  def summary
53
141
  "#{consumer_name}#{consumer_version_number} #{provider_name}#{provider_version_number || '?'} (r#{pact_revision_number}n#{verification_number || '?'})"
54
142
  end
55
143
 
144
+ def consumer
145
+ @consumer ||= OpenStruct.new(name: consumer_name, id: consumer_id)
146
+ end
147
+
148
+ def provider
149
+ @provider ||= OpenStruct.new(name: provider_name, id: provider_id)
150
+ end
151
+
152
+ def consumer_version
153
+ @consumer_version ||= OpenStruct.new(number: consumer_version_number, id: consumer_version_id, pacticipant: consumer)
154
+ end
155
+
156
+ def provider_version
157
+ if provider_version_number
158
+ @provider_version ||= OpenStruct.new(number: provider_version_number, id: provider_version_id, pacticipant: provider)
159
+ end
160
+ end
161
+
162
+ def pact
163
+ @pact ||= OpenStruct.new(consumer: consumer,
164
+ provider: provider,
165
+ consumer_version: consumer_version,
166
+ consumer_version_number: consumer_version_number,
167
+ created_at: pact_created_at,
168
+ revision_number: pact_revision_number,
169
+ pact_version_sha: pact_version_sha
170
+ )
171
+ end
172
+
173
+ def latest_verification
174
+ if verification_executed_at
175
+ @latest_verification ||= OpenStruct.new(
176
+ id: verification_id,
177
+ success: success,
178
+ number: verification_number,
179
+ execution_date: verification_executed_at,
180
+ created_at: verification_executed_at,
181
+ provider_version_number: provider_version_number,
182
+ build_url: verification_build_url,
183
+ provider_version: provider_version,
184
+ consumer_name: consumer_name,
185
+ provider_name: provider_name
186
+ )
187
+ end
188
+ end
189
+
56
190
  # Add logic for ignoring case
57
191
  def <=> other
58
192
  comparisons = [
@@ -72,6 +206,10 @@ module PactBroker
72
206
  name1 <=> name2
73
207
  end
74
208
 
209
+ def to_s
210
+ "#{consumer_name} v#{consumer_version_number} #{provider_name} #{provider_version_number} #{success}"
211
+ end
212
+
75
213
  def compare_number_desc number1, number2
76
214
  if number1 && number2
77
215
  number2 <=> number1
@@ -81,6 +219,28 @@ module PactBroker
81
219
  -1
82
220
  end
83
221
  end
222
+
223
+ # For some reason, with MySQL, the success column value
224
+ # comes back as an integer rather than a boolean
225
+ # for the latest_matrix view (but not the matrix view!)
226
+ # Maybe something to do with the union?
227
+ # Haven't investigated as this is an easy enough fix.
228
+ def success
229
+ value = super
230
+ value.nil? ? nil : value == true || value == 1
231
+ end
232
+
233
+ def values
234
+ super.merge(success: success)
235
+ end
236
+
237
+ # Need to overwrite eql? from lib/sequel/model/base.rb
238
+ # because it uses @values instead of self.values
239
+ # so the success boolean/integer problem mentioned above
240
+ # screws things up
241
+ def eql?(obj)
242
+ (obj.class == model) && (obj.values == values)
243
+ end
84
244
  end
85
245
  end
86
246
  end