Skip to content

Commit

Permalink
feat: add latest version for branch endpoint (#644)
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque authored Dec 6, 2023
1 parent 4adc657 commit c216bec
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 20 deletions.
1 change: 1 addition & 0 deletions lib/pact_broker/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ def self.build_api(application_context = PactBroker::ApplicationContext.default_
add ["pacticipants", :pacticipant_name, "versions", :pacticipant_version_number, "tags", :tag_name], Api::Resources::Tag, {resource_name: "pacticipant_version_tag"}
add ["pacticipants", :pacticipant_name, "branches"], Api::Resources::PacticipantBranches, {resource_name: "pacticipant_branches"}
add ["pacticipants", :pacticipant_name, "branches", :branch_name], Api::Resources::Branch, { resource_name: "branch" }
add ["pacticipants", :pacticipant_name, "branches", :branch_name, "latest-version"], Api::Resources::LatestVersion, { resource_name: "latest_pacticipant_version_for_branch" }
add ["pacticipants", :pacticipant_name, "branches", :branch_name, "versions", :version_number], Api::Resources::BranchVersion, { resource_name: "branch_version" }
add ["pacticipants", :pacticipant_name, "branches", :branch_name, "latest-version", "can-i-deploy", "to-environment", :environment_name], Api::Resources::CanIDeployPacticipantVersionByBranchToEnvironment, { resource_name: "can_i_deploy_latest_branch_version_to_environment" }
add ["pacticipants", :pacticipant_name, "branches", :branch_name, "latest-version", "can-i-deploy", "to-environment", :environment_name, "badge"], Api::Resources::CanIDeployPacticipantVersionByBranchToEnvironmentBadge, { resource_name: "can_i_deploy_latest_branch_version_to_environment_badge" }
Expand Down
2 changes: 1 addition & 1 deletion lib/pact_broker/api/decorators/branch_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class BranchDecorator < BaseDecorator
link "pb:latest-version" do | user_options |
{
title: "Latest version for branch",
href: branch_versions_url(represented, user_options.fetch(:base_url)) + "?size=1"
href: latest_version_for_branch_url(represented, user_options.fetch(:base_url))
}
end

Expand Down
3 changes: 2 additions & 1 deletion lib/pact_broker/api/decorators/version_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ class VersionDecorator < BaseDecorator
{
title: "Version",
name: represented.number,
href: version_url(options.fetch(:base_url), represented)
# This decorator is used for multiple Version resources, so dynamically fetch the current resource URL
href: options.fetch(:resource_url)
}
end

Expand Down
16 changes: 13 additions & 3 deletions lib/pact_broker/api/decorators/versions_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,23 @@ module PactBroker
module Api
module Decorators
class VersionsDecorator < BaseDecorator
class VersionInCollectionDecorator < PactBroker::Api::Decorators::VersionDecorator
# VersionDecorator has a dynamic self URL, depending which path the Version resource is mounted at.
# Hardcode the URL of the embedded Versions in this collection to use the canonical URL with the version number.
link :self do | user_options |
{
title: "Version",
name: represented.number,
href: version_url(user_options.fetch(:base_url), represented)
}
end
end

collection :entries, as: :versions, embedded: true, :extend => PactBroker::Api::Decorators::VersionDecorator
collection :entries, as: :versions, embedded: true, :extend => VersionInCollectionDecorator

link :self do | user_options |
href = append_query_if_present(user_options[:resource_url], user_options[:query_string])
{
href: href,
href: user_options.fetch(:request_url),
title: user_options[:resource_title] || "All application versions of #{user_options[:pacticipant_name]}"
}
end
Expand Down
4 changes: 4 additions & 0 deletions lib/pact_broker/api/pact_broker_urls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,10 @@ def branch_version_url(branch_version, base_url = "")
"#{branch_versions_url(branch_version.branch, base_url)}/#{url_encode(branch_version.version_number)}"
end

def latest_version_for_branch_url(branch, base_url = "")
"#{branch_url(branch, base_url)}/latest-version"
end

def templated_tag_url_for_pacticipant pacticipant_name, base_url = ""
pacticipant_url_from_params({ pacticipant_name: pacticipant_name }, base_url) + "/versions/{version}/tags/{tag}"
end
Expand Down
2 changes: 2 additions & 0 deletions lib/pact_broker/api/resources/latest_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ def allowed_methods
def version
if identifier_from_path[:tag]
@version ||= version_service.find_by_pacticipant_name_and_latest_tag(identifier_from_path[:pacticipant_name], identifier_from_path[:tag])
elsif identifier_from_path[:branch_name]
@version ||= version_service.find_latest_by_pacticipant_name_and_branch_name(identifier_from_path[:pacticipant_name], identifier_from_path[:branch_name])
else
@version ||= version_service.find_latest_by_pacticpant_name(identifier_from_path)
end
Expand Down
18 changes: 18 additions & 0 deletions spec/features/get_latest_version_for_branch_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
describe "Get latest version for branch" do
before do
td.create_consumer("Foo")
.create_consumer_version("1", branch: "main")
.create_consumer_version("2", branch: "main")
.create_consumer_version("3", branch: "not-main")
end
let(:path) { PactBroker::Api::PactBrokerUrls.latest_version_for_branch_url(PactBroker::Versions::Branch.order(:id).first) }
let(:rack_env) { { "CONTENT_TYPE" => "application/json" } }

subject { get(path, {}, rack_env) }

it { is_expected.to be_a_hal_json_success_response }

it "returns the latest version for the branch" do
expect(JSON.parse(subject.body)["number"]).to eq "2"
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"pb:latest-version": {
"title": "Latest version for branch",
"href": "http://example.org/pacticipants/Foo/branches/main/versions?size=1"
"href": "http://example.org/pacticipants/Foo/branches/main/latest-version"
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions spec/lib/pact_broker/api/decorators/version_decorator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ module Decorators
end

let(:base_url) { "http://example.org" }
let(:options) { { user_options: { base_url: base_url, environments: environments } } }
let(:options) { { user_options: { base_url: base_url, resource_url: "resource_url", environments: environments } } }
let(:decorator) { VersionDecorator.new(version) }

subject { JSON.parse(decorator.to_json(options), symbolize_names: true) }

it "includes a link to itself" do
expect(subject[:_links][:self][:href]).to eq "http://example.org/pacticipants/Consumer/versions/1.2.3"
expect(subject[:_links][:self][:href]).to eq "resource_url"
end

it "includes the version number in the link" do
Expand Down Expand Up @@ -125,7 +125,7 @@ module Decorators
end

context "when the environments option is not present" do
let(:options) { { user_options: { base_url: base_url } } }
let(:options) { { user_options: { base_url: base_url, resource_url: "resource_url" } } }

it "does not include the pb:record-deployment or pb:record-release" do
expect(subject[:_links]).to_not have_key(:'pb:record-deployment')
Expand Down
23 changes: 12 additions & 11 deletions spec/lib/pact_broker/api/decorators/versions_decorator_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,18 @@ module PactBroker
module Api
module Decorators
describe VersionsDecorator do
before do
allow_any_instance_of(VersionsDecorator::VersionInCollectionDecorator).to receive(:version_url).and_return("version_url")
end

let(:options) { { resource_url: "http://versions", base_url: "http://example.org", pacticipant_name: "Consumer", query_string: query_string}}
let(:query_string) { nil }
let(:options) { { request_url: "http://versions?foo=bar", base_url: "http://example.org", pacticipant_name: "Consumer", resource_url: "http://versions" } }
let(:versions) { [] }
let(:decorator) { VersionsDecorator.new(versions) }
let(:json) { decorator.to_json(user_options: options) }

subject { JSON.parse VersionsDecorator.new(versions).to_json(user_options: options), symbolize_names: true }

context "with no query string" do
its([:_links, :self, :href]) { is_expected.to eq "http://versions" }
end
subject { JSON.parse(json, symbolize_names: true) }

context "with a query string" do
let(:query_string) { "foo=bar" }
its([:_links, :self, :href]) { is_expected.to eq "http://versions?foo=bar" }
end
its([:_links, :self, :href]) { is_expected.to eq "http://versions?foo=bar" }

context "with no versions" do
it "doesn't blow up" do
Expand All @@ -41,6 +38,10 @@ module Decorators
expect(subject[:_embedded][:versions]).to be_instance_of(Array)
expect(subject[:_embedded][:versions].size).to eq 1
end

it "has the version href with the version number" do
expect(subject[:_embedded][:versions].first[:_links][:self][:href]).to eq "version_url"
end
end
end
end
Expand Down

0 comments on commit c216bec

Please sign in to comment.