pact_broker 2.40.0 → 2.41.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -0
  3. data/DEVELOPER_DOCUMENTATION.md +11 -0
  4. data/db/ddl_statements/head_pact_tags.rb +10 -0
  5. data/db/ddl_statements/latest_pact_consumer_version_orders.rb +16 -0
  6. data/db/ddl_statements/latest_pact_publications_by_consumer_versions.rb +16 -0
  7. data/db/ddl_statements/latest_tagged_pact_consumer_version_orders.rb +23 -0
  8. data/db/ddl_statements/latest_verification_ids_for_consumer_version_tags.rb +15 -0
  9. data/db/ddl_statements/{latest_verification_ids_for_pact_versions_v001.rb → latest_verification_ids_for_pact_versions.rb} +0 -0
  10. data/db/migrations/000028_create_all_pact_publications.rb +1 -0
  11. data/db/migrations/20180311_optimise_head_matrix.rb +1 -9
  12. data/db/migrations/20180722_recreate_views.rb +6 -19
  13. data/db/migrations/20191028_optimise_latest_tagged_pact_cv_orders.rb +13 -0
  14. data/db/migrations/20191030_optimise_latest_pact_publications_by_consumer_versions_.rb +13 -0
  15. data/db/migrations/20191031_optimise_latest_verification_ids_for_consumer_version_tags.rb +13 -0
  16. data/db/migrations/20191101_create_head_pact_tags.rb +11 -0
  17. data/lib/db.rb +1 -0
  18. data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +15 -0
  19. data/lib/pact_broker/api/contracts/dry_validation_workarounds.rb +38 -0
  20. data/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema.rb +34 -0
  21. data/lib/pact_broker/api/contracts/verifiable_pacts_query_schema.rb +12 -20
  22. data/lib/pact_broker/api/decorators/matrix_decorator.rb +25 -6
  23. data/lib/pact_broker/api/decorators/relationships_csv_decorator.rb +4 -12
  24. data/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb +5 -2
  25. data/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb +21 -9
  26. data/lib/pact_broker/api/renderers/integrations_dot_renderer.rb +1 -1
  27. data/lib/pact_broker/api/resources/base_resource.rb +1 -1
  28. data/lib/pact_broker/api/resources/can_i_deploy.rb +2 -9
  29. data/lib/pact_broker/api/resources/matrix.rb +2 -8
  30. data/lib/pact_broker/api/resources/matrix_for_consumer_and_provider.rb +1 -0
  31. data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +36 -7
  32. data/lib/pact_broker/app.rb +1 -0
  33. data/lib/pact_broker/db/data_migrations/migrate_webhook_headers.rb +1 -1
  34. data/lib/pact_broker/db/seed_example_data.rb +8 -5
  35. data/lib/pact_broker/diagnostic/resources/base_resource.rb +0 -8
  36. data/lib/pact_broker/domain/index_item.rb +47 -16
  37. data/lib/pact_broker/domain/pact.rb +12 -4
  38. data/lib/pact_broker/domain/version.rb +2 -0
  39. data/lib/pact_broker/hash_refinements.rb +48 -0
  40. data/lib/pact_broker/index/page.rb +12 -0
  41. data/lib/pact_broker/index/service.rb +156 -21
  42. data/lib/pact_broker/integrations/integration.rb +22 -0
  43. data/lib/pact_broker/locale/en.yml +2 -0
  44. data/lib/pact_broker/logging.rb +0 -1
  45. data/lib/pact_broker/matrix/aggregated_row.rb +3 -9
  46. data/lib/pact_broker/matrix/deployment_status_summary.rb +5 -5
  47. data/lib/pact_broker/matrix/head_row.rb +2 -0
  48. data/lib/pact_broker/matrix/quick_row.rb +7 -7
  49. data/lib/pact_broker/matrix/repository.rb +2 -4
  50. data/lib/pact_broker/pacticipants/repository.rb +1 -1
  51. data/lib/pact_broker/pacts/pact_publication.rb +27 -4
  52. data/lib/pact_broker/pacts/repository.rb +41 -18
  53. data/lib/pact_broker/pacts/service.rb +23 -3
  54. data/lib/pact_broker/pacts/verifiable_pact.rb +8 -2
  55. data/lib/pact_broker/pacts/verifiable_pact_messages.rb +14 -8
  56. data/lib/pact_broker/string_refinements.rb +36 -1
  57. data/lib/pact_broker/tags/head_pact_tags.rb +12 -0
  58. data/lib/pact_broker/tags/tag_with_latest_flag.rb +0 -1
  59. data/lib/pact_broker/test/test_data_builder.rb +1 -1
  60. data/lib/pact_broker/ui/controllers/index.rb +23 -2
  61. data/lib/pact_broker/ui/view_models/index_item.rb +7 -1
  62. data/lib/pact_broker/ui/view_models/index_items.rb +10 -8
  63. data/lib/pact_broker/ui/view_models/matrix_line.rb +14 -21
  64. data/lib/pact_broker/ui/view_models/matrix_tag.rb +6 -8
  65. data/lib/pact_broker/ui/views/index/_pagination.haml +31 -0
  66. data/lib/pact_broker/ui/views/index/show-with-tags.haml +6 -3
  67. data/lib/pact_broker/ui/views/index/show.haml +5 -2
  68. data/lib/pact_broker/ui/views/matrix/show.haml +6 -9
  69. data/lib/pact_broker/version.rb +1 -1
  70. data/lib/pact_broker/webhooks/webhook.rb +2 -2
  71. data/lib/pact_broker/webhooks/webhook_execution_result.rb +3 -18
  72. data/public/javascripts/matrix.js +26 -1
  73. data/public/javascripts/pagination.js +1127 -0
  74. data/public/stylesheets/index.css +13 -0
  75. data/public/stylesheets/matrix.css +10 -1
  76. data/spec/features/get_provider_pacts_for_verification_spec.rb +44 -9
  77. data/spec/features/pending_pacts_spec.rb +1 -1
  78. data/spec/features/wip_pacts_spec.rb +138 -0
  79. data/spec/integration/app_spec.rb +1 -1
  80. data/spec/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema_spec.rb +90 -0
  81. data/spec/lib/pact_broker/api/contracts/verifiable_pacts_query_schema_spec.rb +26 -4
  82. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +36 -2
  83. data/spec/lib/pact_broker/api/decorators/verifiable_pact_decorator_spec.rb +24 -1
  84. data/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb +62 -18
  85. data/spec/lib/pact_broker/api/resources/base_resource_spec.rb +10 -0
  86. data/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb +75 -6
  87. data/spec/lib/pact_broker/hash_refinements_spec.rb +24 -0
  88. data/spec/lib/pact_broker/index/service_spec.rb +38 -2
  89. data/spec/lib/pact_broker/integrations/integration_spec.rb +79 -41
  90. data/spec/lib/pact_broker/pacts/pact_publication_spec.rb +2 -0
  91. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_spec.rb +17 -2
  92. data/spec/lib/pact_broker/pacts/service_spec.rb +56 -0
  93. data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +12 -1
  94. data/spec/lib/pact_broker/ui/controllers/index_spec.rb +28 -6
  95. data/spec/lib/pact_broker/ui/view_models/index_items_spec.rb +8 -29
  96. data/spec/lib/pact_broker/ui/view_models/matrix_line_spec.rb +41 -0
  97. metadata +24 -3
