Skip to content

Commit

Permalink
feat(clean): support keeping currently deployed and released versions…
Browse files Browse the repository at this point in the history
…, and the latest version for each branch
  • Loading branch information
bethesque committed Aug 17, 2021
1 parent a93513f commit e4fbd76
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 9 deletions.
8 changes: 7 additions & 1 deletion lib/pact_broker/db/clean.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require "pact_broker/project_root"
require "pact_broker/pacts/latest_tagged_pact_publications"
require "pact_broker/logging"
require "pact_broker/db/clean/selector"

module PactBroker
module DB
Expand All @@ -24,7 +25,12 @@ def initialize database_connection, options = {}
end

def keep
options[:keep] || [PactBroker::Matrix::UnresolvedSelector.new(tag: true, latest: true), PactBroker::Matrix::UnresolvedSelector.new(latest: true)]
@keep ||= if options[:keep]
# Could be a Matrix::UnresolvedSelector from the docker image, convert it
options[:keep].collect { | unknown_thing | Selector.from_hash(unknown_thing.to_hash) }
else
[Selector.new(tag: true, latest: true), Selector.new(branch: true, latest: true), Selector.new(latest: true), Selector.new(deployed: true), Selector.new(released: true)]
end
end

def resolve_ids(query, column_name = :id)
Expand Down
54 changes: 54 additions & 0 deletions lib/pact_broker/db/clean/selector.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
require "pact_broker/hash_refinements"

module PactBroker
module DB
class Clean
class Selector
using PactBroker::HashRefinements

ATTRIBUTES = [:pacticipant_name, :latest, :tag, :branch, :environment_name, :max_age, :deployed, :released, :main_branch]

attr_accessor *ATTRIBUTES

def initialize(attributes = {})
attributes.each do | (name, value) |
instance_variable_set("@#{name}", value) if respond_to?(name)
end
@source_hash = attributes[:source_hash]
end

def self.from_hash(hash)
standard_hash = hash.symbolize_keys.snakecase_keys
new_hash = standard_hash.slice(*ATTRIBUTES)
new_hash[:pacticipant_name] ||= standard_hash[:pacticipant] if standard_hash[:pacticipant]
new_hash[:environment_name] ||= standard_hash[:environment] if standard_hash[:environment]
new_hash[:source_hash] = hash
new(new_hash.compact)
end

def to_hash
ATTRIBUTES.each_with_object({}) do | key, hash |
hash[key] = send(key)
end.compact
end
alias_method :to_h, :to_hash

def to_json
(@source_hash || to_hash).to_json
end

def currently_deployed?
!!deployed
end

def currently_supported?
!!released
end

def latest?
!!latest
end
end
end
end
end
31 changes: 28 additions & 3 deletions lib/pact_broker/domain/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,16 @@ def currently_supported_in_environment(environment_name, pacticipant_name)
where(id: supported_version_query.select(:version_id))
end

def currently_deployed
deployed_version_query = PactBroker::Deployments::DeployedVersion.currently_deployed
where(id: deployed_version_query.select(:version_id))
end

def currently_supported
supported_version_query = PactBroker::Deployments::ReleasedVersion.currently_supported
where(id: supported_version_query.select(:version_id))
end

def where_tag(tag)
if tag == true
join(:tags, Sequel[:tags][:version_id] => Sequel[first_source_alias][:id])
Expand All @@ -129,7 +139,19 @@ def where_tag(tag)
end

def where_branch(branch)
where(branch: branch)
if branch == true
exclude(branch: nil)
else
where(branch: branch)
end
end

def for_main_branches
pacticipants_join = {
Sequel[:versions][:pacticipant_id] => Sequel[:pacticipants][:id],
Sequel[:pacticipants][:main_branch] => Sequel[:versions][:branch]
}
where(id: select(Sequel[:versions][:id]).join(:pacticipants, pacticipants_join))
end

