This is an automated email from the ASF dual-hosted git repository.

ndimiduk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/yetus.git


The following commit(s) were added to refs/heads/main by this push:
     new 2a831e7e YETUS-1260. Add GitHub Actions Job Summary support (#362)
2a831e7e is described below

commit 2a831e7e6a2f6a2f41bc1944a06d89afc65ca510
Author: Nick Dimiduk <[email protected]>
AuthorDate: Mon Feb 9 13:39:08 2026 +0100

    YETUS-1260. Add GitHub Actions Job Summary support (#362)
    
    * YETUS-1260. Add GitHub Actions Job Summary support
    
    * add docker support
---
 .../precommit/robots/githubactions.html.md         |  19 +++
 precommit/src/main/shell/core.d/docker.sh          |   6 +-
 precommit/src/main/shell/robots.d/githubactions.sh | 153 +++++++++++++++++-
 .../src/test/shell/githubactions_finalreport.bats  | 175 +++++++++++++++++++++
 4 files changed, 351 insertions(+), 2 deletions(-)

diff --git 
a/asf-site-src/source/documentation/in-progress/precommit/robots/githubactions.html.md
 
b/asf-site-src/source/documentation/in-progress/precommit/robots/githubactions.html.md
index 698cbb55..346f6dce 100644
--- 
a/asf-site-src/source/documentation/in-progress/precommit/robots/githubactions.html.md
+++ 
b/asf-site-src/source/documentation/in-progress/precommit/robots/githubactions.html.md
@@ -24,6 +24,8 @@ GitHub Action support is available in two different ways.  
There are some settin
 * Annotations will be used to mark problems in the files for those plug-ins 
that support this feature and
 if `--linecomments` has `github` as a configured bug system (the default).
 * Statuses will be added if the GitHub Token gives permission.
+* Job Summary will be written with a Markdown-formatted report of the test 
results, visible directly on the
+workflow run page without downloading artifacts.
 
 ## Workflow Action
 
@@ -108,6 +110,23 @@ TRIGGER: ${GITHUB_ACTIONS}=True
 
 GitHub Actions support has only been tested on the ubuntu-latest image. It 
automatically configures `--patch-dir` to be `${GITHUB_WORKSAPCE}/yetus` if not 
previously set.
 
+## Job Summary
+
+When running under GitHub Actions, Apache Yetus automatically writes a summary 
of the test results to the
+[Job 
Summary](https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/).
 This provides
+immediate visibility of pass/fail status and details directly on the workflow 
run page, without needing to
+download artifacts or parse log files.
+
+The Job Summary includes:
+
+* Overall pass/fail status with vote counts
+* Vote table showing each subsystem's result, runtime, and comments
+* Failed tests section (if any tests failed)
+* Links to log files (if artifact URLs are available)
+
+This feature requires no configuration and is automatically enabled when the 
`GITHUB_STEP_SUMMARY` environment
+variable is present (which GitHub Actions sets automatically).
+
 See also:
 
 * Apache Yetus' [workflow action 
source](https://github.com/apache/yetus-test-patch-action) for lower level 
details on the workflow action implementation.
diff --git a/precommit/src/main/shell/core.d/docker.sh 
b/precommit/src/main/shell/core.d/docker.sh
index fa518e94..3a5581c7 100755
--- a/precommit/src/main/shell/core.d/docker.sh
+++ b/precommit/src/main/shell/core.d/docker.sh
@@ -939,9 +939,13 @@ function docker_handler
 
   determine_user
 
-  # need to call this explicitly
+  # need to call these explicitly (not in plugin lists)
   console_docker_support
 
+  if declare -f githubactions_docker_support >/dev/null; then
+    githubactions_docker_support
+  fi
+
   for plugin in ${PROJECT_NAME} ${BUILDTOOL} "${BUGSYSTEMS[@]}" 
"${TESTTYPES[@]}" "${TESTFORMATS[@]}"; do
     if declare -f "${plugin}_docker_support" >/dev/null; then
       "${plugin}_docker_support"
diff --git a/precommit/src/main/shell/robots.d/githubactions.sh 
b/precommit/src/main/shell/robots.d/githubactions.sh
index 461cb362..d614e07b 100755
--- a/precommit/src/main/shell/robots.d/githubactions.sh
+++ b/precommit/src/main/shell/robots.d/githubactions.sh
@@ -85,7 +85,158 @@ function githubactions_set_plugin_defaults
   GITHUB_REPO="${GITHUB_REPOSITORY}"
 }
 
+## @description  Docker support for GitHub Actions
+## @audience     private
+## @stability    evolving
+## @replaceable  no
+function githubactions_docker_support
+{
+  if [[ -z "${GITHUB_STEP_SUMMARY}" ]]; then
+    return 0
+  fi
+
+  if [[ ! -f "${GITHUB_STEP_SUMMARY}" ]]; then
+    return 0
+  fi
+
+  DOCKER_EXTRAARGS+=("-v" 
"${GITHUB_STEP_SUMMARY}:${DOCKER_WORK_DIR}/step_summary.md")
+  GITHUB_STEP_SUMMARY="${DOCKER_WORK_DIR}/step_summary.md"
+  add_docker_env GITHUB_STEP_SUMMARY
+}
+
 function githubactions_cleanup_and_exit
 {
   echo "::endgroup::"
-}
\ No newline at end of file
+}
+
+## @description  Write a summary report to GitHub Actions Job Summary
+## @audience     private
+## @stability    evolving
+## @replaceable  no
+function githubactions_finalreport
+{
+  declare -i i=0
+  declare ourstring
+  declare vote
+  declare subs
+  declare ela
+  declare calctime
+  declare logfile
+  declare comment
+  declare url
+  declare emoji
+  declare loglink
+
+  if [[ -z "${GITHUB_STEP_SUMMARY}" ]]; then
+    return 0
+  fi
+
+  if [[ ! -w "${GITHUB_STEP_SUMMARY}" ]]; then
+    yetus_error "WARNING: GITHUB_STEP_SUMMARY (${GITHUB_STEP_SUMMARY}) is not 
writable"
+    return 0
+  fi
+
+  big_console_header "Writing GitHub Actions Job Summary"
+
+  url=$(get_artifact_url)
+
+  {
+    if [[ ${RESULT} == 0 ]]; then
+      printf '## :confetti_ball: +1 overall\n\n'
+    else
+      printf '## :broken_heart: -1 overall\n\n'
+    fi
+
+    i=0
+    until [[ ${i} -ge ${#TP_HEADER[@]} ]]; do
+      printf '%s\n\n' "${TP_HEADER[i]}"
+      ((i=i+1))
+    done
+
+    printf '| Vote | Subsystem | Runtime | Logfile | Comment |\n'
+    printf '|:----:|----------:|--------:|:-------:|:--------|\n'
+
+    i=0
+    until [[ ${i} -ge ${#TP_VOTE_TABLE[@]} ]]; do
+      ourstring=$(echo "${TP_VOTE_TABLE[i]}" | tr -s ' ')
+      vote=$(echo "${ourstring}" | cut -f2 -d\| | tr -d ' ')
+      subs=$(echo "${ourstring}" | cut -f3 -d\|)
+      ela=$(echo "${ourstring}" | cut -f4 -d\|)
+      calctime=$(clock_display "${ela}")
+      logfile=$(echo "${ourstring}" | cut -f5 -d\| | tr -d ' ')
+      comment=$(echo "${ourstring}" | cut -f6 -d\|)
+
+      if [[ "${vote}" = "H" ]]; then
+        printf '| | | | | _%s_ |\n' "${comment}"
+        ((i=i+1))
+        continue
+      fi
+
+      # Honor GITHUB_USE_EMOJI_VOTE setting
+      if [[ ${GITHUB_USE_EMOJI_VOTE} == true ]]; then
+        case ${vote} in
+          1|"+1")
+            emoji="+1 :green_heart:"
+          ;;
+          -1)
+            emoji="-1 :x:"
+          ;;
+          0)
+            emoji="+0 :ok:"
+          ;;
+          -0)
+            emoji="-0 :warning:"
+          ;;
+          *)
+            emoji=${vote}
+          ;;
+        esac
+      else
+        emoji="${vote}"
+      fi
+
+      # Format logfile as link if URL is available
+      if [[ -n "${logfile}" ]]; then
+        if [[ -n "${url}" ]]; then
+          loglink=$(echo "${logfile}" | "${SED}" -e "s,@@BASE@@,${url},g")
+          loglink="[${logfile/@@BASE@@\//}](${loglink})"
+        else
+          loglink="${logfile/@@BASE@@\//}"
+        fi
+      else
+        loglink=""
+      fi
+
+      printf '| %s | %s | %s | %s | %s |\n' \
+        "${emoji}" \
+        "${subs}" \
+        "${calctime}" \
+        "${loglink}" \
+        "${comment}"
+
+      ((i=i+1))
+    done
+
+    if [[ ${#TP_TEST_TABLE[@]} -gt 0 ]]; then
+      printf '\n### Failed Tests\n\n'
+      printf '| Reason | Tests |\n'
+      printf '|-------:|:------|\n'
+      i=0
+      until [[ ${i} -ge ${#TP_TEST_TABLE[@]} ]]; do
+        echo "${TP_TEST_TABLE[i]}"
+        ((i=i+1))
+      done
+    fi
+
+    printf '\n### Subsystem Report\n\n'
+    printf '| Subsystem | Report/Notes |\n'
+    printf '|----------:|:-------------|\n'
+
+    i=0
+    until [[ ${i} -ge ${#TP_FOOTER_TABLE[@]} ]]; do
+      comment=$(echo "${TP_FOOTER_TABLE[i]}" | "${SED}" -e 
"s,@@BASE@@,${url},g")
+      printf '%s\n' "${comment}"
+      ((i=i+1))
+    done
+  } >> "${GITHUB_STEP_SUMMARY}"
+}
diff --git a/precommit/src/test/shell/githubactions_finalreport.bats 
b/precommit/src/test/shell/githubactions_finalreport.bats
new file mode 100644
index 00000000..cd4e003d
--- /dev/null
+++ b/precommit/src/test/shell/githubactions_finalreport.bats
@@ -0,0 +1,175 @@
+#!/usr/bin/env bash
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+load functions_test_helper
+
+setup_gha() {
+  # Source the githubactions robot
+  # shellcheck disable=SC1090
+  . "${BATS_TEST_DIRNAME}/../../main/shell/robots.d/githubactions.sh"
+
+  # Mock required functions
+  big_console_header() { :; }
+  clock_display() { echo "$1s"; }
+  get_artifact_url() { echo ""; }
+  yetus_error() { echo "$*" >&2; }
+  SED="sed"
+
+  # Set up step summary file
+  GITHUB_STEP_SUMMARY="${TMP}/step_summary.md"
+  touch "${GITHUB_STEP_SUMMARY}"
+  export GITHUB_STEP_SUMMARY
+
+  # Initialize arrays and settings
+  TP_VOTE_TABLE=()
+  TP_TEST_TABLE=()
+  TP_HEADER=()
+  TP_FOOTER_TABLE=()
+  VERSION="0.0.0-test"
+  GITHUB_USE_EMOJI_VOTE=false
+}
+
+@test "githubactions_finalreport (no GITHUB_STEP_SUMMARY)" {
+  setup_gha
+  unset GITHUB_STEP_SUMMARY
+  run githubactions_finalreport
+  [ "${status}" -eq 0 ]
+}
+
+@test "githubactions_finalreport (GITHUB_STEP_SUMMARY not writable)" {
+  setup_gha
+  GITHUB_STEP_SUMMARY="/nonexistent/path/summary.md"
+  run githubactions_finalreport
+  [ "${status}" -eq 0 ]
+}
+
+@test "githubactions_finalreport (success result)" {
+  setup_gha
+  RESULT=0
+  TP_VOTE_TABLE=("|+1| compile |60||passed|")
+  run githubactions_finalreport
+  [ "${status}" -eq 0 ]
+  grep -q ":confetti_ball:" "${GITHUB_STEP_SUMMARY}"
+  grep -q "+1 overall" "${GITHUB_STEP_SUMMARY}"
+  grep -q "compile" "${GITHUB_STEP_SUMMARY}"
+}
+
+@test "githubactions_finalreport (failure result)" {
+  setup_gha
+  RESULT=1
+  TP_VOTE_TABLE=("|-1| unit |120||tests failed|")
+  run githubactions_finalreport
+  [ "${status}" -eq 0 ]
+  grep -q ":broken_heart:" "${GITHUB_STEP_SUMMARY}"
+  grep -q -- "-1 overall" "${GITHUB_STEP_SUMMARY}"
+  grep -q "unit" "${GITHUB_STEP_SUMMARY}"
+}
+
+@test "githubactions_finalreport (with headers)" {
+  setup_gha
+  RESULT=0
+  TP_HEADER=("Build completed successfully")
+  TP_VOTE_TABLE=("|+1| compile |60||passed|")
+  run githubactions_finalreport
+  [ "${status}" -eq 0 ]
+  grep -q "Build completed successfully" "${GITHUB_STEP_SUMMARY}"
+}
+
+@test "githubactions_finalreport (with failed tests)" {
+  setup_gha
+  RESULT=1
+  TP_VOTE_TABLE=("|-1| unit |120||tests failed|")
+  TP_TEST_TABLE=("| Failed tests | org.example.TestFoo |")
+  run githubactions_finalreport
+  [ "${status}" -eq 0 ]
+  grep -q "Failed Tests" "${GITHUB_STEP_SUMMARY}"
+  grep -q "TestFoo" "${GITHUB_STEP_SUMMARY}"
+}
+
+@test "githubactions_finalreport (vote table header row)" {
+  setup_gha
+  RESULT=0
+  TP_VOTE_TABLE=("|H||||Prechecks|")
+  run githubactions_finalreport
+  [ "${status}" -eq 0 ]
+  grep -q "_Prechecks_" "${GITHUB_STEP_SUMMARY}"
+}
+
+@test "githubactions_finalreport (emoji vote enabled)" {
+  setup_gha
+  RESULT=0
+  GITHUB_USE_EMOJI_VOTE=true
+  TP_VOTE_TABLE=("|+1| compile |60||passed|")
+  run githubactions_finalreport
+  [ "${status}" -eq 0 ]
+  grep -q ":green_heart:" "${GITHUB_STEP_SUMMARY}"
+}
+
+@test "githubactions_finalreport (emoji vote disabled)" {
+  setup_gha
+  RESULT=0
+  GITHUB_USE_EMOJI_VOTE=false
+  TP_VOTE_TABLE=("|+1| compile |60||passed|")
+  run githubactions_finalreport
+  [ "${status}" -eq 0 ]
+  # Should have +1 but not the emoji
+  grep -q "+1" "${GITHUB_STEP_SUMMARY}"
+  ! grep -q ":green_heart:" "${GITHUB_STEP_SUMMARY}"
+}
+
+setup_docker_support() {
+  # Source the githubactions robot
+  # shellcheck disable=SC1090
+  . "${BATS_TEST_DIRNAME}/../../main/shell/robots.d/githubactions.sh"
+
+  # Mock add_docker_env
+  DOCKER_EXTRAENVS=()
+  add_docker_env() {
+    for k in "$@"; do
+      DOCKER_EXTRAENVS+=("${k}")
+    done
+  }
+
+  DOCKER_EXTRAARGS=()
+  DOCKER_WORK_DIR="/workdir"
+}
+
+@test "githubactions_docker_support (no GITHUB_STEP_SUMMARY)" {
+  setup_docker_support
+  unset GITHUB_STEP_SUMMARY
+  run githubactions_docker_support
+  [ "${status}" -eq 0 ]
+  [ "${#DOCKER_EXTRAARGS[@]}" -eq 0 ]
+}
+
+@test "githubactions_docker_support (GITHUB_STEP_SUMMARY file missing)" {
+  setup_docker_support
+  GITHUB_STEP_SUMMARY="/nonexistent/path/summary.md"
+  run githubactions_docker_support
+  [ "${status}" -eq 0 ]
+  [ "${#DOCKER_EXTRAARGS[@]}" -eq 0 ]
+}
+
+@test "githubactions_docker_support (mounts summary file)" {
+  setup_docker_support
+  GITHUB_STEP_SUMMARY="${TMP}/step_summary.md"
+  touch "${GITHUB_STEP_SUMMARY}"
+  githubactions_docker_support
+  [[ "${DOCKER_EXTRAARGS[*]}" == *"-v"* ]]
+  [[ "${DOCKER_EXTRAARGS[*]}" == 
*"${TMP}/step_summary.md:/workdir/step_summary.md"* ]]
+  [ "${GITHUB_STEP_SUMMARY}" = "/workdir/step_summary.md" ]
+  [[ "${DOCKER_EXTRAENVS[*]}" == *"GITHUB_STEP_SUMMARY"* ]]
+}

Reply via email to