From 77826d36de7ddb53c8279ded69bef8e6c306698d Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Fri, 4 Oct 2024 17:30:05 +0100 Subject: [PATCH] feat: add provider pacts by branch endpoints "pb:latest-provider-pacts-with-branch": { "href": "http://localhost:9292/pacts/provider/{provider}/latest/branch/{branch}", "title": "Latest pacts for provider with the specified branch", "templated": true }, "pb:provider-pacts-with-branch": { "href": "http://localhost:9292/pacts/provider/{provider}/branch/{branch}", "title": "All pact versions for the provider with the specified consumer version branch", "templated": true }, --- lib/pact_broker/api.rb | 2 + lib/pact_broker/api/resources/index.rb | 12 ++++++ .../latest_provider_pacts_for_branch.rb | 22 ++++++++++ .../provider_pacts_for_consumer_branch.rb | 43 +++++++++++++++++++ ...latest-provider-pacts-with-branch.markdown | 7 +++ .../latest-provider-pacts-with-tag.markdown | 4 +- .../index/provider-pacts-with-branch.markdown | 7 +++ .../index/provider-pacts-with-tag.markdown | 2 + lib/pact_broker/pacts/service.rb | 4 ++ .../latest_provider_pacts_for_branch_spec.rb | 36 ++++++++++++++++ 10 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 lib/pact_broker/api/resources/latest_provider_pacts_for_branch.rb create mode 100644 lib/pact_broker/api/resources/provider_pacts_for_consumer_branch.rb create mode 100644 lib/pact_broker/doc/views/index/latest-provider-pacts-with-branch.markdown create mode 100644 lib/pact_broker/doc/views/index/provider-pacts-with-branch.markdown create mode 100644 spec/lib/pact_broker/api/resources/latest_provider_pacts_for_branch_spec.rb diff --git a/lib/pact_broker/api.rb b/lib/pact_broker/api.rb index a9e5f9ef8..9f6b76f1b 100644 --- a/lib/pact_broker/api.rb +++ b/lib/pact_broker/api.rb @@ -43,6 +43,7 @@ def self.build_api(application_context = PactBroker::ApplicationContext.default_ add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "version", :consumer_version_number, "diff", "previous-distinct"], Api::Resources::PactContentDiff, {resource_name: "previous_distinct_pact_version_diff"} add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "version", :consumer_version_number, "diff", "version", :comparison_consumer_version], Api::Resources::PactContentDiff, {resource_name: "pact_version_diff_by_consumer_version"} add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "pact-version", :pact_version_sha, "diff", "pact-version", :comparison_pact_version_sha], Api::Resources::PactContentDiff, {resource_name: "pact_version_diff_by_pact_version_sha"} + add ["pacts", "provider", :provider_name, "branch", :branch], Api::Resources::ProviderPactsForConsumerBranch, {resource_name: "branch_provider_pact_publications"} # Verifications add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "pact-version", :pact_version_sha, "verification-results"], Api::Resources::Verifications, {resource_name: "verification_results"} @@ -70,6 +71,7 @@ def self.build_api(application_context = PactBroker::ApplicationContext.default_ add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "latest-untagged"], Api::Resources::LatestPact, {resource_name: "latest_untagged_pact_publication", tag: :untagged} add ["pacts", "provider", :provider_name, "latest"], Api::Resources::LatestProviderPacts, {resource_name: "latest_provider_pact_publications"} add ["pacts", "provider", :provider_name, "latest", :tag], Api::Resources::LatestProviderPacts, {resource_name: "latest_tagged_provider_pact_publications"} + add ["pacts", "provider", :provider_name, "latest", "branch", :branch], Api::Resources::LatestProviderPactsForBranch, {resource_name: "latest_branch_provider_pact_publications"} add ["pacts", "latest"], Api::Resources::LatestPacts, {resource_name: "latest_pacts"} # Pacts for verification diff --git a/lib/pact_broker/api/resources/index.rb b/lib/pact_broker/api/resources/index.rb index 83877f91e..b02aaf731 100644 --- a/lib/pact_broker/api/resources/index.rb +++ b/lib/pact_broker/api/resources/index.rb @@ -73,12 +73,24 @@ def links title: "Latest pacts for provider with the specified tag", templated: true }, + "pb:latest-provider-pacts-with-branch" => + { + href: base_url + "/pacts/provider/{provider}/latest/branch/{branch}", + title: "Latest pacts for provider with the specified branch", + templated: true + }, "pb:provider-pacts-with-tag" => { href: base_url + "/pacts/provider/{provider}/tag/{tag}", title: "All pact versions for the provider with the specified consumer version tag", templated: true }, + "pb:provider-pacts-with-branch" => + { + href: base_url + "/pacts/provider/{provider}/branch/{branch}", + title: "All pact versions for the provider with the specified consumer version branch", + templated: true + }, "pb:provider-pacts" => { href: base_url + "/pacts/provider/{provider}", diff --git a/lib/pact_broker/api/resources/latest_provider_pacts_for_branch.rb b/lib/pact_broker/api/resources/latest_provider_pacts_for_branch.rb new file mode 100644 index 000000000..0ff91a16b --- /dev/null +++ b/lib/pact_broker/api/resources/latest_provider_pacts_for_branch.rb @@ -0,0 +1,22 @@ +require "pact_broker/api/resources/provider_pacts" +require "pact_broker/configuration" +require "pact_broker/api/decorators/provider_pacts_decorator" + +module PactBroker + module Api + module Resources + class LatestProviderPactsForBranch < ProviderPacts + private + + def pacts + pact_service.find_latest_pacts_for_provider_for_branch(provider_name, branch: identifier_from_path[:branch]) + end + + def resource_title + suffix = identifier_from_path[:branch] ? " with consumer version branch '#{identifier_from_path[:branch]}'" : "" + "Latest pact versions for the provider #{identifier_from_path[:provider_name]}#{suffix}" + end + end + end + end +end diff --git a/lib/pact_broker/api/resources/provider_pacts_for_consumer_branch.rb b/lib/pact_broker/api/resources/provider_pacts_for_consumer_branch.rb new file mode 100644 index 000000000..1ee86e588 --- /dev/null +++ b/lib/pact_broker/api/resources/provider_pacts_for_consumer_branch.rb @@ -0,0 +1,43 @@ +require "pact_broker/api/resources/base_resource" +require "pact_broker/configuration" +require "pact_broker/api/decorators/provider_pacts_decorator" + +module PactBroker + module Api + module Resources + class ProviderPactsForConsumerBranch < BaseResource + + def content_types_provided + [["application/hal+json", :to_json]] + end + + def allowed_methods + ["GET", "OPTIONS"] + end + + def resource_exists? + !!provider + end + + def policy_name + :'pacts::provider_pacts' + end + + def to_json + decorator_class(:provider_pacts_decorator).new(pacts).to_json(**decorator_options(identifier_from_path.merge(title: resource_title))) + end + + private + + def pacts + pact_service.find_pact_versions_for_provider provider_name, branch: identifier_from_path[:branch] + end + + def resource_title + suffix = identifier_from_path[:branch] ? " with consumer version branch '#{identifier_from_path[:branch]}'" : "" + "All pact versions for the provider #{identifier_from_path[:provider_name]}#{suffix}" + end + end + end + end +end diff --git a/lib/pact_broker/doc/views/index/latest-provider-pacts-with-branch.markdown b/lib/pact_broker/doc/views/index/latest-provider-pacts-with-branch.markdown new file mode 100644 index 000000000..790eb6773 --- /dev/null +++ b/lib/pact_broker/doc/views/index/latest-provider-pacts-with-branch.markdown @@ -0,0 +1,7 @@ +# Latest pacts for provider with the specified consumer branch + +Allowed methods: `GET` + +Path: `/pacts/provider/{provider}/latest/branch/{branch}` + +Given a provider name and a consumer version branch name, this resource returns the latest pact for each consumer that has the specified branch. diff --git a/lib/pact_broker/doc/views/index/latest-provider-pacts-with-tag.markdown b/lib/pact_broker/doc/views/index/latest-provider-pacts-with-tag.markdown index d31cfa756..a12e5202c 100644 --- a/lib/pact_broker/doc/views/index/latest-provider-pacts-with-tag.markdown +++ b/lib/pact_broker/doc/views/index/latest-provider-pacts-with-tag.markdown @@ -1,5 +1,7 @@ -# Latest pacts for provider with the specified tag +# Latest pacts for provider with the specified consumer version tag Allowed methods: `GET` +Path: `/pacts/provider/{provider}/latest/{tag}` + Given a provider name and a consumer version tag name, this resource returns the latest pact for each consumer that has the specified tag. diff --git a/lib/pact_broker/doc/views/index/provider-pacts-with-branch.markdown b/lib/pact_broker/doc/views/index/provider-pacts-with-branch.markdown new file mode 100644 index 000000000..61d49733b --- /dev/null +++ b/lib/pact_broker/doc/views/index/provider-pacts-with-branch.markdown @@ -0,0 +1,7 @@ +# Provider pacts with consumer branch + +Allowed methods: `GET` + +Path: `/pacts/provider/{provider}/branch/{branch}` + +Given a pacticipant name and a consumer branch, this resource returns all the pact versions for all consumers of this provider with the specified consumer branch. For most use cases, the `latest-provider-pacts-with-branch` relation will better serve consumer needs by only returning the latest pact version for specified consumer branches. diff --git a/lib/pact_broker/doc/views/index/provider-pacts-with-tag.markdown b/lib/pact_broker/doc/views/index/provider-pacts-with-tag.markdown index 77262ec32..ddfaa49f8 100644 --- a/lib/pact_broker/doc/views/index/provider-pacts-with-tag.markdown +++ b/lib/pact_broker/doc/views/index/provider-pacts-with-tag.markdown @@ -2,4 +2,6 @@ Allowed methods: `GET` +Path: `/pacts/provider/{provider}/tag/{tag}` + Given a pacticipant name and a consumer version tag, this resource returns all the pact versions for all consumers of this provider with the specified tag. The most common use of this resource is to find all the `production` pact versions for the mobile consumers of an API, so that backwards compatibility can be maintained. diff --git a/lib/pact_broker/pacts/service.rb b/lib/pact_broker/pacts/service.rb index 6ec1adacb..b476e57e7 100644 --- a/lib/pact_broker/pacts/service.rb +++ b/lib/pact_broker/pacts/service.rb @@ -95,6 +95,10 @@ def find_latest_pacts_for_provider provider_name, options = {} pact_repository.find_latest_pacts_for_provider provider_name, options[:tag] end + def find_latest_pacts_for_provider_for_branch provider_name, options = {} + pact_repository.find_latest_pacts_for_provider provider_name, options[:branch] + end + def find_pact_versions_for_provider provider_name, options = {} pact_repository.find_pact_versions_for_provider provider_name, options[:tag] end diff --git a/spec/lib/pact_broker/api/resources/latest_provider_pacts_for_branch_spec.rb b/spec/lib/pact_broker/api/resources/latest_provider_pacts_for_branch_spec.rb new file mode 100644 index 000000000..6ac17c258 --- /dev/null +++ b/spec/lib/pact_broker/api/resources/latest_provider_pacts_for_branch_spec.rb @@ -0,0 +1,36 @@ +require "pact_broker/api/resources/latest_provider_pacts_for_branch" + +module PactBroker + module Api + module Resources + describe LatestProviderPactsForBranch do + before do + allow(PactBroker::Pacts::Service).to receive(:find_latest_pacts_for_provider_for_branch).and_return(pacts) + allow(PactBroker::Api::Decorators::ProviderPactsDecorator).to receive(:new).and_return(decorator) + allow_any_instance_of(LatestProviderPactsForBranch).to receive(:resource_exists?).and_return(provider) + end + + let(:provider) { double("provider") } + let(:pacts) { double("pacts") } + let(:path) { "/pacts/provider/Bar/latest/branch/prod" } + let(:decorator) { instance_double("PactBroker::Api::Decorators::ProviderPactsDecorator") } + + subject { get path; last_response } + + context "with a branch" do + it "finds the pacts with a branch" do + expect(PactBroker::Pacts::Service).to receive(:find_latest_pacts_for_provider_for_branch).with("Bar", branch: "prod") + subject + end + + it "sets the correct resource title" do + expect(decorator).to receive(:to_json) do | options | + expect(options[:user_options][:title]).to eq "Latest pact versions for the provider Bar with consumer version branch 'prod'" + end + subject + end + end + end + end + end +end