class Pact::ProviderVerifier::App

Constants

EMPTY_ARRAY
PROXY_PACT_HELPER

Attributes

consumer_version_selectors[R]
consumer_version_tags[R]
options[R]
pact_urls[R]
provider_version_branch[R]
provider_version_tags[R]
publish_verification_results[R]

Public Class Methods

call(pact_urls, options) click to toggle source
# File lib/pact/provider_verifier/app.rb, line 33
def self.call pact_urls, options
  new(pact_urls, options).call
end
new(pact_urls, options = {}) click to toggle source
# File lib/pact/provider_verifier/app.rb, line 23
def initialize pact_urls, options = {}
  @pact_urls = pact_urls
  @options = options
  @consumer_version_tags = options.consumer_version_tag || EMPTY_ARRAY
  @provider_version_tags = merge_provider_version_tags(options)
  @provider_version_branch = options.provider_version_branch
  @consumer_version_selectors = parse_consumer_version_selectors(options.consumer_version_selector || EMPTY_ARRAY)
  @publish_verification_results = options.publish_verification_results || ENV['PACT_BROKER_PUBLISH_VERIFICATION_RESULTS'] == 'true'
end

Public Instance Methods

call() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 37
def call
  setup
  warn_empty_pact_set
  wait_until_provider_available
  pacts_pass_verification?
end

Private Instance Methods

all_pact_urls() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 198
def all_pact_urls
  @all_pact_urls ||= begin
    http_client_options = {
      username: options.broker_username || ENV['PACT_BROKER_USERNAME'],
      password: options.broker_password || ENV['PACT_BROKER_PASSWORD'],
      token: options.broker_token || ENV['PACT_BROKER_TOKEN'],
      verbose: verbose?
    }
    opts = {
      enable_pending: options.enable_pending,
      include_wip_pacts_since: options.include_wip_pacts_since
    }
    AggregatePactConfigs.call(
      pact_urls,
      options.provider,
      consumer_version_tags,
      consumer_version_selectors,
      provider_version_branch,
      provider_version_tags,
      options.pact_broker_base_url || ENV['PACT_BROKER_BASE_URL'],
      http_client_options,
      opts)
  end
end
apply_custom_middleware(app) click to toggle source
# File lib/pact/provider_verifier/app.rb, line 158
def apply_custom_middleware app
  CustomMiddleware.descendants.inject(app) do | app, clazz |
    Pact.configuration.output_stream.puts "INFO: Adding custom middleware #{clazz}"
    clazz.new(app)
  end
end
configure_custom_header_middleware(rack_reverse_proxy) click to toggle source
# File lib/pact/provider_verifier/app.rb, line 125
def configure_custom_header_middleware rack_reverse_proxy
  if options.custom_provider_header
    Pact::ProviderVerifier::AddHeaderMiddlware.new(rack_reverse_proxy, parse_header)
  else
    rack_reverse_proxy
  end
end
configure_custom_middleware(app) click to toggle source
# File lib/pact/provider_verifier/app.rb, line 133
def configure_custom_middleware app
  if options.custom_middleware && options.custom_middleware.any?
    require_custom_middlware
    apply_custom_middleware(app)
  else
    app
  end
end
configure_output() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 103
def configure_output
  if options[:format] && !options[:out]
    # Don't want to mess up the JSON parsing with messages to stdout, so send it to stderr
    require 'pact/configuration'
    Pact.configuration.output_stream = Pact.configuration.error_stream
  end
  Pact.configuration.log_dir = options.log_dir if options.log_dir
  Pact.configuration.logger.level = Kernel.const_get('Logger').const_get(options.log_level.upcase) if options.log_level
end
configure_provider_states_header_removal_middleware(app) click to toggle source
# File lib/pact/provider_verifier/app.rb, line 142
def configure_provider_states_header_removal_middleware app
  ProviderStates::RemoveProviderStatesHeaderMiddleware.new(app)
end
configure_reverse_proxy() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 113
def configure_reverse_proxy
  provider_base_url = options.provider_base_url
  Rack::ReverseProxy.new do
    reverse_proxy_options(
      verify_mode: OpenSSL::SSL::VERIFY_NONE,
      preserve_host: true,
      x_forwarded_headers: false
    )
    reverse_proxy %r{(.*)}, "#{provider_base_url}$1"
  end
end
configure_service_provider() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 73
def configure_service_provider
  # Have to declare these locally as the class scope gets lost within the block
  application = configure_reverse_proxy
  application = configure_provider_states_header_removal_middleware(application)
  application = configure_custom_middleware(application)
  application = configure_custom_header_middleware(application)

  this = self

  Pact.service_provider "Running Provider Application" do
    app do
      application
    end

    if this.options.provider_app_version
      app_version this.options.provider_app_version
    end

    if this.options.provider_version_branch
      app_version_branch this.options.provider_version_branch
    end

    if this.provider_version_tags.any?
      app_version_tags this.provider_version_tags
    end

    publish_verification_results this.publish_verification_results
  end
end
custom_provider_headers_for_env_var() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 240
def custom_provider_headers_for_env_var
  if options.custom_provider_header && options.custom_provider_header.any?
    options.custom_provider_header.join("\n")
  end
