pact_broker 2.106.0 → 2.107.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -0
  3. data/Gemfile +3 -0
  4. data/db/migrations/20230131_add_cons_ver_id_ndx_to_latest_pp_id_for_cons_ver.rb +8 -4
  5. data/db/migrations/20230216_add_branch_heads_branch_version_id_index.rb +21 -0
  6. data/db/migrations/20230428_add_index_for_webhook_executions_pact_publication_id.rb +17 -0
  7. data/lib/pact_broker/api/contracts/base_contract.rb +22 -7
  8. data/lib/pact_broker/api/contracts/can_i_deploy_query_schema.rb +34 -0
  9. data/lib/pact_broker/api/contracts/configuration.rb +2 -0
  10. data/lib/pact_broker/api/contracts/consumer_version_selector_contract.rb +140 -0
  11. data/lib/pact_broker/api/contracts/dry_validation_errors_formatter.rb +50 -0
  12. data/lib/pact_broker/api/contracts/dry_validation_macros.rb +79 -0
  13. data/lib/pact_broker/api/contracts/dry_validation_methods.rb +71 -0
  14. data/lib/pact_broker/api/contracts/environment_schema.rb +19 -33
  15. data/lib/pact_broker/api/contracts/pacticipant_create_schema.rb +4 -17
  16. data/lib/pact_broker/api/contracts/pacticipant_schema.rb +15 -24
  17. data/lib/pact_broker/api/contracts/pacts_for_verification_json_query_schema.rb +37 -146
  18. data/lib/pact_broker/api/contracts/pacts_for_verification_query_string_schema.rb +7 -20
  19. data/lib/pact_broker/api/contracts/publish_contracts_contract_contract.rb +62 -0
  20. data/lib/pact_broker/api/contracts/publish_contracts_schema.rb +25 -124
  21. data/lib/pact_broker/api/contracts/put_pact_params_contract.rb +21 -26
  22. data/lib/pact_broker/api/contracts/utf_8_validation.rb +2 -0
  23. data/lib/pact_broker/api/contracts/validation_helpers.rb +71 -0
  24. data/lib/pact_broker/api/contracts/verification_contract.rb +10 -29
  25. data/lib/pact_broker/api/contracts/webhook_contract.rb +20 -172
  26. data/lib/pact_broker/api/contracts/webhook_pacticipant_contract.rb +33 -0
  27. data/lib/pact_broker/api/contracts/webhook_request_contract.rb +125 -0
  28. data/lib/pact_broker/api/contracts.rb +3 -0
  29. data/lib/pact_broker/api/decorators/custom_error_problem_json_decorator.rb +4 -4
  30. data/lib/pact_broker/api/decorators/dashboard_text_decorator.rb +2 -2
  31. data/lib/pact_broker/api/decorators/extended_pact_decorator.rb +1 -1
  32. data/lib/pact_broker/api/decorators/matrix_decorator.rb +4 -4
  33. data/lib/pact_broker/api/decorators/matrix_text_decorator.rb +1 -1
  34. data/lib/pact_broker/api/decorators/pact_decorator.rb +1 -1
  35. data/lib/pact_broker/api/decorators/pacticipant_collection_decorator.rb +2 -2
  36. data/lib/pact_broker/api/decorators/pacticipant_decorator.rb +2 -1
  37. data/lib/pact_broker/api/decorators/pacts_for_verification_query_decorator.rb +4 -1
  38. data/lib/pact_broker/api/decorators/pagination_links.rb +6 -6
  39. data/lib/pact_broker/api/decorators/runtime_error_problem_json_decorator.rb +4 -4
  40. data/lib/pact_broker/api/decorators/validation_errors_problem_json_decorator.rb +6 -6
  41. data/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb +4 -4
  42. data/lib/pact_broker/api/decorators/webhook_decorator.rb +2 -3
  43. data/lib/pact_broker/api/decorators/webhook_execution_result_decorator.rb +5 -12
  44. data/lib/pact_broker/api/resources/all_webhooks.rb +5 -11
  45. data/lib/pact_broker/api/resources/base_resource.rb +3 -20
  46. data/lib/pact_broker/api/resources/branch_version.rb +3 -3
  47. data/lib/pact_broker/api/resources/can_i_deploy.rb +4 -19
  48. data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_branch_to_environment.rb +1 -4
  49. data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_tag_to_tag.rb +0 -2
  50. data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_tag_to_tag_badge.rb +1 -2
  51. data/lib/pact_broker/api/resources/currently_deployed_versions_for_environment.rb +2 -2
  52. data/lib/pact_broker/api/resources/currently_supported_versions_for_environment.rb +2 -2
  53. data/lib/pact_broker/api/resources/dashboard.rb +3 -3
  54. data/lib/pact_broker/api/resources/deployed_version.rb +1 -1
  55. data/lib/pact_broker/api/resources/deployed_versions_for_version_and_environment.rb +2 -2
  56. data/lib/pact_broker/api/resources/environment.rb +1 -1
  57. data/lib/pact_broker/api/resources/environments.rb +2 -2
  58. data/lib/pact_broker/api/resources/error_handling_methods.rb +2 -2
  59. data/lib/pact_broker/api/resources/integrations.rb +1 -1
  60. data/lib/pact_broker/api/resources/label.rb +1 -1
  61. data/lib/pact_broker/api/resources/latest_pact.rb +2 -2
  62. data/lib/pact_broker/api/resources/latest_pacts.rb +1 -1
  63. data/lib/pact_broker/api/resources/latest_verifications_for_consumer_version.rb +1 -1
  64. data/lib/pact_broker/api/resources/matrix.rb +2 -2
  65. data/lib/pact_broker/api/resources/matrix_for_consumer_and_provider.rb +1 -1
  66. data/lib/pact_broker/api/resources/pact.rb +7 -4
  67. data/lib/pact_broker/api/resources/pact_triggered_webhooks.rb +1 -1
  68. data/lib/pact_broker/api/resources/pact_versions.rb +1 -1
  69. data/lib/pact_broker/api/resources/pact_webhooks.rb +7 -14
  70. data/lib/pact_broker/api/resources/pact_webhooks_status.rb +6 -2
  71. data/lib/pact_broker/api/resources/pacticipant.rb +1 -1
  72. data/lib/pact_broker/api/resources/pacticipant_webhooks.rb +7 -5
  73. data/lib/pact_broker/api/resources/pacticipants.rb +2 -2
  74. data/lib/pact_broker/api/resources/pacticipants_for_label.rb +1 -1
  75. data/lib/pact_broker/api/resources/previous_distinct_pact_version.rb +1 -1
  76. data/lib/pact_broker/api/resources/provider_pacts.rb +1 -1
  77. data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +4 -13
  78. data/lib/pact_broker/api/resources/publish_contracts.rb +8 -3
  79. data/lib/pact_broker/api/resources/released_version.rb +1 -1
  80. data/lib/pact_broker/api/resources/released_versions_for_version_and_environment.rb +2 -2
  81. data/lib/pact_broker/api/resources/tag.rb +1 -1
  82. data/lib/pact_broker/api/resources/tagged_pact_versions.rb +1 -1
  83. data/lib/pact_broker/api/resources/triggered_webhook_logs.rb +2 -2
  84. data/lib/pact_broker/api/resources/verification.rb +2 -2
  85. data/lib/pact_broker/api/resources/verification_triggered_webhooks.rb +1 -1
  86. data/lib/pact_broker/api/resources/verifications.rb +4 -6
  87. data/lib/pact_broker/api/resources/version.rb +1 -1
  88. data/lib/pact_broker/api/resources/versions.rb +1 -1
  89. data/lib/pact_broker/api/resources/webhook.rb +7 -6
  90. data/lib/pact_broker/api/resources/webhook_execution.rb +6 -4
  91. data/lib/pact_broker/api.rb +3 -12
  92. data/lib/pact_broker/certificates/certificate.rb +1 -0
  93. data/lib/pact_broker/config/setting.rb +1 -0
  94. data/lib/pact_broker/contracts/service.rb +1 -0
  95. data/lib/pact_broker/date_helper.rb +1 -1
  96. data/lib/pact_broker/db/clean_incremental.rb +1 -1
  97. data/lib/pact_broker/db/delete_overwritten_data.rb +6 -2
  98. data/lib/pact_broker/deployments/currently_deployed_version_id.rb +2 -0
  99. data/lib/pact_broker/deployments/deployed_version.rb +2 -0
  100. data/lib/pact_broker/deployments/deployed_version_service.rb +5 -1
  101. data/lib/pact_broker/deployments/environment.rb +2 -0
  102. data/lib/pact_broker/deployments/environment_service.rb +4 -3
  103. data/lib/pact_broker/deployments/released_version.rb +2 -0
  104. data/lib/pact_broker/deployments/released_version_service.rb +4 -0
  105. data/lib/pact_broker/diagnostic/resources/base_resource.rb +1 -1
  106. data/lib/pact_broker/doc/views/index/publish-contracts.markdown +5 -5
  107. data/lib/pact_broker/domain/label.rb +1 -0
  108. data/lib/pact_broker/domain/tag.rb +2 -0
  109. data/lib/pact_broker/domain/verification.rb +1 -1
  110. data/lib/pact_broker/domain/version.rb +4 -1
  111. data/lib/pact_broker/domain/webhook.rb +1 -1
  112. data/lib/pact_broker/index/service.rb +1 -1
  113. data/lib/pact_broker/integrations/integration.rb +1 -0
  114. data/lib/pact_broker/locale/en.yml +35 -14
  115. data/lib/pact_broker/matrix/query_ids.rb +4 -4
  116. data/lib/pact_broker/matrix/resolved_selector.rb +6 -1
  117. data/lib/pact_broker/matrix/service.rb +1 -0
  118. data/lib/pact_broker/messages.rb +5 -1
  119. data/lib/pact_broker/pacticipants/repository.rb +12 -3
  120. data/lib/pact_broker/pacticipants/service.rb +7 -0
  121. data/lib/pact_broker/pacts/pact_params.rb +6 -17
  122. data/lib/pact_broker/pacts/pact_version.rb +1 -0
  123. data/lib/pact_broker/policies.rb +4 -4
  124. data/lib/pact_broker/test/http_test_data_builder.rb +46 -2
  125. data/lib/pact_broker/ui/app.rb +2 -2
  126. data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +1 -1
  127. data/lib/pact_broker/verifications/pact_version_provider_tag_successful_verification.rb +1 -0
  128. data/lib/pact_broker/verifications/service.rb +0 -6
  129. data/lib/pact_broker/version.rb +1 -1
  130. data/lib/pact_broker/versions/branch.rb +1 -0
  131. data/lib/pact_broker/versions/branch_head.rb +2 -1
  132. data/lib/pact_broker/versions/branch_version.rb +11 -0
  133. data/lib/pact_broker/webhooks/execution.rb +1 -1
  134. data/lib/pact_broker/webhooks/repository.rb +1 -1
  135. data/lib/pact_broker/webhooks/service.rb +3 -25
  136. data/lib/pact_broker/webhooks/triggered_webhook.rb +1 -0
  137. data/lib/pact_broker/webhooks/webhook_event.rb +1 -0
  138. data/lib/pact_broker/webmachine.rb +22 -0
  139. data/lib/rack/pact_broker/invalid_uri_protection.rb +1 -1
  140. data/lib/rack/pact_broker/use_when.rb +6 -5
  141. data/lib/sequel/plugins/age.rb +13 -0
  142. data/lib/webmachine/application_monkey_patch.rb +5 -0
  143. data/lib/webmachine/describe_routes.rb +35 -8
  144. data/lib/webmachine/render_error_monkey_patch.rb +1 -1
  145. data/pact_broker.gemspec +7 -17
  146. metadata +65 -67
  147. data/lib/pact/doc/README.md +0 -5
  148. data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +0 -36
  149. data/lib/pact_broker/api/contracts/dry_validation_workarounds.rb +0 -39
  150. data/lib/pact_broker/api/contracts/pacticipant_name_contract.rb +0 -24
  151. data/lib/pact_broker/api/contracts/pacticipant_name_validation.rb +0 -30
  152. data/lib/pact_broker/api/contracts/request_validations.rb +0 -33
  153. data/lib/pact_broker/api/resources/webhook_resource_methods.rb +0 -17
  154. data/lib/pact_broker/matrix/can_i_deploy_query_schema.rb +0 -46
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8cbd7d902684d2fc82497cc897310eabd8b9d9fdf1e8fd8073202349d659d82a
4
- data.tar.gz: 3eaa5717c1bd08a4eda4bde312d120f18a95c7ed7a2297a603e351fed1bac93a
3
+ metadata.gz: f9881ffd064564475de2bbc1cd60aaf0cad09786e9437906d7957fcb8480c01c
4
+ data.tar.gz: 0a7963e22d25104777e600bc90e749c07e0d0c455a2bd7e5bfc55e477648c1fd
5
5
  SHA512:
6
- metadata.gz: 98abd64cec0b9ba9496de89d32aaf3598d4a7058e6e72e328fd9e8049d9ef9d2429dc0a9275b4e138c8b3a8dcde14ccb554b3b537fd00ae0ac6b06bd5a8b0e47
7
- data.tar.gz: 2ad84a36e17e170bed9f617e3f5b93bd9fff140dbf47c36490cf2df46e2222677cca04aab6542f0808492f20494766a76fa69b765cd4ddb9ed1557b6741f830b
6
+ metadata.gz: b72bd8f07a6d294f33bc67177ec52496860fe9f9e16cd07cb32c67d2688233bd11a1cd5d7186a4b8db2187c72aa91b13c1a8f19f987f93c572920cb213a54adf
7
+ data.tar.gz: 03573560b349ad41a2fac931a31bcadb51e9c11e4421d01ae0edf06e8ffa20d317c2d40a358dc6335dfad504a9d6148ec82501e5f347328788bd81aa404d6c23
data/CHANGELOG.md CHANGED
@@ -1,3 +1,27 @@
1
+ <a name="v2.107.0"></a>
2
+ ### v2.107.0 (2023-05-02)
3
+
4
+ <a name="v2.107.0.beta.1"></a>
5
+ ### v2.107.0.beta.1 (2023-05-01)
6
+
7
+ #### Features
8
+
9
+ * add index to webhook_executions pact_publication_id column ([37d1a4cf](/../../commit/37d1a4cf))
10
+ * update webmachine to support ruby 3 ([9bb014e6](/../../commit/9bb014e6))
11
+ * upgrade dry-validation gem in preparation for ruby 3 upgrade ([3b4b66bf](/../../commit/3b4b66bf))
12
+ * restructure logs from DeleteOverwrittenData to match CleanIncremental ([f11a9417](/../../commit/f11a9417))
13
+ * add branch_heads_branch_version_id_index ([b1b4cefb](/../../commit/b1b4cefb))
14
+
15
+ #### Bug Fixes
16
+
17
+ * **pacts for verification**
18
+ * do not allow empty string for provider version branch when it is required for calculating WIP/pending pacts ([412c4289](/../../commit/412c4289))
19
+
20
+ * fix error raised when clean selectors include a selector with a max age and a selector with a max age and a branch ([53b171bd](/../../commit/53b171bd))
21
+
22
+ * **can-i-deploy**
23
+ * correct logic for detecting when only the pacticipant name has been specified for a selector ([85bcdb35](/../../commit/85bcdb35))
24
+
1
25
  <a name="v2.106.0"></a>