@@ -19,7 +19,9 @@ module PactBroker
19
19
  # the query down.
20
20
  # This relation relies on consumer_version_tags already being loaded
21
21
  one_to_one :latest_verification_for_consumer_version_tag, :class => "PactBroker::Verifications::LatestVerificationForConsumerVersionTag", primary_keys: [], key: [], :eager_loader=>(proc do |eo_opts|
22
+ # create an index of provider_id/consumer_id/consumer_version_tag_name => row
22
23
  tag_to_row = eo_opts[:rows].each_with_object({}) { | row, map | map[[row.provider_id, row.consumer_id, row.consumer_version_tag_name]] = row }
24
+ # Initialise the association with nil - not sure why?
23
25
  eo_opts[:rows].each{|row| row.associations[:latest_verification_for_consumer_version_tag] = nil}
24
26
 
25
27
  # Need the all then the each to ensure the eager loading works
@@ -41,15 +41,15 @@ module PactBroker
41
41
  .join(:versions, CONSUMER_VERSION_JOIN, { table_alias: :cv })
42
42
  .left_outer_join(:versions, PROVIDER_VERSION_JOIN, { table_alias: :pv } )
43
43
 
44
- ALIASED_QUERY = Sequel.as(RAW_QUERY, :smart_rows)
44
+ ALIASED_QUERY = Sequel.as(RAW_QUERY, :quick_rows)
45
45
 
46
46
  class QuickRow < Sequel::Model(ALIASED_QUERY)
47
- CONSUMER_ID = Sequel[:smart_rows][:consumer_id]
48
- PROVIDER_ID = Sequel[:smart_rows][:provider_id]
49
- CONSUMER_VERSION_ID = Sequel[:smart_rows][:consumer_version_id]
50
- PROVIDER_VERSION_ID = Sequel[:smart_rows][:provider_version_id]
51
- PACT_PUBLICATION_ID = Sequel[:smart_rows][:pact_publication_id]
52
- VERIFICATION_ID = Sequel[:smart_rows][:verification_id]
47
+ CONSUMER_ID = Sequel[:quick_rows][:consumer_id]
48
+ PROVIDER_ID = Sequel[:quick_rows][:provider_id]
49
+ CONSUMER_VERSION_ID = Sequel[:quick_rows][:consumer_version_id]
50
+ PROVIDER_VERSION_ID = Sequel[:quick_rows][:provider_version_id]
51
+ PACT_PUBLICATION_ID = Sequel[:quick_rows][:pact_publication_id]
52
+ VERIFICATION_ID = Sequel[:quick_rows][:verification_id]
53
53
 
54
54
  associate(:many_to_one, :pact_publication, :class => "PactBroker::Pacts::PactPublication", :key => :pact_publication_id, :primary_key => :id)
55
55
  associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id)