end
merge_provider_version_tags(options) click to toggle source
# File lib/pact/provider_verifier/app.rb, line 257
def merge_provider_version_tags(options)
  (options.provider_version_tag || EMPTY_ARRAY) + (options.tag_with_git_branch ? [Git.branch] : EMPTY_ARRAY)
end
pacts_pass_verification?() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 46
def pacts_pass_verification?
  return false if all_pact_urls.empty? && options.fail_if_no_pacts_found

  exit_statuses = all_pact_urls.collect do |pact_uri|
    verify_pact pact_uri
  end

  exit_statuses.all?{ | status | status == 0 }
end
parse_consumer_version_selectors(consumer_version_selectors) click to toggle source
# File lib/pact/provider_verifier/app.rb, line 253
def parse_consumer_version_selectors consumer_version_selectors
  consumer_version_selectors.collect{ | string | JSON.parse(string, symbolize_names: true) }
end
parse_header() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 246
def parse_header
  options.custom_provider_header.each_with_object({}) do | custom_provider_header, header_hash |
    header_name, header_value = custom_provider_header.split(":", 2).collect(&:strip)
    header_hash[header_name] = header_value
  end
end
print_deprecation_note() click to toggle source
require_custom_middlware() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 146
def require_custom_middlware
  options.custom_middleware.each do |file|
    $stdout.puts "DEBUG: Requiring custom middleware file #{file}" if verbose?
    begin
      require file
    rescue LoadError => e
      $stderr.puts "ERROR: #{e.class} - #{e.message}. Please specify an absolute path."
      exit(1)
    end
  end
end
require_pact_project_pact_helper() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 230
def require_pact_project_pact_helper
  require ENV['PACT_PROJECT_PACT_HELPER'] if ENV.fetch('PACT_PROJECT_PACT_HELPER','') != ''
end
require_rspec_monkeypatch_for_jsonl() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 234
def require_rspec_monkeypatch_for_jsonl
  if options.format == 'json'
    require 'pact/provider_verifier/rspec_json_formatter_monkeypatch'
  end
end
reset_pact_configuration() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 187
def reset_pact_configuration
  require 'pact/configuration'
  require 'pact/consumer/world'
  require 'pact/provider/world'
  Pact.clear_configuration
  Pact.clear_consumer_world
  Pact.clear_provider_world
  configure_output
  configure_service_provider
end
set_broker_token_env_var() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 280
def set_broker_token_env_var
  if options.broker_token && !ENV['PACT_BROKER_TOKEN']
    ENV['PACT_BROKER_TOKEN'] = options.broker_token
  end
end
set_environment_variables() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 66
def set_environment_variables
  ENV['PROVIDER_STATES_SETUP_URL'] = options.provider_states_setup_url
  ENV['VERBOSE_LOGGING'] = options.verbose if options.verbose
  ENV['CUSTOM_PROVIDER_HEADER'] = custom_provider_headers_for_env_var if custom_provider_headers_for_env_var
  ENV['MONKEYPATCH'] = options.monkeypatch.join("\n") if options.monkeypatch && options.monkeypatch.any?
end
setup() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 57
def setup
  configure_output
  print_deprecation_note
  set_environment_variables
  require_rspec_monkeypatch_for_jsonl
  require_pact_project_pact_helper # Beth: not sure if this is needed, hangover from pact-provider-proxy?
  set_broker_token_env_var
end
verbose?() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 286
def verbose?
  options.verbose || ENV['VERBOSE'] == 'true'
end
verify_pact(pact_uri) click to toggle source
# File lib/pact/provider_verifier/app.rb, line 165
def verify_pact(pact_uri)
  begin
    verify_options = {
      pact_helper: PROXY_PACT_HELPER,
      pact_uri: pact_uri,
      backtrace: ENV['BACKTRACE'] == 'true',
      verbose: verbose?,
      format: options.format,
      out: options.out,
      request_customizer: ProviderStates::AddProviderStatesHeader
    }
    verify_options[:description] = ENV['PACT_DESCRIPTION'] if ENV['PACT_DESCRIPTION']
    verify_options[:provider_state] = ENV['PACT_PROVIDER_STATE'] if ENV['PACT_PROVIDER_STATE']

    reset_pact_configuration
    # Really, this should call the PactSpecRunner directly, rather than using the CLI class.
    Cli::RunPactVerification.call(verify_options)
  rescue SystemExit => e
    e.status
  end
end
wait_until_provider_available() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 267
def wait_until_provider_available
  if options.wait && options.wait != 0
    uri = URI(options.provider_base_url)
    $stderr.puts "INFO: Polling for up to #{options.wait} seconds for provider to become available at #{uri.host}:#{uri.port}..."
    up = wait_until_server_available(uri.host, uri.port, options.wait)
    if up
      $stderr.puts "INFO: Provider available, proceeding with verifications"
    else
      $stderr.puts "WARN: Provider does not appear to be up on #{uri.host}:#{uri.port}... proceeding with verifications anyway"
    end
  end
end
warn_empty_pact_set() click to toggle source
# File lib/pact/provider_verifier/app.rb, line 223
def warn_empty_pact_set
  if all_pact_urls.empty?
    level = options.fail_if_no_pacts_found ? "ERROR" : "WARN"
    $stderr.puts  "#{level}: No pacts were found for the consumer versions selected"
  end
end