From a086214a32692031a8abc3f147d9b619d70cb769 Mon Sep 17 00:00:00 2001 From: Beth Skurrie Date: Fri, 6 Aug 2021 21:30:54 +1000 Subject: [PATCH] feat: allow the first tag to be used as the branch name to assist migrating to branches (#478) --- .../config/runtime_configuration.rb | 2 + .../pacts_for_verification_repository.rb | 11 ++- lib/pact_broker/tags/service.rb | 20 ++++- lib/pact_broker/versions/repository.rb | 5 ++ spec/lib/pact_broker/tags/service_spec.rb | 90 +++++++++++++++++-- 5 files changed, 118 insertions(+), 10 deletions(-) diff --git a/lib/pact_broker/config/runtime_configuration.rb b/lib/pact_broker/config/runtime_configuration.rb index 7d52eb6c6..6a20ad497 100644 --- a/lib/pact_broker/config/runtime_configuration.rb +++ b/lib/pact_broker/config/runtime_configuration.rb @@ -60,6 +60,8 @@ class RuntimeConfiguration < Anyway::Config base_equality_only_on_content_that_affects_verification_results: true, check_for_potential_duplicate_pacticipant_names: true, create_deployed_versions_for_tags: true, + use_first_tag_as_branch: true, + use_first_tag_as_branch_time_limit: 10, semver_formats: ["%M.%m.%p%s%d", "%M.%m", "%M"], features: [] ) diff --git a/lib/pact_broker/pacts/pacts_for_verification_repository.rb b/lib/pact_broker/pacts/pacts_for_verification_repository.rb index 877cb3c17..03a7f9dcc 100644 --- a/lib/pact_broker/pacts/pacts_for_verification_repository.rb +++ b/lib/pact_broker/pacts/pacts_for_verification_repository.rb @@ -270,8 +270,15 @@ def remove_non_wip_for_tag(pact_publications_query, provider, tag, specified_pac def collect_consumer_name_and_version_number(pact_publications_query) pact_publications_query.eager(:provider).eager(:consumer).eager(:consumer_version).order(:consumer_version_order).all.sort.collect do |p| - tag_suffix = p.values[:tag_name] ? " (tag #{p.values[:tag_name]})" : "" - "#{p.consumer_name} #{p.consumer_version_number}" + tag_suffix + suffix = if p.values[:tag_name] + " (tag #{p.values[:tag_name]})" + elsif p.values[:branch] + " (branch #{p.values[:branch]})" + else + "" + end + + "#{p.consumer_name} #{p.consumer_version_number}" + suffix end end diff --git a/lib/pact_broker/tags/service.rb b/lib/pact_broker/tags/service.rb index 7a775f918..07b5dec22 100644 --- a/lib/pact_broker/tags/service.rb +++ b/lib/pact_broker/tags/service.rb @@ -1,15 +1,23 @@ require "pact_broker/repositories" +require "pact_broker/configuration" +require "pact_broker/logging" module PactBroker module Tags module Service extend self extend PactBroker::Repositories + include PactBroker::Logging def create args + tag_name = args.fetch(:tag_name) pacticipant = pacticipant_repository.find_by_name_or_create args.fetch(:pacticipant_name) version = version_repository.find_by_pacticipant_id_and_number_or_create pacticipant.id, args.fetch(:pacticipant_version_number) - tag_repository.create version: version, name: args.fetch(:tag_name) + if use_tag_as_branch?(version) && !version.branch + logger.info "Setting #{version.pacticipant.name} version #{version.number} branch to '#{tag_name}' from first tag (because use_first_tag_as_branch=true)" + version_repository.set_branch_if_unset(version, tag_name) + end + tag_repository.create version: version, name: tag_name end def find args @@ -25,6 +33,16 @@ def delete args def find_all_tag_names_for_pacticipant pacticipant_name tag_repository.find_all_tag_names_for_pacticipant pacticipant_name end + + def use_tag_as_branch?(version) + version.tags.count == 0 && + PactBroker.configuration.use_first_tag_as_branch && + ((now - version.created_at.to_datetime) * 24 * 60 * 60) <= PactBroker.configuration.use_first_tag_as_branch_time_limit + end + + def now + Time.now.utc.to_datetime + end end end end diff --git a/lib/pact_broker/versions/repository.rb b/lib/pact_broker/versions/repository.rb index 8fbb34bb6..6804018f6 100644 --- a/lib/pact_broker/versions/repository.rb +++ b/lib/pact_broker/versions/repository.rb @@ -129,6 +129,11 @@ def find_versions_for_selector(selector) PactBroker::Domain::Version.select_all_qualified.for_selector(selector).all end + def set_branch_if_unset(version, branch) + version.update(branch: branch) if version.branch.nil? + version + end + def find_latest_version_from_main_branch(pacticipant) if pacticipant.main_branch latest_from_main_branch = PactBroker::Domain::Version diff --git a/spec/lib/pact_broker/tags/service_spec.rb b/spec/lib/pact_broker/tags/service_spec.rb index 3d09852c9..1e44c8023 100644 --- a/spec/lib/pact_broker/tags/service_spec.rb +++ b/spec/lib/pact_broker/tags/service_spec.rb @@ -4,33 +4,109 @@ module PactBroker module Tags describe Service do - + before do + allow(PactBroker.configuration).to receive(:use_first_tag_as_branch).and_return(use_first_tag_as_branch) + end let(:pacticipant_name) { "test_pacticipant" } let(:version_number) { "1.2.3" } let(:tag_name) { "prod" } + let(:options) { { pacticipant_name: pacticipant_name, pacticipant_version_number: version_number, tag_name: tag_name }} + let(:use_first_tag_as_branch) { false } - let(:options) { {pacticipant_name: pacticipant_name, pacticipant_version_number: version_number, tag_name: tag_name}} - let(:test_data_builder) { TestDataBuilder.new } describe ".create" do - subject { Service.create(options) } - # Naughty integration test... didn't seem much point unit testing this - it "creates the new tag" do expect(subject.name).to eq tag_name expect(subject.version.number).to eq version_number expect(subject.version.pacticipant.name).to eq pacticipant_name end + context "when use_first_tag_as_branch_time_limit is true" do + let(:use_first_tag_as_branch) { true } + + context "when there is already a tag" do + before do + td.create_consumer(pacticipant_name) + .create_consumer_version(version_number, tag_name: "foo") + end + + it "does not set the branch" do + subject + expect(td.find_version(pacticipant_name, version_number).branch).to be_nil + end + end + + context "when the branch is already set" do + before do + td.create_consumer(pacticipant_name) + .create_consumer_version(version_number, branch: "foo") + end + + it "does not update the branch" do + subject + expect(td.find_version(pacticipant_name, version_number).branch).to eq "foo" + end + end + + context "when use_first_tag_as_branch is false" do + let(:use_first_tag_as_branch) { false } + + it "does not set the branch" do + subject + expect(td.find_version(pacticipant_name, version_number).branch).to be_nil + end + end + + context "when the version was outside of the time difference limit" do + before do + version = td.create_consumer(pacticipant_name) + .create_consumer_version(version_number) + .and_return(:consumer_version) + + version.update(created_at: created_at) + allow(PactBroker.configuration).to receive(:use_first_tag_as_branch_time_limit).and_return(10) + allow(Time).to receive(:now).and_return(td.in_utc { Time.new(2021, 1, 2, 10, 10, 11) } ) + end + + let(:created_at) { td.in_utc { Time.new(2021, 1, 2, 10, 10, 0) }.to_datetime } + + let(:one_second) { 1/(24 * 60 * 60) } + + it "does not set the branch" do + subject + expect(td.find_version(pacticipant_name, version_number).branch).to be_nil + end + end + + context "when the version was created within the limit" do + before do + version = td.create_consumer(pacticipant_name) + .create_consumer_version(version_number) + .and_return(:consumer_version) + + version.update(created_at: created_at) + allow(PactBroker.configuration).to receive(:use_first_tag_as_branch_time_limit).and_return(10) + allow(Time).to receive(:now).and_return(td.in_utc { Time.new(2021, 1, 2, 10, 10, 10) } ) + end + + let(:created_at) { td.in_utc { Time.new(2021, 1, 2, 10, 10, 0) }.to_datetime } + let(:one_second) { 1/(24 * 60 * 60) } + + it "sets the branch" do + subject + expect(td.find_version(pacticipant_name, version_number).branch).to eq "prod" + end + end + end end describe "delete" do let(:second_pacticipant_name) { "second_test_pacticipant" } let(:second_version_number) { "4.5.6" } - let(:second_options_same_tag_name) { {pacticipant_name: second_pacticipant_name, pacticipant_version_number: second_version_number, tag_name: tag_name}} + let(:second_options_same_tag_name) { { pacticipant_name: second_pacticipant_name, pacticipant_version_number: second_version_number, tag_name: tag_name }} before do Service.create(options)