@@ -74,7 +74,7 @@ module PactBroker
74
74
  end
75
75
 
76
76
  def find_compatible_pacticipant_versions selectors
77
- find(selectors, latestby: 'cvpv').select{|line| line.success }
77
+ find(selectors, latestby: 'cvpv').select(&:success)
78
78
  end
79
79
 
80
80
  # If one pacticipant is specified, find all the integrations that involve that pacticipant
@@ -86,9 +86,7 @@ module PactBroker
86
86
  .matching_selectors(resolved_specified_selectors)
87
87
  .distinct
88
88
  .all
89
- .collect do |row |
90
- row.to_hash
91
- end
89
+ .collect(&:to_hash)
92
90
  .uniq
93
91
  .collect do | hash |
94
92
  required = is_a_row_for_this_integration_required?(specified_pacticipant_names, hash[:consumer_name])
@@ -55,7 +55,7 @@ module PactBroker
55
55
  end
56
56
 
57
57
  def pacticipant_names
58
- PactBroker::Domain::Pacticipant.select(:name).order(:name).collect{ | pacticipant| pacticipant.name }
58
+ PactBroker::Domain::Pacticipant.select(:name).order(:name).collect(&:name)
59
59
  end
60
60
 
61
61
  def delete_if_orphan(pacticipant)
@@ -1,6 +1,8 @@
1
1
  require 'pact_broker/domain/pact'
2
2
  require 'pact_broker/pacts/pact_version'
3
3
  require 'pact_broker/repositories/helpers'
4
+ require 'pact_broker/integrations/integration'
5
+ require 'pact_broker/tags/head_pact_tags'
4
6
 