2
26
  ### v2.106.0 (2023-01-31)
3
27
 
data/Gemfile CHANGED
@@ -2,6 +2,9 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
+ # While https://github.com/brandonhilkert/sucker_punch/pull/253 is outstanding
6
+ gem "sucker_punch", git: "https://github.com/pact-foundation/sucker_punch.git", ref: "fix/rename-is-singleton-class-method-2"
7
+
5
8
  gem "rake", "~>12.3.3"
6
9
  gem "sqlite3", "~>1.3"
7
10
  gem "conventional-changelog", "~>1.3"
@@ -4,14 +4,18 @@ include PactBroker::MigrationHelper
4
4
 
5
5
  Sequel.migration do
6
6
  up do
7
- alter_table(:latest_pact_publication_ids_for_consumer_versions) do
8
- add_index([:consumer_version_id], name: "latest_pp_ids_for_cons_ver_con_ver_id_ndx")
7
+ if !mysql?
8
+ alter_table(:latest_pact_publication_ids_for_consumer_versions) do
9
+ add_index([:consumer_version_id], name: "latest_pp_ids_for_cons_ver_con_ver_id_ndx")
10
+ end
9
11
  end
10
12
  end
11
13
 
12
14
  down do
13
- alter_table(:latest_pact_publication_ids_for_consumer_versions) do
14
- drop_index([:consumer_version_id], name: "latest_pp_ids_for_cons_ver_con_ver_id_ndx")
15
+ if !mysql?
16
+ alter_table(:latest_pact_publication_ids_for_consumer_versions) do
17
+ drop_index([:consumer_version_id], name: "latest_pp_ids_for_cons_ver_con_ver_id_ndx")
18
+ end
15
19
  end
