pact_broker 2.40.0 → 2.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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