From bff4611db519f0bb199dce447d53ce712487bbcd Mon Sep 17 00:00:00 2001 From: Beth Skurrie Date: Mon, 30 Oct 2017 21:29:22 +1100 Subject: [PATCH] feat(verifications): allow provider version tags to be specified --- .../configuration/service_provider_config.rb | 7 ++- .../configuration/service_provider_dsl.rb | 9 +++- .../provider/verification_results/publish.rb | 46 ++++++++++++++++--- .../verification_results/publish_all.rb | 1 + lib/tasks/pact.rake | 1 - .../service_provider_config_spec.rb | 4 +- .../verification_results/publish_spec.rb | 39 +++++++++++++++- spec/support/bar_pact_helper.rb | 1 + tasks/foo-bar.rake | 3 +- 9 files changed, 94 insertions(+), 17 deletions(-) diff --git a/lib/pact/provider/configuration/service_provider_config.rb b/lib/pact/provider/configuration/service_provider_config.rb index 92a323a9..2b3068a2 100644 --- a/lib/pact/provider/configuration/service_provider_config.rb +++ b/lib/pact/provider/configuration/service_provider_config.rb @@ -5,8 +5,9 @@ class ServiceProviderConfig attr_accessor :application_version - def initialize application_version, publish_verification_results, &app_block + def initialize application_version, tags, publish_verification_results, &app_block @application_version = application_version + @tags = [*tags] @publish_verification_results = publish_verification_results @app_block = app_block end @@ -18,6 +19,10 @@ def app def publish_verification_results? @publish_verification_results end + + def tags + @tags + end end end end diff --git a/lib/pact/provider/configuration/service_provider_dsl.rb b/lib/pact/provider/configuration/service_provider_dsl.rb index 79907d7b..90795f6a 100644 --- a/lib/pact/provider/configuration/service_provider_dsl.rb +++ b/lib/pact/provider/configuration/service_provider_dsl.rb @@ -13,7 +13,7 @@ class ServiceProviderDSL extend Pact::DSL - attr_accessor :name, :app_block, :application_version, :publish_verification_results + attr_accessor :name, :app_block, :application_version, :tags, :publish_verification_results CONFIG_RU_APP = lambda { unless File.exist? Pact.configuration.config_ru_path @@ -25,6 +25,7 @@ class ServiceProviderDSL def initialize name @name = name @publish_verification_results = false + @tags = [] @app_block = CONFIG_RU_APP end @@ -37,6 +38,10 @@ def app_version application_version self.application_version = application_version end + def app_version_tags tags + self.tags = tags + end + def publish_verification_results publish_verification_results self.publish_verification_results = publish_verification_results Pact::RSpec.with_rspec_2 do @@ -70,7 +75,7 @@ def application_version_blank? end def create_service_provider - Pact.configuration.provider = ServiceProviderConfig.new(application_version, publish_verification_results, &@app_block) + Pact.configuration.provider = ServiceProviderConfig.new(application_version, tags, publish_verification_results, &@app_block) end end end diff --git a/lib/pact/provider/verification_results/publish.rb b/lib/pact/provider/verification_results/publish.rb index 3f97d01b..f9d10d49 100644 --- a/lib/pact/provider/verification_results/publish.rb +++ b/lib/pact/provider/verification_results/publish.rb @@ -1,6 +1,9 @@ require 'json' require 'pact/errors' +# TODO move this to the pact broker client +# TODO retries + module Pact module Provider module VerificationResults @@ -20,6 +23,11 @@ def initialize pact_source, verification_result def call if Pact.configuration.provider.publish_verification_results? + if tag_url('') + tag + else + Pact.configuration.error_stream.puts "WARN: Cannot tag provider version as there is no link named pb:tag-version in the pact JSON." + end if publication_url publish else @@ -34,11 +42,35 @@ def publication_url @publication_url ||= pact_source.pact_hash.fetch('_links', {}).fetch('pb:publish-verification-results', {})['href'] end + def tag_url tag + href = pact_source.pact_hash.dig('_links', 'pb:tag-version', 'href') + href ? href.gsub('{tag}', tag) : nil + end + + def tag + Pact.configuration.provider.tags.each do | tag | + uri = URI(tag_url(tag)) + request = build_request('Put', uri, nil, "Tagging provider version at") + response = nil + begin + options = {:use_ssl => uri.scheme == 'https'} + response = Net::HTTP.start(uri.host, uri.port, options) do |http| + http.request request + end + rescue StandardError => e + error_message = "Failed to tag provider version due to: #{e.class} #{e.message}" + raise PublicationError.new(error_message) + end + + unless response.code.start_with?("2") + raise PublicationError.new("Error returned from tagging request #{response.code} #{response.body}") + end + end + end + def publish - #TODO https - #TODO username/password uri = URI(publication_url) - request = build_request(uri) + request = build_request('Post', uri, verification_result.to_json, "Publishing verification result #{verification_result.to_json} to") response = nil begin options = {:use_ssl => uri.scheme == 'https'} @@ -55,16 +87,16 @@ def publish end end - def build_request uri - request = Net::HTTP::Post.new(uri.path) + def build_request meth, uri, body, action + request = Net::HTTP.const_get(meth).new(uri.path) request['Content-Type'] = "application/json" - request.body = verification_result.to_json + request.body = body if body debug_uri = uri if pact_source.uri.basic_auth? request.basic_auth pact_source.uri.username, pact_source.uri.password debug_uri = URI(uri.to_s).tap { |x| x.userinfo="#{pact_source.uri.username}:*****"} end - Pact.configuration.output_stream.puts "INFO: Publishing verification result #{verification_result.to_json} to #{debug_uri}" + Pact.configuration.output_stream.puts "INFO: #{action} #{debug_uri}" request end diff --git a/lib/pact/provider/verification_results/publish_all.rb b/lib/pact/provider/verification_results/publish_all.rb index 2776825f..7c2721fe 100644 --- a/lib/pact/provider/verification_results/publish_all.rb +++ b/lib/pact/provider/verification_results/publish_all.rb @@ -15,6 +15,7 @@ def initialize pact_sources, rspec_summary @rspec_summary = rspec_summary end + # TODO do not publish unless all interactions have been run def call verification_results.collect do | pair | Publish.call(pair.first, pair.last) diff --git a/lib/tasks/pact.rake b/lib/tasks/pact.rake index 20f79258..743e9731 100644 --- a/lib/tasks/pact.rake +++ b/lib/tasks/pact.rake @@ -31,5 +31,4 @@ namespace :pact do require 'pact/provider/help/console_text' puts Pact::Provider::Help::ConsoleText.(args[:reports_dir]) end - end diff --git a/spec/lib/pact/provider/configuration/service_provider_config_spec.rb b/spec/lib/pact/provider/configuration/service_provider_config_spec.rb index 898e3574..fd5e46cb 100644 --- a/spec/lib/pact/provider/configuration/service_provider_config_spec.rb +++ b/spec/lib/pact/provider/configuration/service_provider_config_spec.rb @@ -10,7 +10,7 @@ module Configuration let(:app_block) { ->{ Object.new } } - subject { ServiceProviderConfig.new("1.2.3'", true, &app_block) } + subject { ServiceProviderConfig.new("1.2.3'", [], true, &app_block) } it "should execute the app_block each time" do expect(subject.app.object_id).to_not equal(subject.app.object_id) @@ -20,4 +20,4 @@ module Configuration end end end -end \ No newline at end of file +end diff --git a/spec/lib/pact/provider/verification_results/publish_spec.rb b/spec/lib/pact/provider/verification_results/publish_spec.rb index 9e9adf7a..0950fa78 100644 --- a/spec/lib/pact/provider/verification_results/publish_spec.rb +++ b/spec/lib/pact/provider/verification_results/publish_spec.rb @@ -6,13 +6,27 @@ module VerificationResults describe Publish do describe "call" do let(:publish_verification_url) { nil } + let(:tag_version_url) { 'http://tag-me/{tag}' } let(:pact_source) { instance_double("Pact::Provider::PactSource", pact_hash: pact_hash, uri: pact_url)} let(:pact_url) { instance_double("Pact::Provider::PactURI", basic_auth?: basic_auth, username: 'username', password: 'password')} let(:basic_auth) { false } - let(:pact_hash) { {'consumer' => {'name' => 'Foo'}, '_links' => {'pb:publish-verification-results'=> {'href' => publish_verification_url}}} } + let(:pact_hash) do + { + 'consumer' => { + 'name' => 'Foo' + }, + '_links' => { + 'pb:publish-verification-results'=> { + 'href' => publish_verification_url + }, + 'pb:tag-version'=> {'href' => tag_version_url} + } + } + end let(:app_version_set) { false } let(:verification_json) { '{"foo": "bar"}' } let(:publish_verification_results) { false } + let(:tags) { [] } let(:verification) do instance_double("Pact::Verifications::Verification", to_json: verification_json, @@ -21,13 +35,14 @@ module VerificationResults end let(:provider_configuration) do - double('provider config', publish_verification_results?: publish_verification_results) + double('provider config', publish_verification_results?: publish_verification_results, tags: tags) end before do allow($stdout).to receive(:puts) allow(Pact.configuration).to receive(:provider).and_return(provider_configuration) stub_request(:post, 'http://broker/verifications') + stub_request(:put, /tag-me/) end subject { Publish.call(pact_source, verification)} @@ -50,6 +65,26 @@ module VerificationResults expect(WebMock).to have_requested(:post, publish_verification_url).with(body: verification_json, headers: {'Content-Type' => 'application/json'}) end + context "with tags" do + let(:tags) { ['foo'] } + + it "tags the provider version" do + subject + expect(WebMock).to have_requested(:put, 'http://tag-me/foo').with(headers: {'Content-Type' => 'application/json'}) + end + + context "when there is no pb:tag-version link" do + before do + pact_hash['_links'].delete('pb:tag-version') + end + + it "prints a warning" do + expect($stderr).to receive(:puts).with /WARN: Cannot tag provider version/ + subject + end + end + end + context "when basic auth is configured on the pact URL" do let(:basic_auth) { true } it "sets the username and password for the pubication URL" do diff --git a/spec/support/bar_pact_helper.rb b/spec/support/bar_pact_helper.rb index 2b8e6e6a..e518fb3f 100644 --- a/spec/support/bar_pact_helper.rb +++ b/spec/support/bar_pact_helper.rb @@ -16,6 +16,7 @@ def call env Pact.service_provider "Bar" do app { BarApp.new } app_version '1.2.3' + app_version_tags ['master'] publish_verification_results true honours_pact_with 'Foo' do diff --git a/tasks/foo-bar.rake b/tasks/foo-bar.rake index 3f8a58c4..b359f6d8 100644 --- a/tasks/foo-bar.rake +++ b/tasks/foo-bar.rake @@ -1,11 +1,10 @@ require 'pact/tasks/verification_task' # Use for end to end manual debugging of issues. -BROKER_BASE_URL = 'http://127.0.0.1:9292' +BROKER_BASE_URL = 'http://localhost:9292' RSpec::Core::RakeTask.new('pact:foobar:create') do | task | task.pattern = "spec/features/foo_bar_spec.rb" - end task 'pact:foobar:publish' do