5
7
  module PactBroker
6
8
  module Pacts
@@ -16,6 +18,9 @@ module PactBroker
16
18
  associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
17
19
  associate(:many_to_one, :consumer_version, :class => "PactBroker::Domain::Version", :key => :consumer_version_id, :primary_key => :id)
18
20
  associate(:many_to_one, :pact_version, class: "PactBroker::Pacts::PactVersion", :key => :pact_version_id, :primary_key => :id)
21
+ associate(:many_to_one, :integration, class: "PactBroker::Integrations::Integration", key: [:consumer_id, :provider_id], primary_key: [:consumer_id, :provider_id])
22
+ one_to_one(:latest_verification, class: "PactBroker::Verifications::LatestVerificationForPactVersion", key: :pact_version_id, primary_key: :pact_version_id)
23
+ one_to_many(:head_pact_tags, class: "PactBroker::Tags::HeadPactTag", primary_key: :id, key: :pact_publication_id)
19
24
 
20
25
  dataset_module do
21
26
  include PactBroker::Repositories::Helpers
@@ -49,21 +54,39 @@ module PactBroker
49
54
  PactBroker::Domain::Pact.new(
50
55
  id: id,
51
56
  provider: provider,
52
- consumer: consumer_version.pacticipant,
57
+ consumer: consumer,
53
58
  consumer_version_number: consumer_version.number,
54
59
  consumer_version: to_version_domain,
55
60
  revision_number: revision_number,
56
61
  json_content: pact_version.content,
57
62
  pact_version_sha: pact_version.sha,
58
- latest_verification: latest_verification,
63
+ latest_verification: nil,
64
+ created_at: created_at,
65
+ head_tag_names: [],
66
+ db_model: self
67
+ )
68
+ end
69
+
70
+ def to_domain_lightweight
71
+ PactBroker::Domain::Pact.new(
72
+ id: id,
73
+ provider: provider,
74
+ consumer: consumer,
75
+ consumer_version_number: consumer_version.number,
76
+ consumer_version: to_version_domain_lightweight,
77
+ revision_number: revision_number,
78
+ pact_version_sha: pact_version.sha,
59
79
  created_at: created_at,
60
- head_tag_names: head_tag_names,
61
80
  db_model: self
62
81
  )
63
82
  end
64
83
 
65
84
  def to_version_domain
66
- OpenStruct.new(number: consumer_version.number, pacticipant: consumer_version.pacticipant, tags: consumer_version.tags, order: consumer_version.order)
85
+ OpenStruct.new(number: consumer_version.number, pacticipant: consumer, tags: consumer_version.tags, order: consumer_version.order)
86
+ end
87
+
88
+ def to_version_domain_lightweight
89
+ OpenStruct.new(number: consumer_version.number, pacticipant: consumer, order: consumer_version.order)
67
90
  end
68
91
 
69
92
  def upsert
@@ -125,29 +125,21 @@ module PactBroker
125
125
  end
126
126
  end
127
127
 
128
- def find_wip_pact_versions_for_provider provider_name, provider_tags = []
128
+ def find_wip_pact_versions_for_provider provider_name, provider_tags = [], options = {}
129
129
  return [] if provider_tags.empty?
130
- successfully_verified_pact_publication_ids_for_each_tag = provider_tags.collect do | provider_tag |
131
- ids = LatestTaggedPactPublications
132
- .join(:verifications, { pact_version_id: :pact_version_id })
133
- .join(:tags, { Sequel[:verifications][:provider_version_id] => Sequel[:provider_tags][:version_id] }, {table_alias: :provider_tags})
134
- .where(Sequel[:provider_tags][:name] => provider_tag)
135
- .provider(provider_name)
136
- .where(Sequel[:verifications][:success] => true)
137
- .select(Sequel[:latest_tagged_pact_publications][:id].as(:id))
138
- .collect(&:id)
139
- [provider_tag, ids]
140
- end
141
130
 