16
20
  end
17
21
  end
@@ -0,0 +1,21 @@
1
+ require_relative "migration_helper"
2
+
3
+ include PactBroker::MigrationHelper
4
+
5
+ Sequel.migration do
6
+ up do
7
+ if !mysql?
8
+ alter_table(:branch_heads) do
9
+ add_index([:branch_version_id], name: "branch_heads_branch_version_id_index")
10
+ end
11
+ end
12
+ end
13
+
14
+ down do
15
+ if !mysql?
16
+ alter_table(:branch_heads) do
17
+ drop_index([:branch_version_id], name: "branch_heads_branch_version_id_index")
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ Sequel.migration do
2
+ up do
3
+ if !mysql?
4
+ alter_table(:webhook_executions) do
5
+ add_index([:pact_publication_id], name: "webhook_executions_pact_publication_id_index")
6
+ end
7
+ end
8
+ end
9
+
10
+ down do
11
+ if !mysql?
12
+ alter_table(:webhook_executions) do
13
+ drop_index([:pact_publication_id], name: "webhook_executions_pact_publication_id_index")
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,14 +1,29 @@
1
- require "reform"
2
- require "reform/form/dry"
3
-
4
- Reform::Form.class_eval do
5
- feature Reform::Form::Dry
6
- end
1
+ require "dry-validation"
2
+ require "pact_broker/api/contracts/dry_validation_macros"
3
+ require "pact_broker/api/contracts/dry_validation_methods"
4
+ require "pact_broker/api/contracts/dry_validation_errors_formatter"
5
+ require "pact_broker/messages"
6
+ require "pact_broker/hash_refinements"
7
7
 
8
8
  module PactBroker
9
9
  module Api
10
10
  module Contracts
11
- class BaseContract < Reform::Form
11
+ class BaseContract < Dry::Validation::Contract
12
+ include DryValidationMethods
13
+ extend DryValidationErrorsFormatter
14
+
15
+ using PactBroker::HashRefinements
16
+
17
+ # The entry method for all the Dry::Validation::Contract classes
18
+ # eg. MyContract.call(params)
19
+ # It takes the params (doesn't matter if they're string or symbol keys)
20
+ # executes the dry-validation validation, and formats the errors into the Pactflow format.
21
+ #
22
+ # @param [Hash] the parameters to validate
23
+ # @return [Hash] the validation errors to display to the user
24
+ def self.call(params)
25
+ format_errors(new.call(params&.symbolize_keys).errors)
26
+ end
12
27
  end
13
28
  end
14
29
  end
