Cookbook
Use the Knapsack Pro binary
You can install Knapsack Pro globally as a binary if you don't want it as a dependency in your Gemfile:
gem install knapsack_pro
knapsack_pro queue:rspec "--tag MY_TAG --profile"
Set a custom logger
Consider KNAPSACK_PRO_LOG_LEVEL
and KNAPSACK_PRO_LOG_DIR
instead.
In your rails_helper.rb
, you can set a custom Knapsack Pro logger:
# This line should be already in your rails_helper.rb
require File.expand_path('../../config/environment', __FILE__)
require 'logger'
KnapsackPro.logger = Logger.new(Rails.root.join('log', "knapsack_pro_node_#{KnapsackPro::Config::Env.ci_node_index}.log"))
KnapsackPro.logger.level = Logger::DEBUG
The very first request to the Knapsack Pro API will still be sent to stdout because Knapsack Pro needs the subset of test files to execute before loading rails_helper.rb
.
Run Knapsack Pro on a subset of parallel CI nodes (instead of all)
You may want to run Knapsack Pro only on a subset of parallel CI nodes, and use the others nodes for something else (e.g., linters).
For example, you could decide to run Knapsack Pro on all the CI nodes but the last one:
KNAPSACK_PRO_CI_NODE_TOTAL=$((MY_CI_NODE_TOTAL-1)) bundle exec rake knapsack_pro:queue:rspec
To find out which environment variable to use in place of MY_CI_NODE_TOTAL
, take a look at what Knapsack Pro uses as node_total
for your CI provider (e.g., for CircleCI it would be CIRCLE_NODE_TOTAL
)
Fail the CI build if one of the test files exceeds a certain time limit
In the after_queue
hook, retrieve the slowest test file and create a file on disk if it exceeds a given THRESHOLD
:
KnapsackPro::Hooks::Queue.after_queue do |queue_id|
THRESHOLD = 120 # seconds
# all recorded test files by knapsack_pro gem on particular CI node index
slowest = Dir.glob(".knapsack_pro/queue/#{queue_id}/*.json")
.flat_map { |file| JSON.parse(File.read(file)) }
.max_by { |test_file| test_file['time_execution'] }
if slowest['time_execution'].to_f > THRESHOLD
puts '!' * 50
puts "The slowest test file (#{slowest['path']}) took #{slowest['time_execution']} seconds and exceeded the threshold (#{THRESHOLD} seconds)."
puts '!' * 50
File.open('tmp/slowest_test_file_exceeded_threshold.txt', 'w+') do |file|
file.write(slowest.to_json)
end
end
end
Then, in a bash script fail the CI build if the file exists:
#!/bin/bash
THRESHOLD_FILE_PATH="tmp/slowest_test_file_exceeded_threshold.txt"
if [ -f "$THRESHOLD_FILE_PATH" ]; then
rm "$THRESHOLD_FILE_PATH"
cat "$THRESHOLD_FILE_PATH"
echo "Slow test file exceeded threshold. Fail CI build."
exit 1
fi
Run multiple test commands with one script
#!/bin/bash
# Cucumber suite
bundle exec rake knapsack_pro:queue:cucumber
export CUCUMBER_EXIT_CODE=$?
# RSpec suite
bundle exec rake knapsack_pro:queue:rspec
export RSPEC_EXIT_CODE=$?
if [ "$CUCUMBER_EXIT_CODE" -ne "0" ]; then
exit $CUCUMBER_EXIT_CODE
fi
if [ "$RSPEC_EXIT_CODE" -ne "0" ]; then
exit $RSPEC_EXIT_CODE
fi
Run (and fail fast) multiple test commands with one script
CI nodes that fail on the first suite won't run the second suite: tests will be distributed to fewer CI nodes and the CI run will take longer.
#!/bin/bash
set -e # exit on error
bundle exec rake knapsack_pro:queue:rspec
bundle exec rake knapsack_pro:queue:cucumber