142
- successfully_verified_pact_publication_ids_for_all_tags = successfully_verified_pact_publication_ids_for_each_tag.collect(&:last).reduce(:&)
143
- pact_publication_ids = LatestTaggedPactPublications.provider(provider_name).exclude(id: successfully_verified_pact_publication_ids_for_all_tags).select_for_subquery(:id)
131
+ # Hash of provider tag names => list of pact_publication_ids
132
+ successfully_verified_head_pact_publication_ids_for_each_provider_tag = find_successfully_verified_head_pacts_by_provider_tag(provider_name, provider_tags, options)
133
+
134
+ pact_publication_ids = find_head_pacts_that_have_not_been_successfully_verified_by_all_provider_tags(
135
+ provider_name,
136
+ successfully_verified_head_pact_publication_ids_for_each_provider_tag.values.reduce(:&),
137
+ options)
144
138
 
145
139
  pacts = AllPactPublications.where(id: pact_publication_ids).order_ignore_case(:consumer_name).order_append(:consumer_version_order).collect(&:to_domain)
146
140
  pacts.collect do | pact|
147
- pending_tags = successfully_verified_pact_publication_ids_for_each_tag.select do | (provider_tag, pact_publication_ids) |
148
- !pact_publication_ids.include?(pact.id)
149
- end.collect(&:first)
150
- VerifiablePact.new(pact, true, pending_tags, [], pact.consumer_version_tag_names)
141
+ pending_tags = find_provider_tags_for_which_pact_publication_id_is_pending(pact.id, successfully_verified_head_pact_publication_ids_for_each_provider_tag)
142
+ VerifiablePact.new(pact, true, pending_tags, [], pact.consumer_version_tag_names, nil, true)
151
143
  end
152
144
  end
153
145
 
@@ -340,6 +332,37 @@ module PactBroker
340
332
  query = query.tag(options[:tag]) if options[:tag]
341
333
  query
342
334
  end
335
+
336
+ def find_provider_tags_for_which_pact_publication_id_is_pending(pact_publication_id, successfully_verified_head_pact_publication_ids_for_each_provider_tag)
337
+ successfully_verified_head_pact_publication_ids_for_each_provider_tag
338
+ .select do | provider_tag, pact_publication_ids |
339
+ !pact_publication_ids.include?(pact_publication_id)
340
+ end.keys
341
+ end
342
+
343
+ def find_head_pacts_that_have_not_been_successfully_verified_by_all_provider_tags(provider_name, pact_publication_ids_successfully_verified_by_all_provider_tags, options)
344
+ # Exclude the head pacts that have been successfully verified by all the specified provider tags
345
+ pact_publication_ids = LatestTaggedPactPublications
346
+ .provider(provider_name)
347
+ .exclude(id: pact_publication_ids_successfully_verified_by_all_provider_tags)
348
+ .where(Sequel.lit('latest_tagged_pact_publications.created_at > ?', options.fetch(:include_wip_pacts_since)))
349
+ .select_for_subquery(:id)
350
+ end
351
+
352
+ def find_successfully_verified_head_pacts_by_provider_tag(provider_name, provider_tags, options)
353
+ provider_tags.compact.each_with_object({}) do | provider_tag, tag_to_ids_hash |
354
+ ids = LatestTaggedPactPublications
355
+ .join(:verifications, { pact_version_id: :pact_version_id })
356
+ .join(:tags, { Sequel[:verifications][:provider_version_id] => Sequel[:provider_tags][:version_id] }, {table_alias: :provider_tags})
357
+ .where(Sequel[:provider_tags][:name] => provider_tag)
358
+ .provider(provider_name)
359
+ .where(Sequel[:verifications][:success] => true)
360
+ .where(Sequel.lit('latest_tagged_pact_publications.created_at > ?', options.fetch(:include_wip_pacts_since)))
361
+ .select(Sequel[:latest_tagged_pact_publications][:id].as(:id))
362
+ .collect(&:id)
363
+ tag_to_ids_hash[provider_tag] = ids
364
+ end
365
+ end
343
366
  end