@@ -0,0 +1,34 @@
1
+ require "dry-validation"
2
+ require "pact_broker/messages"
3
+ require "pact_broker/project_root"
4
+ require "pact_broker/string_refinements"
5
+
6
+ module PactBroker
7
+ module Api
8
+ module Contracts
9
+ class CanIDeployQuerySchema < BaseContract
10
+ using PactBroker::StringRefinements
11
+
12
+ params do
13
+ required(:pacticipant).filled(:string)
14
+ required(:version).filled(:string)
15
+ optional(:to).filled(:string)
16
+ optional(:environment).filled(:string)
17
+ end
18
+
19
+ rule(:pacticipant).validate(:pacticipant_with_name_exists)
20
+ rule(:environment).validate(:environment_with_name_exists)
21
+
22
+ rule(:to, :environment) do
23
+ if provided?(values[:to]) && provided?(values[:environment])
24
+ base.failure(PactBroker::Messages.message("errors.validation.cannot_specify_tag_and_environment"))
25
+ end
26
+
27
+ if not_provided?(values[:to]) && not_provided?(values[:environment])
28
+ base.failure(PactBroker::Messages.message("errors.validation.must_specify_environment_or_tag"))
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,5 +1,7 @@
1
1
  require "pact_broker/string_refinements"
2
2
 
3
+ # Allow contracts to be accessed by name and configured/overridden for pf
4
+
3
5
  module PactBroker
4
6
  module Api
5
7
  module Contracts
