-
Notifications
You must be signed in to change notification settings - Fork 1.7k
chore: [WIP] experimental parallel kokoro system test #17608
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -46,6 +46,10 @@ run_package_test() { | |||||||||||||||||||||||||||||||||||||||||||||||
| # Inherit NOX_SESSION from environment to allow configs (like prerelease.cfg) to pass it in | ||||||||||||||||||||||||||||||||||||||||||||||||
| local NOX_SESSION="${NOX_SESSION}" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # ISOLATION: Create a unique gcloud config dir for this run | ||||||||||||||||||||||||||||||||||||||||||||||||
| local gcloud_config_dir=$(mktemp -d -t "gcloud-config-${package_name}-XXXXXX") | ||||||||||||||||||||||||||||||||||||||||||||||||
| local CLOUDSDK_CONFIG="${gcloud_config_dir}" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| echo "------------------------------------------------------------" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Configuring environment for: ${package_name}" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "------------------------------------------------------------" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -80,7 +84,7 @@ run_package_test() { | |||||||||||||||||||||||||||||||||||||||||||||||
| esac | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Export variables for the duration of this function's sub-processes | ||||||||||||||||||||||||||||||||||||||||||||||||
| export PROJECT_ID GOOGLE_APPLICATION_CREDENTIALS NOX_FILE NOX_SESSION | ||||||||||||||||||||||||||||||||||||||||||||||||
| export PROJECT_ID GOOGLE_APPLICATION_CREDENTIALS NOX_FILE NOX_SESSION CLOUDSDK_CONFIG | ||||||||||||||||||||||||||||||||||||||||||||||||
| export GOOGLE_CLOUD_PROJECT="${PROJECT_ID}" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| gcloud auth activate-service-account --key-file="$GOOGLE_APPLICATION_CREDENTIALS" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -94,12 +98,15 @@ run_package_test() { | |||||||||||||||||||||||||||||||||||||||||||||||
| set -e | ||||||||||||||||||||||||||||||||||||||||||||||||
| popd > /dev/null | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| rm -rf "${gcloud_config_dir}" | ||||||||||||||||||||||||||||||||||||||||||||||||
| return $res | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+101
to
102
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # A file for running system tests | ||||||||||||||||||||||||||||||||||||||||||||||||
| system_test_script="${PROJECT_ROOT}/.kokoro/system-single.sh" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| PACKAGES_TO_TEST=() | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Run system tests for each package with directory packages/*/tests/system | ||||||||||||||||||||||||||||||||||||||||||||||||
| for path in `find 'packages' \ | ||||||||||||||||||||||||||||||||||||||||||||||||
| \( -type d -wholename 'packages/*/tests/system' \) -o \ | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -147,10 +154,112 @@ for path in `find 'packages' \ | |||||||||||||||||||||||||||||||||||||||||||||||
| set -e | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ "${package_modified}" -gt 0 || "$KOKORO_BUILD_ARTIFACTS_SUBDIR" == *"continuous"* ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| # Call the function - its internal exports won't affect the next loop | ||||||||||||||||||||||||||||||||||||||||||||||||
| run_package_test "$package_name" || RETVAL=$? | ||||||||||||||||||||||||||||||||||||||||||||||||
| PACKAGES_TO_TEST+=("$package_name") | ||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "No changes in ${package_name} and not a continuous build, skipping." | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||
| exit ${RETVAL} | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Parallel Execution Logic | ||||||||||||||||||||||||||||||||||||||||||||||||
| MAX_JOBS=${MAX_JOBS:-4} | ||||||||||||||||||||||||||||||||||||||||||||||||
| active_jobs=0 | ||||||||||||||||||||||||||||||||||||||||||||||||
| declare -A job_pids | ||||||||||||||||||||||||||||||||||||||||||||||||
| declare -A job_pkgs | ||||||||||||||||||||||||||||||||||||||||||||||||
| failed_packages=() | ||||||||||||||||||||||||||||||||||||||||||||||||
| passed_packages=() | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+163
to
+169
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To avoid duplicating the complex process reaping logic, we can extract it into a helper function # Parallel Execution Logic
MAX_JOBS=${MAX_JOBS:-4}
active_jobs=0
declare -A job_pids
declare -A job_pkgs
failed_packages=()
passed_packages=()
reap_finished_jobs() {
for pid in "${!job_pids[@]}"; do
if ! kill -0 "$pid" 2>/dev/null; then
wait "$pid" && status=0 || status=$?
finished_pkg=${job_pkgs[$pid]}
if [ "$status" -eq 0 ]; then
echo "✔ [SUCCESS] ${finished_pkg}"
passed_packages+=("$finished_pkg")
else
echo "✘ [FAILURE] ${finished_pkg} (Exit Code: ${status})"
failed_packages+=("$finished_pkg")
fi
unset "job_pids[$pid]"
unset "job_pkgs[$pid]"
active_jobs=$((active_jobs - 1))
fi
done
} |
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Temporary directory for clean log segregation | ||||||||||||||||||||||||||||||||||||||||||||||||
| LOG_DIR=$(mktemp -d -t test-logs-XXXXXX) | ||||||||||||||||||||||||||||||||||||||||||||||||
| # Clean up logs on exit | ||||||||||||||||||||||||||||||||||||||||||||||||
| trap 'rm -rf "$LOG_DIR"' EXIT | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if [ ${#PACKAGES_TO_TEST[@]} -eq 0 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "No packages to test." | ||||||||||||||||||||||||||||||||||||||||||||||||
| exit 0 | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| echo "==================================================" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Starting parallel test execution for ${#PACKAGES_TO_TEST[@]} packages" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Concurrency limit: ${MAX_JOBS}" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "==================================================" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| for pkg in "${PACKAGES_TO_TEST[@]}"; do | ||||||||||||||||||||||||||||||||||||||||||||||||
| # Maintain concurrency limit | ||||||||||||||||||||||||||||||||||||||||||||||||
| while [ "$active_jobs" -ge "$MAX_JOBS" ]; do | ||||||||||||||||||||||||||||||||||||||||||||||||
| for pid in "${!job_pids[@]}"; do | ||||||||||||||||||||||||||||||||||||||||||||||||
| if ! kill -0 "$pid" 2>/dev/null; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| wait "$pid" && status=0 || status=$? | ||||||||||||||||||||||||||||||||||||||||||||||||
| finished_pkg=${job_pkgs[$pid]} | ||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$status" -eq 0 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "✔ [SUCCESS] ${finished_pkg}" | ||||||||||||||||||||||||||||||||||||||||||||||||
| passed_packages+=("$finished_pkg") | ||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "✘ [FAILURE] ${finished_pkg} (Exit Code: ${status})" | ||||||||||||||||||||||||||||||||||||||||||||||||
| failed_packages+=("$finished_pkg") | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
| unset "job_pids[$pid]" | ||||||||||||||||||||||||||||||||||||||||||||||||
| unset "job_pkgs[$pid]" | ||||||||||||||||||||||||||||||||||||||||||||||||
| active_jobs=$((active_jobs - 1)) | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||
| sleep 0.1 | ||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+188
to
+206
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the extracted
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| safe_pkg_name=$(echo "$pkg" | tr '/' '_') | ||||||||||||||||||||||||||||||||||||||||||||||||
| log_file="${LOG_DIR}/${safe_pkg_name}.log" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Spawning tests for ${pkg}..." | ||||||||||||||||||||||||||||||||||||||||||||||||
| run_package_test "$pkg" > "$log_file" 2>&1 & | ||||||||||||||||||||||||||||||||||||||||||||||||
| pid=$! | ||||||||||||||||||||||||||||||||||||||||||||||||
| job_pids["$pid"]=$pid | ||||||||||||||||||||||||||||||||||||||||||||||||
| job_pkgs["$pid"]=$pkg | ||||||||||||||||||||||||||||||||||||||||||||||||
| active_jobs=$((active_jobs + 1)) | ||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Reap remaining processes | ||||||||||||||||||||||||||||||||||||||||||||||||
| while [ "$active_jobs" -gt 0 ]; do | ||||||||||||||||||||||||||||||||||||||||||||||||
| for pid in "${!job_pids[@]}"; do | ||||||||||||||||||||||||||||||||||||||||||||||||
| if ! kill -0 "$pid" 2>/dev/null; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| wait "$pid" && status=0 || status=$? | ||||||||||||||||||||||||||||||||||||||||||||||||
| finished_pkg=${job_pkgs[$pid]} | ||||||||||||||||||||||||||||||||||||||||||||||||
| if [ "$status" -eq 0 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "✔ [SUCCESS] ${finished_pkg}" | ||||||||||||||||||||||||||||||||||||||||||||||||
| passed_packages+=("$finished_pkg") | ||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "✘ [FAILURE] ${finished_pkg} (Exit Code: ${status})" | ||||||||||||||||||||||||||||||||||||||||||||||||
| failed_packages+=("$finished_pkg") | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
| unset "job_pids[$pid]" | ||||||||||||||||||||||||||||||||||||||||||||||||
| unset "job_pkgs[$pid]" | ||||||||||||||||||||||||||||||||||||||||||||||||
| active_jobs=$((active_jobs - 1)) | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||
| sleep 0.1 | ||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+220
to
+238
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the extracted
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| echo "" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "==================================================" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo " TEST RUN SUMMARY " | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "==================================================" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Total tested: ${#PACKAGES_TO_TEST[@]}" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Passed: ${#passed_packages[@]}" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Failed: ${#failed_packages[@]}" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "==================================================" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if [ ${#failed_packages[@]} -gt 0 ]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "!!! DETAILED LOGS FOR FAILED PACKAGES !!!" | ||||||||||||||||||||||||||||||||||||||||||||||||
| for pkg in "${failed_packages[@]}"; do | ||||||||||||||||||||||||||||||||||||||||||||||||
| safe_pkg_name=$(echo "$pkg" | tr '/' '_') | ||||||||||||||||||||||||||||||||||||||||||||||||
| log_file="${LOG_DIR}/${safe_pkg_name}.log" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "--------------------------------------------------" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "LOGS FOR: ${pkg}" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "--------------------------------------------------" | ||||||||||||||||||||||||||||||||||||||||||||||||
| [ -f "$log_file" ] && cat "$log_file" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "" | ||||||||||||||||||||||||||||||||||||||||||||||||
| done | ||||||||||||||||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| echo "All tests passed successfully!" | ||||||||||||||||||||||||||||||||||||||||||||||||
| exit 0 | ||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since
set -eis active, if any command fails during the test execution, the function/subshell will exit immediately, and the manual cleanup at the end of the function will be bypassed, leaking the temporary directory.Using a
traponEXITensures that the temporary directory is cleaned up regardless of how the subshell exits. We should use double quotes in the trap definition so that the local variablegcloud_config_diris expanded immediately, as the local variable will be out of scope when the subshell actually exits.Additionally, if
package_namecontains any slashes,mktempwill fail because the template cannot contain directory separators. Sanitizing the package name first prevents this issue.