[PATCH v5 2/2] ci: point test failures and fixed known breakages at their file and line
- From
Harald Nordgren via GitGitGadget <gitgitgadget@gmail.com>
- Date
- Oct 3, 2026, 08:11 UTC
- Message-ID
- <46f93a9e16e27966391a1cedb02a156b26fbd77f.1791015117.git.gitgitgadget@gmail.com>
- In-Reply-To
- <pull.2419.v5.git.git.1791015117.gitgitgadget@gmail.com>
From: Harald Nordgren <haraldnordgren@gmail.com>
When a test fails, GitHub shows an annotation naming it, for example:
failed: t1060.17 partial clone of corrupted repository
but the location GitHub attaches to that annotation is the CI workflow file itself, not the test script, so there is nothing pointing at where the test actually lives.
Find the line a test is defined on by searching its script for the test's own description as a fixed string, using the first match, and attach that file and line to the annotation instead. Fall back to line 1 when the description is not found verbatim, which happens when a test builds its description at runtime instead of writing it out literally.
Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> --- t/test-lib-github-workflow-markup.sh | 30 ++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-)
diff --git a/t/test-lib-github-workflow-markup.sh b/t/test-lib-github-workflow-markup.sh index 0d54496358..ac8c536231 100644 --- a/t/test-lib-github-workflow-markup.sh +++ b/t/test-lib-github-workflow-markup.sh @@ -31,6 +31,15 @@ start_test_output () { github_markup_script_name=${0##*/} } +find_test_case_line_ () { + # A description can contain characters like [ or * that would + # corrupt a regex search, so match it literally and take the first + # hit. The -- keeps a description starting with "-" from being read + # as an option. + grep -n -F -- "$1" "$TEST_DIRECTORY/$github_markup_script_name" | + head -n 1 | cut -d: -f1 +} + github_annotation_ () { echo >>$github_markup_output "::$1 file=$2,line=$3::$4" } @@ -40,18 +49,27 @@ github_annotation_ () { finalize_test_case_output () { test_case_result=$1 shift + + case "$test_case_result" in + ok|broken) + # Exit without printing the "ok" or "broken" tests + return + ;; + esac + + test_case_line=$(find_test_case_line_ "$1") + case "$test_case_result" in failure) - echo >>$github_markup_output "::error::failed: $this_test.$test_count $1" + github_annotation_ error "t/$github_markup_script_name" "${test_case_line:-1}" \ + "failed: $this_test.$test_count $1" ;; fixed) - echo >>$github_markup_output "::notice::fixed: $this_test.$test_count $1" - ;; - ok|broken) - # Exit without printing the "ok" or ""broken" tests - return + github_annotation_ notice "t/$github_markup_script_name" "${test_case_line:-1}" \ + "fixed: $this_test.$test_count $1" ;; esac + echo >>$github_markup_output "::group::$test_case_result: $this_test.$test_count $*" test-tool >>$github_markup_output path-utils skip-n-bytes \ "$GIT_TEST_TEE_OUTPUT_FILE" $GIT_TEST_TEE_OFFSET
-- gitgitgadget