やりたいこと
GitHub Actionsでテストケースを分割して、複数ノードで実行する
CircleCIだとプラットフォーム側で対応してくれていますがGH Actionsだと見当たらなかったので同等のことをやるための設定のメモです。
設定例
rspec: runs-on: ubuntu-latest strategy: max-parallel: 2 matrix: ci_node_total: [2] ci_node_index: [0, 1] steps: - uses: actions/checkout@v2 - uses: ruby/setup-ruby@v1 - name: Bundle install run: bundle install - name: DB setup run: bundle exec rake db:setup - name: Rspec run: | ruby -e 'Dir.glob("spec/**/*_spec.rb").each{|f| puts f}' | awk "NR%${CI_NODE_TOTAL}==${CI_NODE_INDEX} {print}" > /tmp/tests-to-run cat /tmp/tests-to-run bundle exec rspec $(cat /tmp/tests-to-run) env: CI_NODE_TOTAL: ${{ matrix.ci_node_total }} CI_NODE_INDEX: ${{ matrix.ci_node_index }}
GitHub ActionsにはBuild Matrix という機能があって、本来はOSのバージョンと言語のバージョンの複数のマトリクステストを実施するための機能なのですが、これを使って ci_node_total
と ci_node_index
という2つのパラメタを登録します。
ci_node_total
: ノードの合計,max-parallel
と同じ数にする必要があるci_node_index
: ノードのインデックス, 0始まりでci_node_total-1
で終わる配列
これで、 rspec
のJobは (2, 0) と (2, 1) という2つの設定で実施されることになります
あとはindex毎にspec配下のファイルを分割してrspecコマンドに渡すだけです。CircleCIだとsizeの大きさとか各exampleのかかった時間とかでいい感じに平準化してくれますが、GitHub Actionsにはそういう機能は無いので、単にspecファイルを2分割して渡すのみです。
ちなみに、Go言語の場合はこんな感じでテストを分割実行できます
$ go test $(go list ./... | awk "NR%${CI_NODE_TOTAL}==${CI_NODE_INDEX} {print}")