diff --git a/lib/pact_broker/client/cli/broker.rb b/lib/pact_broker/client/cli/broker.rb index 887fddbb..ef62fc7c 100644 --- a/lib/pact_broker/client/cli/broker.rb +++ b/lib/pact_broker/client/cli/broker.rb @@ -7,6 +7,7 @@ require 'rake/file_list' require 'thor/error' require 'pact_broker/client/create_tag' +require 'pact_broker/client/versions/describe' module PactBroker module Client @@ -72,6 +73,32 @@ def create_version_tag pact_broker_client_options) end + method_option :pacticipant, required: true, aliases: "-a", desc: "The name of the pacticipant that the version belongs to." + method_option :version, required: false, aliases: "-e", desc: "The pacticipant version number." + method_option :latest, required: false, aliases: "-l", banner: '[TAG]', desc: "Describe the latest pacticipant version. Optionally specify a TAG to describe the latest version with the specified tag." + method_option :broker_base_url, required: true, aliases: "-b", desc: "The base URL of the Pact Broker" + method_option :broker_username, aliases: "-u", desc: "Pact Broker basic auth username" + method_option :broker_password, aliases: "-p", desc: "Pact Broker basic auth password" + method_option :output, aliases: "-o", desc: "json or table or id", default: 'table' + method_option :verbose, aliases: "-v", type: :boolean, default: false, required: false, desc: "Verbose output. Default: false" + + desc 'describe-version', 'Describes a pacticipant version. If no version or tag is specified, the latest version is described.' + def describe_version + latest = !options.latest.nil? || (options.latest.nil? && options.version.nil?) + params = { + pacticipant: options.pacticipant, + version: options.version, + latest: latest, + tag: options.latest.is_a?(String) ? options.latest : nil + } + opts = { + output: options.output + } + result = PactBroker::Client::Versions::Describe.call(params, opts, options.broker_base_url, pact_broker_client_options) + $stdout.puts result.message + exit(1) unless result.success + end + desc 'version', "Show the pact_broker-client gem version" def version $stdout.puts PactBroker::Client::VERSION diff --git a/lib/pact_broker/client/versions.rb b/lib/pact_broker/client/versions.rb index 02097d99..49b04d3e 100644 --- a/lib/pact_broker/client/versions.rb +++ b/lib/pact_broker/client/versions.rb @@ -5,7 +5,15 @@ module PactBroker module Client class Versions < BaseClient + def find options + response = get("#{version_base_url(options)}", headers: default_get_headers) + handle_response(response) do + JSON.parse(response.body, symbolize_names: true) + end + end + + # TODO this is not a valid URL! def latest options query = options[:tag] ? {tag: options[:tag]} : {} response = self.class.get("#{versions_base_url(options)}/latest", query: query, headers: default_get_headers) diff --git a/lib/pact_broker/client/versions/describe.rb b/lib/pact_broker/client/versions/describe.rb new file mode 100644 index 00000000..62331062 --- /dev/null +++ b/lib/pact_broker/client/versions/describe.rb @@ -0,0 +1,56 @@ +require 'pact_broker/client/pact_broker_client' +require 'pact_broker/client/versions/formatter' + +module PactBroker + module Client + class Versions + class Describe + + class Result + attr_reader :success, :message + + def initialize success, message = nil + @success = success + @message = message + end + end + + def self.call params, options, pact_broker_base_url, pact_broker_client_options + new(params, options, pact_broker_base_url, pact_broker_client_options).call + end + + def initialize params, options, pact_broker_base_url, pact_broker_client_options + @params = params + @options = options + @pact_broker_base_url = pact_broker_base_url + @pact_broker_client_options = pact_broker_client_options + end + + def call + version_hash = if params[:version] + versions_client.find params + else + pact_broker_client.pacticipants.versions.latest(params) + end + Result.new(true, format_version(version_hash)) + end + + private + + def format_version(version_hash) + Formatter.call(version_hash, options[:output]) + end + + attr_reader :params, :options, :pact_broker_base_url, :pact_broker_client_options + + def versions_client + pact_broker_client.pacticipants.versions + end + + def pact_broker_client + @pact_broker_client ||= PactBroker::Client::PactBrokerClient.new(base_url: pact_broker_base_url, client_options: pact_broker_client_options) + end + end + end + end +end diff --git a/lib/pact_broker/client/versions/formatter.rb b/lib/pact_broker/client/versions/formatter.rb new file mode 100644 index 00000000..620f09b9 --- /dev/null +++ b/lib/pact_broker/client/versions/formatter.rb @@ -0,0 +1,20 @@ +require 'pact_broker/client/versions/json_formatter' +require 'pact_broker/client/versions/text_formatter' + +module PactBroker + module Client + class Versions + class Formatter + def self.call(matrix_lines, format) + formatter = case format + when 'json' then JsonFormatter + when 'table' then TextFormatter + else + raise PactBroker::Client::Error.new("Invalid output option '#{format}. Must be one of 'table' or 'json'.") + end + formatter.call(matrix_lines) + end + end + end + end +end diff --git a/lib/pact_broker/client/versions/json_formatter.rb b/lib/pact_broker/client/versions/json_formatter.rb new file mode 100644 index 00000000..7067ebed --- /dev/null +++ b/lib/pact_broker/client/versions/json_formatter.rb @@ -0,0 +1,13 @@ +require 'table_print' + +module PactBroker + module Client + class Versions + class JsonFormatter + def self.call(matrix) + JSON.pretty_generate(matrix) + end + end + end + end +end diff --git a/lib/pact_broker/client/versions/text_formatter.rb b/lib/pact_broker/client/versions/text_formatter.rb new file mode 100644 index 00000000..bd2803d2 --- /dev/null +++ b/lib/pact_broker/client/versions/text_formatter.rb @@ -0,0 +1,31 @@ +require 'table_print' + +module PactBroker + module Client + class Versions + class TextFormatter + + Line = Struct.new(:number, :tags) + + OPTIONS = [ + { number: {} }, + { tags: {} } + ] + + def self.call(version_hash) + tags = (lookup(version_hash, [], :_embedded, :tags) || []).collect{ | t| t[:name] }.join(" ") + data = Line.new(version_hash[:number], tags) + + printer = TablePrint::Printer.new([data], OPTIONS) + printer.table_print + end + + def self.lookup line, default, *keys + keys.reduce(line) { | line, key | line[key] } + rescue NoMethodError + default + end + end + end + end +end diff --git a/spec/lib/pact_broker/client/versions/describe_spec.rb b/spec/lib/pact_broker/client/versions/describe_spec.rb new file mode 100644 index 00000000..d7b7eaef --- /dev/null +++ b/spec/lib/pact_broker/client/versions/describe_spec.rb @@ -0,0 +1,65 @@ +require 'pact_broker/client/versions/describe' + +module PactBroker + module Client + class Versions + describe Describe do + describe ".call" do + + let(:versions_client) do + instance_double('PactBroker::Client::Versions', latest: version_hash) + end + + let(:pact_broker_base_url) { 'http://broker' } + let(:pact_broker_client_options) { {} } + let(:pact_broker_client) { instance_double('PactBroker::Client::PactBrokerClient')} + let(:version_hash) do + { + foo: 'bar' + } + end + + let(:params) do + { + pacticipant: 'foo', + latest: true, + tag: 'bar' + } + end + + let(:options) do + { + output: 'someformat' + } + end + + before do + allow(PactBroker::Client::PactBrokerClient).to receive(:new).and_return(pact_broker_client) + allow(pact_broker_client).to receive_message_chain(:pacticipants, :versions).and_return(versions_client) + allow(Formatter).to receive(:call).and_return('formatted_output') + end + + subject { Describe.call(params, options, pact_broker_base_url, pact_broker_client_options) } + + it "invokes the versions client" do + expect(versions_client).to receive(:latest).with(params) + subject + end + + it "formats the output" do + expect(Formatter).to receive(:call).with(version_hash, 'someformat') + subject + end + + it "returns a successful result" do + expect(subject.success).to be true + end + + it "returns a result with the formatted output as the message" do + expect(subject.message).to eq 'formatted_output' + end + end + end + end + end +end