def where_number(number)
Expand Down Expand Up @@ -161,10 +183,13 @@ def for_selector(selector)
query = self
query = query.where_pacticipant_name(selector.pacticipant_name) if selector.pacticipant_name
query = query.currently_in_environment(selector.environment_name, selector.pacticipant_name) if selector.environment_name
query = query.currently_deployed if selector.respond_to?(:currently_deployed?) && selector.currently_deployed?
query = query.currently_supported if selector.respond_to?(:currently_supported?) && selector.currently_supported?
query = query.where_tag(selector.tag) if selector.tag
query = query.where_branch(selector.branch) if selector.branch
query = query.where_number(selector.pacticipant_version_number) if selector.pacticipant_version_number
query = query.where_age_less_than(selector.max_age) if selector.max_age
query = query.for_main_branches if selector.respond_to?(:main_branch) && selector.main_branch
query = query.where_number(selector.pacticipant_version_number) if selector.respond_to?(:pacticipant_version_number) && selector.pacticipant_version_number
query = query.where_age_less_than(selector.max_age) if selector.respond_to?(:max_age) && selector.max_age

if selector.latest
calculate_max_version_order_and_join_back_to_versions(query, selector)
Expand Down
5 changes: 3 additions & 2 deletions lib/pact_broker/matrix/unresolved_selector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def initialize(params = {})
end

def self.from_hash(hash)
new(hash.symbolize_keys.snakecase_keys.slice(:pacticipant_name, :pacticipant_version_number, :latest, :tag, :branch, :environment_name, :max_age))
new(hash.symbolize_keys.snakecase_keys.slice(:pacticipant_name, :pacticipant_version_number, :latest, :tag, :branch, :environment_name))
end

def pacticipant_name
Expand All @@ -26,7 +26,7 @@ def latest?
end

def overall_latest?
latest? && !tag && !max_age
latest? && !tag && !branch
end

def latest
Expand Down Expand Up @@ -69,6 +69,7 @@ def pacticipant_version_number= pacticipant_version_number
self[:pacticipant_version_number] = pacticipant_version_number
end

# TODO delete this once docker image uses new selector class for clean
def max_age= max_age
self[:max_age] = max_age
end
Expand Down
4 changes: 2 additions & 2 deletions spec/lib/pact_broker/db/clean_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ def pact_publication_count_for(consumer_name, version_number)
let(:db) { PactBroker::DB.connection }

subject { Clean.call(PactBroker::DB.connection, options) }
let(:latest_dev_selector) { PactBroker::Matrix::UnresolvedSelector.new(tag: "dev", latest: true) }
let(:all_prod_selector) { PactBroker::Matrix::UnresolvedSelector.new(tag: "prod") }
let(:latest_dev_selector) { { tag: "dev", latest: true } }
let(:all_prod_selector) { { tag: "prod" } }

describe ".call"do
context "when there are specified versions to keep" do
Expand Down
128 changes: 127 additions & 1 deletion spec/lib/pact_broker/domain/version_spec.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "pact_broker/domain/version"
require "pact_broker/db/clean/selector"

module PactBroker
module Domain
Expand Down Expand Up @@ -131,16 +132,87 @@ def version_numbers
.create_consumer_version("3", tag_names: %w{master})
end

let(:selector) { PactBroker::Matrix::UnresolvedSelector.new(tag: "master", max_age: max_age) }
let(:selector) { PactBroker::DB::Clean::Selector.new(tag: "master", max_age: max_age) }

let(:max_age) { 3 }
let(:four_days_ago) { Date.today - 4 }

it "selects the consumer versions younger than the max age" do
require 'pry'; pry(binding);
expect(version_numbers).to eq %w{2 3}
end
end

context "when selecting the latest version for each branch" do
before do
td.create_consumer("Foo")
.create_consumer_version("1", branch: "main")
.create_consumer_version("2", branch: "main")
.create_consumer("Bar")
.create_consumer_version("3", branch: "main")
end

let(:selector) { PactBroker::DB::Clean::Selector.new(branch: true, latest: true) }

