diff --git a/lib/pact_broker/api.rb b/lib/pact_broker/api.rb index c628aab2a..9bf8c4e30 100644 --- a/lib/pact_broker/api.rb +++ b/lib/pact_broker/api.rb @@ -83,6 +83,8 @@ module PactBroker add ['dashboard'], Api::Resources::Dashboard, {resource_name: "dashboard"} add ['test','error'], Api::Resources::ErrorTest, {resource_name: "error_test"} + + add ['integrations'], Api::Resources::Integrations, {resource_name: "integrations"} add [], Api::Resources::Index, {resource_name: "index"} end end diff --git a/lib/pact_broker/api/renderers/integrations_dot_renderer.rb b/lib/pact_broker/api/renderers/integrations_dot_renderer.rb new file mode 100644 index 000000000..f77fe471c --- /dev/null +++ b/lib/pact_broker/api/renderers/integrations_dot_renderer.rb @@ -0,0 +1,36 @@ +module PactBroker + module Api + module Renderers + class IntegrationsDotRenderer + def initialize(integrations) + @integrations = integrations + end + + def self.call(integrations) + new(integrations).call + end + + def call + "digraph { ranksep=3; ratio=auto; overlap=false; node [ shape = plaintext, fontname = Helvetica ]; +#{integrations_graph} +} +" + end + + private + + attr_reader :integrations + + def integrations_graph + integrations + .collect{ | integration| " #{escape_name(integration.consumer_name)} -> #{escape_name(integration.provider_name)}" } + .join("\n") + end + + def escape_name(name) + name.gsub(" ", "_") + end + end + end + end +end diff --git a/lib/pact_broker/api/resources/index.rb b/lib/pact_broker/api/resources/index.rb index 25184c6e2..076218567 100644 --- a/lib/pact_broker/api/resources/index.rb +++ b/lib/pact_broker/api/resources/index.rb @@ -83,6 +83,11 @@ def links title: 'Webhooks', templated: false }, + 'pb:integrations' => { + href: base_url + '/integrations', + title: 'Integrations', + templated: false + }, 'beta:pending-provider-pacts' => { href: base_url + '/pacts/provider/{provider}/pending', diff --git a/lib/pact_broker/api/resources/integrations.rb b/lib/pact_broker/api/resources/integrations.rb new file mode 100644 index 000000000..b852d495e --- /dev/null +++ b/lib/pact_broker/api/resources/integrations.rb @@ -0,0 +1,26 @@ +require 'pact_broker/api/resources/base_resource' +require 'pact_broker/api/renderers/integrations_dot_renderer' + +module PactBroker + module Api + module Resources + class Integrations < BaseResource + def content_types_provided + [["text/vnd.graphviz", :to_dot]] + end + + def allowed_methods + ["GET", "OPTIONS"] + end + + def to_dot + PactBroker::Api::Renderers::IntegrationsDotRenderer.call(integrations) + end + + def integrations + pact_service.find_latest_pacts + end + end + end + end +end diff --git a/lib/pact_broker/doc/views/integrations.markdown b/lib/pact_broker/doc/views/integrations.markdown new file mode 100644 index 000000000..7abd5ff55 --- /dev/null +++ b/lib/pact_broker/doc/views/integrations.markdown @@ -0,0 +1,7 @@ +# Integrations + +Allowed methods: `GET` + +Content types: `text/vnd.graphviz` + +A list of all the integrations (consumer/provider pairs) stored in the Pact Broker. diff --git a/spec/features/get_integrations_dot_file_spec.rb b/spec/features/get_integrations_dot_file_spec.rb new file mode 100644 index 000000000..05d5c830c --- /dev/null +++ b/spec/features/get_integrations_dot_file_spec.rb @@ -0,0 +1,23 @@ +describe "Get integrations dot file" do + before do + TestDataBuilder.new + .create_pact_with_hierarchy("Foo", "1", "Bar") + end + + let(:path) { "/integrations" } + let(:response_body_hash) { JSON.parse(subject.body, symbolize_names: true) } + + subject { get path, nil, {'HTTP_ACCEPT' => 'text/vnd.graphviz' }; last_response } + + it "returns a 200 OK" do + expect(subject.status).to eq 200 + end + + it "returns a dot file content type" do + expect(subject.headers['Content-Type']).to eq 'text/vnd.graphviz;charset=utf-8' + end + + it "returns dot file content" do + expect(subject.body).to include "Foo -> Bar" + end +end diff --git a/spec/fixtures/expected.gv b/spec/fixtures/expected.gv new file mode 100644 index 000000000..677d1b3ef --- /dev/null +++ b/spec/fixtures/expected.gv @@ -0,0 +1,4 @@ +digraph { ranksep=3; ratio=auto; overlap=false; node [ shape = plaintext, fontname = Helvetica ]; + Foo -> Bar + Wiffle -> Foo_Thing +} diff --git a/spec/lib/pact_broker/api/renderers/integrations_dot_renderer_spec.rb b/spec/lib/pact_broker/api/renderers/integrations_dot_renderer_spec.rb new file mode 100644 index 000000000..8954d31cc --- /dev/null +++ b/spec/lib/pact_broker/api/renderers/integrations_dot_renderer_spec.rb @@ -0,0 +1,29 @@ +require 'pact_broker/api/renderers/integrations_dot_renderer' + +module PactBroker + module Api + module Renderers + describe IntegrationsDotRenderer do + + # TODO work out how to handle apostrophes etc + + let(:integrations) do + [ + double('integration', consumer_name: "Foo", provider_name: "Bar"), + double('integration', consumer_name: "Wiffle", provider_name: "Foo Thing") + ] + end + + let(:expected_content) { load_fixture('expected.gv') } + + describe "#call" do + subject { IntegrationsDotRenderer.call(integrations) } + + it "renders a dot file" do + expect(subject).to eq expected_content + end + end + end + end + end +end