Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add branch endpoint supporting GET and DELETE #635

Merged
merged 1 commit into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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