pact_broker 2.106.0 → 2.107.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 (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