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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9640609d3cd63f00f72cd919503c9753e7f14901
4
- data.tar.gz: c538742c6e384659661609b059e24ca1c5732ae2
3
+ metadata.gz: 5aea6eddd75f874a8b5e1994d0269b72e4f8745c
4
+ data.tar.gz: bf9c5cc37f4d5df1dcaa53d21e8c902c645a0973
5
5
  SHA512:
6
- metadata.gz: 9a6918c28db99e46a2c28c6ac608aadec4efe8780369328956a8617bd1f17dd3bb8899c80f0e597920d0005e9856e0cce56303f108df98240d32556808f1fd46
7
- data.tar.gz: 99cc9f3892e31cd11c449de7f4da9469f70d96df2ec6501df37225f3d98b5068ac71fbf42e1f359e5acbe7c29f572aa2d6baaa066a180c3ffa65fea29e777979
6
+ metadata.gz: ea61f5bf743380ce29ab3ad0d5dadf842ae5aead4e0dd209157c8841ccbfc9b0614245463eaf596b40764e349635652394144f2769fc3ffd6a1f900e7e45a930
7
+ data.tar.gz: 1c023a21856fbbb8ca7e8a172b0720016b7509231270b64cf18a8bc8f6ba485131484debf7d261a7a6aff9cfd90de4d7b927da00d793e1744be679322f567d33
@@ -1,3 +1,39 @@
1
+ <a name="v2.41.0"></a>
2
+ ### v2.41.0 (2019-11-21)
3
+
4
+
5
+ #### Features
6
+
7
+ * **pacts for verification**
8
+ * make latest flag required and true for now, until the 'all pacts for tag' is implemented ([ebbbbec9](/../../commit/ebbbbec9))
9
+ * include WIP pacts in list of pacts to verify ([04a0f40c](/../../commit/04a0f40c))
10
+ * allow pending status information to be optionall included ([a80f2fd6](/../../commit/a80f2fd6))
11
+ * support querying by POST ([5556b814](/../../commit/5556b814))
12
+
13
+ * **matrix**
14
+ * show pact version SHA in popup text, and highlight pact publications with the same pact version ([0d539093](/../../commit/0d539093))
15
+ * update 'pre-verifed' pop up text, and add icon to indicate when a pact is pre-verified ([a86010e5](/../../commit/a86010e5))
16
+ * add tags to json response ([6d099f59](/../../commit/6d099f59))
17
+
18
+ * **example data**
19
+ * include a pre-verified pact ([49fd5004](/../../commit/49fd5004))
20
+
21
+ * **index**
22
+ * enable pagination feature ([9bb87eca](/../../commit/9bb87eca))
23
+ * add pagination controls to the bottom of the page ([9d9e6378](/../../commit/9d9e6378))
24
+ * optimise query, feature toggled ([e238749e](/../../commit/e238749e))
25
+ * optimise server side rendered page ([1f54ccf4](/../../commit/1f54ccf4))
26
+
27
+ * **diagnostic**
28
+ * remove before_resource and after_resource hook calls from diagnostics endpoints ([b1dac2bd](/../../commit/b1dac2bd))
29
+
30
+ * add missing super calls in BaseResource child classes ([1071ca8a](/../../commit/1071ca8a))
31
+ * optimise latest_verification_ids_for_consumer_version_tags ([9e84ce7d](/../../commit/9e84ce7d))
32
+ * optimise latest_pact_publications_by_consumer_versions ([86846271](/../../commit/86846271))
33
+ * optimise latest_pact_consumer_version_orders ([c4febeaa](/../../commit/c4febeaa))
34
+ * optimise latest_tagged_pact_consumer_version_orders view ([d92cb8f2](/../../commit/d92cb8f2))
35
+
36
+
1
37
  <a name="v2.40.0"></a>
2
38
  ### v2.40.0 (2019-10-26)
3
39
 
@@ -106,8 +106,19 @@ pact publication resource will be created, but it will reuse the existing pact v
106
106
  -> versions
107
107
  -> latest_tagged_pact_consumer_version_orders
108
108
  -> latest_pact_publications_by_consumer_versions
