Skip to content

Live E2E Notifications #269

Live E2E Notifications

Live E2E Notifications #269

name: Live E2E Notifications
on:
workflow_run:
workflows: [Live E2E, Release]
types: [completed]
permissions:
actions: read
contents: read
jobs:
notify:
if: github.event.workflow_run.conclusion == 'failure' || github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
timeout-minutes: 5
continue-on-error: true
steps:
- name: Notify Slack
env:
GH_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
RUN_ID: ${{ github.event.workflow_run.id }}
RUN_NUMBER: ${{ github.event.workflow_run.run_number }}
RUN_ATTEMPT: ${{ github.event.workflow_run.run_attempt }}
WORKFLOW_ID: ${{ github.event.workflow_run.workflow_id }}
WORKFLOW_NAME: ${{ github.event.workflow_run.name }}
SHA: ${{ github.event.workflow_run.head_sha }}
BRANCH: ${{ github.event.workflow_run.head_branch }}
CONCLUSION: ${{ github.event.workflow_run.conclusion }}
SLACK_WEBHOOK: ${{ secrets.SLACK_RELEASE_WEBHOOK }}
run: |
set -euo pipefail
# A reusable suite job is named "Live e2e" or ends with the exact
# " / Live e2e" suffix. Keep this aligned with the producer and gate.
suite_conclusion() {
jq -r '([.jobs[]? | select(.name == "Live e2e" or (.name | endswith(" / Live e2e"))) | .conclusion] | if any(.[]; . == "failure") then "failure" elif any(.[]; . == "success") then "success" else "none" end)'
}
if ! current_jobs="$(gh api --paginate "/repos/${REPOSITORY}/actions/runs/${RUN_ID}/attempts/${RUN_ATTEMPT}/jobs?per_page=100")"; then
echo "::warning::Could not inspect jobs for ${WORKFLOW_NAME} run ${RUN_ID}; suppressing notification because the suite result is unknown."
exit 0
fi
current_suite="$(printf '%s\n' "$current_jobs" | jq -s '{jobs: map(.jobs[])}' | suite_conclusion)"
startup_failure=false
if [[ "$current_suite" == none && "$WORKFLOW_NAME" == "Live E2E" && "$CONCLUSION" == failure ]]; then
current_suite=failure
startup_failure=true
elif [[ "$current_suite" == none || ("$current_suite" == failure && "$WORKFLOW_NAME" == "Release") ]]; then
# Release's generic notification covers release failures and runs
# that reused a staging result without creating a suite job.
exit 0
fi
prior_conclusion=""
if (( RUN_ATTEMPT > 1 )); then
if ! prior_jobs="$(gh api --paginate "/repos/${REPOSITORY}/actions/runs/${RUN_ID}/attempts/$((RUN_ATTEMPT - 1))/jobs?per_page=100")"; then
echo "::warning::Could not inspect the prior attempt for ${WORKFLOW_NAME} run ${RUN_ID}; suppressing transition notification."
exit 0
fi
prior_conclusion="$(printf '%s\n' "$prior_jobs" | jq -s '{jobs: map(.jobs[])}' | suite_conclusion)"
[[ "$prior_conclusion" != none ]] || prior_conclusion=""
fi
if ! history="$(gh api -X GET "/repos/${REPOSITORY}/actions/workflows/${WORKFLOW_ID}/runs" -f "branch=${BRANCH}" -F per_page=25)"; then
if [[ "$current_suite" == success && -z "$prior_conclusion" ]]; then
echo "::warning::Could not inspect recent ${WORKFLOW_NAME} history; suppressing recovery notification."
exit 0
fi
echo "::warning::Could not inspect recent ${WORKFLOW_NAME} history; continuing with the confirmed current result."
else
candidates="$(jq -r --argjson current_number "$RUN_NUMBER" --argjson current_attempt "$RUN_ATTEMPT" '(.workflow_runs // []) | map(select((.run_number != $current_number or (.run_attempt // 1) != $current_attempt) and .status == "completed" and (.conclusion == "failure" or .conclusion == "success"))) | sort_by(.run_number, (.run_attempt // 1)) | reverse | .[] | [.id, (.run_attempt // 1), .run_number, .conclusion] | @tsv' <<< "$history")"
while IFS=$'\t' read -r candidate_id candidate_attempt candidate_number candidate_conclusion; do
[[ -z "$candidate_id" ]] && continue
if (( candidate_number > RUN_NUMBER || (candidate_number == RUN_NUMBER && candidate_attempt > RUN_ATTEMPT) )); then
relation=newer
else
relation=older
fi
if [[ "$relation" == newer || -z "$prior_conclusion" ]]; then
if ! candidate_jobs="$(gh api --paginate "/repos/${REPOSITORY}/actions/runs/${candidate_id}/attempts/${candidate_attempt}/jobs?per_page=100")"; then
echo "::warning::Could not inspect candidate run ${candidate_id}; suppressing notification because history is incomplete."
exit 0
fi
candidate_suite="$(printf '%s\n' "$candidate_jobs" | jq -s '{jobs: map(.jobs[])}' | suite_conclusion)"
if [[ "$candidate_suite" == none && "$WORKFLOW_NAME" == "Live E2E" && "$candidate_conclusion" == failure ]]; then
candidate_suite=failure
fi
if [[ "$candidate_suite" == failure || "$candidate_suite" == success ]]; then
if [[ "$relation" == newer ]]; then
echo "A newer completed relevant suite exists; suppressing stale notification."
exit 0
fi
prior_conclusion="$candidate_suite"
break
fi
fi
done <<< "$candidates"
fi
if [[ "$current_suite" == success ]]; then
[[ "$prior_conclusion" == failure ]] || exit 0
header="✅ Live E2E recovered"
text="Live E2E recovered"
detail="The previous relevant ${WORKFLOW_NAME} live suite failed; this run passed."
else
[[ "$prior_conclusion" != failure ]] || exit 0
if [[ "$startup_failure" == true ]]; then
header="❌ Live E2E failed to start"
text="Live E2E failed to start"
detail="The Live E2E workflow failed before it produced a Live e2e job."
else
header="❌ Live E2E failed"
text="Live E2E failed"
detail="The ${WORKFLOW_NAME} live suite failed."
fi
fi
run_url="https://github.com/${REPOSITORY}/actions/runs/${RUN_ID}"
commit_url="https://github.com/${REPOSITORY}/commit/${SHA}"
payload="$(jq -n --arg text "$text" --arg header "$header" --arg detail "$detail" --arg run_url "$run_url" --arg commit_url "$commit_url" --arg branch "$BRANCH" --arg sha "${SHA:0:7}" '{text:$text,blocks:[{type:"header",text:{type:"plain_text",text:$header,emoji:true}},{type:"section",text:{type:"mrkdwn",text:($detail + "\n*Branch:* `" + $branch + "`\n*Commit:* <" + $commit_url + "|" + $sha + ">\n*Workflow run:* <" + $run_url + "|view logs and failed tests>")}}]}')"
curl -fsSL -X POST -H 'Content-type: application/json' --data "$payload" "$SLACK_WEBHOOK"