class PactBroker::Matrix::DeploymentStatusSummary

Attributes

all_rows[R]
dummy_selectors[R]
query_results[R]

Public Class Methods

new(query_results) click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 14
def initialize(query_results)
  @query_results = query_results
  @all_rows = query_results.rows
  @dummy_selectors = create_dummy_selectors
end

Public Instance Methods

counts() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 20
def counts
  {
    success: considered_rows.count(&:success),
    failed: considered_rows.count { |row| row.success == false },
    unknown: required_integrations_without_a_row.count + considered_rows.count { |row| row.success.nil? },
    ignored: resolved_ignore_selectors.any? ? ignored_rows.count : nil
  }.compact
end
deployable?() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 29
def deployable?
  return false if considered_specified_selectors_that_do_not_exist.any?
  return nil if considered_rows.any?{ |row| row.success.nil? }
  return nil if required_integrations_without_a_row.any?
  considered_rows.all?(&:success) # true if considered_rows is empty
end
reasons() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 36
def reasons
  error_messages.any? ? warning_messages + error_messages  : warning_messages + success_messages
end

Private Instance Methods

bad_practice_warnings() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 62
def bad_practice_warnings
  warnings = []

  if resolved_selectors.count(&:specified?) == 1 && no_to_tag_or_branch_or_environment_specified?
    warnings << NoEnvironmentSpecified.new
  end

  if selector_without_pacticipant_version_number_specified?
    warnings << SelectorWithoutPacticipantVersionNumberSpecified.new
  end

  warnings
end
considered_specified_selectors_that_do_not_exist() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 102
def considered_specified_selectors_that_do_not_exist
  resolved_selectors.select(&:consider?).select(&:specified_version_that_does_not_exist?)
end
create_dummy_selectors() click to toggle source

When the user has not specified a version of the provider (eg no ‘latest’ and/or ‘tag’, which means ‘all versions’) so the “add inferred selectors” code in the Matrix::Repository has not run, we may end up with considered_rows for which we do not have a selector. To solve this, create dummy selectors from the row and integration data.

# File lib/pact_broker/matrix/deployment_status_summary.rb, line 221
def create_dummy_selectors
  (dummy_selectors_from_considered_rows + dummy_selectors_from_integrations).uniq
end
dummy_selector_for(pacticipant_name) click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 213
def dummy_selector_for(pacticipant_name)
  dummy_selectors.find{ | s| s.pacticipant_name == pacticipant_name }
end
dummy_selectors_from_considered_rows() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 233
def dummy_selectors_from_considered_rows
  considered_rows.collect do | row |
    dummy_consumer_selector = ResolvedSelector.for_pacticipant_and_version(row.consumer, row.consumer_version, {}, :inferred, false)
    dummy_provider_selector = row.provider_version ?
      ResolvedSelector.for_pacticipant_and_version(row.provider, row.provider_version, {}, :inferred, false) :
      ResolvedSelector.for_pacticipant(row.provider, {}, :inferred, false)
    [dummy_consumer_selector, dummy_provider_selector]
  end.flatten
end
dummy_selectors_from_integrations() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 225
def dummy_selectors_from_integrations
  integrations.collect do | row |
    dummy_consumer_selector = ResolvedSelector.for_pacticipant(row.consumer, {}, :inferred, false)
    dummy_provider_selector = ResolvedSelector.for_pacticipant(row.provider, {}, :inferred, false)
    [dummy_consumer_selector, dummy_provider_selector]
  end.flatten
end
error_messages() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 44
def error_messages
  @error_messages ||= begin
    messages = []
    messages.concat(specified_selectors_do_not_exist_messages)
    if messages.empty?
      messages.concat(missing_reasons)
      messages.concat(failure_messages)
      messages.concat(not_ever_verified_reasons)
    end
    messages.uniq
  end
end
failure_messages() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 118
def failure_messages
  considered_rows.select{ |row| row.success == false }.collect { | row | VerificationFailed.new(*selectors_for(row)) }
end
log_required_integrations_without_a_row_occurred(integrations) click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 163
def log_required_integrations_without_a_row_occurred integrations
  logger.info("required_integrations_without_a_row returned non empty", integrations: integrations, considered_rows: considered_rows)
end
missing_reasons() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 171
def missing_reasons
  required_integrations_without_a_row.collect do | integration |
    pact_not_verified_by_required_provider_version(integration)
  end.flatten
end
missing_specified_version_reasons(selectors) click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 177
def missing_specified_version_reasons(selectors)
  selectors.collect(&:version_does_not_exist_description)
end
more_than_one_selector_specified?() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 90
def more_than_one_selector_specified?
  # If only the pacticipant name is specified, it can't be a can-i-deploy query, must be a matrix UI query
  resolved_selectors
    .select(&:specified?)
    .reject(&:only_pacticipant_name_specified?)
    .any?
end
no_to_tag_or_branch_or_environment_specified?() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 98
def no_to_tag_or_branch_or_environment_specified?
  !(query_results.options[:tag] || query_results.options[:environment_name] || query_results.options[:main_branch])
end
not_ever_verified_reasons() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 114
def not_ever_verified_reasons
  considered_rows.select{ | row | row.success.nil? }.collect{ |row | pact_not_ever_verified_by_provider(row) }
end
pact_not_ever_verified_by_provider(row) click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 185
def pact_not_ever_verified_by_provider(row)
  PactNotEverVerifiedByProvider.new(*selectors_for(row))
