@@ -264,7 +264,7 @@ cleanup_on_exit() {
264264 local -A seen
265265 local unique_workflows=()
266266 for workflow in " ${GLOBAL_WORKFLOWS_TO_DISABLE[@]} " ; do
267- if [[ -z " ${seen[$workflow]:- } " ]]; then
267+ if [[ -z " ${seen[$workflow]} " ]]; then
268268 seen[$workflow ]=1
269269 unique_workflows+=(" $workflow " )
270270 fi
@@ -310,12 +310,6 @@ get_target_repo() {
310310 fi
311311}
312312
313- # Escape ERE regex metacharacters in a string so it can be safely
314- # interpolated into grep -E patterns.
315- re_escape () {
316- printf ' %s' " $1 " | sed ' s/[][\\.^$*+?(){}|]/\\&/g'
317- }
318-
319313# Extract AI type from workflow name
320314extract_ai_type () {
321315 local workflow_name=" $1 "
@@ -1128,7 +1122,7 @@ create_test_pr() {
11281122 local title=" $1 "
11291123 local body=" $2 "
11301124 local repo=" ${3:- } "
1131- local branch=" test-pr-$( date +%s) - $$ - ${RANDOM} "
1125+ local branch=" test-pr-$( date +%s) "
11321126
11331127 # Parallel-safety marker (see create_test_issue)
11341128 if [[ -n " ${E2E_TRIGGER_MARKER:- } " ]]; then
@@ -1187,7 +1181,7 @@ create_test_pr_with_branch() {
11871181 local title=" $1 "
11881182 local body=" $2 "
11891183 local repo=" ${3:- } "
1190- local branch=" test-pr-$( date +%s) - $$ - ${RANDOM} "
1184+ local branch=" test-pr-$( date +%s) "
11911185
11921186 # Parallel-safety marker (see create_test_issue)
11931187 if [[ -n " ${E2E_TRIGGER_MARKER:- } " ]]; then
@@ -2485,9 +2479,7 @@ run_single_test() {
24852479 sleep 10
24862480 case " $workflow " in
24872481 * " add-comment" )
2488- local ai_name_re
2489- ai_name_re=$( re_escape " $ai_display_name " )
2490- if wait_for_comment " $issue_num " " Reply from $ai_name_re " " $workflow " " $target_repo " ; then
2482+ if wait_for_comment " $issue_num " " Reply from $ai_display_name " " $workflow " " $target_repo " ; then
24912483 test_result=" PASS"
24922484 fi
24932485 ;;
@@ -2525,9 +2517,7 @@ run_single_test() {
25252517
25262518 if [[ " $workflow_success " == true ]]; then
25272519 sleep 10
2528- local ai_name_re
2529- ai_name_re=$( re_escape " $ai_display_name " )
2530- if wait_for_discussion_comment " $discussion_num " " Reply from $ai_name_re Discussion" " $workflow " " $target_repo " ; then
2520+ if wait_for_discussion_comment " $discussion_num " " Reply from $ai_display_name Discussion" " $workflow " " $target_repo " ; then
25312521 test_result=" PASS"
25322522 fi
25332523 fi
@@ -2593,7 +2583,7 @@ run_single_test() {
25932583 fi
25942584 ;;
25952585 # Workflow dispatch tests - triggered with gh aw run
2596- * " create-issue" |* " create-discussion" |* " create-pull-request" |* " create-two-pull-requests " | * " code-scanning-alert" |* " mcp" |* " safe-jobs" |* " gh-steps" |* " custom-safe-outputs" )
2586+ * " create-issue" |* " create-discussion" |* " create-pull-request" |* " code-scanning-alert" |* " mcp" |* " safe-jobs" |* " gh-steps" |* " custom-safe-outputs" )
25972587 local workflow_success=false
25982588 if trigger_workflow_dispatch_and_await_completion " $workflow " ; then
25992589 workflow_success=true
@@ -2656,20 +2646,15 @@ run_single_test() {
26562646 local expected_run_id=" ${run_url##*/ } "
26572647 local repo_flag=" "
26582648 [[ -n " $target_repo " ]] && repo_flag=" --repo $target_repo "
2659- # Other tests share the [copilot-test] prefix, so filter to titles
2660- # that look like gh-steps output (either the run-id form or the sample title).
2661- local issue_title=$( gh issue list $repo_flag --limit 50 --json title \
2662- --jq " .[] | select(.title | startswith(\" $title_prefix \" )) | .title" \
2663- | grep -E " The number of issues is|Issue count report" \
2664- | head -1)
2649+ local issue_title=$( gh issue list $repo_flag --limit 10 --json title --jq " .[] | select(.title | startswith(\" $title_prefix \" )) | .title" | head -1)
26652650 if [[ -n " $expected_run_id " ]] && echo " $issue_title " | grep -q " Test ${expected_run_id} :.*The number of issues is" ; then
26662651 success " Issue title contains run ID $expected_run_id and expected gh-steps output: $issue_title "
26672652 validation_success=true
26682653 elif echo " $issue_title " | grep -q " The number of issues is\|Issue count report" ; then
26692654 success " Issue title contains expected gh-steps output (run ID not verified): $issue_title "
26702655 validation_success=true
26712656 else
2672- error " No issue with title prefix ' $title_prefix ' contains ' The number of issues is' or 'Issue count report' (got: ' $issue_title ') "
2657+ error " Issue title does not contain expected pattern 'Test <run_id>: The number of issues is' or sample title 'Issue count report': $issue_title "
26732658 fi
26742659 fi
26752660 ;;
@@ -2717,9 +2702,7 @@ run_single_test() {
27172702 [[ -n " $target_repo " ]] && repo_url=" $target_repo "
27182703 success " Created test discussion #$discussion_num to trigger $workflow : https://github.com/$repo_url /discussions/$discussion_num "
27192704 sleep 10
2720- local ai_name_re
2721- ai_name_re=$( re_escape " $ai_display_name " )
2722- if wait_for_discussion_comment " $discussion_num " " Reply from $ai_name_re Discussion" " $workflow " " $target_repo " ; then
2705+ if wait_for_discussion_comment " $discussion_num " " Reply from $ai_display_name Discussion" " $workflow " " $target_repo " ; then
27232706 test_result=" PASS"
27242707 fi
27252708 else
@@ -2753,9 +2736,7 @@ run_single_test() {
27532736 [[ -n " $target_repo " ]] && repo_url=" $target_repo "
27542737 success " Created test issue #$issue_num for $workflow : https://github.com/$repo_url /issues/$issue_num "
27552738 sleep 10
2756- local ai_name_re
2757- ai_name_re=$( re_escape " $ai_display_name " )
2758- if wait_for_comment " $issue_num " " Reply from $ai_name_re " " $workflow " " $target_repo " ; then
2739+ if wait_for_comment " $issue_num " " Reply from $ai_display_name " " $workflow " " $target_repo " ; then
27592740 test_result=" PASS"
27602741 fi
27612742 fi
@@ -2877,9 +2858,7 @@ run_single_test() {
28772858 [[ -n " $target_repo " ]] && repo_url=" $target_repo "
28782859 success " Created test issue #$issue_num for $workflow : https://github.com/$repo_url /issues/$issue_num "
28792860 post_issue_command " $issue_num " " /test-${ai_type} -command What is 102+103?" " $target_repo "
2880- local ai_name_re
2881- ai_name_re=$( re_escape " $ai_display_name " )
2882- if wait_for_command_comment " $issue_num " " 205|I'm $ai_name_re " " $workflow " " $target_repo " ; then
2861+ if wait_for_command_comment " $issue_num " " 205|I'm $ai_display_name " " $workflow " " $target_repo " ; then
28832862 test_result=" PASS"
28842863 fi
28852864 fi
@@ -2999,7 +2978,7 @@ run_single_test() {
29992978 [[ -n " $target_repo " ]] && repo_url=" $target_repo "
30002979 success " Created test PR #$pr_num for $workflow : https://github.com/$repo_url /pull/$pr_num "
30012980 sleep 10
3002- if wait_for_pr_reviewer_added " $pr_num " " copilot " " $workflow " " $target_repo " ; then
2981+ if wait_for_pr_reviewer_added " $pr_num " " pelikhan " " $workflow " " $target_repo " ; then
30032982 test_result=" PASS"
30042983 fi
30052984 fi
@@ -3124,25 +3103,11 @@ run_tests_parallel() {
31243103 local completed=0
31253104 local total_in_batch=${# batch_tests[@]}
31263105 # Hard ceiling per test — these tests should normally finish in ~1-2 min
3127- local per_test_kill_seconds=480
3106+ local per_test_kill_seconds=300
31283107 echo
31293108 info " ⏳ Waiting for $total_in_batch tests to complete (per-test kill after ${per_test_kill_seconds} s)..."
31303109
3131- # Decide on output style: interactive TTY redraws in place; non-TTY (CI,
3132- # piped logs) prints a single status line at a coarse interval.
3133- local is_tty=false
3134- if [[ -t 1 ]]; then is_tty=true; fi
3135- local term_cols=${COLUMNS:- 0}
3136- if [[ " $is_tty " == true && $term_cols -eq 0 ]]; then
3137- term_cols=$( tput cols 2> /dev/null || echo 100)
3138- fi
3139- [[ $term_cols -le 20 ]] && term_cols=100
31403110 local last_status_line_len=0
3141- local loop_iter=0
3142- # Print non-TTY status every NONTTY_STATUS_EVERY seconds
3143- local nontty_status_every=30
3144- local nontty_last_print=0
3145-
31463111 while [[ $completed -lt $total_in_batch ]]; do
31473112 completed=0
31483113 local running_summary=()
@@ -3156,11 +3121,12 @@ run_tests_parallel() {
31563121 # Kill tests that exceed the hard ceiling
31573122 if [[ $elapsed -gt $per_test_kill_seconds ]]; then
31583123 local stuck_test=" ${pid_to_test[$pid]} "
3159- [[ " $is_tty " == true ]] && echo
3124+ echo
31603125 warning " ⏰ Killing '$stuck_test ' (pid $pid ) — exceeded ${per_test_kill_seconds} s"
31613126 kill -TERM " $pid " 2> /dev/null
31623127 sleep 1
31633128 kill -KILL " $pid " 2> /dev/null
3129+ # Record as FAIL so the results reader sees it
31643130 (
31653131 flock -x 200
31663132 echo " $stuck_test |FAIL" >> " $RESULTS_FILE "
@@ -3171,57 +3137,29 @@ run_tests_parallel() {
31713137 running_summary+=(" ${pid_to_test[$pid]} (${elapsed} s)" )
31723138 done
31733139
3140+ # Show progress bar + running test names
31743141 if [[ $total_in_batch -gt 0 ]]; then
31753142 local progress_pct=$(( completed * 100 / total_in_batch ))
31763143 local filled=$(( completed * 40 / total_in_batch ))
31773144 local empty=$(( 40 - filled ))
3178- local running_count=${# running_summary[@]}
3179- # Build a compact running-text that fits in the terminal
31803145 local running_text=" "
3181- if [[ $running_count -gt 0 ]]; then
3182- # bar + counters take ~60 visible chars; reserve that
3183- local budget=$(( term_cols - 60 ))
3184- [[ $budget -lt 20 ]] && budget=20
3185- local joined
3186- joined=$( IFS=' ,' ; echo " ${running_summary[*]} " )
3187- if (( ${# joined} > budget )) ; then
3188- # Truncate and append "…(+N more)"
3189- local more=$(( running_count - 1 ))
3190- local first=" ${running_summary[0]} "
3191- if [[ $more -gt 0 ]]; then
3192- running_text=" — running: ${first} , …(+${more} more)"
3193- else
3194- running_text=" — running: ${first} "
3195- fi
3196- else
3197- running_text=" — running: ${joined} "
3198- fi
3146+ if [[ ${# running_summary[@]} -gt 0 ]]; then
3147+ running_text=" — running: $( IFS=' , ' ; echo " ${running_summary[*]} " ) "
31993148 fi
3200-
3201- if [[ " $is_tty " == true ]]; then
3202- local line
3203- line=$( printf " \r ${BLUE} [${GREEN} %${filled} s${NC} %${empty} s${BLUE} ]${NC} ${completed} /${total_in_batch} (${progress_pct} %%)%s" " $( printf ' #%.0s' $( seq 1 $filled 2> /dev/null) ) " " $( printf ' %.0s' $( seq 1 $empty 2> /dev/null) ) " " $running_text " )
3204- local pad=" "
3205- if (( ${# line} < last_status_line_len )) ; then
3206- pad=$( printf ' %*s' $(( last_status_line_len - ${# line} )) " " )
3207- fi
3208- printf " %s%s" " $line " " $pad "
3209- last_status_line_len=${# line}
3210- else
3211- # Non-TTY: print a single line every nontty_status_every seconds
3212- if (( now - nontty_last_print >= nontty_status_every )) || (( loop_iter == 0 )) ; then
3213- printf " [%d/%d] %d%% running=%d%s\n" \
3214- " $completed " " $total_in_batch " " $progress_pct " " $running_count " " $running_text " \
3215- | tee -a " $LOG_FILE "
3216- nontty_last_print=$now
3217- fi
3149+ local line
3150+ line=$( printf " \r ${BLUE} [${GREEN} %${filled} s${NC} %${empty} s${BLUE} ]${NC} ${completed} /${total_in_batch} (${progress_pct} %%)%s" " $( printf ' #%.0s' $( seq 1 $filled 2> /dev/null) ) " " $( printf ' %.0s' $( seq 1 $empty 2> /dev/null) ) " " $running_text " )
3151+ # Pad with spaces to overwrite previous longer line, then carriage return
3152+ local pad=" "
3153+ if (( ${# line} < last_status_line_len )) ; then
3154+ pad=$( printf ' %*s' $(( last_status_line_len - ${# line} )) " " )
32183155 fi
3156+ printf " %s%s" " $line " " $pad "
3157+ last_status_line_len=${# line}
32193158 fi
32203159
3221- loop_iter=$(( loop_iter + 1 ))
32223160 sleep 1
32233161 done
3224- [[ " $is_tty " == true ]] && echo
3162+ echo
32253163 echo
32263164
32273165 # Read batch results
0 commit comments