Skip to content

Commit

Permalink
feat: add branch endpoint supporting GET and DELETE (#635)
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque authored Sep 12, 2023
1 parent d0c5ad2 commit 1bb6088
Show file tree
Hide file tree
Showing 14 changed files with 246 additions and 27 deletions.
1 change: 1 addition & 0 deletions lib/pact_broker/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ def self.build_api(application_context = PactBroker::ApplicationContext.default_
add ["pacticipants", :pacticipant_name, "latest-version", :tag, "can-i-deploy", "to", :to, "badge"], Api::Resources::CanIDeployPacticipantVersionByTagToTagBadge, { resource_name: "can_i_deploy_latest_tagged_version_to_tag_badge" }
add ["pacticipants", :pacticipant_name, "latest-version"], Api::Resources::LatestVersion, {resource_name: "latest_pacticipant_version"}
add ["pacticipants", :pacticipant_name, "versions", :pacticipant_version_number, "tags", :tag_name], Api::Resources::Tag, {resource_name: "pacticipant_version_tag"}
add ["pacticipants", :pacticipant_name, "branches", :branch_name], Api::Resources::Branch, { resource_name: "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
29 changes: 29 additions & 0 deletions lib/pact_broker/api/decorators/branch_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require "pact_broker/api/decorators/base_decorator"
require "pact_broker/api/decorators/timestamps"

module PactBroker
module Api
module Decorators
class BranchDecorator < BaseDecorator

property :name

link :self do | user_options |
{
title: "Branch",
href: branch_url(represented, user_options.fetch(:base_url))
}
end

link "pb:latest-version" do | user_options |
{
title: "Latest version for branch",
href: branch_versions_url(represented, user_options.fetch(:base_url)) + "?pageSize=1"
}
end

include Timestamps
end
end
end
end
16 changes: 16 additions & 0 deletions lib/pact_broker/api/decorators/branch_version_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@ class BranchVersionDecorator < BaseDecorator
}
end

link :"pb:branch" do | user_options |
{
title: "Branch",
name: represented.branch.name,
href: branch_url(represented.branch, user_options.fetch(:base_url))
}
end

link :"pb:version" do | user_options |
{
title: "Version",
name: represented.version.number,
href: version_url(user_options.fetch(:base_url), represented.version)
}
end

include Timestamps
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class EmbeddedBranchVersionDecorator < BaseDecorator

link :self do | options |
{
title: "Version branch",
title: "Branch version",
name: represented.branch_name,
href: branch_version_url(represented, options[:base_url])
}
Expand Down
6 changes: 5 additions & 1 deletion lib/pact_broker/api/pact_broker_urls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,12 @@ def tag_url base_url, tag
"#{tags_url(base_url, tag.version)}/#{url_encode(tag.name)}"
end

def branch_url(branch, base_url = "")
"#{pacticipant_url(base_url, branch.pacticipant)}/branches/#{url_encode(branch.name)}"
end

def branch_versions_url(branch, base_url = "")
"#{pacticipant_url(base_url, branch.pacticipant)}/branches/#{url_encode(branch.name)}/versions"
"#{branch_url(branch, base_url)}/versions"
end

def branch_version_url(branch_version, base_url = "")
Expand Down
40 changes: 40 additions & 0 deletions lib/pact_broker/api/resources/branch.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
require "pact_broker/api/resources/base_resource"

module PactBroker
module Api
module Resources
class Branch < BaseResource
def content_types_provided
[["application/hal+json", :to_json]]
end

def allowed_methods
["GET", "DELETE", "OPTIONS"]
end

def resource_exists?
!!branch
end

def to_json
decorator_class(:branch_decorator).new(branch).to_json(**decorator_options)
end

def delete_resource
branch_service.delete_branch(branch)
true
end

def policy_name
:'versions::branch'
end

private

def branch
@branch_version ||= branch_service.find_branch(**identifier_from_path.slice(:pacticipant_name, :branch_name))
end
end
end
end
end
9 changes: 9 additions & 0 deletions lib/pact_broker/repositories.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ def matrix_repository
get_repository(:matrix_repository)
end

def branch_repository
get_repository(:branch_repository)
end

def branch_version_repository
get_repository(:branch_version_repository)
end
Expand Down Expand Up @@ -96,6 +100,11 @@ def register_default_repositories
Matrix::Repository.new
end

register_repository(:branch_repository) do
require "pact_broker/versions/branch_repository"
PactBroker::Versions::BranchRepository.new
end

register_repository(:branch_version_repository) do
require "pact_broker/versions/branch_version_repository"
PactBroker::Versions::BranchVersionRepository.new
Expand Down
28 changes: 28 additions & 0 deletions lib/pact_broker/versions/branch_repository.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module PactBroker
module Versions
class BranchRepository
include PactBroker::Services

# @param [String] pacticipant_name
# @param [String] branch_name
# @return [PactBroker::Versions::Branch, nil]
def find_branch(pacticipant_name:, branch_name:)
Branch
.select_all_qualified
.join(:pacticipants, { Sequel[:branches][:pacticipant_id] => Sequel[:pacticipants][:id] }) do
Sequel.name_like(Sequel[:pacticipants][:name], pacticipant_name)
end
.where(Sequel[:branches][:name] => branch_name)
.single_record
end

# Deletes a branch, its branch head and branch_version objects, without deleting the
# pacticipant version objects
#
# @param [PactBroker::Versions::Branch] the branch to delete
def delete_branch(branch)
branch.delete
end
end
end
end
27 changes: 2 additions & 25 deletions lib/pact_broker/versions/branch_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,8 @@ class BranchService

class << self
extend Forwardable
delegate [:delete_branch_version] => :branch_version_repository
end


def self.find_branch_version(pacticipant_name:, branch_name:, version_number:, **)
BranchVersion.where(
version: PactBroker::Domain::Version.where_pacticipant_name_and_version_number(pacticipant_name, version_number),
branch: Branch.where(name: branch_name)
).single_record
end

def self.find_or_create_branch_version(pacticipant_name:, branch_name:, version_number:, **)
pacticipant = pacticipant_repository.find_by_name_or_create(pacticipant_name)
version = version_repository.find_by_pacticipant_id_and_number_or_create(pacticipant.id, version_number)
branch_version_repository.add_branch(version, branch_name)
end

def self.find_branch(pacticipant_name:, branch_name:)
Branch
.select_all_qualified
.join(:pacticipants, { Sequel[:branches][:pacticipant_id] => Sequel[:pacticipants][:id] }) do
Sequel.name_like(Sequel[:pacticipants][:name], pacticipant_name)
end
.where(Sequel[:branches][:name] => branch_name)
.single_record
delegate [:find_branch_version, :find_or_create_branch_version, :delete_branch_version] => :branch_version_repository
delegate [:find_branch, :delete_branch] => :branch_repository
end
end
end
Expand Down
17 changes: 17 additions & 0 deletions lib/pact_broker/versions/branch_version_repository.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
require "pact_broker/versions/branch_version"
require "pact_broker/services"

module PactBroker
module Versions
class BranchVersionRepository
include PactBroker::Services
include PactBroker::Repositories

def find_branch_version(pacticipant_name:, branch_name:, version_number:, **)
BranchVersion.where(
version: PactBroker::Domain::Version.where_pacticipant_name_and_version_number(pacticipant_name, version_number),
branch: Branch.where(name: branch_name)
).single_record
end

def find_or_create_branch_version(pacticipant_name:, branch_name:, version_number:, **)
pacticipant = pacticipant_repository.find_by_name_or_create(pacticipant_name)
version = version_repository.find_by_pacticipant_id_and_number_or_create(pacticipant.id, version_number)
branch_version_repository.add_branch(version, branch_name)
end

def add_branch(version, branch_name, auto_created: false)
branch = find_or_create_branch(version.pacticipant, branch_name)
Expand Down
46 changes: 46 additions & 0 deletions spec/features/delete_branch_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
describe "Deleting a branch (removing all versions from a branch)" do
before do
td.create_consumer("foo")
.create_consumer_version("1234", branch: "main")
.create_consumer_version("1234", branch: "not-main")
.create_consumer_version("555", branch: "main")
.create_consumer("bar")
.create_consumer_version("1234", branch: "main")
end

let(:path) { "/pacticipants/foo/branches/main" }
let(:headers) { {} }
let(:response_body) { JSON.parse(subject.body, symbolize_names: true) }

subject { delete(path, nil, headers) }

it "returns a 204 response" do
expect(subject.status).to be 204
end

it "deletes the branch" do
expect { subject }.to change { PactBroker::Versions::Branch.count }.by(-1)
end

it "does not delete the pacticipant versions" do
expect { subject }.to_not change { PactBroker::Domain::Version.count }
end

context "when the branch version does not exist" do
let(:path) { "/pacticipants/waffle/branches/main" }

its(:status) { is_expected.to eq 404 }
end

context "when there is some flag to indicate that the versions should be deleted too" do
subject { delete(path, { deletedAssociatedVersions: true }, headers) }

it "deletes the branch" do
expect { subject }.to change { PactBroker::Versions::Branch.count }.by(-1)
end

it "DOES delete the pacticipant versions", pending: true do
expect { subject }.to change { PactBroker::Domain::Version.count }.by(-2)
end
end
end
12 changes: 12 additions & 0 deletions spec/features/get_branch_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
describe "Get a branch" do
before do
td.create_consumer("Foo")
.create_consumer_version("1234", branch: "main")
end
let(:path) { PactBroker::Api::PactBrokerUrls.branch_url(PactBroker::Versions::Branch.first) }
let(:headers) { { "CONTENT_TYPE" => "application/json" } }

subject { get(path, nil, headers) }

it { is_expected.to be_a_hal_json_success_response }
end
38 changes: 38 additions & 0 deletions spec/lib/pact_broker/versions/branch_repository_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require "pact_broker/versions/branch_repository"

module PactBroker
module Versions
describe BranchRepository do
describe "delete_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")
.create_consumer("bar")
.create_consumer_version("1", branch: "main")
end

let(:branch) { BranchRepository.new.find_branch(pacticipant_name: "foo", branch_name: "main") }

subject { BranchRepository.new.delete_branch(branch) }

it "deletes the branch" do
expect{ subject }.to change { Branch.count }.by(-1)
end

it "deletes the branch versions" do
expect{ subject }.to change { BranchVersion.count }.by(-2)
end

it "deletes the branch head" do
expect{ subject }.to change { BranchHead.count }.by(-1)
end

it "does not delete the versions" do
expect{ subject }.to_not change { PactBroker::Domain::Version.count }
end
end
end
end
end
2 changes: 2 additions & 0 deletions spec/support/all_routes_spec_support.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ requests_which_are_exected_to_have_no_policy_record:
- pacticipant DELETE
- can_i_deploy_latest_branch_version_to_environment GET
- can_i_deploy_latest_branch_version_to_environment_badge GET
- branch GET
- branch DELETE
- branch_version GET
- branch_version PUT
- branch_version DELETE
Expand Down

0 comments on commit 1bb6088

Please sign in to comment.