Skip to content

Commit 2a831e7

Browse files
authored
YETUS-1260. Add GitHub Actions Job Summary support (#362)
* YETUS-1260. Add GitHub Actions Job Summary support * add docker support
1 parent 900fec2 commit 2a831e7

4 files changed

Lines changed: 351 additions & 2 deletions

File tree

asf-site-src/source/documentation/in-progress/precommit/robots/githubactions.html.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ GitHub Action support is available in two different ways. There are some settin
2424
* Annotations will be used to mark problems in the files for those plug-ins that support this feature and
2525
if `--linecomments` has `github` as a configured bug system (the default).
2626
* Statuses will be added if the GitHub Token gives permission.
27+
* Job Summary will be written with a Markdown-formatted report of the test results, visible directly on the
28+
workflow run page without downloading artifacts.
2729

2830
## Workflow Action
2931

@@ -108,6 +110,23 @@ TRIGGER: ${GITHUB_ACTIONS}=True
108110

109111
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.
110112

113+
## Job Summary
114+
115+
When running under GitHub Actions, Apache Yetus automatically writes a summary of the test results to the
116+
[Job Summary](https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/). This provides
117+
immediate visibility of pass/fail status and details directly on the workflow run page, without needing to
118+
download artifacts or parse log files.
119+
120+
The Job Summary includes:
121+
122+
* Overall pass/fail status with vote counts
123+
* Vote table showing each subsystem's result, runtime, and comments
124+
* Failed tests section (if any tests failed)
125+
* Links to log files (if artifact URLs are available)
126+
127+
This feature requires no configuration and is automatically enabled when the `GITHUB_STEP_SUMMARY` environment
128+
variable is present (which GitHub Actions sets automatically).
129+
111130
See also:
112131

113132
* Apache Yetus' [workflow action source](https://github.com/apache/yetus-test-patch-action) for lower level details on the workflow action implementation.

precommit/src/main/shell/core.d/docker.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,9 +939,13 @@ function docker_handler
939939

940940
determine_user
941941

942-
# need to call this explicitly
942+
# need to call these explicitly (not in plugin lists)
943943
console_docker_support
944944

945+
if declare -f githubactions_docker_support >/dev/null; then
946+
githubactions_docker_support
947+
fi
948+
945949
for plugin in ${PROJECT_NAME} ${BUILDTOOL} "${BUGSYSTEMS[@]}" "${TESTTYPES[@]}" "${TESTFORMATS[@]}"; do
946950
if declare -f "${plugin}_docker_support" >/dev/null; then
947951
"${plugin}_docker_support"

precommit/src/main/shell/robots.d/githubactions.sh

Lines changed: 152 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,158 @@ function githubactions_set_plugin_defaults
8585
GITHUB_REPO="${GITHUB_REPOSITORY}"
8686
}
8787