344
367
  end
345
368
  end
@@ -62,7 +62,9 @@ module PactBroker
62
62
  consumer_version = version_repository.find_by_pacticipant_id_and_number_or_create consumer.id, params[:consumer_version_number]
63
63
  existing_pact = pact_repository.find_by_version_and_provider(consumer_version.id, provider.id)
64
64
 
65
- params.merge!(json_content: Merger.merge_pacts(existing_pact.json_content, params[:json_content]))
65
+ params[:json_content] = Merger.merge_pacts(
66
+ existing_pact.json_content, params[:json_content]
67
+ )
66
68
 
67
69
  update_pact params, existing_pact, webhook_options
68
70
  end
@@ -113,18 +115,36 @@ module PactBroker
113
115
  distinct
114
116
  end
115
117
 
116
- def find_for_verification(provider_name, provider_version_tags, consumer_version_selectors)
117
- pact_repository
118
+ def find_for_verification(provider_name, provider_version_tags, consumer_version_selectors, options)
119
+ verifiable_pacts_specified_in_request = pact_repository
118
120
  .find_for_verification(provider_name, consumer_version_selectors)
119
121
  .group_by(&:pact_version_sha)
120
122
  .values
121
123
  .collect do | head_pacts |
122
124
  squash_pacts_for_verification(provider_version_tags, head_pacts)
123
125
  end
126
+
127
+ verifiable_wip_pacts = if options[:include_wip_pacts_since]
128
+ exclude_specified_pacts(
129
+ pact_repository.find_wip_pact_versions_for_provider(provider_name, provider_version_tags, options),
130
+ verifiable_pacts_specified_in_request)
131
+ else
132
+ []
133
+ end
134
+
135
+ verifiable_pacts_specified_in_request + verifiable_wip_pacts
124
136
  end
125
137
 
126
138
  private
127
139
 
140
+ def exclude_specified_pacts(wip_pacts, specified_pacts)
141
+ wip_pacts.select do | wip_pact |
142
+ !specified_pacts.any? do | specified_pacts |
143
+ wip_pact.pact_version_sha == specified_pacts.pact_version_sha
144
+ end
145
+ end
146
+ end
147
+
128
148
  # Overwriting an existing pact with the same consumer/provider/consumer version number
129
149
  def update_pact params, existing_pact, webhook_options
130
150
  logger.info "Updating existing pact publication with params #{params.reject{ |k, v| k == :json_content}}"
@@ -3,15 +3,17 @@ require 'delegate'
3
3
  module PactBroker
4
4
  module Pacts
5
5
  class VerifiablePact < SimpleDelegator
6
- attr_reader :pending, :pending_provider_tags, :non_pending_provider_tags, :head_consumer_tags
6
+ attr_reader :pending, :pending_provider_tags, :non_pending_provider_tags, :head_consumer_tags, :wip
7
7
 
8
- def initialize(pact, pending, pending_provider_tags = [], non_pending_provider_tags = [], head_consumer_tags = [], overall_latest = false)
8
+ # TODO refactor this constructor
9
+ def initialize(pact, pending, pending_provider_tags = [], non_pending_provider_tags = [], head_consumer_tags = [], overall_latest = false, wip = false)
9
10
  super(pact)
10
11
  @pending = pending
11
12
  @pending_provider_tags = pending_provider_tags
12
13
  @non_pending_provider_tags = non_pending_provider_tags
13
14
  @head_consumer_tags = head_consumer_tags
14
15
  @overall_latest = overall_latest
16
+ @wip = wip
15
17
  end
16
18
 
17
19
  def consumer_tags
@@ -25,6 +27,10 @@ module PactBroker
25
27
  def pending?
26
28
  pending
27
29
  end
30
+
31
+ def wip?
32
+ wip
33
+ end
28
34
  end
29
35
  end
30
36
  end
@@ -3,28 +3,34 @@ module PactBroker
3
3
  class VerifiablePactMessages
4
4
  extend Forwardable
5
5
 
6
- READ_MORE = "Read more at https://pact.io/pending"
6
+ READ_MORE_PENDING = "Read more at https://pact.io/pending"
7
+ READ_MORE_WIP = "Read more at https://pact.io/wip"
7
8
 
8
- delegate [:consumer_name, :provider_name, :head_consumer_tags, :pending_provider_tags, :non_pending_provider_tags, :pending?] => :verifiable_pact
9
+ delegate [:consumer_name, :provider_name, :head_consumer_tags, :pending_provider_tags, :non_pending_provider_tags, :pending?, :wip?] => :verifiable_pact
9
10
 
10
11
  def initialize(verifiable_pact)
11
12
  @verifiable_pact = verifiable_pact
12
13
  end
13
14
 
14
15
  def inclusion_reason
15
- if head_consumer_tags.any?
16
- version_text = head_consumer_tags.size == 1 ? "version" : "versions"
17
- "This pact is being verified because it is the pact for the latest #{version_text} of Foo tagged with #{joined_head_consumer_tags}"
16
+ version_text = head_consumer_tags.size == 1 ? "version" : "versions"
17
+ if wip?
18
+ # WIP pacts will always have tags, because it is part of the definition of being a WIP pact
19
+ "This pact is being verified because it is a 'work in progress' pact (ie. it is the pact for the latest #{version_text} of Foo tagged with #{joined_head_consumer_tags} and is still in pending state). #{READ_MORE_WIP}"
18
20
  else
19
- "This pact is being verified because it is the latest pact between #{consumer_name} and #{provider_name}."
21
+ if head_consumer_tags.any?
22
+ "This pact is being verified because it is the pact for the latest #{version_text} of Foo tagged with #{joined_head_consumer_tags}"
23
+ else
24
+ "This pact is being verified because it is the latest pact between #{consumer_name} and #{provider_name}."
25
+ end
20
26
  end
21
27
  end
22
28
 
23
29
  def pending_reason
24
30
  if pending?
25
- "This pact is in pending state because it has not yet been successfully verified by #{pending_provider_tags_description}. If this verification fails, it will not cause the overall build to fail. #{READ_MORE}"
31
+ "This pact is in pending state because it has not yet been successfully verified by #{pending_provider_tags_description}. If this verification fails, it will not cause the overall build to fail. #{READ_MORE_PENDING}"
26
32
  else
27
- "This pact has previously been successfully verified by #{non_pending_provider_tags_description}. If this verification fails, it will fail the build. #{READ_MORE}"
33
+ "This pact has previously been successfully verified by #{non_pending_provider_tags_description}. If this verification fails, it will fail the build. #{READ_MORE_PENDING}"
28
34
  end
29
35
  end
30
36
 
@@ -8,6 +8,41 @@ module PactBroker
8
8
  def blank?
9
9
  self.strip.size == 0
10
10
  end