@@ -0,0 +1,140 @@
1
+ require "pact_broker/api/contracts/base_contract"
2
+
3
+ module PactBroker
4
+ module Api
5
+ module Contracts
6
+ class ConsumerVersionSelectorContract < BaseContract
7
+ option :parent # the parent hash in which the ConsumerVersionSelector is embedded
8
+
9
+ BRANCH_KEYS = [:latest, :tag, :fallbackTag, :branch, :fallbackBranch, :matchingBranch, :mainBranch]
10
+ ENVIRONMENT_KEYS = [:environment, :deployed, :released, :deployedOrReleased]
11
+ ALL_KEYS = BRANCH_KEYS + ENVIRONMENT_KEYS + [:consumer]
12
+
13
+ json do
14
+ optional(:mainBranch).filled(included_in?: [true])
15
+ optional(:tag).filled(:str?)
16
+ optional(:branch).filled(:str?)
17
+ optional(:matchingBranch).filled(included_in?: [true])
18
+ optional(:latest).filled(included_in?: [true, false])
19
+ optional(:fallbackTag).filled(:str?)
20
+ optional(:fallbackBranch).filled(:str?)
21
+ optional(:consumer).filled(:str?)
22
+ optional(:deployed).filled(included_in?: [true])
23
+ optional(:released).filled(included_in?: [true])
24
+ optional(:deployedOrReleased).filled(included_in?: [true])
25
+ optional(:environment).filled(:str?)
26
+ end
27
+
28
+ rule(:consumer).validate(:not_blank_if_present)
29
+
30
+ # has minimum required params
31
+ rule(*ALL_KEYS) do
32
+ if not_provided?(values[:mainBranch]) &&
33
+ not_provided?(values[:tag]) &&
34
+ not_provided?(values[:branch]) &&
35
+ not_provided?(values[:environment]) &&
36
+ values[:matchingBranch] != true &&
37
+ values[:deployed] != true &&
38
+ values[:released] != true &&
39
+ values[:deployedOrReleased] != true &&
40
+ values[:latest] != true
41
+
42
+ base.failure(validation_message("pacts_for_verification_selector_required_params_missing"))
43
+ end
44
+ end
45
+
46
+ # mainBranch
47
+ rule(*ALL_KEYS) do
48
+ if values[:mainBranch] && values.slice(*ALL_KEYS - [:consumer, :mainBranch, :latest]).any?
49
+ base.failure(validation_message("pacts_for_verification_selector_main_branch_with_other_param_disallowed"))
50
+ end
51
+ end
52
+
53
+ # mainBranch/latest
54
+ rule(:mainBranch, :latest) do
55
+ if values[:mainBranch] && values[:latest] == false
56
+ base.failure(validation_message("pacts_for_verification_selector_main_branch_and_latest_false_disallowed"))
57
+ end
58
+ end
59
+
60
+ # matchingBranch
61
+ rule(*ALL_KEYS) do
62
+ if values[:matchingBranch] && values.slice(*ALL_KEYS - [:consumer, :matchingBranch]).any?
63
+ base.failure(validation_message("pacts_for_verification_selector_matching_branch_with_other_param_disallowed"))
64
+ end
65
+
66
+ if values[:matchingBranch] && not_provided?(parent[:providerVersionBranch])
67
+ base.failure(validation_message("pacts_for_verification_selector_matching_branch_requires_provider_version_branch"))
68
+ end
69
+ end
70
+
71
+ # tag and branch
72
+ rule(:tag, :branch) do
73
+ if values[:tag] && values[:branch]
74
+ base.failure(validation_message("pacts_for_verification_selector_tag_and_branch_disallowed"))
75
+ end
76
+ end
77
+
78
+ # branch/environment keys
79
+ rule(*ALL_KEYS) do
80
+ non_environment_fields = values.slice(*BRANCH_KEYS).keys.sort
81
+ environment_related_fields = values.slice(*ENVIRONMENT_KEYS).keys.sort
82
+
83
+ if (non_environment_fields.any? && environment_related_fields.any?)
84
+ base.failure("cannot specify the #{PactBroker::Messages.pluralize("field", non_environment_fields.count)} #{non_environment_fields.join("/")} with the #{PactBroker::Messages.pluralize("field", environment_related_fields.count)} #{environment_related_fields.join("/")}")
85
+ end
86
+ end
87
+
88
+ # fallbackTag
89
+ rule(:fallbackTag, :tag, :latest) do
90
+ if values[:fallbackTag] && !values[:latest]
91
+ base.failure(validation_message("pacts_for_verification_selector_fallback_tag"))
92
+ end
93
+
94
+ if values[:fallbackTag] && !values[:tag]
95
+ base.failure(validation_message("pacts_for_verification_selector_fallback_tag_requires_tag"))
96
+ end
97
+ end
98
+
99
+ # fallbackBranch
100
+ rule(:fallbackBranch, :branch, :latest) do
101
+ if values[:fallbackBranch] && !values[:branch]
102
+ base.failure(validation_message("pacts_for_verification_selector_fallback_branch_requires_branch"))
103
+ end
104
+
105
+
106
+ if values[:fallbackBranch] && values[:latest] == false
107
+ base.failure(validation_message("pacts_for_verification_selector_fallback_branch_and_latest_false_disallowed"))
108
+ end
109
+ end
110
+
111
+ # branch/latest
112
+ rule(:branch, :latest) do
113
+ if values[:branch] && values[:latest] == false
114
+ base.failure(validation_message("pacts_for_verification_selector_branch_and_latest_false_disallowed"))
115
+ end
116
+ end
117
+
118
+ # environment
119
+ rule(:environment) do
120
+ validate_environment_with_name_exists(value, key) if provided?(value)
121
+ end
122
+
123
+ # deployed, released, deployedOrReleased
124
+ rule(:deployed, :released, :deployedOrReleased) do
125
+ if values[:deployed] && values[:released]
126
+ base.failure(validation_message("pacts_for_verification_selector_deployed_and_released_disallowed"))
127
+ end
128
+
129
+ if values[:deployed] && values[:deployedOrReleased]
130
+ base.failure(validation_message("pacts_for_verification_selector_deployed_and_deployed_or_released_disallowed"))
131
+ end
132
+
133
+ if values[:released] && values[:deployedOrReleased]
134
+ base.failure(validation_message("pacts_for_verification_selector_released_and_deployed_or_released_disallowed"))
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,50 @@
1
+ require "pact_broker/error"
2
+
3
+ module PactBroker
4
+ module Api
5
+ module Contracts
6
+ module DryValidationErrorsFormatter
7
+
8
+ # Formats the dry validation errors in the expected PactBroker error format of { :key => ["errors"] }
9
+ # where there are no nested hashes.
10
+ # @param [Dry::Validation::MessageSet] errors
11
+ # @return [Hash]
12
+ def format_errors(errors)
13
+ errors.each_with_object({}) do | error, errors_hash |
14
+ integers = error.path.select{ | k | k.is_a?(Integer) }
15
+
16
+ if integers.size > 1
17
+ raise PactBroker::Error, "Cannot currently format an error message with more than one index"
18
+ end
19
+
20
+ if integers.empty?
21
+ key = error.path == [nil] ? nil : error.path.join(".").to_sym
22
+ add_error(errors_hash, key, error.text)
23
+ else
24
+ add_indexed_error(errors_hash, error)
25
+ end
26
+ end
27
+ end
28
+
29
+ # @private
30
+ def add_error(errors_hash, key, text)
31
+ errors_hash[key] ||= []
32
+ errors_hash[key] << text
33
+ end
34
+
35
+ # @private
36
+ def add_indexed_error(errors_hash, error)
37
+ error_path_classes = error.path.collect(&:class)
38
+ if error_path_classes == [Symbol, Integer, Symbol]
39
+ add_error(errors_hash, error.path.first, "#{error.path.last} #{error.text} (at index #{error.path[1]})")
40
+ elsif error_path_classes == [Symbol, Integer]
41
+ add_error(errors_hash, error.path.first, "#{error.text} (at index #{error.path[1]})")
42
+ else
43
+ # Don't have any usecases for this - will deal with it when it happens
44
+ raise PactBroker::Error, "Cannot currently format an error message with path classes #{error_path_classes}"
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,79 @@
1
+ require "pact_broker/api/contracts/dry_validation_methods"
2
+
3
+ Dry::Validation.register_macro(:not_multiple_lines) do
4
+ PactBroker::Api::Contracts::DryValidationMethods.validate_not_multiple_lines(value, key)
5
+ end
6
+
7
+ Dry::Validation.register_macro(:no_spaces_if_present) do
8
+ PactBroker::Api::Contracts::DryValidationMethods.validate_no_spaces_if_present(value, key)
9
+ end
10
+
11
+ Dry::Validation.register_macro(:not_blank_if_present) do
12
+ PactBroker::Api::Contracts::DryValidationMethods.validate_not_blank_if_present(value, key)
13
+ end
14
+
15
+ Dry::Validation.register_macro(:array_values_not_blank_if_any) do
16
+ value&.each_with_index do | item, index |
17
+ PactBroker::Api::Contracts::DryValidationMethods.validate_not_blank_if_present(item, key(path.keys + [index]))
18
+ end
19
+ end
20
+
21
+ Dry::Validation.register_macro(:valid_url_if_present) do
22
+ PactBroker::Api::Contracts::DryValidationMethods.validate_valid_url(value, key)
23
+ end
24
+
25
+ Dry::Validation.register_macro(:valid_version_number) do
26
+ PactBroker::Api::Contracts::DryValidationMethods.validate_version_number(value, key)
27
+ end
28
+
29
+ Dry::Validation.register_macro(:pacticipant_with_name_exists) do
30
+ PactBroker::Api::Contracts::DryValidationMethods.validate_pacticipant_with_name_exists(value, key)
31
+ end
32
+
33
+ Dry::Validation.register_macro(:environment_with_name_exists) do
34
+ PactBroker::Api::Contracts::DryValidationMethods.validate_environment_with_name_exists(value, key)
35
+ end
36
+
37
+ # Validate each object in an array with the specified contract,
38
+ # and merge the errors into the appropriate path in the parent
39
+ # validation results.
40
+ # eg.
41
+ # rule(:myChildArray).validate(validate_each_with_contract: MyChildContract)
42
+ #
43
+ # If the child contract defines a option called `parent` then it can access the parent
44
+ # hash for validation rules that need to work across the levels.
45
+ # eg. ConsumerVersionSelectorContract for the matchingBranch rule
46
+ #
47
+ # Will not add any errors if the array is nil
48
+ Dry::Validation.register_macro(:validate_each_with_contract) do |macro:|
49
+ value&.each_with_index do | item, index |
50
+ child_contract_class = macro.args[0]
51
+ messages = child_contract_class.new(parent: values).call(item).errors(full: true).to_hash.values.flatten
52
+ messages.each do | message |
53
+ key(path.keys + [index]).failure(message)
54
+ end
55
+ end
56
+ end
57
+
58
+ # Validate a child node with the specified contract,
59
+ # and merge the errors into the appropriate path in the parent
60
+ # validation results.
61
+ # eg.
62
+ # rule(:myChildHash).validate(validate_with_contract: MyChildContract)
63
+ #
64
+ # If the child contract defines a option called `parent` then it can access the parent
65
+ # hash for validation rules that need to work across the levels.
66
+ # eg. ConsumerVersionSelectorContract for the matchingBranch rule
67
+ #
68
+ # Will not add any errors if the value is nil
69
+ Dry::Validation.register_macro(:validate_with_contract) do |macro:|
70
+ if value
71
+ child_contract_class = macro.args[0]
72
+ errors = child_contract_class.new(parent: values).call(value).errors.to_hash
73
+ errors.each do | key, messages |
74
+ messages.each do | message |
75
+ key(path.keys + [key]).failure(message)
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,71 @@
1
+ require "pact_broker/api/contracts/validation_helpers"
2
+
3
+ module PactBroker
4
+ module Api
5
+ module Contracts
6
+ module DryValidationMethods
7
+ extend self
8
+
9
+ def validation_message(key, params = {})
10
+ PactBroker::Messages.validation_message(key, params)
11
+ end
12
+
13
+ def provided?(value)
14
+ ValidationHelpers.provided?(value)
15
+ end
16
+
17
+ def not_provided?(value)
18
+ ValidationHelpers.not_provided?(value)
19
+ end
20
+
21
+ def validate_version_number(value, key)
22
+ if !PactBroker::Api::Contracts::ValidationHelpers.valid_version_number?(value)
23
+ key.failure(PactBroker::Messages.validation_message("invalid_version_number", value: value))
24
+ end
25
+ end
26
+
27
+ def validate_url(value, key)
28
+ if PactBroker::Api::Contracts::ValidationHelpers.valid_url?(value)
29
+ key.failure(PactBroker::Messages.validation_message("invalid_url"))
30
+ end
31
+ end
32
+
33
+ def validate_pacticipant_with_name_exists(value, key)
34
+ if ValidationHelpers.provided?(value) && !ValidationHelpers.pacticipant_with_name_exists?(value)
35
+ key.failure(PactBroker::Messages.validation_message("pacticipant_with_name_not_found"))
36
+ end
37
+ end
38
+
39
+ def validate_environment_with_name_exists(value, key)
40
+ if ValidationHelpers.provided?(value) && !ValidationHelpers.environment_with_name_exists?(value)
41
+ key.failure(PactBroker::Messages.validation_message("environment_not_found", value: value))
42
+ end
43
+ end
44
+
45
+ def validate_not_blank_if_present(value, key)
46
+ if value && ValidationHelpers.blank?(value)
47
+ key.failure(PactBroker::Messages.validation_message("blank"))
48
+ end
49
+ end
50
+
51
+ def validate_no_spaces_if_present(value, key)
52
+ if value && ValidationHelpers.includes_space?(value)
53
+ key.failure(PactBroker::Messages.validation_message("no_spaces"))
54
+ end
55
+ end
56
+
57
+ def validate_not_multiple_lines(value, key)
58
+ if value && ValidationHelpers.multiple_lines?(value)
59
+ key.failure(PactBroker::Messages.validation_message("single_line"))
60
+ end
61
+ end
62
+
63
+ def validate_valid_url(value, key)
64
+ if value && !ValidationHelpers.valid_url?(value)
65
+ key.failure(PactBroker::Messages.validation_message("invalid_url"))
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -1,48 +1,34 @@
1
- require "dry-validation"
2
- require "pact_broker/api/contracts/dry_validation_workarounds"
3
- require "pact_broker/api/contracts/dry_validation_predicates"
4
- require "pact_broker/messages"
1
+ require "pact_broker/api/contracts/base_contract"
5
2
 