it "selects the consumer versions that are the latest for their branches" do
expect(version_numbers).to eq %w{2 3}
end
end

context "when selecting all versions with a branch" do
before do
td.create_consumer("Foo")
.create_consumer_version("1", branch: "main")
.create_consumer_version("2")
.create_consumer("Bar")
.create_consumer_version("3", branch: "main")
end

let(:selector) { PactBroker::DB::Clean::Selector.new(branch: true, latest: true) }

it "selects the consumer versions that are the latest for their branches" do
expect(version_numbers).to eq %w{1 3}
end
end

context "when selecting the latest versions from the main branches" do
before do
td.create_consumer("Foo", main_branch: "main")
.create_consumer_version("1", branch: "main")
.create_consumer_version("2", branch: "main")
.create_consumer_version("3", branch: "not-main")
.create_consumer("Bar", main_branch: "develop")
.create_consumer_version("4", branch: "develop")
.create_consumer_version("5", branch: "develop")
.create_consumer_version("6", branch: "main")
end

let(:selector) { PactBroker::DB::Clean::Selector.new(main_branch: true, latest: true) }

it "selects the consumer versions that are the latest for their branches" do
expect(version_numbers).to eq %w{2 5}
end
end

context "when selecting all versions from the main branches" do
before do
td.create_consumer("Foo", main_branch: "main")
.create_consumer_version("1", branch: "main")
.create_consumer_version("2", branch: "main")
.create_consumer_version("3", branch: "not-main")
.create_consumer("Bar", main_branch: "develop")
.create_consumer_version("4", branch: "develop")
.create_consumer_version("5", branch: "develop")
.create_consumer_version("6", branch: "main")
end

let(:selector) { PactBroker::DB::Clean::Selector.new(main_branch: true) }

it "selects the consumer versions that are the latest for their branches" do
expect(version_numbers).to eq %w{1 2 4 5}
end
end

context "when selecting all versions of a pacticipant currently deployed to an environment" do
let(:selector) { PactBroker::Matrix::UnresolvedSelector.new(environment_name: "prod", pacticipant_name: "Foo") }

Expand Down Expand Up @@ -194,6 +266,60 @@ def version_numbers
end
end

context "when selecting all currently deployed versions" do
let(:selector) { PactBroker::DB::Clean::Selector.new(deployed: true) }

before do
td.create_environment("test")
.create_consumer("Foo")
.create_consumer_version("1")
.create_deployed_version_for_consumer_version(target: "1")
.create_consumer_version("2")
.create_environment("prod")
.create_deployed_version_for_consumer_version(target: "2")
.create_consumer_version("3")
.create_consumer_version("5")
.create_consumer("Bar")
.create_consumer_version("10")
.create_deployed_version_for_consumer_version(target: "3")
.create_consumer_version("11")
.create_deployed_version_for_consumer_version(currently_deployed: false)
.create_consumer_version("12")
.create_released_version_for_consumer_version
end

it "returns the versions that are currently deployed" do
expect(version_numbers).to eq %w{1 2 10}
end
end

context "when selecting all currently released+supported versions" do
let(:selector) { PactBroker::DB::Clean::Selector.new(released: true) }

before do
td.create_environment("test")
.create_consumer("Foo")
.create_consumer_version("1")
.create_released_version_for_consumer_version
.create_consumer_version("2")
.create_environment("prod")
.create_released_version_for_consumer_version
.create_consumer_version("3")
.create_consumer_version("5")
.create_consumer("Bar")
.create_consumer_version("10")
.create_released_version_for_consumer_version
.create_consumer_version("11")
.create_released_version_for_consumer_version(currently_supported: false)
.create_consumer_version("12")
.create_deployed_version_for_consumer_version
end

it "returns the versions that are currently released+supported" do
expect(version_numbers).to eq %w{1 2 10}
end
end

context "selecting versions for a branch" do
before do
td.create_consumer("Foo")
Expand Down

0 comments on commit e4fbd76

Please sign in to comment.