@@ -46,6 +46,10 @@ run_package_test() {
4646 # Inherit NOX_SESSION from environment to allow configs (like prerelease.cfg) to pass it in
4747 local NOX_SESSION=" ${NOX_SESSION} "
4848
49+ # ISOLATION: Create a unique gcloud config dir for this run
50+ local gcloud_config_dir=$( mktemp -d -t " gcloud-config-${package_name} -XXXXXX" )
51+ export CLOUDSDK_CONFIG=" ${gcloud_config_dir} "
52+
4953 echo " ------------------------------------------------------------"
5054 echo " Configuring environment for: ${package_name} "
5155 echo " ------------------------------------------------------------"
@@ -94,12 +98,15 @@ run_package_test() {
9498 set -e
9599 popd > /dev/null
96100
101+ rm -rf " ${gcloud_config_dir} "
97102 return $res
98103}
99104
100105# A file for running system tests
101106system_test_script=" ${PROJECT_ROOT} /.kokoro/system-single.sh"
102107
108+ PACKAGES_TO_TEST=()
109+
103110# Run system tests for each package with directory packages/*/tests/system
104111for path in ` find ' packages' \
105112 \( -type d -wholename ' packages/*/tests/system' \) -o \
@@ -147,10 +154,112 @@ for path in `find 'packages' \
147154 set -e
148155
149156 if [[ " ${package_modified} " -gt 0 || " $KOKORO_BUILD_ARTIFACTS_SUBDIR " == * " continuous" * ]]; then
150- # Call the function - its internal exports won't affect the next loop
151- run_package_test " $package_name " || RETVAL=$?
157+ PACKAGES_TO_TEST+=(" $package_name " )
152158 else
153159 echo " No changes in ${package_name} and not a continuous build, skipping."
154160 fi
155161done
156- exit ${RETVAL}
162+
163+ # Parallel Execution Logic
164+ MAX_JOBS=${MAX_JOBS:- 4}
165+ active_jobs=0
166+ declare -A job_pids
167+ declare -A job_pkgs
168+ failed_packages=()
169+ passed_packages=()
170+
171+ # Temporary directory for clean log segregation
172+ LOG_DIR=$( mktemp -d -t test-logs-XXXXXX)
173+ # Clean up logs on exit
174+ trap ' rm -rf "$LOG_DIR"' EXIT
175+
176+ if [ ${# PACKAGES_TO_TEST[@]} -eq 0 ]; then
177+ echo " No packages to test."
178+ exit 0
179+ fi
180+
181+ echo " =================================================="
182+ echo " Starting parallel test execution for ${# PACKAGES_TO_TEST[@]} packages"
183+ echo " Concurrency limit: ${MAX_JOBS} "
184+ echo " =================================================="
185+
186+ for pkg in " ${PACKAGES_TO_TEST[@]} " ; do
187+ # Maintain concurrency limit
188+ while [ " $active_jobs " -ge " $MAX_JOBS " ]; do
189+ for pid in " ${! job_pids[@]} " ; do
190+ if ! kill -0 " $pid " 2> /dev/null; then
191+ wait " $pid " && status=0 || status=$?
192+ finished_pkg=${job_pkgs[$pid]}
193+ if [ " $status " -eq 0 ]; then
194+ echo " ✔ [SUCCESS] ${finished_pkg} "
195+ passed_packages+=(" $finished_pkg " )
196+ else
197+ echo " ✘ [FAILURE] ${finished_pkg} (Exit Code: ${status} )"
198+ failed_packages+=(" $finished_pkg " )
199+ fi
200+ unset " job_pids[$pid ]"
201+ unset " job_pkgs[$pid ]"
202+ active_jobs=$(( active_jobs - 1 ))
203+ fi
204+ done
205+ sleep 0.1
206+ done
207+
208+ safe_pkg_name=$( echo " $pkg " | tr ' /' ' _' )
209+ log_file=" ${LOG_DIR} /${safe_pkg_name} .log"
210+
211+ echo " Spawning tests for ${pkg} ..."
212+ run_package_test " $pkg " > " $log_file " 2>&1 &
213+ pid=$!
214+ job_pids[" $pid " ]=$pid
215+ job_pkgs[" $pid " ]=$pkg
216+ active_jobs=$(( active_jobs + 1 ))
217+ done
218+
219+ # Reap remaining processes
220+ while [ " $active_jobs " -gt 0 ]; do
221+ for pid in " ${! job_pids[@]} " ; do
222+ if ! kill -0 " $pid " 2> /dev/null; then
223+ wait " $pid " && status=0 || status=$?
224+ finished_pkg=${job_pkgs[$pid]}
225+ if [ " $status " -eq 0 ]; then
226+ echo " ✔ [SUCCESS] ${finished_pkg} "
227+ passed_packages+=(" $finished_pkg " )
228+ else
229+ echo " ✘ [FAILURE] ${finished_pkg} (Exit Code: ${status} )"
230+ failed_packages+=(" $finished_pkg " )
231+ fi
232+ unset " job_pids[$pid ]"
233+ unset " job_pkgs[$pid ]"
234+ active_jobs=$(( active_jobs - 1 ))
235+ fi
236+ done
237+ sleep 0.1
238+ done
239+
240+ echo " "
241+ echo " =================================================="
242+ echo " TEST RUN SUMMARY "
243+ echo " =================================================="
244+ echo " Total tested: ${# PACKAGES_TO_TEST[@]} "
245+ echo " Passed: ${# passed_packages[@]} "
246+ echo " Failed: ${# failed_packages[@]} "
247+ echo " =================================================="
248+
249+ if [ ${# failed_packages[@]} -gt 0 ]; then
250+ echo " "
251+ echo " !!! DETAILED LOGS FOR FAILED PACKAGES !!!"
252+ for pkg in " ${failed_packages[@]} " ; do
253+ safe_pkg_name=$( echo " $pkg " | tr ' /' ' _' )
254+ log_file=" ${LOG_DIR} /${safe_pkg_name} .log"
255+ echo " --------------------------------------------------"
256+ echo " LOGS FOR: ${pkg} "
257+ echo " --------------------------------------------------"
258+ [ -f " $log_file " ] && cat " $log_file "
259+ echo " "
260+ done
261+ exit 1
262+ fi
263+
264+ echo " All tests passed successfully!"
265+ exit 0
0 commit comments