88+
## @description Docker support for GitHub Actions
89+
## @audience private
90+
## @stability evolving
91+
## @replaceable no
92+
function githubactions_docker_support
93+
{
94+
if [[ -z "${GITHUB_STEP_SUMMARY}" ]]; then
95+
return 0
96+
fi
97+
98+
if [[ ! -f "${GITHUB_STEP_SUMMARY}" ]]; then
99+
return 0
100+
fi
101+
102+
DOCKER_EXTRAARGS+=("-v" "${GITHUB_STEP_SUMMARY}:${DOCKER_WORK_DIR}/step_summary.md")
103+
GITHUB_STEP_SUMMARY="${DOCKER_WORK_DIR}/step_summary.md"
104+
add_docker_env GITHUB_STEP_SUMMARY
105+
}
106+
88107
function githubactions_cleanup_and_exit
89108
{
90109
echo "::endgroup::"
91-
}
110+
}
111+
112+
## @description Write a summary report to GitHub Actions Job Summary
113+
## @audience private
114+
## @stability evolving
115+
## @replaceable no
116+
function githubactions_finalreport
117+
{
118+
declare -i i=0
119+
declare ourstring
120+
declare vote
121+
declare subs
122+
declare ela
123+
declare calctime
124+
declare logfile
125+
declare comment
126+
declare url
127+
declare emoji
128+
declare loglink
129+
130+
if [[ -z "${GITHUB_STEP_SUMMARY}" ]]; then
131+
return 0
132+
fi
133+
134+
if [[ ! -w "${GITHUB_STEP_SUMMARY}" ]]; then
135+
yetus_error "WARNING: GITHUB_STEP_SUMMARY (${GITHUB_STEP_SUMMARY}) is not writable"
136+
return 0
137+
fi
138+
139+
big_console_header "Writing GitHub Actions Job Summary"
140+
141+
url=$(get_artifact_url)
142+
143+
{
144+
if [[ ${RESULT} == 0 ]]; then
145+
printf '## :confetti_ball: +1 overall\n\n'
146+
else
147+
printf '## :broken_heart: -1 overall\n\n'
148+
fi
149+
150+
i=0
151+
until [[ ${i} -ge ${#TP_HEADER[@]} ]]; do
152+
printf '%s\n\n' "${TP_HEADER[i]}"
153+
((i=i+1))
154+
done
155+
156+
printf '| Vote | Subsystem | Runtime | Logfile | Comment |\n'
157+
printf '|:----:|----------:|--------:|:-------:|:--------|\n'
158+
159+
i=0
160+
until [[ ${i} -ge ${#TP_VOTE_TABLE[@]} ]]; do
161+
ourstring=$(echo "${TP_VOTE_TABLE[i]}" | tr -s ' ')
162+
vote=$(echo "${ourstring}" | cut -f2 -d\| | tr -d ' ')
163+
subs=$(echo "${ourstring}" | cut -f3 -d\|)
164+
ela=$(echo "${ourstring}" | cut -f4 -d\|)
165+
calctime=$(clock_display "${ela}")
166+
logfile=$(echo "${ourstring}" | cut -f5 -d\| | tr -d ' ')
167+
comment=$(echo "${ourstring}" | cut -f6 -d\|)
168+
169+
if [[ "${vote}" = "H" ]]; then
170+
printf '| | | | | _%s_ |\n' "${comment}"
171+
((i=i+1))
172+
continue
173+
fi
174+
175+
# Honor GITHUB_USE_EMOJI_VOTE setting
176+
if [[ ${GITHUB_USE_EMOJI_VOTE} == true ]]; then
177+
case ${vote} in
178+
1|"+1")
179+
emoji="+1 :green_heart:"
180+
;;
181+
-1)
182+
emoji="-1 :x:"
183+
;;
184+
0)
185+
emoji="+0 :ok:"
186+
;;
187+
-0)
188+
emoji="-0 :warning:"
189+
;;
190+
*)
191+
emoji=${vote}
192+
;;
193+
esac
194+
else
195+
emoji="${vote}"
196+
fi
197+
198+
# Format logfile as link if URL is available
199+
if [[ -n "${logfile}" ]]; then
200+
if [[ -n "${url}" ]]; then
201+
loglink=$(echo "${logfile}" | "${SED}" -e "s,@@BASE@@,${url},g")
202+
loglink="[${logfile/@@BASE@@\//}](${loglink})"
203+
else
204+
loglink="${logfile/@@BASE@@\//}"
205+
fi
206+
else
207+
loglink=""
208+
fi
209+
210+
printf '| %s | %s | %s | %s | %s |\n' \
211+
"${emoji}" \
212+
"${subs}" \
213+
"${calctime}" \
214+
"${loglink}" \
215+
"${comment}"
216+
217+
((i=i+1))
218+
done
219+
220+
if [[ ${#TP_TEST_TABLE[@]} -gt 0 ]]; then
221+
printf '\n### Failed Tests\n\n'
222+
printf '| Reason | Tests |\n'
223+
printf '|-------:|:------|\n'
224+
i=0
225+
until [[ ${i} -ge ${#TP_TEST_TABLE[@]} ]]; do
226+
echo "${TP_TEST_TABLE[i]}"
227+
((i=i+1))
228+
done
229+
fi
230+
231+
printf '\n### Subsystem Report\n\n'
232+
printf '| Subsystem | Report/Notes |\n'
233+
printf '|----------:|:-------------|\n'
234+
235+
i=0
236+
until [[ ${i} -ge ${#TP_FOOTER_TABLE[@]} ]]; do
237+
comment=$(echo "${TP_FOOTER_TABLE[i]}" | "${SED}" -e "s,@@BASE@@,${url},g")
238+
printf '%s\n' "${comment}"
239+
((i=i+1))
240+
done
241+
} >> "${GITHUB_STEP_SUMMARY}"
242+
}
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#!/usr/bin/env bash
2+
# Licensed to the Apache Software Foundation (ASF) under one or more
3+
# contributor license agreements. See the NOTICE file distributed with
4+
# this work for additional information regarding copyright ownership.
5+
# The ASF licenses this file to You under the Apache License, Version 2.0
6+
# (the "License"); you may not use this file except in compliance with
7+
# the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
load functions_test_helper
18+
19+
setup_gha() {
20+
# Source the githubactions robot
21+
# shellcheck disable=SC1090
22+
. "${BATS_TEST_DIRNAME}/../../main/shell/robots.d/githubactions.sh"
23+
24+
# Mock required functions
25+
big_console_header() { :; }
26+
clock_display() { echo "$1s"; }
27+
get_artifact_url() { echo ""; }
28+
yetus_error() { echo "$*" >&2; }
29+
SED="sed"
30+
31+
# Set up step summary file
32+
GITHUB_STEP_SUMMARY="${TMP}/step_summary.md"
33+
touch "${GITHUB_STEP_SUMMARY}"
34+
export GITHUB_STEP_SUMMARY
35+
36+
# Initialize arrays and settings
37+
TP_VOTE_TABLE=()
38+
TP_TEST_TABLE=()
39+
TP_HEADER=()
40+
TP_FOOTER_TABLE=()
41+
VERSION="0.0.0-test"
42+
GITHUB_USE_EMOJI_VOTE=false
43+
}
44+
45+
@test "githubactions_finalreport (no GITHUB_STEP_SUMMARY)" {
46+
setup_gha
47+
unset GITHUB_STEP_SUMMARY
48+
run githubactions_finalreport
49+
[ "${status}" -eq 0 ]
50+
}
51+
52+
@test "githubactions_finalreport (GITHUB_STEP_SUMMARY not writable)" {
53+
setup_gha
54+
GITHUB_STEP_SUMMARY="/nonexistent/path/summary.md"
55+
run githubactions_finalreport
56+
[ "${status}" -eq 0 ]
57+
}
58+
59+
@test "githubactions_finalreport (success result)" {
60+
setup_gha
61+
RESULT=0
62+
TP_VOTE_TABLE=("|+1| compile |60||passed|")
63+
run githubactions_finalreport
64+
[ "${status}" -eq 0 ]
65+
grep -q ":confetti_ball:" "${GITHUB_STEP_SUMMARY}"
66+
grep -q "+1 overall" "${GITHUB_STEP_SUMMARY}"
67+
grep -q "compile" "${GITHUB_STEP_SUMMARY}"
68+
}
69+
70+
@test "githubactions_finalreport (failure result)" {
71+
setup_gha
72+
RESULT=1
73+
TP_VOTE_TABLE=("|-1| unit |120||tests failed|")
74+
run githubactions_finalreport
75+
[ "${status}" -eq 0 ]
76+
grep -q ":broken_heart:" "${GITHUB_STEP_SUMMARY}"
77+
grep -q -- "-1 overall" "${GITHUB_STEP_SUMMARY}"
78+
grep -q "unit" "${GITHUB_STEP_SUMMARY}"
79+
}
80+
81+
@test "githubactions_finalreport (with headers)" {
82+
setup_gha
83+
RESULT=0
84+
TP_HEADER=("Build completed successfully")
85+
TP_VOTE_TABLE=("|+1| compile |60||passed|")
86+
run githubactions_finalreport
87+
[ "${status}" -eq 0 ]
88+
grep -q "Build completed successfully" "${GITHUB_STEP_SUMMARY}"
89+
}
90+
91+
@test "githubactions_finalreport (with failed tests)" {
92+
setup_gha
93+
RESULT=1
94+
TP_VOTE_TABLE=("|-1| unit |120||tests failed|")
95+
TP_TEST_TABLE=("| Failed tests | org.example.TestFoo |")
96+
run githubactions_finalreport
97+
[ "${status}" -eq 0 ]
98+
grep -q "Failed Tests" "${GITHUB_STEP_SUMMARY}"
99+
grep -q "TestFoo" "${GITHUB_STEP_SUMMARY}"
100+
}
101+
102+
@test "githubactions_finalreport (vote table header row)" {
103+
setup_gha
104+
RESULT=0
105+
TP_VOTE_TABLE=("|H||||Prechecks|")
106+
run githubactions_finalreport
107+
[ "${status}" -eq 0 ]
108+
grep -q "_Prechecks_" "${GITHUB_STEP_SUMMARY}"
109+
}
110+
111+
@test "githubactions_finalreport (emoji vote enabled)" {
112+
setup_gha
113+
RESULT=0
114+
GITHUB_USE_EMOJI_VOTE=true
115+
TP_VOTE_TABLE=("|+1| compile |60||passed|")
116+
run githubactions_finalreport
117+
[ "${status}" -eq 0 ]
118+
grep -q ":green_heart:" "${GITHUB_STEP_SUMMARY}"
119+
}
120+
121+
@test "githubactions_finalreport (emoji vote disabled)" {
122+
setup_gha
123+
RESULT=0
124+
GITHUB_USE_EMOJI_VOTE=false
125+
TP_VOTE_TABLE=("|+1| compile |60||passed|")
126+
run githubactions_finalreport
127+
[ "${status}" -eq 0 ]
128+
# Should have +1 but not the emoji
129+
grep -q "+1" "${GITHUB_STEP_SUMMARY}"
130+
! grep -q ":green_heart:" "${GITHUB_STEP_SUMMARY}"
131+
}
132+
133+
setup_docker_support() {
134+
# Source the githubactions robot
135+
# shellcheck disable=SC1090
136+
. "${BATS_TEST_DIRNAME}/../../main/shell/robots.d/githubactions.sh"
137+
138+
# Mock add_docker_env
139+
DOCKER_EXTRAENVS=()
140+
add_docker_env() {
141+
for k in "$@"; do
142+
DOCKER_EXTRAENVS+=("${k}")
143+
done
144+
}
145+
146+
DOCKER_EXTRAARGS=()
147+
DOCKER_WORK_DIR="/workdir"
148+
}
149+
150+
@test "githubactions_docker_support (no GITHUB_STEP_SUMMARY)" {
151+
setup_docker_support
152+
unset GITHUB_STEP_SUMMARY
153+
run githubactions_docker_support
154+
[ "${status}" -eq 0 ]
155+
[ "${#DOCKER_EXTRAARGS[@]}" -eq 0 ]
156+
}
157+
158+
@test "githubactions_docker_support (GITHUB_STEP_SUMMARY file missing)" {
159+
setup_docker_support
160+
GITHUB_STEP_SUMMARY="/nonexistent/path/summary.md"
161+
run githubactions_docker_support
162+
[ "${status}" -eq 0 ]
163+
[ "${#DOCKER_EXTRAARGS[@]}" -eq 0 ]
164+
}
165+
166+
@test "githubactions_docker_support (mounts summary file)" {
167+
setup_docker_support
168+
GITHUB_STEP_SUMMARY="${TMP}/step_summary.md"
169+
touch "${GITHUB_STEP_SUMMARY}"
170+
githubactions_docker_support
171+
[[ "${DOCKER_EXTRAARGS[*]}" == *"-v"* ]]
172+
[[ "${DOCKER_EXTRAARGS[*]}" == *"${TMP}/step_summary.md:/workdir/step_summary.md"* ]]
173+
[ "${GITHUB_STEP_SUMMARY}" = "/workdir/step_summary.md" ]
174+
[[ "${DOCKER_EXTRAENVS[*]}" == *"GITHUB_STEP_SUMMARY"* ]]
175+
}

0 commit comments

Comments
 (0)