Created
May 20, 2021 14:22
-
-
Save ykpythemind/f51f8a84e96ce6c9bd42d30621071480 to your computer and use it in GitHub Desktop.
GitHub Action + Rails test example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# テストの並列実行用にspecファイルを分割する | |
require 'optparse' | |
options = {} | |
OptionParser.new do |o| | |
o.on('--glob=OPT', 'glob') { |v| options[:glob] = v } | |
o.on('--node-index=OPT', 'node-index') { |v| options[:node_index] = v.to_i } | |
o.on('--node-count=OPT', 'node-count') { |v| options[:node_count] = v.to_i } | |
end.parse!(ARGV.dup) | |
SpecFile = Struct.new(:filepath, :line_count) | |
files = | |
Dir | |
.glob(options[:glob]) | |
.map do |f| | |
# テストの実行時間の指標として、ファイルの行数を重み付けに使用する | |
line_count = File.open(f, 'r').each_line.count | |
# 特別遅いspecファイル. 偏るので雑に重み付け | |
line_count = 30_000 if f.include?('api/v2/reservations_spec.rb') | |
SpecFile.new(f, line_count) | |
end | |
result = {} | |
options[:node_count].times { |i| result[i] = [] } | |
# 行数が多い順に並び替える ( sort_byが不安定なソートなので indexをもちいて安定なソートにする必要がある ) | |
sorted_files = files.sort_by.with_index { |f, i| [f.line_count, i] }.reverse | |
sorted_files.each do |file| | |
# 行数が多いファイルから順番に, 現時点で一番軽い箱 (result[min_node_index]) に詰めていく (貪欲法) | |
min_node = result.values.sort_by.with_index { |f, i| [f.sum(&:line_count), i] }[0] | |
min_node_index = result.find { |_k, v| v == min_node }[0] | |
result[min_node_index] << file | |
end | |
# result objectはコードの同一ならば常に同じ結果になる (matrix buildされるので同じ結果を返さないと壊れるので注意) | |
target_files = result[options[:node_index]].map(&:filepath) | |
# 実行ごとにファイルの順序がランダムになるようにする. https://shime.sh/til/running-parallel-rails-tests-on-github-actions | |
puts target_files.shuffle(random: Random.new(ENV['GITHUB_RUN_ID']&.to_i || 1)).join(' ') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment