Class: PactBroker::Api::Contracts::PactsForVerificationJSONQuerySchema

Inherits:
Object
  • Object
show all
Extended by:
DryValidationWorkarounds, Messages
Defined in:
lib/pact_broker/api/contracts/pacts_for_verification_json_query_schema.rb

Constant Summary collapse

BRANCH_KEYS =
[:latest, :tag, :fallbackTag, :branch, :fallbackBranch, :matchingBranch]
ENVIRONMENT_KEYS =
[:environment, :deployed, :released, :deployedOrReleased]
ALL_KEYS =
BRANCH_KEYS + ENVIRONMENT_KEYS
SCHEMA =
Dry::Validation.Schema do
  configure do
    predicates(DryValidationPredicates)
    config.messages_file = File.expand_path("../../../locale/en.yml", __FILE__)
  end
  optional(:providerVersionTags).maybe(:array?)
  optional(:consumerVersionSelectors).each do
    schema do
      # configure do
      #   def self.messages
      #     super.merge(en: { errors: { fallbackTagMustBeForLatest: 'can only be set if latest=true' }})
      #   end
      # end

      optional(:mainBranch).filled(included_in?: [true])
      optional(:tag).filled(:str?)
      optional(:branch).filled(:str?)
      optional(:matchingBranch).filled(included_in?: [true])
      optional(:latest).filled(included_in?: [true, false])
      optional(:fallbackTag).filled(:str?)
      optional(:fallbackBranch).filled(:str?)
      optional(:consumer).filled(:str?, :not_blank?)
      optional(:deployed).filled(included_in?: [true])
      optional(:released).filled(included_in?: [true])
      optional(:deployedOrReleased).filled(included_in?: [true])
      optional(:environment).filled(:str?, :environment_with_name_exists?)

      # rule(fallbackTagMustBeForLatest: [:fallbackTag, :latest]) do | fallback_tag, latest |
      #   fallback_tag.filled?.then(latest.eql?(true))
      # end
    end
  end
  optional(:includePendingStatus).filled(included_in?: [true, false])
  optional(:includeWipPactsSince).filled(:date?)
end

Class Method Summary collapse

Methods included from DryValidationWorkarounds

flatten_array_of_hashes, flatten_indexed_messages, is_indexed_structure?, select_first_message

Methods included from Messages

message, pluralize, potential_duplicate_pacticipant_message, validation_message

Class Method Details

.add_cross_field_validation_errors(params, results) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/pact_broker/api/contracts/pacts_for_verification_json_query_schema.rb', line 65

def self.add_cross_field_validation_errors(params, results)
  # This is a ducking joke. Need to get rid of dry-validation
  if params[:consumerVersionSelectors].is_a?(Array)
    errors = params[:consumerVersionSelectors].each_with_index.flat_map do | selector, index |
      validate_consumer_version_selector(selector, index, params)
    end
    if errors.any?
      results[:consumerVersionSelectors] ||= []
      results[:consumerVersionSelectors].concat(errors)
    end
  end
end

.call(params) ⇒ Object



58
59
60
61
62
63
# File 'lib/pact_broker/api/contracts/pacts_for_verification_json_query_schema.rb', line 58

def self.call(params)
  symbolized_params = params&.symbolize_keys
  results = select_first_message(flatten_indexed_messages(SCHEMA.call(symbolized_params).messages(full: true)))
  add_cross_field_validation_errors(symbolized_params, results)
  results
end

.not_provided?(value) ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
# File 'lib/pact_broker/api/contracts/pacts_for_verification_json_query_schema.rb', line 78

def self.not_provided?(value)
  value.nil? || value.blank?
end

.validate_consumer_version_selector(selector, index, params) ⇒ Object

when setting a tag, latest=true and latest=false are both valid when setting the branch, it doesn’t make sense to verify all pacts for a branch, so latest is not required, but cannot be set to false rubocop: disable Metrics/CyclomaticComplexity, Metrics/MethodLength



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/pact_broker/api/contracts/pacts_for_verification_json_query_schema.rb', line 86

def self.validate_consumer_version_selector(selector, index, params)
  errors = []

  if selector[:fallbackTag] && !selector[:latest]
    errors << "fallbackTag can only be set if latest is true (at index #{index})"
  end

  if selector[:fallbackBranch] && selector[:latest] == false
    errors << "fallbackBranch can only be set if latest is true (at index #{index})"
  end

  if not_provided?(selector[:mainBranch]) &&
      not_provided?(selector[:tag]) &&
      not_provided?(selector[:branch]) &&
      not_provided?(selector[:environment]) &&
      selector[:matchingBranch] != true &&
      selector[:deployed] != true &&
      selector[:released] != true &&
      selector[:deployedOrReleased] != true &&
      selector[:latest] != true
    errors << "must specify a value for environment or tag or branch, or specify mainBranch=true, matchingBranch=true, latest=true, deployed=true, released=true or deployedOrReleased=true (at index #{index})"
  end

  if selector[:mainBranch] && selector.slice(*ALL_KEYS - [:consumer, :mainBranch]).any?
    errors << "cannot specify mainBranch=true with any other criteria apart from consumer (at index #{index})"
  end

  if selector[:matchingBranch] && selector.slice(*ALL_KEYS - [:consumer, :matchingBranch]).any?
    errors << "cannot specify matchingBranch=true with any other criteria apart from consumer (at index #{index})"
  end

  if selector[:tag] && selector[:branch]
    errors << "cannot specify both a tag and a branch (at index #{index})"
  end

  if selector[:fallbackBranch] && !selector[:branch]
    errors << "a branch must be specified when a fallbackBranch is specified (at index #{index})"
  end

  if selector[:fallbackTag] && !selector[:tag]
    errors << "a tag must be specified when a fallbackTag is specified (at index #{index})"
  end

  if selector[:branch] && selector[:latest] == false
    errors << "cannot specify a branch with latest=false (at index #{index})"
  end

  if selector[:deployed] && selector[:released]
    errors << "cannot specify both deployed=true and released=true (at index #{index})"
  end

  if selector[:deployed] && selector[:deployedOrReleased]
    errors << "cannot specify both deployed=true and deployedOrReleased=true (at index #{index})"
  end

  if selector[:released] && selector[:deployedOrReleased]
    errors << "cannot specify both released=true and deployedOrReleased=true (at index #{index})"
  end

  if selector[:matchingBranch] && not_provided?(params[:providerVersionBranch])
    errors << "the providerVersionBranch must be specified when the selector matchingBranch=true is used (at index #{index})"
  end

  non_environment_fields = selector.slice(*BRANCH_KEYS).keys.sort
  environment_related_fields = selector.slice(*ENVIRONMENT_KEYS).keys.sort

  if (non_environment_fields.any? && environment_related_fields.any?)
    errors << "cannot specify the #{pluralize("field", non_environment_fields.count)} #{non_environment_fields.join("/")} with the #{pluralize("field", environment_related_fields.count)} #{environment_related_fields.join("/")} (at index #{index})"
  end

  errors
end