From b1fc670d220d39575b2c98a25a39b88efcfaea48 Mon Sep 17 00:00:00 2001 From: Brian Glusman Date: Sun, 27 Dec 2015 23:22:26 -0500 Subject: [PATCH 1/3] Increment Archeology record version Includes project name, shorter config hash string, separated by underscores and underscores in pro name are (weirdly, i know) transformed to dashes --- .../analysis_caches/analysis_cache.rb | 39 ++++++++++--------- .../analysis_caches/git_note_adapter.rb | 2 +- lib/debt_ceiling/archeological_dig.rb | 23 ++++++----- 3 files changed, 35 insertions(+), 29 deletions(-) diff --git a/lib/debt_ceiling/analysis_caches/analysis_cache.rb b/lib/debt_ceiling/analysis_caches/analysis_cache.rb index 4513a2d..1671c1b 100644 --- a/lib/debt_ceiling/analysis_caches/analysis_cache.rb +++ b/lib/debt_ceiling/analysis_caches/analysis_cache.rb @@ -1,27 +1,16 @@ require_relative "git_note_adapter" module DebtCeiling class AnalysisCache - attr_reader :adapter - - def self.commit_identifier(commit) - "debt_ceiling_#{commit}_#{config_string}" - end - - def self.config_string - @config_string ||= config_hash_string + ArcheologicalDig::ARCHEOLOGY_RECORD_VERSION_NUMBER - end - - def self.config_hash_string - Digest::SHA1.hexdigest(DebtCeiling.config_array.to_json) - end - - def initialize(adapter=nil) + attr_reader :adapter, :project_name + ANALYSIS_CACHE_HASH_LENGTH = 6 + def initialize(project_name, adapter=nil) @adapter = adapter + @project_name = project_name @adapter ||= auto_select_adapter end def get(commit) - text = adapter.get(self.class.commit_identifier(commit)) + text = adapter.get(commit_identifier(commit)) if text extract_record_from_text(text) else @@ -37,15 +26,15 @@ def set(commit, result) def create_text_on_commit(commit, result) text = <<-DATA - #{self.class.commit_identifier(commit)} + #{commit_identifier(commit)} #{result.to_json} DATA - adapter.set(self.class.commit_identifier(commit), text) + adapter.set(commit_identifier(commit), text) end def extract_record_from_text(text) text.split("\n").each_cons(2).each do |comment, json| - return JSON.parse(json) if comment.match(AnalysisCache.config_string) + return JSON.parse(json) if comment.match(config_string) end end @@ -60,5 +49,17 @@ def redis_if_available Redis.new(host: host, port: port) rescue LoadError end + + def commit_identifier(commit) + "DebtCeiling_#{project_name}_#{commit}_#{config_string}" + end + + def config_string + @config_string ||= "#{config_hash_string}_#{ArcheologicalDig::ARCHEOLOGY_RECORD_VERSION_NUMBER}" + end + + def config_hash_string + Digest::SHA1.hexdigest(DebtCeiling.config_array.to_json).slice(0...ANALYSIS_CACHE_HASH_LENGTH) + end end end \ No newline at end of file diff --git a/lib/debt_ceiling/analysis_caches/git_note_adapter.rb b/lib/debt_ceiling/analysis_caches/git_note_adapter.rb index f2207bc..5fac0c0 100644 --- a/lib/debt_ceiling/analysis_caches/git_note_adapter.rb +++ b/lib/debt_ceiling/analysis_caches/git_note_adapter.rb @@ -19,7 +19,7 @@ def set(key, result) private def actual_commit(key) - key.split('_')[2] + key.split('_')[2] #for now we sanitize underscores into dashes in project name end def read_note_on(commit) diff --git a/lib/debt_ceiling/archeological_dig.rb b/lib/debt_ceiling/archeological_dig.rb index c9f97ec..b6b8512 100644 --- a/lib/debt_ceiling/archeological_dig.rb +++ b/lib/debt_ceiling/archeological_dig.rb @@ -4,30 +4,35 @@ require 'json' module DebtCeiling class ArcheologicalDig - ARCHEOLOGY_RECORD_VERSION_NUMBER = "v0" #increment for backward incompatible changes in record format - attr_reader :source_control, :records, :cache, :path, :opts - - def self.dig_json_key(path) - project_name = File.expand_path(path).split('/').last - "DebtCeiling_#{project_name}_#{ARCHEOLOGY_RECORD_VERSION_NUMBER}" - end + ARCHEOLOGY_RECORD_VERSION_NUMBER = "v1" #increment for backward incompatible changes in record format + attr_reader :source_control, :records, :cache, :project_name, :path, :opts def initialize(path='.', opts={}) - @cache = AnalysisCache.new(opts[:analysis_cache]) @path = path @opts = opts + @project_name = sanitized_project_name + @cache = AnalysisCache.new(project_name, opts[:analysis_cache]) @source_control = SourceControlSystem::Base.create end def process DebtCeiling.load_configuration unless opts[:preconfigured] @records = source_control.revisions_refs(path).map {|commit| process_commit(commit) } - cache.set(self.class.dig_json_key(path), records.to_json) if opts[:store_results] + cache.set(dig_json_key(path), records.to_json) if opts[:store_results] self end private + def sanitized_project_name + name = opts[:project_name] || File.expand_path(path).split('/').last + name.gsub('_', '-') + end + + def dig_json_key(path) + "DebtCeiling_#{project_name}_#{ARCHEOLOGY_RECORD_VERSION_NUMBER}" + end + def process_commit(commit) cache.get(commit) { audit_commit(commit) } end From 05503330d509f116f8aed92addda02f669ecd208 Mon Sep 17 00:00:00 2001 From: Brian Glusman Date: Sun, 27 Dec 2015 23:23:31 -0500 Subject: [PATCH 2/3] Fix small bug with sparkline output Format hash with strings since Redis/git note cached hashes will be string keyed, better consistency without using active support magic. --- lib/debt_ceiling/archeological_dig.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/debt_ceiling/archeological_dig.rb b/lib/debt_ceiling/archeological_dig.rb index b6b8512..bc1e224 100644 --- a/lib/debt_ceiling/archeological_dig.rb +++ b/lib/debt_ceiling/archeological_dig.rb @@ -62,7 +62,7 @@ def archeology_record(result, commit) end def default_record(result, commit) - {debt: result.total_debt, failed: !!result.failed_condition?, commit: commit} + {'debt' => result.total_debt, 'failed' => !!result.failed_condition?, 'commit' => commit} end end From 9679d79a968a133e3d432fe04b14ca9dcecef992 Mon Sep 17 00:00:00 2001 From: Brian Date: Mon, 25 Jul 2016 21:14:45 -0400 Subject: [PATCH 3/3] WIP/stash/whatever --- spec/archeological_dig_spec.rb | 2 +- spec/debt_ceiling_spec.rb | 37 ++++++++-------------------------- spec/spec_helper.rb | 2 +- 3 files changed, 10 insertions(+), 31 deletions(-) diff --git a/spec/archeological_dig_spec.rb b/spec/archeological_dig_spec.rb index 0ebe784..0fc0a69 100644 --- a/spec/archeological_dig_spec.rb +++ b/spec/archeological_dig_spec.rb @@ -6,7 +6,7 @@ describe DebtCeiling::ArcheologicalDig do CONFIG_STRING = "fake_config_string" - COMMIT_SHA_MSG = "debt_ceiling_#{COMMIT_SHA}_#{CONFIG_STRING}#{described_class::ARCHEOLOGY_RECORD_VERSION_NUMBER}\n {\"debt\":100,\"failed\":false,\"commit\":\"#{COMMIT_SHA}\"}\n" + COMMIT_SHA_MSG = "DebtCeiling_#{COMMIT_SHA}_#{CONFIG_STRING}#{described_class::ARCHEOLOGY_RECORD_VERSION_NUMBER}\n {\"debt\":100,\"failed\":false,\"commit\":\"#{COMMIT_SHA}\"}\n" let(:fake_source_control) { double(DebtCeiling::SourceControlSystem::Git) } let(:fake_audit) { double(DebtCeiling::Audit) } diff --git a/spec/debt_ceiling_spec.rb b/spec/debt_ceiling_spec.rb index f7e2310..87256db 100644 --- a/spec/debt_ceiling_spec.rb +++ b/spec/debt_ceiling_spec.rb @@ -2,57 +2,36 @@ require 'debt_ceiling' describe DebtCeiling do + let(:fake_audit) { double(DebtCeiling::Audit) } + before(:each) { allow(DebtCeiling::Audit).to receive(:new).and_return(fake_audit)} + it 'has failing exit status when debt_ceiling is exceeded' do DebtCeiling.configure {|c| c.debt_ceiling = 0 } expect(DebtCeiling.debt_ceiling).to eq(0) - expect_any_instance_of(DebtCeiling::Audit).to receive(:fail_test) + allow(fake_audit).to receive(:fail_test) DebtCeiling.audit('.', preconfigured: true) end it 'has failing exit status when target debt reduction is missed' do DebtCeiling.configure {|c| c.reduction_target =0; c.reduction_date = Time.now.to_s } expect(DebtCeiling.debt_ceiling).to eq(nil) - expect_any_instance_of(DebtCeiling::Audit).to receive(:fail_test) + allow(fake_audit).to receive(:fail_test) DebtCeiling.audit('.', preconfigured: true) end it 'has failing exit status when max debt per module is exceeded' do DebtCeiling.configure {|c| c.max_debt_per_module =5 } expect(DebtCeiling.debt_ceiling).to eq(nil) - expect_any_instance_of(DebtCeiling::Audit).to receive(:fail_test) + allow(fake_audit).to receive(:fail_test) DebtCeiling.audit('.', preconfigured: true) end it 'has no failing exit status when in warn only mode' do DebtCeiling.configure {|c| c.max_debt_per_module =5 } expect(DebtCeiling.debt_ceiling).to eq(nil) - expect_any_instance_of(DebtCeiling::Audit).to receive(:failed_condition?).at_least(:once).and_return(true) - expect_any_instance_of(DebtCeiling::Audit).not_to receive(:fail_test) + allow(fake_audit).to receive(:failed_condition?).at_least(:once).and_return(true) + expect(fake_audit).not_to receive(:fail_test) DebtCeiling.audit('.', preconfigured: true, warn_only: true) end - it 'returns quantity of total debt' do - expect(DebtCeiling.audit('.').total_debt).to be > 5 # arbitrary non-zero amount - end - - it 'adds debt for todos with specified value' do - todo_amount = 50 - DebtCeiling.configure {|c| c.cost_per_todo = todo_amount } - expect(DebtCeiling.audit('spec/support/todo_example.rb', preconfigured: true).total_debt).to be todo_amount - end - - it 'allows manual debt with TECH DEBT comment' do - expect(DebtCeiling.audit('spec/support/manual_example.rb', preconfigured: true).total_debt).to be 100 # hardcoded in example file - end - - it 'allows manual debt with arbitrarily defined comment' do - DebtCeiling.configure {|c| c.manual_callouts += ['REFACTOR'] } - expect(DebtCeiling.audit('spec/support/manual_example.rb', preconfigured: true).total_debt).to be 150 # hardcoded in example file - end - - it 'assigns debt for file length over ideal file size' do - DebtCeiling.configure {|c| c.ideal_max_line_count = 10; c.cost_per_line_over_ideal = 100 } - expect(DebtCeiling.audit('spec/support/long_file_example.rb', preconfigured: true).total_debt).to be 300 # hardcoded 13 lines long example file - end - end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 51f4d9e..75b0e4c 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -4,5 +4,5 @@ RSpec.configure do |config| config.before { allow($stdout).to receive(:puts) } - config.after(:all) { DebtCeiling.audit unless ENV['SKIP'] } + at_exit { DebtCeiling.audit unless ENV['SKIP'] } end