Skip to content

Commit

Permalink
feat: allow verification status badges to be served via a redirect in…
Browse files Browse the repository at this point in the history
…stead of proxying the response
  • Loading branch information
bethesque committed Feb 10, 2020
1 parent 3ae072b commit a34d5f7
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 33 deletions.
17 changes: 13 additions & 4 deletions lib/pact_broker/api/resources/badge.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@
module PactBroker
module Api
module Resources

class Badge < BaseResource

def allowed_methods
["GET", "OPTIONS", "OPTIONS"]
["GET", "OPTIONS"]
end

def content_types_provided
[['image/svg+xml', :to_svg]]
end

def resource_exists?
!badge_service.can_provide_badge_using_redirect?
end

# Only called if resource_exists? returns false
def previously_existed?
true
end

Expand All @@ -28,13 +32,18 @@ def forbidden?
false
end

private

def to_svg
response.headers['Cache-Control'] = 'no-cache'
comment + badge_service.pact_verification_badge(pact, label, initials, pseudo_branch_verification_status)
end

def moved_temporarily?
response.headers['Cache-Control'] = 'no-cache'
badge_service.pact_verification_badge_url(pact, label, initials, pseudo_branch_verification_status)
end

private

def pact
@pact ||= pact_service.find_latest_pact(identifier_from_path)
end
Expand Down
21 changes: 14 additions & 7 deletions lib/pact_broker/badges/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,21 @@ module Service
SPACE_DASH_UNDERSCORE = /[\s_\-]/
CACHE = {}

def can_provide_badge_using_redirect?
PactBroker.configuration.badge_provider_mode == :redirect && !!PactBroker.configuration.shields_io_base_url
end

def pact_verification_badge pact, label, initials, pseudo_branch_verification_status
return static_svg(pact, pseudo_branch_verification_status) unless pact

title = badge_title pact, label, initials
status = badge_status pseudo_branch_verification_status
color = badge_color pseudo_branch_verification_status
dynamic_svg(pact, label, initials, pseudo_branch_verification_status) || static_svg(pact, pseudo_branch_verification_status)
end

dynamic_svg(title, status, color) || static_svg(pact, pseudo_branch_verification_status)
def pact_verification_badge_url(pact, label, initials, pseudo_branch_verification_status)
title = badge_title(pact, label, initials)
status = badge_status(pseudo_branch_verification_status)
color = badge_color(pseudo_branch_verification_status)
build_shield_io_uri(title, status, color)
end

def clear_cache
Expand Down Expand Up @@ -78,9 +85,9 @@ def badge_color pseudo_branch_verification_status
end
end

def dynamic_svg left_text, right_text, color
def dynamic_svg pact, label, initials, pseudo_branch_verification_status
return nil unless PactBroker.configuration.shields_io_base_url
uri = build_uri(left_text, right_text, color)
uri = pact_verification_badge_url(pact, label, initials, pseudo_branch_verification_status)
begin
response = do_request(uri)
response.code == '200' ? response.body : nil
Expand All @@ -93,7 +100,7 @@ def dynamic_svg left_text, right_text, color
end
end

def build_uri left_text, right_text, color
def build_shield_io_uri left_text, right_text, color
shield_base_url = PactBroker.configuration.shields_io_base_url
path = "/badge/#{escape_text(left_text)}-#{escape_text(right_text)}-#{color}.svg"
URI.parse(shield_base_url + path)
Expand Down
6 changes: 4 additions & 2 deletions lib/pact_broker/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class Configuration
:webhook_scheme_whitelist,
:webhook_host_whitelist,
:base_equality_only_on_content_that_affects_verification_results,
:seed_example_data
:seed_example_data,
:badge_provider_mode
]