6
3
  module PactBroker
7
4
  module Api
8
5
  module Contracts
9
- class EnvironmentSchema
10
- extend DryValidationWorkarounds
11
- extend PactBroker::Messages
12
- using PactBroker::HashRefinements
13
-
14
- SCHEMA = Dry::Validation.Schema do
15
- configure do
16
- predicates(DryValidationPredicates)
17
- config.messages_file = File.expand_path("../../../locale/en.yml", __FILE__)
18
- end
19
- required(:name).filled(:str?, :single_line?, :no_spaces?)
20
- optional(:displayName).maybe(:str?, :single_line?)
6
+ class EnvironmentSchema < BaseContract
7
+ json do
8
+ optional(:uuid)
9
+ required(:name).filled(:string)
10
+ optional(:displayName).maybe(:string)
21
11
  required(:production).filled(included_in?: [true, false])
22
- optional(:contacts).each do
23
- schema do
24
- required(:name).filled(:str?, :single_line?)
25
- optional(:details).schema do
26
- end
27
- end
12
+ optional(:contacts).array(:hash) do
13
+ required(:name).filled(:string)
14
+ optional(:details).hash
28
15
  end
29
16
  end
30
17
 
31
- def self.call(params_with_string_keys)
32
- params = params_with_string_keys&.symbolize_keys
33
- results = select_first_message(flatten_indexed_messages(SCHEMA.call(params).messages(full: true)))
34
- validate_name(params, results)
35
- results
36
- end
18
+ rule(:name).validate(:not_multiple_lines, :no_spaces_if_present)
19
+ rule(:displayName).validate(:not_multiple_lines)
37
20
 
