From bd95e755ed9bd2dbeb35817759a7c7ecd7e55b26 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sat, 15 Oct 2016 21:00:00 +0200 Subject: [PATCH 01/43] Add draft task for queue rsepc --- lib/knapsack_pro.rb | 1 + .../runners/queue/rspec_runner.rb | 29 +++++++++++++++++++ lib/knapsack_pro/task_loader.rb | 2 +- lib/tasks/queue/rspec.rake | 9 ++++++ 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 lib/knapsack_pro/runners/queue/rspec_runner.rb create mode 100644 lib/tasks/queue/rspec.rake diff --git a/lib/knapsack_pro.rb b/lib/knapsack_pro.rb index eefc2ffe..b496510c 100644 --- a/lib/knapsack_pro.rb +++ b/lib/knapsack_pro.rb @@ -46,6 +46,7 @@ require_relative 'knapsack_pro/runners/cucumber_runner' require_relative 'knapsack_pro/runners/minitest_runner' require_relative 'knapsack_pro/runners/spinach_runner' +require_relative 'knapsack_pro/runners/queue/rspec_runner' require_relative 'knapsack_pro/crypto/encryptor' require_relative 'knapsack_pro/crypto/decryptor' require_relative 'knapsack_pro/crypto/digestor' diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb new file mode 100644 index 00000000..55164261 --- /dev/null +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -0,0 +1,29 @@ +module KnapsackPro + module Runners + module Queue + class RSpecRunner < BaseRunner + def self.run(args) + ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_rspec + ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true' + + runner = new(KnapsackPro::Adapters::RSpecAdapter) + + if runner.test_files_to_execute_exist? + require 'rspec/core/rake_task' + + task_name = 'knapsack_pro:rspec_run' + if Rake::Task.task_defined?(task_name) + Rake::Task[task_name].clear + end + + RSpec::Core::RakeTask.new(task_name) do |t| + t.rspec_opts = "#{args} --default-path #{runner.test_dir}" + t.pattern = runner.test_file_paths + end + Rake::Task[task_name].invoke + end + end + end + end + end +end diff --git a/lib/knapsack_pro/task_loader.rb b/lib/knapsack_pro/task_loader.rb index 4274209e..03c76388 100644 --- a/lib/knapsack_pro/task_loader.rb +++ b/lib/knapsack_pro/task_loader.rb @@ -5,7 +5,7 @@ class TaskLoader include ::Rake::DSL def load_tasks - Dir.glob("#{KnapsackPro.root}/lib/tasks/*.rake").each { |r| import r } + Dir.glob("#{KnapsackPro.root}/lib/tasks/**/*.rake").each { |r| import r } end end end diff --git a/lib/tasks/queue/rspec.rake b/lib/tasks/queue/rspec.rake new file mode 100644 index 00000000..fbe4d206 --- /dev/null +++ b/lib/tasks/queue/rspec.rake @@ -0,0 +1,9 @@ +require 'knapsack_pro' + +namespace :knapsack_pro do + namespace :queue do + task :rspec, [:rspec_args] do |_, args| + KnapsackPro::Runners::Queue::RSpecRunner.run(args[:rspec_args]) + end + end +end From 73d1f3e1de0f33b141e74ce5ed91574dd86e3410 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sat, 15 Oct 2016 21:07:20 +0200 Subject: [PATCH 02/43] queue --- lib/knapsack_pro/runners/queue/rspec_runner.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index 55164261..c9990ac6 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -11,7 +11,7 @@ def self.run(args) if runner.test_files_to_execute_exist? require 'rspec/core/rake_task' - task_name = 'knapsack_pro:rspec_run' + task_name = 'knapsack_pro:queue:rspec_run' if Rake::Task.task_defined?(task_name) Rake::Task[task_name].clear end From 3768aedc570b0f12cef8d708631393331cc574a7 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sat, 15 Oct 2016 21:35:53 +0200 Subject: [PATCH 03/43] require secure random --- lib/knapsack_pro.rb | 1 + lib/tasks/salt.rake | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/knapsack_pro.rb b/lib/knapsack_pro.rb index b496510c..044e9ace 100644 --- a/lib/knapsack_pro.rb +++ b/lib/knapsack_pro.rb @@ -6,6 +6,7 @@ require 'rake/testtask' require 'timecop' require 'digest' +require 'securerandom' require_relative 'knapsack_pro/version' require_relative 'knapsack_pro/utils' require_relative 'knapsack_pro/logger_wrapper' diff --git a/lib/tasks/salt.rake b/lib/tasks/salt.rake index 453106e9..dab8c700 100644 --- a/lib/tasks/salt.rake +++ b/lib/tasks/salt.rake @@ -1,5 +1,3 @@ -require 'securerandom' - namespace :knapsack_pro do task :salt, [:size] do |_, args| default_size = 32 From 06eaf53d1e2753458360b8c7f82992141e1c86bb Mon Sep 17 00:00:00 2001 From: ArturT Date: Sat, 15 Oct 2016 21:37:41 +0200 Subject: [PATCH 04/43] run tests in queue --- .../runners/queue/rspec_runner.rb | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index c9990ac6..d30e4c52 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -2,6 +2,35 @@ module KnapsackPro module Runners module Queue class RSpecRunner < BaseRunner + class Queue + def initialize(test_file_paths) + @test_file_paths = test_file_paths + end + + def test_file_paths + @test_file_paths.shift + end + end + + def self.run_tests(queue, args, runner) + test_file_paths = queue.test_file_paths + + unless test_file_paths.nil? + task_name = "knapsack_pro:queue:rspec_run_#{SecureRandom.uuid}" + + RSpec::Core::RakeTask.new(task_name) do |t| + t.rspec_opts = "#{args} --default-path #{runner.test_dir}" + t.pattern = test_file_paths + end + + Rake::Task[task_name].invoke + + at_exit do + run_tests(queue, args, runner) if $!.nil? + end + end + end + def self.run(args) ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_rspec ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true' @@ -11,16 +40,8 @@ def self.run(args) if runner.test_files_to_execute_exist? require 'rspec/core/rake_task' - task_name = 'knapsack_pro:queue:rspec_run' - if Rake::Task.task_defined?(task_name) - Rake::Task[task_name].clear - end - - RSpec::Core::RakeTask.new(task_name) do |t| - t.rspec_opts = "#{args} --default-path #{runner.test_dir}" - t.pattern = runner.test_file_paths - end - Rake::Task[task_name].invoke + queue = Queue.new(runner.test_file_paths) + run_tests(queue, args, runner) end end end From 81910be0de0d369967acf8e61ac185b1cc65cc33 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sat, 15 Oct 2016 22:44:29 +0200 Subject: [PATCH 05/43] remember exit status if test fail in one of rake task in the queue --- .../runners/queue/rspec_runner.rb | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index d30e4c52..e4866f0e 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -12,10 +12,12 @@ def test_file_paths end end - def self.run_tests(queue, args, runner) + def self.run_tests(queue, args, runner, exitstatus) test_file_paths = queue.test_file_paths - unless test_file_paths.nil? + if test_file_paths.nil? + exit(exitstatus) unless exitstatus.zero? + else task_name = "knapsack_pro:queue:rspec_run_#{SecureRandom.uuid}" RSpec::Core::RakeTask.new(task_name) do |t| @@ -23,10 +25,17 @@ def self.run_tests(queue, args, runner) t.pattern = test_file_paths end - Rake::Task[task_name].invoke + begin + Rake::Task[task_name].invoke + rescue Exception => e + puts "Task #{task_name} failed" + puts "#{e.class}: #{e.message}" + puts "Exit status: #{$?.exitstatus}" + exitstatus = $?.exitstatus if $?.exitstatus != 0 + end at_exit do - run_tests(queue, args, runner) if $!.nil? + run_tests(queue, args, runner, exitstatus) end end end @@ -41,7 +50,7 @@ def self.run(args) require 'rspec/core/rake_task' queue = Queue.new(runner.test_file_paths) - run_tests(queue, args, runner) + run_tests(queue, args, runner, 0) end end end From 49e2b9bf6063e7cb7fc990df97505001eca5f306 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sat, 15 Oct 2016 22:45:35 +0200 Subject: [PATCH 06/43] =?UTF-8?q?return=20exit=20status=20(unless=20doesn?= =?UTF-8?q?=E2=80=99t=20make=20sense=20here)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/knapsack_pro/runners/queue/rspec_runner.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index e4866f0e..f436164f 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -16,7 +16,7 @@ def self.run_tests(queue, args, runner, exitstatus) test_file_paths = queue.test_file_paths if test_file_paths.nil? - exit(exitstatus) unless exitstatus.zero? + exit(exitstatus) else task_name = "knapsack_pro:queue:rspec_run_#{SecureRandom.uuid}" From 684f28d5a5a5c7a651b7cd76bbfec8b6653f0499 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 16 Oct 2016 15:13:52 +0200 Subject: [PATCH 07/43] remove empty line --- lib/knapsack_pro/config/ci/circle.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/knapsack_pro/config/ci/circle.rb b/lib/knapsack_pro/config/ci/circle.rb index 920d549a..a61c510d 100644 --- a/lib/knapsack_pro/config/ci/circle.rb +++ b/lib/knapsack_pro/config/ci/circle.rb @@ -26,4 +26,3 @@ def project_dir end end end - From cc802e2e85450bcabf898ce38ac1b061313318f7 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 16 Oct 2016 16:21:26 +0200 Subject: [PATCH 08/43] Save subset queue to json files --- lib/knapsack_pro.rb | 1 + lib/knapsack_pro/adapters/base_adapter.rb | 10 ++++++++ lib/knapsack_pro/adapters/rspec_adapter.rb | 8 ++++++ lib/knapsack_pro/config/env.rb | 16 ++++++++++++ lib/knapsack_pro/config/env_generator.rb | 19 ++++++++++++++ lib/knapsack_pro/report.rb | 25 +++++++++++++++++++ .../runners/queue/rspec_runner.rb | 7 ++++-- 7 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 lib/knapsack_pro/config/env_generator.rb diff --git a/lib/knapsack_pro.rb b/lib/knapsack_pro.rb index 044e9ace..e5cd5b5c 100644 --- a/lib/knapsack_pro.rb +++ b/lib/knapsack_pro.rb @@ -17,6 +17,7 @@ require_relative 'knapsack_pro/config/ci/travis' require_relative 'knapsack_pro/config/ci/snap_ci' require_relative 'knapsack_pro/config/env' +require_relative 'knapsack_pro/config/env_generator' require_relative 'knapsack_pro/client/api/action' require_relative 'knapsack_pro/client/api/v1/base' require_relative 'knapsack_pro/client/api/v1/build_distributions' diff --git a/lib/knapsack_pro/adapters/base_adapter.rb b/lib/knapsack_pro/adapters/base_adapter.rb index ad2f00cd..a07be0d3 100644 --- a/lib/knapsack_pro/adapters/base_adapter.rb +++ b/lib/knapsack_pro/adapters/base_adapter.rb @@ -16,6 +16,12 @@ def bind bind_time_tracker bind_save_report end + + if KnapsackPro::Config::Env.queue_recording_enabled? + KnapsackPro.logger.info('Test suite time execution queue recording enabled.') + bind_time_tracker + bind_save_queue_report + end end def bind_time_tracker @@ -25,6 +31,10 @@ def bind_time_tracker def bind_save_report raise NotImplementedError end + + def bind_save_queue_report + raise NotImplementedError + end end end end diff --git a/lib/knapsack_pro/adapters/rspec_adapter.rb b/lib/knapsack_pro/adapters/rspec_adapter.rb index 613948ce..c0af2350 100644 --- a/lib/knapsack_pro/adapters/rspec_adapter.rb +++ b/lib/knapsack_pro/adapters/rspec_adapter.rb @@ -49,6 +49,14 @@ def bind_save_report end end end + + def bind_save_queue_report + ::RSpec.configure do |config| + config.after(:suite) do + KnapsackPro::Report.save_subset_queue_to_file + end + end + end end # This is added to provide backwards compatibility diff --git a/lib/knapsack_pro/config/env.rb b/lib/knapsack_pro/config/env.rb index c2f8e1e5..c88f4a53 100644 --- a/lib/knapsack_pro/config/env.rb +++ b/lib/knapsack_pro/config/env.rb @@ -45,6 +45,22 @@ def recording_enabled? recording_enabled == 'true' end + def queue_recording_enabled + ENV['KNAPSACK_PRO_QUEUE_RECORDING_ENABLED'] + end + + def queue_recording_enabled? + queue_recording_enabled == 'true' + end + + def queue_id + ENV['KNAPSACK_PRO_QUEUE_ID'] || raise('Missing Queue ID') + end + + def subset_queue_id + ENV['KNAPSACK_PRO_SUBSET_QUEUE_ID'] || raise('Missing Subset Queue ID') + end + def test_files_encrypted ENV['KNAPSACK_PRO_TEST_FILES_ENCRYPTED'] end diff --git a/lib/knapsack_pro/config/env_generator.rb b/lib/knapsack_pro/config/env_generator.rb new file mode 100644 index 00000000..be9c9ee7 --- /dev/null +++ b/lib/knapsack_pro/config/env_generator.rb @@ -0,0 +1,19 @@ +module KnapsackPro + module Config + class EnvGenerator + class << self + def set_queue_id + if ENV['KNAPSACK_PRO_QUEUE_ID'] + raise 'Queue ID already generated' + else + ENV['KNAPSACK_PRO_QUEUE_ID'] = "#{Time.now.to_i}_#{SecureRandom.uuid}" + end + end + + def set_subset_queue_id + ENV['KNAPSACK_PRO_SUBSET_QUEUE_ID'] = SecureRandom.uuid + end + end + end + end +end diff --git a/lib/knapsack_pro/report.rb b/lib/knapsack_pro/report.rb index bd16a8d7..222a4612 100644 --- a/lib/knapsack_pro/report.rb +++ b/lib/knapsack_pro/report.rb @@ -2,7 +2,32 @@ module KnapsackPro class Report def self.save test_files = KnapsackPro.tracker.to_a + create_build_subset(test_files) + end + + def self.save_subset_queue_to_file + test_files = KnapsackPro.tracker.to_a + queue_id = KnapsackPro::Config::Env.queue_id + subset_queue_id = KnapsackPro::Config::Env.subset_queue_id + queue_path = "tmp/knapsack_pro/#{queue_id}" + + FileUtils.mkdir_p(queue_path) + + subset_queue_file_name = "#{subset_queue_id}.json" + report_path = File.join(queue_path, subset_queue_file_name) + report_json = JSON.pretty_generate(test_files) + + File.open(report_path, 'w+') do |f| + f.write(report_json) + end + end + + def self.save_node_queue_to_api + test_files = [] # TODO + create_build_subset(test_files) + end + def self.create_build_subset(test_files) if test_files.empty? KnapsackPro.logger.info("Didn't save time execution report on API server because there are no test files matching criteria on this node. Probably reason might be very narrowed tests list - you run only tests with specified tag and there are fewer test files with the tag than node total number.") return diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index f436164f..e92430f6 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -18,7 +18,9 @@ def self.run_tests(queue, args, runner, exitstatus) if test_file_paths.nil? exit(exitstatus) else - task_name = "knapsack_pro:queue:rspec_run_#{SecureRandom.uuid}" + subset_queue_id = KnapsackPro::Config::EnvGenerator.set_subset_queue_id + ENV['KNAPSACK_PRO_SUBSET_QUEUE_ID'] = subset_queue_id + task_name = "knapsack_pro:queue:rspec_run_#{subset_queue_id}" RSpec::Core::RakeTask.new(task_name) do |t| t.rspec_opts = "#{args} --default-path #{runner.test_dir}" @@ -42,7 +44,8 @@ def self.run_tests(queue, args, runner, exitstatus) def self.run(args) ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_rspec - ENV['KNAPSACK_PRO_RECORDING_ENABLED'] = 'true' + ENV['KNAPSACK_PRO_QUEUE_RECORDING_ENABLED'] = 'true' + ENV['KNAPSACK_PRO_QUEUE_ID'] = KnapsackPro::Config::EnvGenerator.set_queue_id runner = new(KnapsackPro::Adapters::RSpecAdapter) From 52e1d1164eb60b7b2fdc0983d127c006c52eeebf Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 16 Oct 2016 17:59:49 +0200 Subject: [PATCH 09/43] save node queue tests to API at the end of running tests for particular node --- lib/knapsack_pro/report.rb | 16 +++++++++++++--- lib/knapsack_pro/runners/queue/rspec_runner.rb | 1 + 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/knapsack_pro/report.rb b/lib/knapsack_pro/report.rb index 222a4612..6f5d692a 100644 --- a/lib/knapsack_pro/report.rb +++ b/lib/knapsack_pro/report.rb @@ -7,9 +7,7 @@ def self.save def self.save_subset_queue_to_file test_files = KnapsackPro.tracker.to_a - queue_id = KnapsackPro::Config::Env.queue_id subset_queue_id = KnapsackPro::Config::Env.subset_queue_id - queue_path = "tmp/knapsack_pro/#{queue_id}" FileUtils.mkdir_p(queue_path) @@ -23,7 +21,12 @@ def self.save_subset_queue_to_file end def self.save_node_queue_to_api - test_files = [] # TODO + test_files = [] + Dir.glob("#{queue_path}/*.json").each do |file| + report = JSON.parse(File.read(file)) + test_files += report + end + create_build_subset(test_files) end @@ -50,5 +53,12 @@ def self.create_build_subset(test_files) KnapsackPro.logger.info('Saved time execution report on API server.') end end + + private + + def self.queue_path + queue_id = KnapsackPro::Config::Env.queue_id + "tmp/knapsack_pro/#{queue_id}" + end end end diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index e92430f6..f1c864f1 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -16,6 +16,7 @@ def self.run_tests(queue, args, runner, exitstatus) test_file_paths = queue.test_file_paths if test_file_paths.nil? + KnapsackPro::Report.save_node_queue_to_api exit(exitstatus) else subset_queue_id = KnapsackPro::Config::EnvGenerator.set_subset_queue_id From 2501702714c2567bed93a7af771e666d20dee3d1 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 23 Oct 2016 00:06:26 +0200 Subject: [PATCH 10/43] Add support for ci node build id and specs --- lib/knapsack_pro/config/ci/base.rb | 3 +++ lib/knapsack_pro/config/ci/buildkite.rb | 4 ++++ lib/knapsack_pro/config/ci/circle.rb | 4 ++++ lib/knapsack_pro/config/ci/semaphore.rb | 4 ++++ lib/knapsack_pro/config/ci/snap_ci.rb | 4 ++++ lib/knapsack_pro/config/ci/travis.rb | 4 ++++ lib/knapsack_pro/config/env.rb | 5 ++++ spec/knapsack_pro/config/ci/base_spec.rb | 1 + spec/knapsack_pro/config/ci/buildkite_spec.rb | 13 +++++++++++ spec/knapsack_pro/config/ci/circle_spec.rb | 13 +++++++++++ spec/knapsack_pro/config/ci/semaphore_spec.rb | 13 +++++++++++ spec/knapsack_pro/config/ci/snap_ci_spec.rb | 13 +++++++++++ spec/knapsack_pro/config/ci/travis_spec.rb | 13 +++++++++++ spec/knapsack_pro/config/env_spec.rb | 23 +++++++++++++++++++ 14 files changed, 117 insertions(+) diff --git a/lib/knapsack_pro/config/ci/base.rb b/lib/knapsack_pro/config/ci/base.rb index 5001772c..86865dcf 100644 --- a/lib/knapsack_pro/config/ci/base.rb +++ b/lib/knapsack_pro/config/ci/base.rb @@ -8,6 +8,9 @@ def node_total def node_index end + def node_build_id + end + def commit_hash end diff --git a/lib/knapsack_pro/config/ci/buildkite.rb b/lib/knapsack_pro/config/ci/buildkite.rb index ab3fa337..bd782713 100644 --- a/lib/knapsack_pro/config/ci/buildkite.rb +++ b/lib/knapsack_pro/config/ci/buildkite.rb @@ -10,6 +10,10 @@ def node_index ENV['BUILDKITE_PARALLEL_JOB'] end + def node_build_id + ENV['BUILDKITE_BUILD_NUMBER'] + end + def commit_hash ENV['BUILDKITE_COMMIT'] end diff --git a/lib/knapsack_pro/config/ci/circle.rb b/lib/knapsack_pro/config/ci/circle.rb index a61c510d..01e3f56a 100644 --- a/lib/knapsack_pro/config/ci/circle.rb +++ b/lib/knapsack_pro/config/ci/circle.rb @@ -10,6 +10,10 @@ def node_index ENV['CIRCLE_NODE_INDEX'] end + def node_build_id + ENV['CIRCLE_BUILD_NUM'] + end + def commit_hash ENV['CIRCLE_SHA1'] end diff --git a/lib/knapsack_pro/config/ci/semaphore.rb b/lib/knapsack_pro/config/ci/semaphore.rb index b63cb149..fdc12f37 100644 --- a/lib/knapsack_pro/config/ci/semaphore.rb +++ b/lib/knapsack_pro/config/ci/semaphore.rb @@ -11,6 +11,10 @@ def node_index index.to_i - 1 if index end + def node_build_id + ENV['SEMAPHORE_BUILD_NUMBER'] + end + def commit_hash ENV['REVISION'] end diff --git a/lib/knapsack_pro/config/ci/snap_ci.rb b/lib/knapsack_pro/config/ci/snap_ci.rb index 270711ff..fc97399c 100644 --- a/lib/knapsack_pro/config/ci/snap_ci.rb +++ b/lib/knapsack_pro/config/ci/snap_ci.rb @@ -11,6 +11,10 @@ def node_index index.to_i - 1 if index end + def node_build_id + ENV['SNAP_PIPELINE_COUNTER'] + end + def commit_hash ENV['SNAP_COMMIT'] end diff --git a/lib/knapsack_pro/config/ci/travis.rb b/lib/knapsack_pro/config/ci/travis.rb index 7d92c081..186b4e7b 100644 --- a/lib/knapsack_pro/config/ci/travis.rb +++ b/lib/knapsack_pro/config/ci/travis.rb @@ -2,6 +2,10 @@ module KnapsackPro module Config module CI class Travis < Base + def node_build_id + ENV['TRAVIS_BUILD_NUMBER'] + end + def commit_hash ENV['TRAVIS_COMMIT'] end diff --git a/lib/knapsack_pro/config/env.rb b/lib/knapsack_pro/config/env.rb index c88f4a53..2278b66a 100644 --- a/lib/knapsack_pro/config/env.rb +++ b/lib/knapsack_pro/config/env.rb @@ -14,6 +14,11 @@ def ci_node_index 0).to_i end + def ci_node_build_id + ENV['KNAPSACK_PRO_CI_NODE_BUILD_ID'] || + ci_env_for(:node_build_id) + end + def commit_hash ENV['KNAPSACK_PRO_COMMIT_HASH'] || ci_env_for(:commit_hash) diff --git a/spec/knapsack_pro/config/ci/base_spec.rb b/spec/knapsack_pro/config/ci/base_spec.rb index 558bc4f3..c2beb6f6 100644 --- a/spec/knapsack_pro/config/ci/base_spec.rb +++ b/spec/knapsack_pro/config/ci/base_spec.rb @@ -1,6 +1,7 @@ describe KnapsackPro::Config::CI::Base do its(:node_total) { should be nil } its(:node_index) { should be nil } + its(:node_build_id) { should be nil } its(:commit_hash) { should be nil } its(:branch) { should be nil } its(:project_dir) { should be nil } diff --git a/spec/knapsack_pro/config/ci/buildkite_spec.rb b/spec/knapsack_pro/config/ci/buildkite_spec.rb index d642222f..9faa9580 100644 --- a/spec/knapsack_pro/config/ci/buildkite_spec.rb +++ b/spec/knapsack_pro/config/ci/buildkite_spec.rb @@ -33,6 +33,19 @@ end end + describe '#node_build_id' do + subject { described_class.new.node_build_id } + + context 'when environment exists' do + let(:env) { { 'BUILDKITE_BUILD_NUMBER' => 1514 } } + it { should eql 1514 } + end + + context "when environment doesn't exist" do + it { should be nil } + end + end + describe '#commit_hash' do subject { described_class.new.commit_hash } diff --git a/spec/knapsack_pro/config/ci/circle_spec.rb b/spec/knapsack_pro/config/ci/circle_spec.rb index 2f4b9a9e..5b95a576 100644 --- a/spec/knapsack_pro/config/ci/circle_spec.rb +++ b/spec/knapsack_pro/config/ci/circle_spec.rb @@ -33,6 +33,19 @@ end end + describe '#node_build_id' do + subject { described_class.new.node_build_id } + + context 'when environment exists' do + let(:env) { { 'CIRCLE_BUILD_NUM' => 123 } } + it { should eql 123 } + end + + context "when environment doesn't exist" do + it { should be nil } + end + end + describe '#commit_hash' do subject { described_class.new.commit_hash } diff --git a/spec/knapsack_pro/config/ci/semaphore_spec.rb b/spec/knapsack_pro/config/ci/semaphore_spec.rb index 7fc3371d..6c00c1e1 100644 --- a/spec/knapsack_pro/config/ci/semaphore_spec.rb +++ b/spec/knapsack_pro/config/ci/semaphore_spec.rb @@ -33,6 +33,19 @@ end end + describe '#node_build_id' do + subject { described_class.new.node_build_id } + + context 'when environment exists' do + let(:env) { { 'SEMAPHORE_BUILD_NUMBER' => 23 } } + it { should eql 23 } + end + + context "when environment doesn't exist" do + it { should be nil } + end + end + describe '#commit_hash' do subject { described_class.new.commit_hash } diff --git a/spec/knapsack_pro/config/ci/snap_ci_spec.rb b/spec/knapsack_pro/config/ci/snap_ci_spec.rb index 29a717b4..16dc9102 100644 --- a/spec/knapsack_pro/config/ci/snap_ci_spec.rb +++ b/spec/knapsack_pro/config/ci/snap_ci_spec.rb @@ -33,6 +33,19 @@ end end + describe '#node_build_id' do + subject { described_class.new.node_build_id } + + context 'when environment exists' do + let(:env) { { 'SNAP_PIPELINE_COUNTER' => 123 } } + it { should eql 123 } + end + + context "when environment doesn't exist" do + it { should be nil } + end + end + describe '#commit_hash' do subject { described_class.new.commit_hash } diff --git a/spec/knapsack_pro/config/ci/travis_spec.rb b/spec/knapsack_pro/config/ci/travis_spec.rb index b3a744b6..2f5f19c8 100644 --- a/spec/knapsack_pro/config/ci/travis_spec.rb +++ b/spec/knapsack_pro/config/ci/travis_spec.rb @@ -19,6 +19,19 @@ it { should be nil } end + describe '#node_build_id' do + subject { described_class.new.node_build_id } + + context 'when environment exists' do + let(:env) { { 'TRAVIS_BUILD_NUMBER' => 4 } } + it { should eql 4 } + end + + context "when environment doesn't exist" do + it { should be nil } + end + end + describe '#commit_hash' do subject { described_class.new.commit_hash } diff --git a/spec/knapsack_pro/config/env_spec.rb b/spec/knapsack_pro/config/env_spec.rb index 745a8227..75a09e84 100644 --- a/spec/knapsack_pro/config/env_spec.rb +++ b/spec/knapsack_pro/config/env_spec.rb @@ -47,6 +47,29 @@ end end + describe '.ci_node_build_id' do + subject { described_class.ci_node_build_id } + + context 'when ENV exists' do + context 'when KNAPSACK_PRO_CI_NODE_BUILD_ID has value' do + before { stub_const("ENV", { 'KNAPSACK_PRO_CI_NODE_BUILD_ID' => '7' }) } + it { should eq '7' } + end + + context 'when CI environment has value' do + before do + expect(described_class).to receive(:ci_env_for).with(:node_build_id).and_return('8') + end + + it { should eq '8' } + end + end + + context "when ENV doesn't exist" do + it { should be_nil } + end + end + describe '.commit_hash' do subject { described_class.commit_hash } From 6fdce41c85916400a3849961d3a9b1ee3ab1b6bc Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 23 Oct 2016 15:57:02 +0200 Subject: [PATCH 11/43] Add action for queue endpoint --- lib/knapsack_pro.rb | 1 + lib/knapsack_pro/client/api/v1/queues.rb | 28 +++++++++++++ .../knapsack_pro/client/api/v1/queues_spec.rb | 42 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 lib/knapsack_pro/client/api/v1/queues.rb create mode 100644 spec/knapsack_pro/client/api/v1/queues_spec.rb diff --git a/lib/knapsack_pro.rb b/lib/knapsack_pro.rb index e5cd5b5c..d7a3baf8 100644 --- a/lib/knapsack_pro.rb +++ b/lib/knapsack_pro.rb @@ -22,6 +22,7 @@ require_relative 'knapsack_pro/client/api/v1/base' require_relative 'knapsack_pro/client/api/v1/build_distributions' require_relative 'knapsack_pro/client/api/v1/build_subsets' +require_relative 'knapsack_pro/client/api/v1/queues' require_relative 'knapsack_pro/client/connection' require_relative 'knapsack_pro/repository_adapters/base_adapter' require_relative 'knapsack_pro/repository_adapters/env_adapter' diff --git a/lib/knapsack_pro/client/api/v1/queues.rb b/lib/knapsack_pro/client/api/v1/queues.rb new file mode 100644 index 00000000..abb96458 --- /dev/null +++ b/lib/knapsack_pro/client/api/v1/queues.rb @@ -0,0 +1,28 @@ +module KnapsackPro + module Client + module API + module V1 + class Queues < Base + class << self + def queue(args) + action_class.new( + endpoint_path: '/v1/queues/queue', + http_method: :post, + request_hash: { + :can_initialize_queue => args.fetch(:can_initialize_queue), + :commit_hash => args.fetch(:commit_hash), + :branch => args.fetch(:branch), + :node_total => args.fetch(:node_total), + :node_index => args.fetch(:node_index), + :node_build_id => KnapsackPro::Config::Env.ci_node_build_id, + :test_files => args.fetch(:test_files) + } + ) + end + end + end + end + end + end +end + diff --git a/spec/knapsack_pro/client/api/v1/queues_spec.rb b/spec/knapsack_pro/client/api/v1/queues_spec.rb new file mode 100644 index 00000000..0885fb6e --- /dev/null +++ b/spec/knapsack_pro/client/api/v1/queues_spec.rb @@ -0,0 +1,42 @@ +describe KnapsackPro::Client::API::V1::Queues do + describe '.queue' do + let(:can_initialize_queue) { double } + let(:commit_hash) { double } + let(:branch) { double } + let(:node_total) { double } + let(:node_index) { double } + let(:test_files) { double } + + subject do + described_class.queue( + can_initialize_queue: can_initialize_queue, + commit_hash: commit_hash, + branch: branch, + node_total: node_total, + node_index: node_index, + test_files: test_files + ) + end + + it do + node_build_id = double + expect(KnapsackPro::Config::Env).to receive(:ci_node_build_id).and_return(node_build_id) + + action = double + expect(KnapsackPro::Client::API::Action).to receive(:new).with({ + endpoint_path: '/v1/queues/queue', + http_method: :post, + request_hash: { + can_initialize_queue: can_initialize_queue, + commit_hash: commit_hash, + branch: branch, + node_total: node_total, + node_index: node_index, + node_build_id: node_build_id, + test_files: test_files + } + }).and_return(action) + expect(subject).to eq action + end + end +end From 02535295b477d5b38b61f662353b52a727d81fc0 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 23 Oct 2016 16:34:35 +0200 Subject: [PATCH 12/43] add queue allocator build and queue allocator --- lib/knapsack_pro/queue_allocator.rb | 41 ++++++++++++++++++ lib/knapsack_pro/queue_allocator_builder.rb | 41 ++++++++++++++++++ .../runners/queue/base_queue_runner.rb | 42 +++++++++++++++++++ .../runners/queue/rspec_runner.rb | 2 +- 4 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 lib/knapsack_pro/queue_allocator.rb create mode 100644 lib/knapsack_pro/queue_allocator_builder.rb create mode 100644 lib/knapsack_pro/runners/queue/base_queue_runner.rb diff --git a/lib/knapsack_pro/queue_allocator.rb b/lib/knapsack_pro/queue_allocator.rb new file mode 100644 index 00000000..ebb23294 --- /dev/null +++ b/lib/knapsack_pro/queue_allocator.rb @@ -0,0 +1,41 @@ +module KnapsackPro + class QueueAllocator + def initialize(args) + @test_files = args.fetch(:test_files) + @ci_node_total = args.fetch(:ci_node_total) + @ci_node_index = args.fetch(:ci_node_index) + @ci_node_build_id = args.fetch(:ci_node_build_id) + @repository_adapter = args.fetch(:repository_adapter) + end + + def test_file_paths(can_initialize_queue:) + encrypted_test_files = KnapsackPro::Crypto::Encryptor.call(test_files) + action = KnapsackPro::Client::API::V1::Queues.queue( + can_initialize_queue: can_initialize_queue, + commit_hash: repository_adapter.commit_hash, + branch: repository_adapter.branch, + node_total: ci_node_total, + node_index: ci_node_index, + node_build_id: ci_node_build_id, + test_files: encrypted_test_files, + ) + connection = KnapsackPro::Client::Connection.new(action) + response = connection.call + if connection.success? + raise ArgumentError.new(response) if connection.errors? + decrypted_test_files = KnapsackPro::Crypto::Decryptor.call(test_files, response['test_files']) + KnapsackPro::TestFilePresenter.paths(decrypted_test_files) + else + raise ArgumentError.new("Couldn't connect with Knapsack Pro API. Response: #{response}") + end + end + + private + + attr_reader :test_files, + :ci_node_total, + :ci_node_index, + :ci_node_build_id, + :repository_adapter + end +end diff --git a/lib/knapsack_pro/queue_allocator_builder.rb b/lib/knapsack_pro/queue_allocator_builder.rb new file mode 100644 index 00000000..584f7eef --- /dev/null +++ b/lib/knapsack_pro/queue_allocator_builder.rb @@ -0,0 +1,41 @@ +module KnapsackPro + class QueueAllocatorBuilder + def initialize(adapter_class) + @adapter_class = adapter_class + end + + def allocator + KnapsackPro::QueueAllocator.new( + test_files: test_files, + ci_node_total: env.ci_node_total, + ci_node_index: env.ci_node_index, + ci_node_build_id: env.ci_node_build_id, + repository_adapter: repository_adapter, + ) + end + + def test_dir + test_file_pattern.split('/').first + end + + private + + attr_reader :adapter_class + + def env + KnapsackPro::Config::Env + end + + def repository_adapter + KnapsackPro::RepositoryAdapterInitiator.call + end + + def test_file_pattern + TestFilePattern.call(adapter_class) + end + + def test_files + KnapsackPro::TestFileFinder.call(test_file_pattern) + end + end +end diff --git a/lib/knapsack_pro/runners/queue/base_queue_runner.rb b/lib/knapsack_pro/runners/queue/base_queue_runner.rb new file mode 100644 index 00000000..733a98be --- /dev/null +++ b/lib/knapsack_pro/runners/queue/base_queue_runner.rb @@ -0,0 +1,42 @@ +module KnapsackPro + module Runners + module Queue + class BaseQueueRunner + def self.run(args) + raise NotImplementedError + end + + def initialize(adapter_class) + @allocator_builder = KnapsackPro::QueueAllocatorBuilder.new(adapter_class) + @allocator = allocator_builder.allocator + end + + def test_file_paths + @test_file_paths ||= allocator.test_file_paths + end + + def stringify_test_file_paths + KnapsackPro::TestFilePresenter.stringify_paths(test_file_paths) + end + + def test_dir + allocator_builder.test_dir + end + + def test_files_to_execute_exist? + if test_file_paths.empty? + KnapsackPro.logger.info("Knapsack Pro API returned no test files to execute for the node this time. The reason might be that you changed recently a number of total nodes or you removed some test files. Please create a new commit to get a better test suite split next time.") + false + else + true + end + end + + private + + attr_reader :allocator_builder, + :allocator + end + end + end +end diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index f1c864f1..b2ebc0d5 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -1,7 +1,7 @@ module KnapsackPro module Runners module Queue - class RSpecRunner < BaseRunner + class RSpecRunner < BaseQueueRunner class Queue def initialize(test_file_paths) @test_file_paths = test_file_paths From 0ba6704796526a083c19c90d327ac36a1610fbdd Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 23 Oct 2016 16:38:58 +0200 Subject: [PATCH 13/43] extract base allocator and require files --- lib/knapsack_pro.rb | 4 +++ lib/knapsack_pro/allocator_builder.rb | 30 +----------------- lib/knapsack_pro/base_allocator_builder.rb | 35 +++++++++++++++++++++ lib/knapsack_pro/queue_allocator_builder.rb | 30 +----------------- 4 files changed, 41 insertions(+), 58 deletions(-) create mode 100644 lib/knapsack_pro/base_allocator_builder.rb diff --git a/lib/knapsack_pro.rb b/lib/knapsack_pro.rb index d7a3baf8..7d2191aa 100644 --- a/lib/knapsack_pro.rb +++ b/lib/knapsack_pro.rb @@ -38,7 +38,10 @@ require_relative 'knapsack_pro/task_loader' require_relative 'knapsack_pro/tracker' require_relative 'knapsack_pro/allocator' +require_relative 'knapsack_pro/queue_allocator' +require_relative 'knapsack_pro/base_allocator_builder' require_relative 'knapsack_pro/allocator_builder' +require_relative 'knapsack_pro/queue_allocator_builder' require_relative 'knapsack_pro/adapters/base_adapter' require_relative 'knapsack_pro/adapters/rspec_adapter' require_relative 'knapsack_pro/adapters/cucumber_adapter' @@ -49,6 +52,7 @@ require_relative 'knapsack_pro/runners/cucumber_runner' require_relative 'knapsack_pro/runners/minitest_runner' require_relative 'knapsack_pro/runners/spinach_runner' +require_relative 'knapsack_pro/runners/queue/base_queue_runner' require_relative 'knapsack_pro/runners/queue/rspec_runner' require_relative 'knapsack_pro/crypto/encryptor' require_relative 'knapsack_pro/crypto/decryptor' diff --git a/lib/knapsack_pro/allocator_builder.rb b/lib/knapsack_pro/allocator_builder.rb index 16780fad..0115e8bf 100644 --- a/lib/knapsack_pro/allocator_builder.rb +++ b/lib/knapsack_pro/allocator_builder.rb @@ -1,9 +1,5 @@ module KnapsackPro - class AllocatorBuilder - def initialize(adapter_class) - @adapter_class = adapter_class - end - + class AllocatorBuilder < BaseAllocatorBuilder def allocator KnapsackPro::Allocator.new( test_files: test_files, @@ -12,29 +8,5 @@ def allocator repository_adapter: repository_adapter, ) end - - def test_dir - test_file_pattern.split('/').first - end - - private - - attr_reader :adapter_class - - def env - KnapsackPro::Config::Env - end - - def repository_adapter - KnapsackPro::RepositoryAdapterInitiator.call - end - - def test_file_pattern - TestFilePattern.call(adapter_class) - end - - def test_files - KnapsackPro::TestFileFinder.call(test_file_pattern) - end end end diff --git a/lib/knapsack_pro/base_allocator_builder.rb b/lib/knapsack_pro/base_allocator_builder.rb new file mode 100644 index 00000000..8f40a583 --- /dev/null +++ b/lib/knapsack_pro/base_allocator_builder.rb @@ -0,0 +1,35 @@ +module KnapsackPro + class BaseAllocatorBuilder + def initialize(adapter_class) + @adapter_class = adapter_class + end + + def allocator + raise NotImplementedError + end + + def test_dir + test_file_pattern.split('/').first + end + + private + + attr_reader :adapter_class + + def env + KnapsackPro::Config::Env + end + + def repository_adapter + KnapsackPro::RepositoryAdapterInitiator.call + end + + def test_file_pattern + TestFilePattern.call(adapter_class) + end + + def test_files + KnapsackPro::TestFileFinder.call(test_file_pattern) + end + end +end diff --git a/lib/knapsack_pro/queue_allocator_builder.rb b/lib/knapsack_pro/queue_allocator_builder.rb index 584f7eef..a728f079 100644 --- a/lib/knapsack_pro/queue_allocator_builder.rb +++ b/lib/knapsack_pro/queue_allocator_builder.rb @@ -1,9 +1,5 @@ module KnapsackPro - class QueueAllocatorBuilder - def initialize(adapter_class) - @adapter_class = adapter_class - end - + class QueueAllocatorBuilder < BaseAllocatorBuilder def allocator KnapsackPro::QueueAllocator.new( test_files: test_files, @@ -13,29 +9,5 @@ def allocator repository_adapter: repository_adapter, ) end - - def test_dir - test_file_pattern.split('/').first - end - - private - - attr_reader :adapter_class - - def env - KnapsackPro::Config::Env - end - - def repository_adapter - KnapsackPro::RepositoryAdapterInitiator.call - end - - def test_file_pattern - TestFilePattern.call(adapter_class) - end - - def test_files - KnapsackPro::TestFileFinder.call(test_file_pattern) - end end end From 507ce0b75cedc61e4a3b3639cbd60d6bafb7fba9 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 23 Oct 2016 16:42:58 +0200 Subject: [PATCH 14/43] test_file_paths can initialise queue or not --- lib/knapsack_pro/queue_allocator.rb | 2 +- .../runners/queue/base_queue_runner.rb | 18 +++--------------- 2 files changed, 4 insertions(+), 16 deletions(-) diff --git a/lib/knapsack_pro/queue_allocator.rb b/lib/knapsack_pro/queue_allocator.rb index ebb23294..067322bf 100644 --- a/lib/knapsack_pro/queue_allocator.rb +++ b/lib/knapsack_pro/queue_allocator.rb @@ -8,7 +8,7 @@ def initialize(args) @repository_adapter = args.fetch(:repository_adapter) end - def test_file_paths(can_initialize_queue:) + def test_file_paths(can_initialize_queue) encrypted_test_files = KnapsackPro::Crypto::Encryptor.call(test_files) action = KnapsackPro::Client::API::V1::Queues.queue( can_initialize_queue: can_initialize_queue, diff --git a/lib/knapsack_pro/runners/queue/base_queue_runner.rb b/lib/knapsack_pro/runners/queue/base_queue_runner.rb index 733a98be..bf2d882b 100644 --- a/lib/knapsack_pro/runners/queue/base_queue_runner.rb +++ b/lib/knapsack_pro/runners/queue/base_queue_runner.rb @@ -11,27 +11,15 @@ def initialize(adapter_class) @allocator = allocator_builder.allocator end - def test_file_paths - @test_file_paths ||= allocator.test_file_paths - end - - def stringify_test_file_paths - KnapsackPro::TestFilePresenter.stringify_paths(test_file_paths) + def test_file_paths(args) + can_initialize_queue = args.fetch(:can_initialize_queue) + allocator.test_file_paths(can_initialize_queue) end def test_dir allocator_builder.test_dir end - def test_files_to_execute_exist? - if test_file_paths.empty? - KnapsackPro.logger.info("Knapsack Pro API returned no test files to execute for the node this time. The reason might be that you changed recently a number of total nodes or you removed some test files. Please create a new commit to get a better test suite split next time.") - false - else - true - end - end - private attr_reader :allocator_builder, From 6deeaf77a1475ce55ee11d1c16259e426c3fa17c Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 23 Oct 2016 18:53:44 +0200 Subject: [PATCH 15/43] Get test file paths from queue API --- .../runners/queue/base_queue_runner.rb | 4 +++ .../runners/queue/rspec_runner.rb | 36 ++++++------------- 2 files changed, 15 insertions(+), 25 deletions(-) diff --git a/lib/knapsack_pro/runners/queue/base_queue_runner.rb b/lib/knapsack_pro/runners/queue/base_queue_runner.rb index bf2d882b..6977d898 100644 --- a/lib/knapsack_pro/runners/queue/base_queue_runner.rb +++ b/lib/knapsack_pro/runners/queue/base_queue_runner.rb @@ -6,6 +6,10 @@ def self.run(args) raise NotImplementedError end + def self.run_tests(runner, can_initialize_queue, args, exitstatus) + raise NotImplementedError + end + def initialize(adapter_class) @allocator_builder = KnapsackPro::QueueAllocatorBuilder.new(adapter_class) @allocator = allocator_builder.allocator diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index b2ebc0d5..68bc34e7 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -2,18 +2,19 @@ module KnapsackPro module Runners module Queue class RSpecRunner < BaseQueueRunner - class Queue - def initialize(test_file_paths) - @test_file_paths = test_file_paths - end + def self.run(args) + require 'rspec/core/rake_task' - def test_file_paths - @test_file_paths.shift - end + ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_rspec + ENV['KNAPSACK_PRO_QUEUE_RECORDING_ENABLED'] = 'true' + ENV['KNAPSACK_PRO_QUEUE_ID'] = KnapsackPro::Config::EnvGenerator.set_queue_id + + runner = new(KnapsackPro::Adapters::RSpecAdapter) + run_tests(runner, true, args, 0) end - def self.run_tests(queue, args, runner, exitstatus) - test_file_paths = queue.test_file_paths + def self.run_tests(runner, can_initialize_queue, args, exitstatus) + test_file_paths = runner.test_file_paths(can_initialize_queue: can_initialize_queue) if test_file_paths.nil? KnapsackPro::Report.save_node_queue_to_api @@ -38,25 +39,10 @@ def self.run_tests(queue, args, runner, exitstatus) end at_exit do - run_tests(queue, args, runner, exitstatus) + run_tests(runner, false, args, exitstatus) end end end - - def self.run(args) - ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_rspec - ENV['KNAPSACK_PRO_QUEUE_RECORDING_ENABLED'] = 'true' - ENV['KNAPSACK_PRO_QUEUE_ID'] = KnapsackPro::Config::EnvGenerator.set_queue_id - - runner = new(KnapsackPro::Adapters::RSpecAdapter) - - if runner.test_files_to_execute_exist? - require 'rspec/core/rake_task' - - queue = Queue.new(runner.test_file_paths) - run_tests(queue, args, runner, 0) - end - end end end end From 523e8112f66907ca670644f8baffc7b36851e4eb Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 23 Oct 2016 18:54:10 +0200 Subject: [PATCH 16/43] set missing-bulid-id as node build id when there is not info about node build id --- lib/knapsack_pro/config/env.rb | 3 ++- spec/knapsack_pro/config/env_spec.rb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/knapsack_pro/config/env.rb b/lib/knapsack_pro/config/env.rb index 2278b66a..10221045 100644 --- a/lib/knapsack_pro/config/env.rb +++ b/lib/knapsack_pro/config/env.rb @@ -16,7 +16,8 @@ def ci_node_index def ci_node_build_id ENV['KNAPSACK_PRO_CI_NODE_BUILD_ID'] || - ci_env_for(:node_build_id) + ci_env_for(:node_build_id) || + 'missing-build-id' end def commit_hash diff --git a/spec/knapsack_pro/config/env_spec.rb b/spec/knapsack_pro/config/env_spec.rb index 75a09e84..62076b3e 100644 --- a/spec/knapsack_pro/config/env_spec.rb +++ b/spec/knapsack_pro/config/env_spec.rb @@ -66,7 +66,7 @@ end context "when ENV doesn't exist" do - it { should be_nil } + it { should eq 'missing-build-id' } end end From 89825e689f439592d3cea5a4cc24049a8fdbc071 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 23 Oct 2016 19:03:18 +0200 Subject: [PATCH 17/43] fix bug --- lib/knapsack_pro/runners/queue/rspec_runner.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index 68bc34e7..23952508 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -16,7 +16,7 @@ def self.run(args) def self.run_tests(runner, can_initialize_queue, args, exitstatus) test_file_paths = runner.test_file_paths(can_initialize_queue: can_initialize_queue) - if test_file_paths.nil? + if test_file_paths.empty? KnapsackPro::Report.save_node_queue_to_api exit(exitstatus) else From eb2cfe92d1613d9b85439dbbb443d26bbae82c57 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 23 Oct 2016 22:50:26 +0200 Subject: [PATCH 18/43] task failed --- lib/knapsack_pro/runners/queue/rspec_runner.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index 23952508..54b91d65 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -32,7 +32,7 @@ def self.run_tests(runner, can_initialize_queue, args, exitstatus) begin Rake::Task[task_name].invoke rescue Exception => e - puts "Task #{task_name} failed" + puts "Task failed: #{task_name}" puts "#{e.class}: #{e.message}" puts "Exit status: #{$?.exitstatus}" exitstatus = $?.exitstatus if $?.exitstatus != 0 From afb889af42c8b666afe98f0952e8d3e2421d690d Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 23 Oct 2016 23:44:36 +0200 Subject: [PATCH 19/43] Rename BaseQueueRunner to BaseRunner inside of Queue scope. Add empty specs --- lib/knapsack_pro.rb | 2 +- .../runners/queue/{base_queue_runner.rb => base_runner.rb} | 2 +- lib/knapsack_pro/runners/queue/rspec_runner.rb | 2 +- spec/knapsack_pro/config/env_generator_spec.rb | 3 +++ spec/knapsack_pro/queue_allocator_builder_spec.rb | 3 +++ spec/knapsack_pro/queue_allocator_spec.rb | 3 +++ spec/knapsack_pro/runners/queue/base_runner_spec.rb | 3 +++ spec/knapsack_pro/runners/queue/rspec_runner_spec.rb | 3 +++ 8 files changed, 18 insertions(+), 3 deletions(-) rename lib/knapsack_pro/runners/queue/{base_queue_runner.rb => base_runner.rb} (96%) create mode 100644 spec/knapsack_pro/config/env_generator_spec.rb create mode 100644 spec/knapsack_pro/queue_allocator_builder_spec.rb create mode 100644 spec/knapsack_pro/queue_allocator_spec.rb create mode 100644 spec/knapsack_pro/runners/queue/base_runner_spec.rb create mode 100644 spec/knapsack_pro/runners/queue/rspec_runner_spec.rb diff --git a/lib/knapsack_pro.rb b/lib/knapsack_pro.rb index 7d2191aa..1ec57789 100644 --- a/lib/knapsack_pro.rb +++ b/lib/knapsack_pro.rb @@ -52,7 +52,7 @@ require_relative 'knapsack_pro/runners/cucumber_runner' require_relative 'knapsack_pro/runners/minitest_runner' require_relative 'knapsack_pro/runners/spinach_runner' -require_relative 'knapsack_pro/runners/queue/base_queue_runner' +require_relative 'knapsack_pro/runners/queue/base_runner' require_relative 'knapsack_pro/runners/queue/rspec_runner' require_relative 'knapsack_pro/crypto/encryptor' require_relative 'knapsack_pro/crypto/decryptor' diff --git a/lib/knapsack_pro/runners/queue/base_queue_runner.rb b/lib/knapsack_pro/runners/queue/base_runner.rb similarity index 96% rename from lib/knapsack_pro/runners/queue/base_queue_runner.rb rename to lib/knapsack_pro/runners/queue/base_runner.rb index 6977d898..54a8213c 100644 --- a/lib/knapsack_pro/runners/queue/base_queue_runner.rb +++ b/lib/knapsack_pro/runners/queue/base_runner.rb @@ -1,7 +1,7 @@ module KnapsackPro module Runners module Queue - class BaseQueueRunner + class BaseRunner def self.run(args) raise NotImplementedError end diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index 54b91d65..d3621e0d 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -1,7 +1,7 @@ module KnapsackPro module Runners module Queue - class RSpecRunner < BaseQueueRunner + class RSpecRunner < BaseRunner def self.run(args) require 'rspec/core/rake_task' diff --git a/spec/knapsack_pro/config/env_generator_spec.rb b/spec/knapsack_pro/config/env_generator_spec.rb new file mode 100644 index 00000000..b5a42352 --- /dev/null +++ b/spec/knapsack_pro/config/env_generator_spec.rb @@ -0,0 +1,3 @@ +describe KnapsackPro::Config::EnvGenerator do + +end diff --git a/spec/knapsack_pro/queue_allocator_builder_spec.rb b/spec/knapsack_pro/queue_allocator_builder_spec.rb new file mode 100644 index 00000000..efb58b0d --- /dev/null +++ b/spec/knapsack_pro/queue_allocator_builder_spec.rb @@ -0,0 +1,3 @@ +describe KnapsackPro::QueueAllocatorBuilder do + +end diff --git a/spec/knapsack_pro/queue_allocator_spec.rb b/spec/knapsack_pro/queue_allocator_spec.rb new file mode 100644 index 00000000..616b1e6c --- /dev/null +++ b/spec/knapsack_pro/queue_allocator_spec.rb @@ -0,0 +1,3 @@ +describe KnapsackPro::QueueAllocator do + +end diff --git a/spec/knapsack_pro/runners/queue/base_runner_spec.rb b/spec/knapsack_pro/runners/queue/base_runner_spec.rb new file mode 100644 index 00000000..29d251f0 --- /dev/null +++ b/spec/knapsack_pro/runners/queue/base_runner_spec.rb @@ -0,0 +1,3 @@ +describe KnapsackPro::Runners::Queue::BaseRunner do + +end diff --git a/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb b/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb new file mode 100644 index 00000000..c1d435c9 --- /dev/null +++ b/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb @@ -0,0 +1,3 @@ +describe KnapsackPro::Runners::Queue::RspecRunner do + +end From 1cb3abb261e026c948069e727156f08b54e56a0c Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 23 Oct 2016 23:49:10 +0200 Subject: [PATCH 20/43] scope tmp files to queue --- lib/knapsack_pro/report.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/knapsack_pro/report.rb b/lib/knapsack_pro/report.rb index 6f5d692a..4e7cc370 100644 --- a/lib/knapsack_pro/report.rb +++ b/lib/knapsack_pro/report.rb @@ -58,7 +58,7 @@ def self.create_build_subset(test_files) def self.queue_path queue_id = KnapsackPro::Config::Env.queue_id - "tmp/knapsack_pro/#{queue_id}" + "tmp/knapsack_pro/queue/#{queue_id}" end end end From 7901d6cbb22cd438764476497f74a2e5d1317db8 Mon Sep 17 00:00:00 2001 From: ArturT Date: Tue, 3 Jan 2017 21:30:27 +0100 Subject: [PATCH 21/43] Show backtrace of error --- lib/knapsack_pro/runners/queue/rspec_runner.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index d3621e0d..dd47241a 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -35,6 +35,7 @@ def self.run_tests(runner, can_initialize_queue, args, exitstatus) puts "Task failed: #{task_name}" puts "#{e.class}: #{e.message}" puts "Exit status: #{$?.exitstatus}" + puts e.backtrace exitstatus = $?.exitstatus if $?.exitstatus != 0 end From 6c302c711afbd7b7baa94b9e1a92b80186bb4951 Mon Sep 17 00:00:00 2001 From: ArturT Date: Tue, 3 Jan 2017 21:31:07 +0100 Subject: [PATCH 22/43] run test file from queue one after another without invoking a new rake task to speed up things --- .../runners/queue/rspec_runner.rb | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index dd47241a..2acdec36 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -3,14 +3,16 @@ module Runners module Queue class RSpecRunner < BaseRunner def self.run(args) - require 'rspec/core/rake_task' + require 'rspec/core' ENV['KNAPSACK_PRO_TEST_SUITE_TOKEN'] = KnapsackPro::Config::Env.test_suite_token_rspec ENV['KNAPSACK_PRO_QUEUE_RECORDING_ENABLED'] = 'true' ENV['KNAPSACK_PRO_QUEUE_ID'] = KnapsackPro::Config::EnvGenerator.set_queue_id runner = new(KnapsackPro::Adapters::RSpecAdapter) - run_tests(runner, true, args, 0) + + cli_args = (args || '').split + run_tests(runner, true, cli_args, 0) end def self.run_tests(runner, can_initialize_queue, args, exitstatus) @@ -22,15 +24,14 @@ def self.run_tests(runner, can_initialize_queue, args, exitstatus) else subset_queue_id = KnapsackPro::Config::EnvGenerator.set_subset_queue_id ENV['KNAPSACK_PRO_SUBSET_QUEUE_ID'] = subset_queue_id - task_name = "knapsack_pro:queue:rspec_run_#{subset_queue_id}" - - RSpec::Core::RakeTask.new(task_name) do |t| - t.rspec_opts = "#{args} --default-path #{runner.test_dir}" - t.pattern = test_file_paths - end begin - Rake::Task[task_name].invoke + cli_args = args + [ + '--default-path', runner.test_dir, + ] + test_file_paths + options = RSpec::Core::ConfigurationOptions.new(cli_args) + RSpec::Core::Runner.new(options).run($stderr, $stdout) + RSpec.world.example_groups.clear rescue Exception => e puts "Task failed: #{task_name}" puts "#{e.class}: #{e.message}" From 7dcef50421afa3e1c2f29b3a241a841ab2640f7b Mon Sep 17 00:00:00 2001 From: ArturT Date: Tue, 3 Jan 2017 21:39:47 +0100 Subject: [PATCH 23/43] fix typo in spec --- spec/knapsack_pro/runners/queue/rspec_runner_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb b/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb index c1d435c9..d0c60861 100644 --- a/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb +++ b/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb @@ -1,3 +1,3 @@ -describe KnapsackPro::Runners::Queue::RspecRunner do +describe KnapsackPro::Runners::Queue::RSpecRunner do end From 9b1c46f1df17aec7ebcff15e1522e689f0c577e3 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sat, 7 Jan 2017 22:48:49 +0100 Subject: [PATCH 24/43] Refactor to keep proper exit code and expose it as exit status --- lib/knapsack_pro/runners/queue/rspec_runner.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index 2acdec36..8d3932a6 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -30,14 +30,15 @@ def self.run_tests(runner, can_initialize_queue, args, exitstatus) '--default-path', runner.test_dir, ] + test_file_paths options = RSpec::Core::ConfigurationOptions.new(cli_args) - RSpec::Core::Runner.new(options).run($stderr, $stdout) + exit_code = RSpec::Core::Runner.new(options).run($stderr, $stdout) + exitstatus = exit_code if exit_code != 0 RSpec.world.example_groups.clear rescue Exception => e - puts "Task failed: #{task_name}" + puts "Test suite subset queue failed: #{subset_queue_id}" puts "#{e.class}: #{e.message}" - puts "Exit status: #{$?.exitstatus}" + puts "Exit status: #{exit_code}" puts e.backtrace - exitstatus = $?.exitstatus if $?.exitstatus != 0 + exitstatus = exit_code if exit_code != 0 end at_exit do From 87d6495d8b1554af9de2ab06220d2340e6e70b36 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sat, 7 Jan 2017 22:56:34 +0100 Subject: [PATCH 25/43] Remove at_exit --- .../runners/queue/rspec_runner.rb | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/lib/knapsack_pro/runners/queue/rspec_runner.rb b/lib/knapsack_pro/runners/queue/rspec_runner.rb index 8d3932a6..ac8f6a74 100644 --- a/lib/knapsack_pro/runners/queue/rspec_runner.rb +++ b/lib/knapsack_pro/runners/queue/rspec_runner.rb @@ -25,25 +25,15 @@ def self.run_tests(runner, can_initialize_queue, args, exitstatus) subset_queue_id = KnapsackPro::Config::EnvGenerator.set_subset_queue_id ENV['KNAPSACK_PRO_SUBSET_QUEUE_ID'] = subset_queue_id - begin - cli_args = args + [ - '--default-path', runner.test_dir, - ] + test_file_paths - options = RSpec::Core::ConfigurationOptions.new(cli_args) - exit_code = RSpec::Core::Runner.new(options).run($stderr, $stdout) - exitstatus = exit_code if exit_code != 0 - RSpec.world.example_groups.clear - rescue Exception => e - puts "Test suite subset queue failed: #{subset_queue_id}" - puts "#{e.class}: #{e.message}" - puts "Exit status: #{exit_code}" - puts e.backtrace - exitstatus = exit_code if exit_code != 0 - end + cli_args = args + [ + '--default-path', runner.test_dir, + ] + test_file_paths + options = RSpec::Core::ConfigurationOptions.new(cli_args) + exit_code = RSpec::Core::Runner.new(options).run($stderr, $stdout) + exitstatus = exit_code if exit_code != 0 + RSpec.world.example_groups.clear - at_exit do - run_tests(runner, false, args, exitstatus) - end + run_tests(runner, false, args, exitstatus) end end end From 7268774991c403dd13474bae1286eaaf8e788aad Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 8 Jan 2017 12:21:12 +0100 Subject: [PATCH 26/43] remove white line --- lib/knapsack_pro/client/api/v1/queues.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/knapsack_pro/client/api/v1/queues.rb b/lib/knapsack_pro/client/api/v1/queues.rb index abb96458..de227e27 100644 --- a/lib/knapsack_pro/client/api/v1/queues.rb +++ b/lib/knapsack_pro/client/api/v1/queues.rb @@ -25,4 +25,3 @@ def queue(args) end end end - From 14d82f126f26479c34934213dbbbb170eddecf4f Mon Sep 17 00:00:00 2001 From: ArturT Date: Mon, 9 Jan 2017 20:44:37 +0100 Subject: [PATCH 27/43] Add test for bind_save_queue_report in base adapter --- spec/knapsack_pro/adapters/base_adapter_spec.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/spec/knapsack_pro/adapters/base_adapter_spec.rb b/spec/knapsack_pro/adapters/base_adapter_spec.rb index 99d3fb15..63041b62 100644 --- a/spec/knapsack_pro/adapters/base_adapter_spec.rb +++ b/spec/knapsack_pro/adapters/base_adapter_spec.rb @@ -60,4 +60,12 @@ }.to raise_error(NotImplementedError) end end + + describe '#bind_save_queue_report' do + it do + expect { + subject.bind_save_queue_report + }.to raise_error(NotImplementedError) + end + end end From 91c12de6070956e01f8c69924ad78300a3e9d903 Mon Sep 17 00:00:00 2001 From: ArturT Date: Mon, 9 Jan 2017 20:59:54 +0100 Subject: [PATCH 28/43] Update spec for bind method in base adapter --- .../adapters/base_adapter_spec.rb | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/spec/knapsack_pro/adapters/base_adapter_spec.rb b/spec/knapsack_pro/adapters/base_adapter_spec.rb index 63041b62..40b7fc4d 100644 --- a/spec/knapsack_pro/adapters/base_adapter_spec.rb +++ b/spec/knapsack_pro/adapters/base_adapter_spec.rb @@ -17,31 +17,54 @@ end describe '#bind' do + let(:recording_enabled?) { false } + let(:queue_recording_enabled?) { false } + before do expect(KnapsackPro::Config::Env).to receive(:recording_enabled?).and_return(recording_enabled?) + expect(KnapsackPro::Config::Env).to receive(:queue_recording_enabled?).and_return(queue_recording_enabled?) end + after { subject.bind } + context 'when recording enabled' do let(:recording_enabled?) { true } + before do + allow(subject).to receive(:bind_time_tracker) + allow(subject).to receive(:bind_save_report) + end + it do logger = instance_double(Logger) expect(KnapsackPro).to receive(:logger).and_return(logger) expect(logger).to receive(:info).with('Test suite time execution recording enabled.') - expect(subject).to receive(:bind_time_tracker) - expect(subject).to receive(:bind_save_report) - subject.bind end + it { expect(subject).to receive(:bind_time_tracker) } + it { expect(subject).to receive(:bind_save_report) } end - context 'when recording not enabled' do - let(:recording_enabled?) { false } + context 'when queue recording enabled' do + let(:queue_recording_enabled?) { true } + + before do + allow(subject).to receive(:bind_time_tracker) + allow(subject).to receive(:bind_save_queue_report) + end it do - expect(subject).not_to receive(:bind_time_tracker) - expect(subject).not_to receive(:bind_save_report) - subject.bind + logger = instance_double(Logger) + expect(KnapsackPro).to receive(:logger).and_return(logger) + expect(logger).to receive(:info).with('Test suite time execution queue recording enabled.') end + it { expect(subject).to receive(:bind_time_tracker) } + it { expect(subject).to receive(:bind_save_queue_report) } + end + + context 'when recording disabled' do + it { expect(subject).not_to receive(:bind_time_tracker) } + it { expect(subject).not_to receive(:bind_save_report) } + it { expect(subject).not_to receive(:bind_save_queue_report) } end end From 894a238245a721cf543c3c6af5ed271f9ee875ed Mon Sep 17 00:00:00 2001 From: ArturT Date: Mon, 9 Jan 2017 21:06:13 +0100 Subject: [PATCH 29/43] Add spec for bind_save_queue_report method --- spec/knapsack_pro/adapters/rspec_adapter_spec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/spec/knapsack_pro/adapters/rspec_adapter_spec.rb b/spec/knapsack_pro/adapters/rspec_adapter_spec.rb index 46055e42..2043d76c 100644 --- a/spec/knapsack_pro/adapters/rspec_adapter_spec.rb +++ b/spec/knapsack_pro/adapters/rspec_adapter_spec.rb @@ -112,5 +112,16 @@ subject.bind_save_report end end + + describe '#bind_save_queue_report' do + it do + expect(config).to receive(:after).with(:suite).and_yield + expect(::RSpec).to receive(:configure).and_yield(config) + + expect(KnapsackPro::Report).to receive(:save_subset_queue_to_file) + + subject.bind_save_queue_report + end + end end end From e9ef45a96535029127f01ede981564c217034100 Mon Sep 17 00:00:00 2001 From: ArturT Date: Mon, 9 Jan 2017 21:20:04 +0100 Subject: [PATCH 30/43] Extract spec for base allocator builder. Refactor spec for allocator builder and add spec for queue allocator builder --- spec/knapsack_pro/allocator_builder_spec.rb | 14 ++------ .../base_allocator_builder_spec.rb | 22 ++++++++++++ .../queue_allocator_builder_spec.rb | 35 +++++++++++++++++++ 3 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 spec/knapsack_pro/base_allocator_builder_spec.rb diff --git a/spec/knapsack_pro/allocator_builder_spec.rb b/spec/knapsack_pro/allocator_builder_spec.rb index 7b8ecfb2..a0961607 100644 --- a/spec/knapsack_pro/allocator_builder_spec.rb +++ b/spec/knapsack_pro/allocator_builder_spec.rb @@ -22,24 +22,14 @@ ci_node_index = double expect(KnapsackPro::Config::Env).to receive(:ci_node_index).and_return(ci_node_index) - expect(KnapsackPro::Allocator).to receive(:new).with({ + expect(KnapsackPro::Allocator).to receive(:new).with( test_files: test_files, ci_node_total: ci_node_total, ci_node_index: ci_node_index, repository_adapter: repository_adapter, - }).and_return(allocator) + ).and_return(allocator) end it { should eq allocator } end - - describe '#test_dir' do - subject { allocator_builder.test_dir } - - before do - expect(KnapsackPro::TestFilePattern).to receive(:call).and_return('spec/**{,/*/**}/*_spec.rb') - end - - it { should eq 'spec' } - end end diff --git a/spec/knapsack_pro/base_allocator_builder_spec.rb b/spec/knapsack_pro/base_allocator_builder_spec.rb new file mode 100644 index 00000000..6d385303 --- /dev/null +++ b/spec/knapsack_pro/base_allocator_builder_spec.rb @@ -0,0 +1,22 @@ +describe KnapsackPro::BaseAllocatorBuilder do + let(:adapter_class) { KnapsackPro::Adapters::BaseAdapter } + let(:allocator_builder) { described_class.new(adapter_class) } + + describe '#allocator' do + subject { allocator_builder.allocator } + + it do + expect { subject }.to raise_error(NotImplementedError) + end + end + + describe '#test_dir' do + subject { allocator_builder.test_dir } + + before do + expect(KnapsackPro::TestFilePattern).to receive(:call).with(adapter_class).and_return('spec/**{,/*/**}/*_spec.rb') + end + + it { should eq 'spec' } + end +end diff --git a/spec/knapsack_pro/queue_allocator_builder_spec.rb b/spec/knapsack_pro/queue_allocator_builder_spec.rb index efb58b0d..2b63111e 100644 --- a/spec/knapsack_pro/queue_allocator_builder_spec.rb +++ b/spec/knapsack_pro/queue_allocator_builder_spec.rb @@ -1,3 +1,38 @@ describe KnapsackPro::QueueAllocatorBuilder do + let(:adapter_class) { KnapsackPro::Adapters::BaseAdapter } + let(:allocator_builder) { described_class.new(adapter_class) } + describe '#allocator' do + let(:allocator) { double } + + subject { allocator_builder.allocator } + + before do + test_file_pattern = double + expect(KnapsackPro::TestFilePattern).to receive(:call).with(adapter_class).and_return(test_file_pattern) + + test_files = double + expect(KnapsackPro::TestFileFinder).to receive(:call).with(test_file_pattern).and_return(test_files) + + repository_adapter = double + expect(KnapsackPro::RepositoryAdapterInitiator).to receive(:call).and_return(repository_adapter) + + ci_node_total = double + expect(KnapsackPro::Config::Env).to receive(:ci_node_total).and_return(ci_node_total) + ci_node_index = double + expect(KnapsackPro::Config::Env).to receive(:ci_node_index).and_return(ci_node_index) + ci_node_build_id = double + expect(KnapsackPro::Config::Env).to receive(:ci_node_build_id).and_return(ci_node_build_id) + + expect(KnapsackPro::QueueAllocator).to receive(:new).with( + test_files: test_files, + ci_node_total: ci_node_total, + ci_node_index: ci_node_index, + ci_node_build_id: ci_node_build_id, + repository_adapter: repository_adapter, + ).and_return(allocator) + end + + it { should eq allocator } + end end From 6fdea6cba1183e41dc2f6debccc31d132e344af0 Mon Sep 17 00:00:00 2001 From: ArturT Date: Mon, 9 Jan 2017 22:11:30 +0100 Subject: [PATCH 31/43] Add spec for queue methods in config env --- spec/knapsack_pro/config/env_spec.rb | 66 ++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/spec/knapsack_pro/config/env_spec.rb b/spec/knapsack_pro/config/env_spec.rb index 62076b3e..5a5dd4aa 100644 --- a/spec/knapsack_pro/config/env_spec.rb +++ b/spec/knapsack_pro/config/env_spec.rb @@ -201,6 +201,72 @@ end end + describe '.queue_recording_enabled' do + subject { described_class.queue_recording_enabled } + + context 'when ENV exists' do + let(:queue_recording_enabled) { 'true' } + before { stub_const("ENV", { 'KNAPSACK_PRO_QUEUE_RECORDING_ENABLED' => queue_recording_enabled }) } + it { should eq queue_recording_enabled } + end + + context "when ENV doesn't exist" do + it { should be_nil } + end + end + + describe '.queue_recording_enabled?' do + subject { described_class.queue_recording_enabled? } + + before do + expect(described_class).to receive(:queue_recording_enabled).and_return(queue_recording_enabled) + end + + context 'when enabled' do + let(:queue_recording_enabled) { 'true' } + + it { should be true } + end + + context 'when disabled' do + let(:queue_recording_enabled) { nil } + + it { should be false } + end + end + + describe '.queue_id' do + subject { described_class.queue_id } + + context 'when ENV exists' do + let(:queue_id) { 'fake-queue-id' } + before { stub_const("ENV", { 'KNAPSACK_PRO_QUEUE_ID' => queue_id }) } + it { should eq queue_id } + end + + context "when ENV doesn't exist" do + it do + expect { subject }.to raise_error('Missing Queue ID') + end + end + end + + describe '.subset_queue_id' do + subject { described_class.subset_queue_id } + + context 'when ENV exists' do + let(:subset_queue_id) { 'fake-subset-queue-id' } + before { stub_const("ENV", { 'KNAPSACK_PRO_SUBSET_QUEUE_ID' => subset_queue_id }) } + it { should eq subset_queue_id } + end + + context "when ENV doesn't exist" do + it do + expect { subject }.to raise_error('Missing Subset Queue ID') + end + end + end + describe '.test_files_encrypted' do subject { described_class.test_files_encrypted } From ef55bbe51b92ed6674c572ac3e4a88381a8a89a7 Mon Sep 17 00:00:00 2001 From: ArturT Date: Mon, 9 Jan 2017 22:24:27 +0100 Subject: [PATCH 32/43] Add spec for set_queue_id --- lib/knapsack_pro/config/env_generator.rb | 2 +- .../knapsack_pro/config/env_generator_spec.rb | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/lib/knapsack_pro/config/env_generator.rb b/lib/knapsack_pro/config/env_generator.rb index be9c9ee7..84b2c01f 100644 --- a/lib/knapsack_pro/config/env_generator.rb +++ b/lib/knapsack_pro/config/env_generator.rb @@ -4,7 +4,7 @@ class EnvGenerator class << self def set_queue_id if ENV['KNAPSACK_PRO_QUEUE_ID'] - raise 'Queue ID already generated' + raise 'Queue ID already generated.' else ENV['KNAPSACK_PRO_QUEUE_ID'] = "#{Time.now.to_i}_#{SecureRandom.uuid}" end diff --git a/spec/knapsack_pro/config/env_generator_spec.rb b/spec/knapsack_pro/config/env_generator_spec.rb index b5a42352..b90ac0d9 100644 --- a/spec/knapsack_pro/config/env_generator_spec.rb +++ b/spec/knapsack_pro/config/env_generator_spec.rb @@ -1,3 +1,37 @@ describe KnapsackPro::Config::EnvGenerator do + describe '.set_queue_id' do + subject { described_class.set_queue_id } + context 'when queue id exists' do + before do + stub_const("ENV", { 'KNAPSACK_PRO_QUEUE_ID' => 'fake-queue-id' }) + end + + it do + expect { subject }.to raise_error('Queue ID already generated.') + end + end + + context "when queue id doesn't exist" do + before { stub_const("ENV", {}) } + + it do + subject + expect(ENV['KNAPSACK_PRO_QUEUE_ID']).not_to be_nil + end + + it do + now = Date.new(2016, 1, 9) + + Timecop.freeze(now) do + uuid = 'fake-uuid' + expect(SecureRandom).to receive(:uuid).and_return(uuid) + + subject + + expect(ENV['KNAPSACK_PRO_QUEUE_ID']).to eq '1452294000_fake-uuid' + end + end + end + end end From ea3772c91d735274618871b0306f9e6831f07161 Mon Sep 17 00:00:00 2001 From: ArturT Date: Mon, 9 Jan 2017 22:25:42 +0100 Subject: [PATCH 33/43] Ensure the ENV is empty before running tests for KNAPSACK_PRO_QUEUE_ID to avoid edge case when other tests overrides the ENV --- spec/knapsack_pro/config/env_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/knapsack_pro/config/env_spec.rb b/spec/knapsack_pro/config/env_spec.rb index 5a5dd4aa..ae2fb832 100644 --- a/spec/knapsack_pro/config/env_spec.rb +++ b/spec/knapsack_pro/config/env_spec.rb @@ -245,6 +245,7 @@ end context "when ENV doesn't exist" do + before { stub_const("ENV", {}) } it do expect { subject }.to raise_error('Missing Queue ID') end From a052923cb44ff234e2cc42575fbd224ea75656d8 Mon Sep 17 00:00:00 2001 From: ArturT Date: Mon, 9 Jan 2017 22:28:02 +0100 Subject: [PATCH 34/43] Add spec for set_subset_queue_id --- spec/knapsack_pro/config/env_generator_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/spec/knapsack_pro/config/env_generator_spec.rb b/spec/knapsack_pro/config/env_generator_spec.rb index b90ac0d9..398d5188 100644 --- a/spec/knapsack_pro/config/env_generator_spec.rb +++ b/spec/knapsack_pro/config/env_generator_spec.rb @@ -34,4 +34,19 @@ end end end + + describe '.set_subset_queue_id' do + subject { described_class.set_subset_queue_id } + + before { stub_const("ENV", {}) } + + it do + uuid = 'fake-uuid' + expect(SecureRandom).to receive(:uuid).and_return(uuid) + + subject + + expect(ENV['KNAPSACK_PRO_SUBSET_QUEUE_ID']).to eq uuid + end + end end From a631517485c5a5e8fff3599bc6f64c738dee2227 Mon Sep 17 00:00:00 2001 From: ArturT Date: Mon, 9 Jan 2017 22:56:23 +0100 Subject: [PATCH 35/43] Add spec for queue allocator --- spec/knapsack_pro/queue_allocator_spec.rb | 82 +++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/spec/knapsack_pro/queue_allocator_spec.rb b/spec/knapsack_pro/queue_allocator_spec.rb index 616b1e6c..7ffb5884 100644 --- a/spec/knapsack_pro/queue_allocator_spec.rb +++ b/spec/knapsack_pro/queue_allocator_spec.rb @@ -1,3 +1,85 @@ describe KnapsackPro::QueueAllocator do + let(:test_files) { double } + let(:ci_node_total) { double } + let(:ci_node_index) { double } + let(:ci_node_build_id) { double } + let(:repository_adapter) { instance_double(KnapsackPro::RepositoryAdapters::EnvAdapter, commit_hash: double, branch: double) } + let(:queue_allocator) do + described_class.new( + test_files: test_files, + ci_node_total: ci_node_total, + ci_node_index: ci_node_index, + ci_node_build_id: ci_node_build_id, + repository_adapter: repository_adapter + ) + end + + describe '#test_file_paths' do + let(:can_initialize_queue) { double } + let(:response) { double } + + subject { queue_allocator.test_file_paths(can_initialize_queue) } + + before do + encrypted_test_files = double + expect(KnapsackPro::Crypto::Encryptor).to receive(:call).with(test_files).and_return(encrypted_test_files) + + action = double + expect(KnapsackPro::Client::API::V1::Queues).to receive(:queue).with( + can_initialize_queue: can_initialize_queue, + commit_hash: repository_adapter.commit_hash, + branch: repository_adapter.branch, + node_total: ci_node_total, + node_index: ci_node_index, + node_build_id: ci_node_build_id, + test_files: encrypted_test_files, + ).and_return(action) + + connection = instance_double(KnapsackPro::Client::Connection, + call: response, + success?: success?, + errors?: errors?) + expect(KnapsackPro::Client::Connection).to receive(:new).with(action).and_return(connection) + end + + context 'when successful request to API' do + let(:success?) { true } + + context 'when response has errors' do + let(:errors?) { true } + + it do + expect { subject }.to raise_error(ArgumentError) + end + end + + context 'when response has no errors' do + let(:errors?) { false } + let(:response) do + { + 'test_files' => [ + { 'path' => 'a_spec.rb' }, + { 'path' => 'b_spec.rb' }, + ] + } + end + + before do + expect(KnapsackPro::Crypto::Decryptor).to receive(:call).with(test_files, response['test_files']).and_call_original + end + + it { should eq ['a_spec.rb', 'b_spec.rb'] } + end + end + + context 'when not successful request to API' do + let(:success?) { false } + let(:errors?) { false } + + it do + expect { subject }.to raise_error("Couldn't connect with Knapsack Pro API. Response: #{response}") + end + end + end end From ecbaf09ec2eca614a28585cffea74042aee1e466 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sat, 14 Jan 2017 22:26:00 +0100 Subject: [PATCH 36/43] Add spec for queue methods in report --- spec/knapsack_pro/report_spec.rb | 69 ++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/spec/knapsack_pro/report_spec.rb b/spec/knapsack_pro/report_spec.rb index c839cb78..b65c89d3 100644 --- a/spec/knapsack_pro/report_spec.rb +++ b/spec/knapsack_pro/report_spec.rb @@ -2,11 +2,80 @@ describe '.save' do subject { described_class.save } + it do + test_files = double + tracker = instance_double(KnapsackPro::Tracker, to_a: test_files) + expect(KnapsackPro).to receive(:tracker).and_return(tracker) + expect(described_class).to receive(:create_build_subset).with(test_files) + + subject + end + end + + describe '.save_subset_queue_to_file' do + let(:fake_path) { SecureRandom.uuid } + + subject { described_class.save_subset_queue_to_file } + before do + test_files = [{path: fake_path}] tracker = instance_double(KnapsackPro::Tracker, to_a: test_files) expect(KnapsackPro).to receive(:tracker).and_return(tracker) + + subset_queue_id = 'fake-subset-queue-id' + expect(KnapsackPro::Config::Env).to receive(:subset_queue_id).and_return(subset_queue_id) + + queue_id = 'fake-queue-id' + expect(KnapsackPro::Config::Env).to receive(:queue_id).twice.and_return(queue_id) end + it do + subject + + expect( + JSON.parse( + File.read('tmp/knapsack_pro/queue/fake-queue-id/fake-subset-queue-id.json') + ) + ).to eq([ + { 'path' => fake_path } + ]) + end + end + + describe '.save_node_queue_to_api' do + let(:json_test_file_a_path) { double } + let(:json_test_file_a) { [{ 'path' => 'a_spec.rb' }] } + + let(:json_test_file_b_path) { double } + let(:json_test_file_b) { [{ 'path' => 'b_spec.rb' }] } + + subject { described_class.save_node_queue_to_api } + + before do + queue_id = 'fake-queue-id' + expect(KnapsackPro::Config::Env).to receive(:queue_id).and_return(queue_id) + + expect(Dir).to receive(:glob).with('tmp/knapsack_pro/queue/fake-queue-id/*.json').and_return([ + json_test_file_a_path, + json_test_file_b_path + ]) + + expect(File).to receive(:read).with(json_test_file_a_path).and_return(json_test_file_a.to_json) + expect(File).to receive(:read).with(json_test_file_b_path).and_return(json_test_file_b.to_json) + end + + it do + expect(described_class).to receive(:create_build_subset).with( + json_test_file_a + json_test_file_b + ) + + subject + end + end + + describe '.create_build_subset' do + subject { described_class.create_build_subset(test_files) } + context "when test files doesn't exist" do let(:test_files) { [] } From e3dd25ba6c4f9f30de894c93457f5a56c7696b68 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sat, 14 Jan 2017 22:38:32 +0100 Subject: [PATCH 37/43] Add spec for queue base runner --- .../runners/queue/base_runner_spec.rb | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/spec/knapsack_pro/runners/queue/base_runner_spec.rb b/spec/knapsack_pro/runners/queue/base_runner_spec.rb index 29d251f0..f0d2663a 100644 --- a/spec/knapsack_pro/runners/queue/base_runner_spec.rb +++ b/spec/knapsack_pro/runners/queue/base_runner_spec.rb @@ -1,3 +1,67 @@ describe KnapsackPro::Runners::Queue::BaseRunner do + describe '.run' do + it do + expect { + described_class.run(nil) + }.to raise_error NotImplementedError + end + end + describe '.run_tests' do + it do + expect { + described_class.run_tests(nil, nil, nil, nil) + }.to raise_error NotImplementedError + end + end + + describe 'instance methods' do + let(:adapter_class) { double } + let(:runner) do + described_class.new(adapter_class) + end + let(:allocator) { instance_double(KnapsackPro::QueueAllocator) } + let(:allocator_builder) { instance_double(KnapsackPro::QueueAllocatorBuilder) } + + before do + expect(KnapsackPro::QueueAllocatorBuilder).to receive(:new).with(adapter_class).and_return(allocator_builder) + expect(allocator_builder).to receive(:allocator).and_return(allocator) + end + + describe '#test_file_paths' do + subject { runner.test_file_paths(args) } + + context 'when can_initialize_queue flag has value' do + let(:can_initialize_queue) { double } + let(:args) { { can_initialize_queue: can_initialize_queue } } + let(:test_file_paths) { double } + + before do + expect(allocator).to receive(:test_file_paths).and_return(test_file_paths) + end + + it { should eq test_file_paths } + end + + context 'when can_initialize_queue flag has no value' do + let(:args) { {} } + + it do + expect { subject }.to raise_error(KeyError) + end + end + end + + describe '#test_dir' do + let(:test_dir) { double } + + subject { runner.test_dir } + + before do + expect(allocator_builder).to receive(:test_dir).and_return(test_dir) + end + + it { should eq test_dir } + end + end end From f6e85b04dacea6336ea7bfb9e84e8cab42a017ae Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 15 Jan 2017 00:26:07 +0100 Subject: [PATCH 38/43] Add spec for queue RSpec runner --- .../runners/queue/rspec_runner_spec.rb | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb b/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb index d0c60861..0c39607c 100644 --- a/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb +++ b/spec/knapsack_pro/runners/queue/rspec_runner_spec.rb @@ -1,3 +1,118 @@ describe KnapsackPro::Runners::Queue::RSpecRunner do + describe '.run' do + let(:test_suite_token_rspec) { 'fake-token' } + let(:queue_id) { 'fake-queue-id' } + let(:runner) { double } + subject { described_class.run(args) } + + before do + expect(KnapsackPro::Config::Env).to receive(:test_suite_token_rspec).and_return(test_suite_token_rspec) + expect(KnapsackPro::Config::EnvGenerator).to receive(:set_queue_id).and_return(queue_id) + + expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_TEST_SUITE_TOKEN', test_suite_token_rspec) + expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_QUEUE_RECORDING_ENABLED', 'true') + expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_QUEUE_ID', queue_id) + + expect(described_class).to receive(:new).with(KnapsackPro::Adapters::RSpecAdapter).and_return(runner) + end + + context 'when args provided' do + let(:args) { '--example-arg example-value' } + + it do + result = double + expect(described_class).to receive(:run_tests).with(runner, true, ['--example-arg', 'example-value'], 0).and_return(result) + + expect(subject).to eq result + end + end + + context 'when args not provided' do + let(:args) { nil } + + it do + result = double + expect(described_class).to receive(:run_tests).with(runner, true, [], 0).and_return(result) + + expect(subject).to eq result + end + end + end + + describe '.run_tests' do + let(:test_dir) { 'fake-test-dir' } + let(:runner) do + instance_double(described_class, test_dir: test_dir) + end + let(:can_initialize_queue) { double(:can_initialize_queue) } + let(:args) { ['--example-arg', 'example-value'] } + let(:exitstatus) { double } + + subject { described_class.run_tests(runner, can_initialize_queue, args, exitstatus) } + + before do + expect(runner).to receive(:test_file_paths).with(can_initialize_queue: can_initialize_queue).and_return(test_file_paths) + end + + context 'when test files exist' do + let(:test_file_paths) { ['a_spec.rb', 'b_spec.rb'] } + + before do + subset_queue_id = 'fake-subset-queue-id' + expect(KnapsackPro::Config::EnvGenerator).to receive(:set_subset_queue_id).and_return(subset_queue_id) + + expect(ENV).to receive(:[]=).with('KNAPSACK_PRO_SUBSET_QUEUE_ID', subset_queue_id) + + options = double + expect(RSpec::Core::ConfigurationOptions).to receive(:new).with([ + '--example-arg', 'example-value', + '--default-path', test_dir, + 'a_spec.rb', 'b_spec.rb', + ]).and_return(options) + + rspec_core_runner = double + expect(RSpec::Core::Runner).to receive(:new).with(options).and_return(rspec_core_runner) + expect(rspec_core_runner).to receive(:run).with($stderr, $stdout).and_return(exit_code) + + expect(RSpec).to receive_message_chain(:world, :example_groups, :clear) + + # second call of run_tests because of recursion + expect(runner).to receive(:test_file_paths).with(can_initialize_queue: false).and_return([]) + end + + context 'when exit code is zero' do + let(:exit_code) { 0 } + + it do + expect(KnapsackPro::Report).to receive(:save_node_queue_to_api) + expect(described_class).to receive(:exit).with(exitstatus) + + subject + end + end + + context 'when exit code is not zero' do + let(:exit_code) { double } + + it do + expect(KnapsackPro::Report).to receive(:save_node_queue_to_api) + expect(described_class).to receive(:exit).with(exit_code) + + subject + end + end + end + + context "when test files don't exist" do + let(:test_file_paths) { [] } + + it do + expect(KnapsackPro::Report).to receive(:save_node_queue_to_api) + expect(described_class).to receive(:exit).with(exitstatus) + + subject + end + end + end end From 34c513f7daad4e614826b0d43d094552c104f271 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 15 Jan 2017 00:34:54 +0100 Subject: [PATCH 39/43] Fix spec failing on CI because of not precise time --- spec/knapsack_pro/config/env_generator_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/knapsack_pro/config/env_generator_spec.rb b/spec/knapsack_pro/config/env_generator_spec.rb index 398d5188..fb985f06 100644 --- a/spec/knapsack_pro/config/env_generator_spec.rb +++ b/spec/knapsack_pro/config/env_generator_spec.rb @@ -21,7 +21,7 @@ end it do - now = Date.new(2016, 1, 9) + now = DateTime.new(2016, 1, 9, 0, 0, 0) Timecop.freeze(now) do uuid = 'fake-uuid' @@ -29,7 +29,7 @@ subject - expect(ENV['KNAPSACK_PRO_QUEUE_ID']).to eq '1452294000_fake-uuid' + expect(ENV['KNAPSACK_PRO_QUEUE_ID']).to eq '1452297600_fake-uuid' end end end From 1929be2c8f1047fea9afab39cb47c26bf50288dc Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 15 Jan 2017 17:51:23 +0100 Subject: [PATCH 40/43] Add queue mode info in read me --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index b902c028..d1767a62 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,10 @@ For instance when you will run tests with rake knapsack_pro:rspec then: - [Repository adapter (How to set up 3 of 3)](#repository-adapter-how-to-set-up-3-of-3) - [When you NOT set global variable `KNAPSACK_PRO_REPOSITORY_ADAPTER` (default)](#when-you-not-set-global-variable-knapsack_pro_repository_adapter-default) - [When you set global variable `KNAPSACK_PRO_REPOSITORY_ADAPTER=git` (required when CI provider is not supported)](#when-you-set-global-variable-knapsack_pro_repository_adaptergit-required-when-ci-provider-is-not-supported) +- [Queue Mode](#queue-mode) + - [How queue mode works?](#how-queue-mode-works) + - [How to use queue mode?](#how-to-use-queue-mode) + - [Additional info about queue mode](#additional-info-about-queue-mode) - [Extra configuration for CI server](#extra-configuration-for-ci-server) - [Info about ENV variables](#info-about-env-variables) - [KNAPSACK_PRO_FIXED_TEST_SUITE_SPLITE (test suite split based on seed)](#knapsack_pro_fixed_test_suite_splite-test-suite-split-based-on-seed) @@ -274,6 +278,35 @@ You can also use git as repository adapter to determine branch and commit hash, `KNAPSACK_PRO_PROJECT_DIR` - Path to the project on CI node for instance `/home/ubuntu/my-app-repository`. It should be main directory of your repository. +## Queue Mode + +knapsack_pro has built in queue mode designed to solve problem with optimal test suite split in case of random time execution of test files caused by +CI node overload and a random decrease of performance that may affect how long the test files are executed. +The problem with random time execution of test files may be caused by many things like external requests done in tests. + +### How queue mode works? + +On the Knapsack Pro API side, there is test files queue generated for your CI build. Each of CI node dynamically asks the Knapsack Pro API for test files +that should be executed. Thanks to that each CI node will finish tests at the same time. + +### How to use queue mode? + +Please use this command to run queue mode: + + bundle exec rake knapsack_pro:queue:rspec + +If above command fails then you may need to explicitly pass an argument to require `rails_helper` file or `spec_helper` in case you are not doing this in some of your test files: + + bundle exec rake "knapsack_pro:queue:rspec[--require rails_helper]" + +Note if you will run queue mode command for the first time it might be slower. +The second build should have better optimal test suite split. + +### Additional info about queue mode + +If you are not using one of supported CI providers then please note that knapsack_pro gem doesn't know what is CI build ID in order to generated queue for particular CI build. This may result in two different CI builds taking tests from the same queue when CI builds are running at the same time against the same git commit. +To avoid this you can specify unique `KNAPSACK_PRO_CI_NODE_BUILD_ID` environment variable for each CI build. This mean that each CI node that is part of particular CI build should have the same value for `KNAPSACK_PRO_CI_NODE_BUILD_ID`. + ## Extra configuration for CI server ### Info about ENV variables From 66f0176e00c8d8464609b564243905f52556f759 Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 15 Jan 2017 17:54:21 +0100 Subject: [PATCH 41/43] Add supported test runners in queue mode --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index d1767a62..d6861e7a 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ For instance when you will run tests with rake knapsack_pro:rspec then: - [How queue mode works?](#how-queue-mode-works) - [How to use queue mode?](#how-to-use-queue-mode) - [Additional info about queue mode](#additional-info-about-queue-mode) + - [Supported test runners in queue mode](#supported-test-runners-in-queue-mode) - [Extra configuration for CI server](#extra-configuration-for-ci-server) - [Info about ENV variables](#info-about-env-variables) - [KNAPSACK_PRO_FIXED_TEST_SUITE_SPLITE (test suite split based on seed)](#knapsack_pro_fixed_test_suite_splite-test-suite-split-based-on-seed) @@ -307,6 +308,12 @@ The second build should have better optimal test suite split. If you are not using one of supported CI providers then please note that knapsack_pro gem doesn't know what is CI build ID in order to generated queue for particular CI build. This may result in two different CI builds taking tests from the same queue when CI builds are running at the same time against the same git commit. To avoid this you can specify unique `KNAPSACK_PRO_CI_NODE_BUILD_ID` environment variable for each CI build. This mean that each CI node that is part of particular CI build should have the same value for `KNAPSACK_PRO_CI_NODE_BUILD_ID`. +### Supported test runners in queue mode + +At this moment the queue mode works for: + +* RSpec + ## Extra configuration for CI server ### Info about ENV variables From a4378955edfdf01ace5d190d8770d3fc2934acac Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 15 Jan 2017 17:58:02 +0100 Subject: [PATCH 42/43] Add info about queue mode in details --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d6861e7a..06712d98 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Next time when you will run tests you will get proper test files for each CI nod ## Details -For instance when you will run tests with rake knapsack_pro:rspec then: +For instance when you will run tests with `rake knapsack_pro:rspec` then: * information about all your existing test files are sent to API http://docs.knapsackpro.com/api/v1/#build_distributions_subset_post * API returns which files should be executed on particular CI node (example KNAPSACK_PRO_CI_NODE_INDEX=0) @@ -41,6 +41,8 @@ For instance when you will run tests with rake knapsack_pro:rspec then: * knapsack_pro will run test files which got from API * after tests finished knapsack_pro will send information about time execution of each file to API http://docs.knapsackpro.com/api/v1/#build_subsets_post so data can be used for future test runs +The knapsack_pro has also [queue mode](#queue-mode) to get most optimal test suite split. + # Requirements * >= Ruby 2.0.0 From e819c1a98b1cc6609552d41c7fd653dda448f20d Mon Sep 17 00:00:00 2001 From: ArturT Date: Sun, 15 Jan 2017 18:21:11 +0100 Subject: [PATCH 43/43] Add queue mode to bin --- README.md | 1 + bin/knapsack_pro | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 06712d98..e3b69319 100644 --- a/README.md +++ b/README.md @@ -404,6 +404,7 @@ Add arguments to knapsack_pro spinach task like this: You can install knapsack_pro globally and use binary. For instance: $ knapsack_pro rspec "--tag custom_tag_name --profile" + $ knapsack_pro queue:rspec "--tag custom_tag_name --profile" $ knapsack_pro cucumber "--name feature" $ knapsack_pro minitest "--verbose --pride" $ knapsack_pro spinach "--arg_name value" diff --git a/bin/knapsack_pro b/bin/knapsack_pro index 722315f9..6dc46f89 100755 --- a/bin/knapsack_pro +++ b/bin/knapsack_pro @@ -7,6 +7,7 @@ arguments = ARGV[1] MAP = { 'rspec' => KnapsackPro::Runners::RSpecRunner, + 'queue:rspec' => KnapsackPro::Runners::Queue::RSpecRunner, 'cucumber' => KnapsackPro::Runners::CucumberRunner, 'minitest' => KnapsackPro::Runners::MinitestRunner, 'spinach' => KnapsackPro::Runners::SpinachRunner,