attr_accessor :base_url, :log_dir, :database_connection, :auto_migrate_db, :auto_migrate_db_data, :example_data_seeder, :seed_example_data, :use_hal_browser, :html_pact_renderer, :use_rack_protection
Expand All @@ -40,7 +41,7 @@ class Configuration
attr_accessor :webhook_retry_schedule
attr_reader :webhook_http_method_whitelist, :webhook_scheme_whitelist, :webhook_host_whitelist
attr_accessor :semver_formats
attr_accessor :enable_public_badge_access, :shields_io_base_url
attr_accessor :enable_public_badge_access, :shields_io_base_url, :badge_provider_mode
attr_accessor :disable_ssl_verification
attr_accessor :base_equality_only_on_content_that_affects_verification_results
attr_reader :api_error_reporters
Expand Down Expand Up @@ -69,6 +70,7 @@ def self.default_configuration
config.enable_diagnostic_endpoints = true
config.enable_public_badge_access = false # For security
config.shields_io_base_url = "https://img.shields.io".freeze
config.badge_provider_mode = :proxy # other option is :redirect
config.use_case_sensitive_resource_names = true
config.html_pact_renderer = default_html_pact_render
config.version_parser = PactBroker::Versions::ParseSemanticVersion
Expand Down
54 changes: 39 additions & 15 deletions spec/lib/pact_broker/api/resources/badge_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ module Resources
allow(PactBroker::Pacts::Service).to receive(:find_latest_pact).and_return(pact)
allow(PactBroker::Verifications::Service).to receive(:find_latest_verification_for).and_return(verification)
allow(PactBroker::Badges::Service).to receive(:pact_verification_badge).and_return("badge")
allow(PactBroker::Badges::Service).to receive(:pact_verification_badge_url).and_return("http://badge")
allow(PactBroker::Verifications::PseudoBranchStatus).to receive(:new).and_return(pseudo_branch_verification_status)
allow(PactBroker::Badges::Service).to receive(:can_provide_badge_using_redirect?).and_return(false)
end

let(:pact) { instance_double("PactBroker::Domain::Pact", consumer: consumer, provider: provider, consumer_version_number: "2", revision_number: "1") }
Expand Down Expand Up @@ -47,7 +49,6 @@ module Resources
end

context "when enable_public_badge_access is true" do

before do
PactBroker.configuration.enable_public_badge_access = true
end
Expand All @@ -67,25 +68,48 @@ module Resources
subject
end

it "creates a badge" do
expect(PactBroker::Badges::Service).to receive(:pact_verification_badge).with(pact, nil, false, :verified)
subject
end
context "when can_provide_badge_using_redirect? is false" do
before do
allow(PactBroker::Badges::Service).to receive(:can_provide_badge_using_redirect?).and_return(false)
end

it "returns a 200 status" do
expect(subject.status).to eq 200
end
it "creates a badge" do
expect(PactBroker::Badges::Service).to receive(:pact_verification_badge).with(pact, nil, false, :verified)
subject
end

it "does not allow caching" do
expect(subject.headers['Cache-Control']).to eq 'no-cache'
end
it "returns a 200 status" do
expect(subject.status).to eq 200
end

it "returns the badge" do
expect(subject.body).to end_with "badge"
it "does not allow caching" do
expect(subject.headers['Cache-Control']).to eq 'no-cache'
end

it "returns the badge" do
expect(subject.body).to end_with "badge"
end

it "returns a comment with the consumer and provider numbers" do
expect(subject.body).to include "<!-- consumer version 2 revision 1 provider version 3 number 7 -->"
end
end

it "returns a comment with the consumer and provider numbers" do
expect(subject.body).to include "<!-- consumer version 2 revision 1 provider version 3 number 7 -->"
context "when can_provide_badge_using_redirect? is true" do
before do
allow(PactBroker::Badges::Service).to receive(:can_provide_badge_using_redirect?).and_return(true)
end

it "determines the URL of the badge to redirect to" do
expect(PactBroker::Badges::Service).to receive(:pact_verification_badge_url).with(pact, nil, false, :verified)
subject
end

it "returns a 301 redirect to the badge URL" do
expect(subject.status).to eq 307
expect(subject.headers['Location']).to eq 'http://badge'
expect(subject.headers['Cache-Control']).to eq 'no-cache'
end
end

context "when the label param is specified" do
Expand Down
25 changes: 20 additions & 5 deletions spec/lib/pact_broker/badges/service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ module Service
let(:expected_url) { "https://img.shields.io/badge/#{expected_left_text}-#{expected_right_text}-#{expected_color}.svg" }
let(:expected_color) { "brightgreen" }
let(:expected_right_text) { "verified" }
let(:expected_left_text) { "foo--bar%2Fthing__blah%20pact" }
let(:expected_left_text) { "foo--bar%2fthing__blah%20pact" }
let(:response_status) { 200 }
let!(:http_request) do
stub_request(:get, expected_url).to_return(:status => response_status, :body => "svg")
end

