66 lines
3 KiB
Bash
Executable file
66 lines
3 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# Script to generate `rspec foss-impact` test child pipeline with dynamically parallelized jobs.
|
|
|
|
source scripts/utils.sh
|
|
|
|
rspec_matching_tests_foss_path="${1}"
|
|
pipeline_yml="${2}"
|
|
|
|
test_file_count=$(wc -w "${rspec_matching_tests_foss_path}" | awk '{ print $1 }')
|
|
echoinfo "test_file_count: ${test_file_count}"
|
|
|
|
if [[ "${test_file_count}" -eq 0 ]]; then
|
|
skip_pipeline=".gitlab/ci/_skip.yml"
|
|
|
|
echo "Using ${skip_pipeline} due to no impacted FOSS rspec tests to run"
|
|
cp $skip_pipeline "$pipeline_yml"
|
|
exit
|
|
fi
|
|
|
|
# As of 2022-09-01:
|
|
# $ find spec -type f | wc -l
|
|
# 12825
|
|
# and
|
|
# $ find ee/spec -type f | wc -l
|
|
# 5610
|
|
# which gives a total of 18435 test files (`number_of_tests_in_total_in_the_test_suite`).
|
|
#
|
|
# Total time to run all tests (based on https://gitlab-org.gitlab.io/rspec_profiling_stats/) is 170183 seconds (`duration_of_the_test_suite_in_seconds`).
|
|
#
|
|
# This gives an approximate 170183 / 18435 = 9.2 seconds per test file (`average_test_file_duration_in_seconds`).
|
|
#
|
|
# If we want each test job to finish in 10 minutes, given we have 3 minutes of setup (`setup_duration_in_seconds`), then we need to give 7 minutes of testing to each test node (`optimal_test_runtime_duration_in_seconds`).
|
|
# (7 * 60) / 9.2 = 45.6
|
|
#
|
|
# So if we'd want to run the full test suites in 10 minutes (`optimal_test_job_duration_in_seconds`), we'd need to run at max 45 test file per nodes (`optimal_test_file_count_per_node`).
|
|
number_of_tests_in_total_in_the_test_suite=18435
|
|
duration_of_the_test_suite_in_seconds=170183
|
|
optimal_test_job_duration_in_seconds=600 # 10 minutes
|
|
setup_duration_in_seconds=180 # 3 minutes
|
|
|
|
optimal_test_runtime_duration_in_seconds=$(( optimal_test_job_duration_in_seconds - setup_duration_in_seconds ))
|
|
echoinfo "optimal_test_runtime_duration_in_seconds: ${optimal_test_runtime_duration_in_seconds}"
|
|
|
|
average_test_file_duration_in_seconds=$(( duration_of_the_test_suite_in_seconds / number_of_tests_in_total_in_the_test_suite ))
|
|
echoinfo "average_test_file_duration_in_seconds: ${average_test_file_duration_in_seconds}"
|
|
|
|
optimal_test_file_count_per_node=$(( optimal_test_runtime_duration_in_seconds / average_test_file_duration_in_seconds ))
|
|
echoinfo "optimal_test_file_count_per_node: ${optimal_test_file_count_per_node}"
|
|
|
|
node_count=$(( test_file_count / optimal_test_file_count_per_node ))
|
|
echoinfo "node_count: ${node_count}"
|
|
|
|
echoinfo "Optimal node count for 'rspec foss-impact' jobs is ${node_count}."
|
|
|
|
MAX_NODES_COUNT=50 # Maximum parallelization allowed by GitLab
|
|
if [[ "${node_count}" -gt "${MAX_NODES_COUNT}" ]]; then
|
|
echoinfo "We don't want to parallelize 'rspec foss-impact' to more than ${MAX_NODES_COUNT} jobs for now! Decreasing the parallelization to ${MAX_NODES_COUNT}."
|
|
node_count=${MAX_NODES_COUNT}
|
|
fi
|
|
|
|
ruby -rerb -e "puts ERB.new(File.read('.gitlab/ci/rails/rspec-foss-impact.gitlab-ci.yml.erb')).result_with_hash(parallel_value: ${node_count})" > "${pipeline_yml}"
|
|
|
|
echosuccess "Generated ${pipeline_yml} pipeline with following content:"
|
|
cat "${pipeline_yml}"
|