109
+
110
+ = head_pact_publications
111
+ -> latest_pact_publications
112
+ -> latest_pact_publication_ids_for_consumer_versions
113
+ -> latest_tagged_pact_publications
114
+ -> latest_pact_publications_by_consumer_versions (optimised for pp_ids)
115
+ -> latest_tagged_pact_consumer_version_orders (optimised for pp_ids)
116
+
109
117
  ```
110
118
 
119
+
120
+
121
+
111
122
  ### Useful to know stuff
112
123
 
113
124
  * The supported database types are Postgres (recommended), MySQL (sigh) and Sqlite (just for testing, not recommended for production). Check the travis.yml file for the supported database versions.
@@ -0,0 +1,10 @@
1
+ def head_pact_tags_v1(connection)
2
+ connection.from(Sequel.as(:latest_pact_publication_ids_for_consumer_versions, :lp))
3
+ .join(:versions,{ Sequel[:lp][:consumer_version_id] => Sequel[:cv][:id]}, { table_alias: :cv })
4
+ .join(:latest_tagged_pact_consumer_version_orders, {
5
+ Sequel[:lp][:consumer_id] => Sequel[:o][:consumer_id],
6
+ Sequel[:lp][:provider_id] => Sequel[:o][:provider_id],
7
+ Sequel[:cv][:order] => Sequel[:o][:latest_consumer_version_order]
8
+ }, { table_alias: :o})
9
+ .select(Sequel[:o][:tag_name].as(:name), Sequel[:lp][:pact_publication_id])
10
+ end
@@ -0,0 +1,16 @@
1
+ # The consumer id, provider id, and consumer version order
2
+ # for the latest consumer version that has a pact with that provider.
3
+
4
+ def latest_pact_consumer_version_orders_v1(connection = nil)
5
+ "select provider_id, consumer_id, max(consumer_version_order) as latest_consumer_version_order
6
+ from all_pact_publications
7
+ group by provider_id, consumer_id"
8
+ end
9
+
10
+ def latest_pact_consumer_version_orders_v2(connection = nil)
11
+ view = Sequel.as(:latest_pact_publication_ids_for_consumer_versions, :lp)
12
+ connection.from(view)
13
+ .select_group(:provider_id, :consumer_id)
14
+ .select_append{ max(order).as(latest_consumer_version_order) }
15
+ .join(:versions, { Sequel[:lp][:consumer_version_id] => Sequel[:cv][:id]}, { table_alias: :cv } )
16
+ end
@@ -0,0 +1,16 @@
1
+ def latest_pact_publications_by_consumer_versions_v2(connection = nil)
2
+ "select app.*
3
+ from latest_pact_publication_ids_for_consumer_versions lpp
4
+ inner join all_pact_publications app
5
+ on lpp.consumer_version_id = app.consumer_version_id
6
+ and lpp.pact_publication_id = app.id
7
+ and lpp.provider_id = app.provider_id"
8
+ end
9
+
10
+ # Don't need all the join keys, just pact_publication_id
11
+ def latest_pact_publications_by_consumer_versions_v3(connection)
12
+ "select app.*
13
+ from latest_pact_publication_ids_for_consumer_versions lpp
14
+ inner join all_pact_publications app
15
+ on lpp.pact_publication_id = app.id"
16
+ end
@@ -0,0 +1,23 @@
1
+ def latest_tagged_pact_consumer_version_orders_v2(connection)
2
+ pp = :pact_publications
3
+ connection.from(pp)
4
+ .select_group(
5
+ Sequel[pp][:provider_id],
6
+ Sequel[:cv][:pacticipant_id].as(:consumer_id),
7
+ Sequel[:t][:name].as(:tag_name))
8
+ .select_append{ max(order).as(latest_consumer_version_order) }
9
+ .join(:versions, { Sequel[pp][:consumer_version_id] => Sequel[:cv][:id] }, { table_alias: :cv} )
10
+ .join(:tags, { Sequel[:t][:version_id] => Sequel[pp][:consumer_version_id] }, { table_alias: :t })
11
+ end
12
+
13
+ def latest_tagged_pact_consumer_version_orders_v3(connection)
14
+ view = Sequel.as(:latest_pact_publication_ids_for_consumer_versions, :lp)
15
+ connection.from(view)
16
+ .select_group(
17
+ Sequel[:lp][:provider_id],
18
+ Sequel[:lp][:consumer_id],
19
+ Sequel[:t][:name].as(:tag_name))
20
+ .select_append{ max(order).as(latest_consumer_version_order) }
21
+ .join(:versions, { Sequel[:lp][:consumer_version_id] => Sequel[:cv][:id] }, { table_alias: :cv} )
22
+ .join(:tags, { Sequel[:t][:version_id] => Sequel[:lp][:consumer_version_id] }, { table_alias: :t })
23
+ end
@@ -36,3 +36,18 @@ LATEST_VERIFICATION_IDS_FOR_CONSUMER_VERSION_TAGS_V2 = "select
36
36
  join versions pv
37
37
  on v.provider_version_id = pv.id
38
38
  group by pv.pacticipant_id, lpp.consumer_id, t.name"
39
+
40
+ LATEST_VERIFICATION_IDS_FOR_CONSUMER_VERSION_TAGS_V3 = "select
41
+ pv.pacticipant_id as provider_id,
42
+ lpp.consumer_id,
43
+ t.name as consumer_version_tag_name,
44
+ max(v.id) as latest_verification_id
45
+ from verifications v
46
+ join latest_pact_publication_ids_for_consumer_versions lpp
47
+ on v.pact_version_id = lpp.pact_version_id
48
+ join tags t
49
+ on lpp.consumer_version_id = t.version_id
50
+ join versions pv
51
+ on v.provider_version_id = pv.id
52
+ where v.id in (select latest_verification_id from latest_verification_ids_for_pact_versions)
53
+ group by pv.pacticipant_id, lpp.consumer_id, t.name"
@@ -23,6 +23,7 @@ Sequel.migration do
23
23
 
24
24
  # Latest pact_publication (revision) for each provider/consumer version
25
25
  # updated in 20180519_recreate_views.rb
26
+ # latest_pact_publications_by_consumer_versions_v1
26
27
  create_view(:latest_pact_publications_by_consumer_versions,
27
28
  "select app.*
28
29
  from all_pact_publications app
@@ -6,15 +6,7 @@ Sequel.migration do
6
6
  pp = :pact_publications
7
7
  # For each consumer_id/provider_id/tag_name, the version order of the latest version that has a pact
8
8
  create_or_replace_view(:latest_tagged_pact_consumer_version_orders,
9
- from(:pact_publications)
10
- .select_group(
11
- Sequel[pp][:provider_id],
12
- Sequel[:cv][:pacticipant_id].as(:consumer_id),
13
- Sequel[:t][:name].as(:tag_name))
14
- .select_append{ max(order).as(latest_consumer_version_order) }
15
- .join(:versions, { Sequel[pp][:consumer_version_id] => Sequel[:cv][:id] }, { table_alias: :cv} )
16
- .join(:tags, { Sequel[:t][:version_id] => Sequel[pp][:consumer_version_id] }, { table_alias: :t })
17
- )
9
+ latest_tagged_pact_consumer_version_orders_v2(self))
18
10
 
19
11
  # Add provider_version_order to original definition
20
12
  # The most recent verification for each pact_version
@@ -1,29 +1,19 @@
1
+ require_relative '../ddl_statements'
2
+
1
3
  Sequel.migration do
2
4
  up do
3
5
  # Latest pact_publication details for each provider/consumer version
4
6
  create_or_replace_view(:latest_pact_publications_by_consumer_versions,
5
- "select app.*
6
- from latest_pact_publication_ids_for_consumer_versions lpp
7
- inner join all_pact_publications app
8
- on lpp.consumer_version_id = app.consumer_version_id
9
- and lpp.pact_publication_id = app.id
10
- and lpp.provider_id = app.provider_id"
11
- )
7
+ latest_pact_publications_by_consumer_versions_v2(self))
12
8
 
13
9
  # Latest consumer version order for consumer/provider
14
10
  # Recreate latest_pact_publication_ids_for_consumer_versions view
15
- lpp = :latest_pact_publication_ids_for_consumer_versions
16
- latest_pact_consumer_version_orders = from(lpp).select_group(
17
- Sequel[lpp][:provider_id],
18
- Sequel[:cv][:pacticipant_id].as(:consumer_id))
19
- .select_append{ max(order).as(latest_consumer_version_order) }
20
- .join(:versions, { Sequel[lpp][:consumer_version_id] => Sequel[:cv][:id] }, { table_alias: :cv })
21
-
22
- create_or_replace_view(:latest_pact_consumer_version_orders, latest_pact_consumer_version_orders)
11
+ create_or_replace_view(:latest_pact_consumer_version_orders, latest_pact_consumer_version_orders_v2(self))
23
12
  end
24
13
 
25
14
  down do
26
15
  # Latest pact_publication details for each provider/consumer version
16
+ # latest_pact_publications_by_consumer_versions_v1
27
17
  create_or_replace_view(:latest_pact_publications_by_consumer_versions,
28
18
  "select app.*
29
19
  from all_pact_publications app
@@ -35,9 +25,6 @@ Sequel.migration do
35
25
  )
36
26
 
37
27
  create_or_replace_view(:latest_pact_consumer_version_orders,
38
- "select provider_id, consumer_id, max(consumer_version_order) as latest_consumer_version_order
39
- from all_pact_publications
40
- group by provider_id, consumer_id"
41
- )
28
+ latest_pact_consumer_version_orders_v1(self))
42
29
  end
43
30
  end
@@ -0,0 +1,13 @@
1
+ require_relative '../ddl_statements'
2
+
3
+ Sequel.migration do
4
+ up do
5
+ create_or_replace_view(:latest_tagged_pact_consumer_version_orders,
6
+ latest_tagged_pact_consumer_version_orders_v3(self))
7
+ end
8
+
9
+ down do
10
+ create_or_replace_view(:latest_tagged_pact_consumer_version_orders,
11
+ latest_tagged_pact_consumer_version_orders_v2(self))
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require_relative '../ddl_statements'
2
+
3
+ Sequel.migration do
4
+ up do
5
+ create_or_replace_view(:latest_pact_publications_by_consumer_versions,
6
+ latest_pact_publications_by_consumer_versions_v3(self))
7
+ end
8
+
9
+ down do
10
+ create_or_replace_view(:latest_pact_publications_by_consumer_versions,
11
+ latest_pact_publications_by_consumer_versions_v2(self))
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require_relative '../ddl_statements'
2
+
3
+ Sequel.migration do
4
+ up do
5
+ create_or_replace_view(:latest_verification_ids_for_consumer_version_tags,
6
+ LATEST_VERIFICATION_IDS_FOR_CONSUMER_VERSION_TAGS_V3)
7
+ end
8
+
9
+ down do
10
+ create_or_replace_view(:latest_verification_ids_for_consumer_version_tags,
11
+ LATEST_VERIFICATION_IDS_FOR_CONSUMER_VERSION_TAGS_V2)
12
+ end
13
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../ddl_statements'
2
+
3
+ Sequel.migration do
4
+ up do
5
+ create_view(:head_pact_tags, head_pact_tags_v1(self))
6
+ end
7
+
8
+ down do
9
+ drop_view(:head_pact_tags)
10
+ end
11
+ end
data/lib/db.rb CHANGED
@@ -29,6 +29,7 @@ module DB
29
29
  # logger = Logger.new($stdout)
30
30
  con = Sequel.connect(db_credentials.merge(:logger => logger, :pool_class => Sequel::ThreadedConnectionPool, :encoding => 'utf8'))
31
31
  con.extension(:connection_validator)
32
+ con.extension(:pagination)
32
33
  con.pool.connection_validation_timeout = -1 #Check the connection on every request
33
34
  con.timezone = :utc
34
35
  con.run("SET sql_mode='STRICT_TRANS_TABLES';") if db_credentials[:adapter].to_s =~ /mysql/
@@ -0,0 +1,15 @@
1
+ require 'dry-validation'
2
+
3
+ module PactBroker
4
+ module Api
5
+ module Contracts
6
+ module DryValidationPredicates
7
+ include Dry::Logic::Predicates
8
+
9
+ predicate(:date?) do |value|
10
+ DateTime.parse(value) rescue false
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ module PactBroker
2
+ module Api
3
+ module Contracts
4
+ module DryValidationWorkarounds
5
+ extend self
6
+
7
+ # I just cannot seem to get the validation to stop on the first error.
8
+ # If one rule fails, they all come back failed, and it's driving me nuts.
9
+ # Why on earth would I want that behaviour?
10
+ def select_first_message(messages)
11
+ messages.each_with_object({}) do | (key, value), new_messages |
12
+ new_messages[key] = [value.first]
13
+ end
14
+ end
15
+
16
+ def flatten_array_of_hashes(array_of_hashes)
17
+ new_messages = array_of_hashes.collect do | index, hash |
18
+ hash.values.flatten.collect { | text | "#{text} at index #{index}"}
19
+ end.flatten
20
+ end
21
+
22
+ def flatten_indexed_messages(messages)
23
+ if messages.values.any?{ | value | is_indexed_structure?(value) }
24
+ messages.each_with_object({}) do | (key, value), new_messages |
25
+ new_messages[key] = is_indexed_structure?(value) ? flatten_array_of_hashes(value) : value
26
+ end
27
+ else
28
+ messages
29
+ end
30
+ end
31
+
32
+ def is_indexed_structure?(thing)
33
+ thing.is_a?(Hash) && thing.keys.first.is_a?(Integer)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,34 @@
1
+ require 'dry-validation'
2
+ require 'pact_broker/hash_refinements'
3
+ require 'pact_broker/api/contracts/dry_validation_workarounds'
4
+ require 'pact_broker/api/contracts/dry_validation_predicates'
5
+
6
+ module PactBroker
7
+ module Api
8
+ module Contracts
9
+ class VerifiablePactsJSONQuerySchema
10
+ extend DryValidationWorkarounds
11
+ using PactBroker::HashRefinements
12
+
13
+ SCHEMA = Dry::Validation.Schema do
14
+ configure do
15
+ predicates(DryValidationPredicates)
16
+ end
17
+ optional(:providerVersionTags).maybe(:array?)
18
+ optional(:consumerVersionSelectors).each do
19
+ schema do
20
+ required(:tag).filled(:str?)
21
+ required(:latest).filled(included_in?: [true])
22
+ end
23
+ end
24
+ optional(:includePendingStatus).filled(included_in?: [true, false])
25
+ optional(:includeWipPactsSince).filled(:date?)
26
+ end
27
+
28
+ def self.call(params)
29
+ select_first_message(flatten_indexed_messages(SCHEMA.call(params&.symbolize_keys).messages(full: true)))
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,39 +1,31 @@
1
1
  require 'dry-validation'
2
+ require 'pact_broker/api/contracts/dry_validation_workarounds'
3
+ require 'pact_broker/api/contracts/dry_validation_predicates'
2
4
 
3
5
  module PactBroker
4
6
  module Api
5
7
  module Contracts
6
8
  class VerifiablePactsQuerySchema
9
+ extend DryValidationWorkarounds
10
+ using PactBroker::HashRefinements
11
+
7
12
  SCHEMA = Dry::Validation.Schema do
13
+ configure do
14
+ predicates(DryValidationPredicates)
15
+ end
8
16
  optional(:provider_version_tags).maybe(:array?)
9
- # optional(:exclude_other_pending).filled(included_in?: ["true", "false"])
10
17
  optional(:consumer_version_selectors).each do
11
18
  schema do
12
19
  required(:tag).filled(:str?)
13
- optional(:latest).filled(included_in?: ["true", "false"])
20
+ required(:latest).filled(included_in?: ["true"])
14
21
  end
15
22
  end
23
+ optional(:include_pending_status).filled(included_in?: ["true", "false"])
24
+ optional(:include_wip_pacts_since).filled(:date?)
16
25
  end
17
26
 
18
27
  def self.call(params)
19
- select_first_message(flatten_index_messages(SCHEMA.call(params).messages(full: true)))
20
- end
21
-
22
- def self.select_first_message(messages)
23
- messages.each_with_object({}) do | (key, value), new_messages |
24
- new_messages[key] = [value.first]
25
- end
26
- end
27
-
28
- def self.flatten_index_messages(messages)
29
- if messages[:consumer_version_selectors]
30
- new_messages = messages[:consumer_version_selectors].collect do | index, value |
31
- value.values.flatten.collect { | text | "#{text} at index #{index}"}
32
- end.flatten
33
- messages.merge(consumer_version_selectors: new_messages)
34
- else
35
- messages
36
- end
28
+ select_first_message(flatten_indexed_messages(SCHEMA.call(params&.symbolize_keys).messages(full: true)))
37
29
  end
38
30
  end
39
31
  end