38
- def self.validate_name(params, results)
39
- if (environment_with_same_name = PactBroker::Deployments::EnvironmentService.find_by_name(params[:name]))
40
- if environment_with_same_name.uuid != params[:uuid]
41
- results[:name] ||= []
42
- results[:name] << message("errors.validation.environment_name_must_be_unique", name: params[:name])
21
+ rule(:name, :uuid) do
22
+ if (environment_with_same_name = PactBroker::Deployments::EnvironmentService.find_by_name(values[:name]))
23
+ if environment_with_same_name.uuid != values[:uuid]
24
+ key.failure(validation_message("environment_name_must_be_unique", name: values[:name]))
43
25
  end
44
26
  end
45
27
  end
28
+
29
+ rule(:contacts).each do
30
+ validate_not_multiple_lines(value[:name], key(path.keys + [:name]))
31
+ end
46
32
  end
47
33
  end
48
34
  end
@@ -3,25 +3,12 @@ require "pact_broker/api/contracts/pacticipant_schema"
3
3
  module PactBroker
4
4
  module Api
5
5
  module Contracts
6
- class PacticipantCreateSchema
7
- extend DryValidationWorkarounds
8
- extend PactBroker::Messages
9
- using PactBroker::HashRefinements
10
-
11
- SCHEMA = Dry::Validation.Schema do
12
- configure do
13
- predicates(DryValidationPredicates)
14
- config.messages_file = File.expand_path("../../../locale/en.yml", __FILE__)
15
- end
16
- required(:name).filled(:str?, :single_line?)
6
+ class PacticipantCreateSchema < PactBroker::Api::Contracts::PacticipantSchema
7
+ json do
8
+ required(:name).filled(:string)
17
9
  end
18
10
 
19
- def self.call(params_with_string_keys)
20
- params = params_with_string_keys&.symbolize_keys
21
- update_errors = PacticipantSchema::SCHEMA.call(params).messages(full: true)
22
- create_errors = SCHEMA.call(params).messages(full: true)
23
- select_first_message(flatten_indexed_messages(update_errors.merge(create_errors)))
24
- end
11
+ rule(:name).validate(:not_blank_if_present, :not_multiple_lines)
25
12
  end
26
13
  end
27
14
  end