fix: replace raw echo with output helpers in check#706
fix: replace raw echo with output helpers in check#706github-actions[bot] wants to merge 7 commits into
Conversation
69c777e to
48513bc
Compare
Super-linter summary
All files and directories linted successfully For more information, see the GitHub Actions workflow run Powered by Super-linter |
48513bc to
c107189
Compare
|
|
||
| hint() { | ||
| echo " ? CHECK: $*" | ||
| success() { |
There was a problem hiding this comment.
success() is defined here but is never called anywhere in the script.
Every file that passes all checks exits the loop silently — the user sees a stream of → progress lines and then nothing, making it impossible to distinguish "completed successfully" from "script terminated mid-run". The convention in shell-scripts.instructions.md states success is for completion (green ✓). At minimum it should be called once after the loop to confirm all checks passed:
| success() { | |
| success() { | |
| if [ -t 1 ]; then | |
| printf '\n\033[32m✓\033[0m %s\n' "$*" | |
| else | |
| printf '\n✓ %s\n' "$*" | |
| fi | |
| } |
And at the end of the script (after done), add:
success "All checks passed"There was a problem hiding this comment.
Fixed in 111228a — added success "All checks passed" after the loop.
| bash -n -u "$FILE" || fail "$SHELL: Invalid Script" | ||
| sh -n "$FILE" > /dev/null 2>&1 && hint "Could be run in bash?" | ||
| bash -n -u "$FILE" || die "$SHELL: Invalid Script" | ||
| sh -n "$FILE" > /dev/null 2>&1 && info "Could be run in sh?" |
There was a problem hiding this comment.
info "Could be run in sh?" uses the wrong semantic level for an advisory message.
The old hint() function emitted ? CHECK: Could be run in bash? — visually and programmatically distinct from progress steps ( + Executable, + Shebang) because of the ? CHECK: prefix. A log scanner or developer could reliably grep for ? CHECK to find actionable advisories.
The replacement info "Could be run in sh?" emits → Could be run in sh?, identical in format to info "Executable", info "Shebang", info "* $FILE", and every other progress line. The advisory is now invisible as a separate category in the output stream.
Since the canonical helpers have no advisory/hint level, consider prefixing the message to preserve the distinction:
| sh -n "$FILE" > /dev/null 2>&1 && info "Could be run in sh?" | |
| bash -n -u "$FILE" || die "$SHELL: Invalid Script" | |
| sh -n "$FILE" > /dev/null 2>&1 && info "Hint: Could be run in sh?" |
Or at minimum use wording that makes the advisory nature clear and distinguishable in log output.
There was a problem hiding this comment.
Fixed in 4673a79 — prefixed both sh-portability advisory messages with Hint: to distinguish them from progress steps.
| for FILE in $FILES; do | ||
| echo "* $FILE" | ||
| testing "Executable" | ||
| info "* $FILE" |
There was a problem hiding this comment.
Pre-existing: for FILE in $FILES iterates over an unquoted variable, which word-splits on $IFS (space, tab, newline). If any file path under $BASEDIR contains a space, the path is split into fragments and each fragment is processed as a separate (nonexistent) filename, causing spurious die "Not Executable" or die "No Shebang" failures.
The fix is to read into an array and iterate with "${FILES[@]}", or collect via mapfile:
mapfile -t FILES < <({ \
find "$BASEDIR" -not -path '*/.*' -type f -executable -print || die "Search: find"
...
} | sort -u)
for FILE in "${FILES[@]}"; doThis is adjacent to the changes in this PR — worth fixing here while the loop is being touched.
There was a problem hiding this comment.
Fixed in cd3db9a — replaced FILES=$(...) + unquoted $FILES with mapfile -t FILES < <(...) and "${FILES[@]}".
success() was defined but never called, leaving the script silent on successful completion — indistinguishable from mid-run termination. Prompt: fix each code-review finding in its own commit
…ogress steps The old hint() function emitted ' ? CHECK: ...' making advisories visually distinct from progress steps. Replacing with info() collapses them to the same format. Prefixing with 'Hint:' restores distinction. Prompt: fix each code-review finding in its own commit
for FILE in \$FILES word-splits on \$IFS, breaking paths containing
spaces. mapfile -t + \"${FILES[@]}\" handles any filename safely.
Prompt: fix each code-review finding in its own commit
|
|
||
| done | ||
|
|
||
| success "All checks passed" |
There was a problem hiding this comment.
success "All checks passed" fires even when FILES is empty (no scripts found).
If BASEDIR is wrong, a mount fails, or all files are excluded by the -not -path '*/.*' filter, mapfile populates an empty array. The for FILE in "${FILES[@]}" loop body is skipped silently. success "All checks passed" then prints unconditionally — a false pass in CI with nothing actually checked.
Add a guard before the loop:
| success "All checks passed" | |
| [ "${#FILES[@]}" -gt 0 ] || die "No script files found in ${BASEDIR}" | |
| info "Testing:" | |
| for FILE in "${FILES[@]}"; do |
There was a problem hiding this comment.
Fixed in 1b089c1 — added [ "${#FILES[@]}" -gt 0 ] || die "No script files found" guard before the loop.
success "All checks passed" fired even with no files found, giving a false-positive result when BASEDIR was wrong or no scripts existed. Prompt: fix each code-review finding in its own commit
| info "Executable" | ||
| if [ ! -x "$FILE" ]; then | ||
| fail "Not Executable" | ||
| die "Not Executable" |
There was a problem hiding this comment.
die "Not Executable" omits the filename, and the context is now on a different stream.
info "* $FILE" (line 65) writes to stdout; die "Not Executable" (line 68) writes to stderr. A CI system capturing stdout and stderr into separate log files will see ✗ Not Executable with no indication of which file failed — the filename is only in the stdout log.
The old fail() wrote to stdout alongside echo "* $FILE", so both appeared in the same stream. This split is a real regression in diagnosability.
Fix: include ${FILE} in all die messages inside the loop:
| die "Not Executable" | |
| die "Not Executable: ${FILE}" |
Same applies to die "$SHELL: Invalid Script", die "Unknown Shell: $SHEBANG_EXEC", die "No Shebang: $FIRST_LINE", and die "Shellcheck" further down in the loop.
There was a problem hiding this comment.
Fixed in 29e568b — added ${FILE} to all six die messages inside the per-file loop.
die() now writes to stderr while info "* \$FILE" writes to stdout.
CI systems capturing them separately lose filename context. Adding
\${FILE} to every die message in the loop restores that context.
Prompt: fix each code-review finding in its own commit
The original entry only mentioned output helper replacement; two correctness fixes (mapfile word-splitting safety and empty-files guard) were omitted and warranted their own entries. Prompt: fix each code-review finding in its own commit
AI Review CompleteAll review rounds and security review passed. Auto-merge enabled. Changes made during reviewCode Review (3 rounds):
Security Review: |
Summary
die,testing,hint, andfailfunctions incheckwith the canonicaldie,info, andsuccesshelpers from shell-scripts.instructions.mdtesting()→info(),hint()→info(),fail()→die(), bareecho "Testing:"andecho "* $FILE"→info()excluded()function'secho "1"/echo "0"internal return values preserved unchanged#!/bin/bash(script uses=~and$BASH_REMATCH)Closes #619
Test plan
bash -n check— syntax cleanshellcheck check— lint clean