-
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
692e1ff
461580e
b8795e4
54f8a72
4206da2
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 | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -35,6 +35,20 @@ RETVAL=0 | |||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| pwd | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| echo "=== KOKORO VM SCOUTING ===" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "CPU Count:" | ||||||||||||||||||||||||||||||||||||||||||||||||
| nproc | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "--------------------------" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Detailed CPU Info:" | ||||||||||||||||||||||||||||||||||||||||||||||||
| lscpu | grep -E "^(Model name|CPU\(s\)|Thread\(s\) per core|Core\(s\) per socket)" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "--------------------------" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Memory Status:" | ||||||||||||||||||||||||||||||||||||||||||||||||
| free -h | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "--------------------------" | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Disk Usage:" | ||||||||||||||||||||||||||||||||||||||||||||||||
| df -h / | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "==========================" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| run_package_test() { | ||||||||||||||||||||||||||||||||||||||||||||||||
| local package_name=$1 | ||||||||||||||||||||||||||||||||||||||||||||||||
| local package_path="packages/${package_name}" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -46,6 +60,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 +98,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 +112,15 @@ run_package_test() { | |||||||||||||||||||||||||||||||||||||||||||||||
| set -e | ||||||||||||||||||||||||||||||||||||||||||||||||
| popd > /dev/null | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| rm -rf "${gcloud_config_dir}" | ||||||||||||||||||||||||||||||||||||||||||||||||
| return $res | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+115
to
116
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 \ | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -113,6 +134,11 @@ for path in `find 'packages' \ | |||||||||||||||||||||||||||||||||||||||||||||||
| package_name=${package_name%%/*} | ||||||||||||||||||||||||||||||||||||||||||||||||
| package_path="packages/${package_name}" | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if [[ "$package_name" == "sqlalchemy-bigquery" ]]; then | ||||||||||||||||||||||||||||||||||||||||||||||||
| echo "Skipping sqlalchemy-bigquery for diagnostics." | ||||||||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| # Determine if we should skip based on git diff | ||||||||||||||||||||||||||||||||||||||||||||||||
| # We always check for changes in these specific versioning/config files | ||||||||||||||||||||||||||||||||||||||||||||||||
| files_to_check=( | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -147,10 +173,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
+182
to
+188
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
+207
to
+225
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
+239
to
+257
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.