11
+
12
+ # ripped from rubyworks/facets, thank you
13
+ def snakecase
14
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
15
+ .gsub(/([a-z\d])([A-Z])/,'\1_\2')
16
+ .tr('-', '_')
17
+ .gsub(/\s/, '_')
18
+ .gsub(/__+/, '_')
19
+ .downcase
20
+ end
21
+
22
+ # ripped from rubyworks/facets, thank you
23
+ def camelcase(*separators)
24
+ case separators.first
25
+ when Symbol, TrueClass, FalseClass, NilClass
26
+ first_letter = separators.shift
27
+ end
28
+
29
+ separators = ['_', '\s'] if separators.empty?
30
+
31
+ str = self.dup
32
+
33
+ separators.each do |s|
34
+ str = str.gsub(/(?:#{s}+)([a-z])/){ $1.upcase }
35
+ end
36
+
37
+ case first_letter
38
+ when :upper, true
39
+ str = str.gsub(/(\A|\s)([a-z])/){ $1 + $2.upcase }
40
+ when :lower, false
41
+ str = str.gsub(/(\A|\s)([A-Z])/){ $1 + $2.downcase }
42
+ end
43
+
44
+ str
45
+ end
11
46
  end
12
47
  end
13
- end
48
+ end
@@ -0,0 +1,12 @@
1
+ require 'pact_broker/db'
2
+ require 'pact_broker/repositories/helpers'
3
+
4
+ module PactBroker
5
+ module Tags
6
+ class HeadPactTag < Sequel::Model
7
+ dataset_module do
8
+ include PactBroker::Repositories::Helpers
9
+ end
10
+ end
11
+ end
12
+ end
@@ -5,7 +5,6 @@ module PactBroker
5
5
  module Tags
6
6
  # The tag associated with the latest verification for a given tag
7
7
  class TagWithLatestFlag < Sequel::Model(:tags_with_latest_flag)
8
-
9
8
  dataset_module do
10
9
  include PactBroker::Repositories::Helpers
11
10
  end
@@ -203,7 +203,7 @@ module PactBroker
203
203
  def republish_same_pact params = {}
204
204
  params.delete(:comment)
205
205
  last_pact_version = PactBroker::Pacts::PactVersion.order(:id).last
206
- create_pact json_content: last_pact_version.content
206
+ create_pact pact_version_sha: last_pact_version.sha, json_content: last_pact_version.content, created_at: params[:created_at]
207
207
  self
208
208
  end
209
209
 
@@ -14,9 +14,30 @@ module PactBroker
14
14
  if params[:tags]
15
15
  tags = params[:tags] == 'true' ? true : [*params[:tags]].compact
16
16
  end
17
- view_model = ViewDomain::IndexItems.new(index_service.find_index_items(tags: tags))
17
+ page_number = params[:page]&.to_i || 1
18
+ # Make page size smaller for data intensive query
19
+ page_size = params[:pageSize]&.to_i || (tags == true ? 30 : 100)
20
+ options = {
21
+ tags: tags,
22
+ page_number: page_number,
23
+ page_size: page_size
24
+ }
25
+
26
+ # TODO remove this code when verified
27
+ options[:optimised] = true unless params[:optimised] == 'false'
28
+ index_items = ViewDomain::IndexItems.new(index_service.find_index_items(options))
29
+
18
30
  page = tags ? :'index/show-with-tags' : :'index/show'
19
- haml page, {locals: {index_items: view_model, title: "Pacts"}, layout: :'layouts/main'}
31
+ locals = {
32
+ title: "Pacts",
33
+ index_items: index_items,
34
+ page_number: page_number,
35
+ page_size: page_size,
36
+ pagination_record_count: index_items.pagination_record_count,
37
+ current_page_size: index_items.size
38
+ }
39
+
40
+ haml page, {locals: locals, layout: :'layouts/main'}
20
41
  end
21
42
 
22
43
  def set_headers
@@ -27,6 +27,10 @@ module PactBroker
27
27
  PactBroker::Versions::AbbreviateNumber.call(@relationship.consumer_version_number)
28
28
  end
29
29
 
30
+ def consumer_version_order
31
+ @relationship.consumer_version_order
32
+ end
33
+
30
34
  def provider_version_number
31
35
  PactBroker::Versions::AbbreviateNumber.call(@relationship.provider_version_number)
32
36
  end
@@ -164,7 +168,9 @@ module PactBroker
164
168
  def <=> other
165
169
  comp = consumer_name.downcase <=> other.consumer_name.downcase
166
170
  return comp unless comp == 0
167
- provider_name.downcase <=> other.provider_name.downcase
171
+ comp = provider_name.downcase <=> other.provider_name.downcase
172
+ return comp unless comp == 0
173
+ other.consumer_version_order <=> consumer_version_order
168
174
  end
169
175
 
170
176
  def short_version_number version_number