diff --git a/ci-notify.sh b/ci-notify.sh index 4d27098..a0455c4 100755 --- a/ci-notify.sh +++ b/ci-notify.sh @@ -18,6 +18,7 @@ SUMMARY="$4" # e.g., "940 passed, 0 failed, 393 skipped" FEATURES="$5" # e.g., "31/31 features verified" DURATION="$6" # e.g., "12.3s" ACTOR="$7" # who pushed +REPORT_FILE="$8" # optional HTML failure report path if [ "$STATUS" = "pass" ]; then ICON="✅" @@ -58,4 +59,14 @@ curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \ -d "message_thread_id=${TOPIC_ID}" \ -d "text=${MSG}" > /dev/null 2>&1 +# Send HTML failure report as attachment if available +if [ -n "$REPORT_FILE" ] && [ -f "$REPORT_FILE" ]; then + curl -s -X POST "https://api.telegram.org/bot${BOT_TOKEN}/sendDocument" \ + -F "chat_id=${CHAT_ID}" \ + -F "message_thread_id=${TOPIC_ID}" \ + -F "document=@${REPORT_FILE}" \ + -F "caption=CI Failure Report — ${BRANCH} (${COMMIT})" > /dev/null 2>&1 + rm -f "$REPORT_FILE" +fi + exit 0 diff --git a/ci-runner.sh b/ci-runner.sh index b0a965e..4961487 100755 --- a/ci-runner.sh +++ b/ci-runner.sh @@ -147,9 +147,121 @@ echo "Features: $FEATURES_RESULT" echo "Duration: ${DURATION}s" echo "=========================" +# ─── Generate Failure Summary HTML ─── +REPORT_FILE="" +if [ "$OVERALL" = "fail" ]; then + REPORT_FILE="/tmp/tsharps-ci-report-${BRANCH}-$(date +%Y%m%d-%H%M%S).html" + FAILED_LINES=$(echo "$TEST_OUTPUT" | grep "^FAILED " || true) + ERROR_LINES=$(echo "$TEST_OUTPUT" | grep "^ERROR " || true) + FAILURE_DETAILS=$(echo "$TEST_OUTPUT" | grep -B0 "^FAILED \|^E \|Error\|assert" | head -60 || true) + + python3 -c " +import html, sys +from datetime import datetime, timezone + +branch = '$BRANCH' +commit = '$COMMIT' +actor = '$ACTOR' +duration = '${DURATION}s' +passed = '$PASS_COUNT' +failed = '$FAIL_COUNT' +skipped = '$SKIP_COUNT' +errors = '$ERROR_COUNT' +features = '''$FEATURES_RESULT''' +failed_lines = '''$FAILED_LINES''' +failure_details = '''$FAILURE_DETAILS''' +pkg_output = '''$PKG_OUTPUT''' + +failed_items = [l.replace('FAILED ', '') for l in failed_lines.strip().split('\n') if l.strip()] +error_items = [l for l in '''$ERROR_LINES'''.strip().split('\n') if l.strip()] + +rows = '' +for item in failed_items: + parts = item.rsplit('::', 1) + file_part = parts[0] if len(parts) > 0 else item + test_part = parts[1] if len(parts) > 1 else '' + rows += f'
{html.escape(file_part)}{html.escape(test_part)}{html.escape(item)}| File | Test |
|---|
{detail_block}
+
+
+
+'''
+
+with open('$REPORT_FILE', 'w') as f:
+ f.write(report)
+print(f'Report written to $REPORT_FILE')
+" 2>&1
+ echo "Failure report: $REPORT_FILE"
+fi
+
# ─── Send Notification ───
bash "$SCRIPT_DIR/ci-notify.sh" \
- "$BRANCH" "$COMMIT" "$OVERALL" "$SUMMARY" "$FEATURES_RESULT" "${DURATION}s" "$ACTOR"
+ "$BRANCH" "$COMMIT" "$OVERALL" "$SUMMARY" "$FEATURES_RESULT" "${DURATION}s" "$ACTOR" "$REPORT_FILE"
# Release lock
flock -u 200