@@ -212,6 +212,133 @@ detect_panic() {
212212 fi
213213}
214214
215+ notify_slack () {
216+ # Required env vars: SLACK_WEBHOOK_URL, GITHUB_REPOSITORY, GITHUB_REF_NAME, GITHUB_SERVER_URL, GITHUB_RUN_ID, GITHUB_SHA
217+ # Required argument: artifacts directory path
218+ local artifacts_dir=" ${1:- artifacts} "
219+ local slack_webhook_url=" ${SLACK_WEBHOOK_URL} "
220+
221+ if [[ -z " ${slack_webhook_url} " ]]; then
222+ echo " SLACK_WEBHOOK_URL is not set, skipping Slack notification"
223+ return 0
224+ fi
225+
226+ if [[ ! -d " ${artifacts_dir} " ]]; then
227+ echo " Artifacts directory '${artifacts_dir} ' not found"
228+ return 1
229+ fi
230+
231+ echo " Scanning artifacts in: ${artifacts_dir} "
232+
233+ local failure_details=" "
234+ local failed_providers=" "
235+
236+ # Use find to get provider directories (more reliable than glob)
237+ local provider_dirs
238+ provider_dirs=$( find " ${artifacts_dir} " -maxdepth 1 -type d -name ' logs-e2e-tests-*' | sort)
239+
240+ if [[ -z " ${provider_dirs} " ]]; then
241+ echo " No provider artifact directories found matching pattern: ${artifacts_dir} /logs-e2e-tests-*"
242+ return 0
243+ fi
244+
245+ echo " Found provider directories:"
246+ echo " ${provider_dirs} "
247+
248+ while IFS= read -r provider_dir; do
249+ local provider
250+ provider=$( basename " ${provider_dir} " | sed ' s/logs-e2e-tests-//' )
251+ echo " Processing provider: ${provider} (${provider_dir} )"
252+
253+ # Extract failed test names from e2e test output log
254+ local failed_tests=" "
255+ if [[ -f " ${provider_dir} /e2e-test-output.log" ]]; then
256+ echo " Found e2e-test-output.log"
257+ failed_tests=$( grep -E " ^--- FAIL:" " ${provider_dir} /e2e-test-output.log" 2> /dev/null | sed ' s/--- FAIL: //' | cut -d' ' -f1 | sort -u | paste -sd ' ,' - || true)
258+ if [[ -n " ${failed_tests} " ]]; then
259+ echo " Failed tests: ${failed_tests} "
260+ else
261+ echo " No failed tests found in log"
262+ fi
263+ else
264+ echo " No e2e-test-output.log found"
265+ ls -la " ${provider_dir} " 2> /dev/null || true
266+ fi
267+
268+ # Check if this provider had failures
269+ if [[ -n " ${failed_tests} " ]]; then
270+ failed_providers=" ${failed_providers}${provider} , "
271+ # Use literal \n for Slack mrkdwn newlines (will be kept as-is in JSON)
272+ failure_details=" ${failure_details} • *${provider} *: ${failed_tests} \\ n"
273+ fi
274+ done <<< " ${provider_dirs}"
275+
276+ # Remove trailing comma and space
277+ failed_providers=" ${failed_providers% , } "
278+
279+ if [[ -z " ${failure_details} " ]]; then
280+ echo " No failures detected, skipping Slack notification"
281+ return 0
282+ fi
283+
284+ # Remove trailing \n
285+ failure_details=" ${failure_details% \\ n} "
286+
287+ local run_url=" ${GITHUB_SERVER_URL} /${GITHUB_REPOSITORY} /actions/runs/${GITHUB_RUN_ID} "
288+ local commit_url=" ${GITHUB_SERVER_URL} /${GITHUB_REPOSITORY} /commit/${GITHUB_SHA} "
289+ local short_sha=" ${GITHUB_SHA: 0: 7} "
290+
291+ # Build Slack message payload using jq to ensure proper JSON escaping
292+ local payload
293+ payload=$( jq -n \
294+ --arg repo " ${GITHUB_REPOSITORY:- unknown} " \
295+ --arg branch " ${GITHUB_REF_NAME:- unknown} " \
296+ --arg run_url " ${run_url} " \
297+ --arg commit_url " ${commit_url} " \
298+ --arg short_sha " ${short_sha:- unknown} " \
299+ --arg failed_providers " ${failed_providers} " \
300+ --arg failure_details " ${failure_details} " \
301+ ' {
302+ "blocks": [
303+ {
304+ "type": "header",
305+ "text": {
306+ "type": "plain_text",
307+ "text": "🔴 E2E Test Failures",
308+ "emoji": true
309+ }
310+ },
311+ {
312+ "type": "section",
313+ "text": {
314+ "type": "mrkdwn",
315+ "text": ("*Repository:* " + $repo + "\n*Branch:* " + $branch + "\n*Commit:* <" + $commit_url + "|" + $short_sha + ">\n*Workflow:* <" + $run_url + "|View Run>")
316+ }
317+ },
318+ {
319+ "type": "divider"
320+ },
321+ {
322+ "type": "section",
323+ "text": {
324+ "type": "mrkdwn",
325+ "text": ("*Failed Providers:* " + $failed_providers)
326+ }
327+ },
328+ {
329+ "type": "section",
330+ "text": {
331+ "type": "mrkdwn",
332+ "text": ("*Failure Details:*\n" + $failure_details)
333+ }
334+ }
335+ ]
336+ }' )
337+
338+ echo " Sending Slack notification for failed providers: ${failed_providers} "
339+ curl -s -X POST -H ' Content-type: application/json' --data " ${payload} " " ${slack_webhook_url} "
340+ }
341+
215342help () {
216343 cat << EOF
217344 Usage: $0 <command>
@@ -239,6 +366,11 @@ help() {
239366 output_logs
240367 Will output logs using snazzy formatting when available or otherwise through a simple
241368 python formatter. This makes debugging easier from the GitHub Actions interface.
369+
370+ notify_slack <artifacts_dir>
371+ Send a combined Slack notification for all failed E2E test providers.
372+ Parses test output logs from artifacts to extract failed test names.
373+ Required env vars: SLACK_WEBHOOK_URL, GITHUB_REPOSITORY, GITHUB_REF_NAME, GITHUB_SERVER_URL, GITHUB_RUN_ID
242374EOF
243375}
244376
@@ -258,6 +390,9 @@ collect_logs)
258390output_logs)
259391 output_logs
260392 ;;
393+ notify_slack)
394+ notify_slack " ${2:- artifacts} "
395+ ;;
261396help)
262397 help
263398 exit 0
0 commit comments