end
pact_not_verified_by_required_provider_version(integration) click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 181
def pact_not_verified_by_required_provider_version(integration)
  PactNotVerifiedByRequiredProviderVersion.new(*selectors_for(integration))
end
report_missing_interaction_verifications(messages) click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 257
def report_missing_interaction_verifications(messages)
  logger.warn("Interactions missing verifications", messages)
end
required_integrations_without_a_row() click to toggle source

For deployment, the consumer requires the provider, but the provider does not require the consumer This method tells us which providers are missing. Technically, it tells us which integrations do not have a row because the pact that belongs to the consumer version has in fact been verified, but not by the provider version specified in the query (because left outer join)

Imagine query for deploying Foo v3 to prod with the following matrix: Foo v2 -> Bar v1 (latest prod) [this line not included because CV doesn’t match] Foo v3 -> Bar v2 [this line not included because PV doesn’t match]

No matrix considered_rows would be returned. This method identifies that we have no row for the Foo -> Bar integration, and therefore cannot deploy Foo. However, if we were to try and deploy the provider, Bar, that would be ok as Bar does not rely on Foo, so this method would not return that integration. UPDATE: The matrix query now returns a row with blank provider version/verification fields so the above comment is now redundant. I’m not sure if this piece of code can ever return a list with anything in it any more. Will log it for a while and see.

# File lib/pact_broker/matrix/deployment_status_summary.rb, line 155
def required_integrations_without_a_row
  @required_integrations_without_a_row ||= begin
    integrations.select(&:required?).select do | integration |
      !row_exists_for_integration(integration)
    end
  end.tap { |it| log_required_integrations_without_a_row_occurred(it) if it.any? }
end
row_exists_for_integration(integration) click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 167
def row_exists_for_integration(integration)
  all_rows.find { | row | integration.matches_pacticipant_ids?(row) }
end
selector_for(pacticipant_name, pacticipant_version_number) click to toggle source

Find the resolved version selector that caused the matrix row with the specified pacticipant name and version number to be returned in the query.

@return [PactBroker::Matrix::ResolvedSelector]

# File lib/pact_broker/matrix/deployment_status_summary.rb, line 193
def selector_for(pacticipant_name, pacticipant_version_number)
  found = resolved_selectors.select{ | s| s.pacticipant_name == pacticipant_name }

  if found.size == 1
    found.first
  elsif pacticipant_version_number
    found.find{ |s| s.pacticipant_version_number == pacticipant_version_number } || dummy_selector_for(pacticipant_name)
  else
    dummy_selector_for(pacticipant_name)
  end
end
selector_without_pacticipant_version_number_specified?() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 76
def selector_without_pacticipant_version_number_specified?
  # If only the pacticipant name is specified, it can't be a can-i-deploy query, must be a matrix UI query
  if resolved_selectors.select(&:specified?).reject(&:only_pacticipant_name_specified?).any?
    # There should be at least one selector with a version number specified
    resolved_selectors
      .select(&:specified?)
      .select(&:pacticipant_version_specified_in_original_selector?)
      .empty?
  else
    false
  end
end
selectors_for(row_or_integration) click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 205
def selectors_for(row_or_integration)
  if row_or_integration.respond_to?(:consumer_version_number)
    [selector_for(row_or_integration.consumer_name, row_or_integration.consumer_version_number), selector_for(row_or_integration.provider_name, row_or_integration.provider_version_number)]
  else
    [selector_for(row_or_integration.consumer_name, nil), selector_for(row_or_integration.provider_name, nil)]
  end
end
specified_selectors_do_not_exist_messages() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 110
def specified_selectors_do_not_exist_messages
  specified_selectors_that_do_not_exist.select(&:consider?).collect { | selector | SpecifiedVersionDoesNotExist.new(selector) }
end
specified_selectors_that_do_not_exist() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 106
def specified_selectors_that_do_not_exist
  resolved_selectors.select(&:specified_version_that_does_not_exist?)
end
success_messages() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 122
def success_messages
  if considered_rows.all?(&:success) && required_integrations_without_a_row.empty?
    if considered_rows.any?
      [Successful.new]
    else
      [NoDependenciesMissing.new]
    end
  else
    []
  end.flatten.uniq
end
warning_messages() click to toggle source
# File lib/pact_broker/matrix/deployment_status_summary.rb, line 57
def warning_messages
  resolved_ignore_selectors.select(&:pacticipant_or_version_does_not_exist?).collect { | s | IgnoreSelectorDoesNotExist.new(s) } +
    bad_practice_warnings
end
warnings_for_missing_interactions() click to toggle source

experimental

# File lib/pact_broker/matrix/deployment_status_summary.rb, line 244
def warnings_for_missing_interactions
  considered_rows.select(&:success).collect do | row |
    begin
      if row.verification.interactions_missing_test_results.any? && !row.verification.all_interactions_missing_test_results?
        InteractionsMissingVerifications.new(selector_for(row.consumer_name, row.consumer_version_number), selector_for(row.provider_name, row.provider_version_number), row.verification.interactions_missing_test_results)
      end
    rescue StandardError => e
      logger.warn("Error determining if there were missing interaction verifications", e)
      nil
    end
  end.compact.tap { |it| report_missing_interaction_verifications(it) if it.any? }
end