subject { PactBroker::Badges::Service.pact_verification_badge pact, label, initials, pseudo_branch_verification_status }

let(:pact_verification_badge_url) { PactBroker::Badges::Service.pact_verification_badge_url(pact, label, initials, pseudo_branch_verification_status) }

before do
Service.clear_cache
allow(Service).to receive(:logger).and_return(logger)
Expand All @@ -41,48 +43,53 @@ module Service
it "creates a badge with the consumer and provider names" do
subject
expect(http_request).to have_been_made
expect(pact_verification_badge_url).to eq URI(expected_url)
end

context "when initials is true" do
let(:expected_left_text) { "fb%2Ftb%20pact" }
let(:expected_left_text) { "fb%2ftb%20pact" }
let(:initials) { true }

it "creates a badge with the consumer and provider initials" do
subject
expect(http_request).to have_been_made
expect(pact_verification_badge_url).to eq URI(expected_url)
end
end

context "when initials is true but the consumer and provider names only contain one word" do
let(:expected_left_text) { "foo%2Fbar%20pact" }
let(:expected_left_text) { "foo%2fbar%20pact" }
let(:initials) { true }
let(:pact) { double("pact", consumer_name: "Foo", provider_name: "Bar") }

it "creates a badge with the consumer and provider names, not initials" do
subject
expect(http_request).to have_been_made
expect(pact_verification_badge_url).to eq URI(expected_url)
end
end

context "when initials is true but the consumer and provider names are one camel cased word" do
let(:expected_left_text) { "fa%2Fbp%20pact" }
let(:expected_left_text) { "fa%2fbp%20pact" }
let(:initials) { true }
let(:pact) { double("pact", consumer_name: "FooApp", provider_name: "barProvider") }

it "creates a badge with the consumer and provider names, not initials" do
subject
expect(http_request).to have_been_made
expect(pact_verification_badge_url).to eq URI(expected_url)
end
end

context "when initials is true but the consumer and provider names are one camel cased word" do
let(:expected_left_text) { "fa%2Fdat%20pact" }
let(:expected_left_text) { "fa%2fdat%20pact" }
let(:initials) { true }
let(:pact) { double("pact", consumer_name: "FooApp", provider_name: "doAThing") }

it "creates a badge with the consumer and provider names, not initials" do
subject
expect(http_request).to have_been_made
expect(pact_verification_badge_url).to eq URI(expected_url)
end
end
end
Expand All @@ -94,6 +101,7 @@ module Service
it "creates a badge with only the consumer name" do
subject
expect(http_request).to have_been_made
expect(pact_verification_badge_url).to eq URI(expected_url)
end

context "when initials is true" do
Expand All @@ -103,6 +111,7 @@ module Service
it "creates a badge with only the consumer initials" do
subject
expect(http_request).to have_been_made
expect(pact_verification_badge_url).to eq URI(expected_url)
end
end
end
Expand All @@ -114,6 +123,7 @@ module Service
it "creates a badge with only the provider name" do
subject
expect(http_request).to have_been_made
expect(pact_verification_badge_url).to eq URI(expected_url)
end

context "when initials is true" do
Expand All @@ -123,6 +133,7 @@ module Service
it "creates a badge with only the provider initials" do
subject
expect(http_request).to have_been_made
expect(pact_verification_badge_url).to eq URI(expected_url)
end
end
end
Expand All @@ -131,6 +142,7 @@ module Service
it "create a green badge with left text 'verified'" do
subject
expect(http_request).to have_been_made
expect(pact_verification_badge_url).to eq URI(expected_url)
end
end

Expand All @@ -142,6 +154,7 @@ module Service
it "create a lightgrey badge with left text 'unknown'" do
subject
expect(http_request).to have_been_made
expect(pact_verification_badge_url).to eq URI(expected_url)
end
end

Expand All @@ -153,6 +166,7 @@ module Service
it "create a red badge with left text 'failed'" do
subject
expect(http_request).to have_been_made
expect(pact_verification_badge_url).to eq URI(expected_url)
end
end

Expand All @@ -164,6 +178,7 @@ module Service
it "create a orange badge with left text 'changed'" do
subject
expect(http_request).to have_been_made
expect(pact_verification_badge_url).to eq URI(expected_url)
end
end

Expand Down

0 comments on commit a34d5f7

Please sign in to comment.